diff --git a/.editorconfig b/.editorconfig index 0e4a261ebed6..0975b5fe1322 100644 --- a/.editorconfig +++ b/.editorconfig @@ -39,3 +39,8 @@ insert_final_newline = false [*.yml,*.yaml] indent_style = space indent_size = 2 + +[*.mdx] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = false diff --git a/.github/actions/load-buildenv/action.yml b/.github/actions/load-buildenv/action.yml new file mode 100644 index 000000000000..697dd1759ed2 --- /dev/null +++ b/.github/actions/load-buildenv/action.yml @@ -0,0 +1,66 @@ +name: Load build environment +description: > + Loads build-server images uploaded by setup-buildenv into the local Docker + daemon, and resolves the image name from the Go version. Use in jobs that + run the container directly (test jobs). For jobs that only need a shell + inside the container, use run-in-buildenv instead. + +inputs: + go-version: + description: "Go version used to construct the image tag (e.g. 1.26.3)." + required: true + fips-enabled: + description: "Set to 'true' to resolve the FIPS build image" + required: false + default: "false" + +outputs: + image: + description: "Fully-qualified build image name (e.g. mattermost/mattermost-build-server:1.26.3)." + value: ${{ steps.resolve.outputs.image }} + +runs: + using: composite + steps: + - name: Set constants + shell: bash + run: | + echo "BUILDENV_ARTIFACT=buildenv-image" >> "${GITHUB_ENV}" + echo "BUILDENV_FIPS_ARTIFACT=buildenv-fips-image" >> "${GITHUB_ENV}" + echo "BUILDENV_TMPDIR=/tmp/buildenv-save" >> "${GITHUB_ENV}" + - name: Download buildenv artifact + id: download + if: ${{ inputs.fips-enabled != 'true' }} + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: ${{ env.BUILDENV_ARTIFACT }} + path: ${{ env.BUILDENV_TMPDIR }}/ + - name: Load buildenv from artifact + if: ${{ inputs.fips-enabled != 'true' && steps.download.outcome == 'success' }} + shell: bash + run: docker load -i "${BUILDENV_TMPDIR}/image.tar.gz" + - name: Download buildenv-fips artifact + id: download-fips + if: ${{ inputs.fips-enabled == 'true' }} + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: ${{ env.BUILDENV_FIPS_ARTIFACT }} + path: ${{ env.BUILDENV_TMPDIR }}/ + - name: Load buildenv-fips from artifact + if: ${{ inputs.fips-enabled == 'true' && steps.download-fips.outcome == 'success' }} + shell: bash + run: docker load -i "${BUILDENV_TMPDIR}/image-fips.tar.gz" + - name: Resolve image name + id: resolve + shell: bash + env: + FIPS: ${{ inputs.fips-enabled }} + GO_VERSION: ${{ inputs.go-version }} + run: | + if [[ "${FIPS}" == 'true' ]]; then + echo "image=mattermost/mattermost-build-server-fips:${GO_VERSION}" >> "${GITHUB_OUTPUT}" + else + echo "image=mattermost/mattermost-build-server:${GO_VERSION}" >> "${GITHUB_OUTPUT}" + fi diff --git a/.github/actions/run-in-buildenv/action.yml b/.github/actions/run-in-buildenv/action.yml new file mode 100644 index 000000000000..5be49822119e --- /dev/null +++ b/.github/actions/run-in-buildenv/action.yml @@ -0,0 +1,69 @@ +name: Run in build environment +description: > + Runs a script inside the build-server container. Use for build and check + jobs that don't need direct control over the docker run invocation. + + Note the special handling of HEAD_REF, REF_NAME, and RUN_ID. Since the + container is not otherwise given access to the runner's environment, we + re-export github.head_ref, github.ref_name, and github.run_id as a + special case for use in safely building up BUILD_NUMBER. In general, + don't extend this: if your use case requires more customization, use + load-buildenv and invoke docker run yourself. + +inputs: + run: + description: "Bash script to execute inside the container" + required: true + go-version: + description: "Go version to use (e.g. 1.24.3). Defaults to the version in server/.go-version." + required: false + default: "" + fips-enabled: + description: "Set to 'true' to use the FIPS build image" + required: false + default: "false" + working-directory: + description: "Working directory inside the container (absolute path under /mattermost/)" + required: false + default: "/mattermost/server" + +runs: + using: composite + steps: + - name: Read Go version + shell: bash + env: + GO_VERSION_INPUT: ${{ inputs.go-version }} + run: | + if [[ -n "${GO_VERSION_INPUT}" ]]; then + echo "GO_VERSION=${GO_VERSION_INPUT}" >> "${GITHUB_ENV}" + else + echo "GO_VERSION=$(cat server/.go-version)" >> "${GITHUB_ENV}" + fi + - uses: ./.github/actions/load-buildenv + id: buildenv + with: + go-version: ${{ env.GO_VERSION }} + fips-enabled: ${{ inputs.fips-enabled }} + - name: Run in buildenv + shell: bash + env: + CMD: ${{ inputs.run }} + IMAGE: ${{ steps.buildenv.outputs.image }} + WORKING_DIR: ${{ inputs.working-directory }} + HEAD_REF: ${{ github.head_ref }} + REF_NAME: ${{ github.ref_name }} + RUN_ID: ${{ github.run_id }} + run: | + SCRIPT=$(mktemp) + printf 'git config --global --add safe.directory /mattermost\n' > "${SCRIPT}" + printf '%s\n' "${CMD}" >> "${SCRIPT}" + docker run --rm \ + --network host \ + -e HEAD_REF -e REF_NAME -e RUN_ID \ + -v "$PWD:/mattermost" \ + -v "${SCRIPT}:/run-script.sh" \ + -w "${WORKING_DIR}" \ + "${IMAGE}" \ + bash -eo pipefail /run-script.sh + rm -f "${SCRIPT}" diff --git a/.github/actions/setup-buildenv/action.yml b/.github/actions/setup-buildenv/action.yml new file mode 100644 index 000000000000..972618702ba2 --- /dev/null +++ b/.github/actions/setup-buildenv/action.yml @@ -0,0 +1,104 @@ +name: Setup build environment +description: > + Builds the mattermost-build-server images if they don't yet exist on Docker + Hub (e.g. during a Go version bump), and uploads them as artifacts for + downstream jobs. Run once per workflow before any build or test jobs. + +inputs: + go-version: + description: "Go version (e.g. 1.26.3)" + required: true + dockerfile: + description: "Path to Dockerfile.buildenv (relative to workspace root)" + required: false + default: "server/build/Dockerfile.buildenv" + dockerfile-fips: + description: "Path to Dockerfile.buildenv-fips (relative to workspace root)" + required: false + default: "server/build/Dockerfile.buildenv-fips" + +runs: + using: composite + steps: + - name: Set constants + shell: bash + run: | + echo "BUILDENV_IMAGE=mattermost/mattermost-build-server" >> "${GITHUB_ENV}" + echo "BUILDENV_ARTIFACT=buildenv-image" >> "${GITHUB_ENV}" + echo "BUILDENV_DOCKERFILE=${{ inputs.dockerfile }}" >> "${GITHUB_ENV}" + echo "BUILDENV_FIPS_IMAGE=mattermost/mattermost-build-server-fips" >> "${GITHUB_ENV}" + echo "BUILDENV_FIPS_ARTIFACT=buildenv-fips-image" >> "${GITHUB_ENV}" + echo "BUILDENV_FIPS_DOCKERFILE=${{ inputs.dockerfile-fips }}" >> "${GITHUB_ENV}" + echo "BUILDENV_TMPDIR=/tmp/buildenv-save" >> "${GITHUB_ENV}" + # ── Regular ──────────────────────────────────────────────────────── + - name: Resolve regular image + id: resolve + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: | + docker manifest inspect "${BUILDENV_IMAGE}:${GO_VERSION}" > /dev/null 2>&1 || \ + echo "needs-build=true" >> "${GITHUB_OUTPUT}" + - name: Build regular image + if: ${{ steps.resolve.outputs.needs-build == 'true' }} + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: docker build -t "${BUILDENV_IMAGE}:${GO_VERSION}" - < "${BUILDENV_DOCKERFILE}" + - name: Save and upload regular image + if: ${{ steps.resolve.outputs.needs-build == 'true' }} + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: | + mkdir -p "${BUILDENV_TMPDIR}" + docker save "${BUILDENV_IMAGE}:${GO_VERSION}" | gzip > "${BUILDENV_TMPDIR}/image.tar.gz" + - name: Upload regular image artifact + if: ${{ steps.resolve.outputs.needs-build == 'true' }} + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ env.BUILDENV_ARTIFACT }} + path: ${{ env.BUILDENV_TMPDIR }}/image.tar.gz + retention-days: 1 + # ── FIPS (skipped on fork PRs) ───────────────────────────────────── + - name: Docker Hub login + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ env.DOCKERHUB_TOKEN }} + - name: Setup Chainctl + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + uses: chainguard-dev/setup-chainctl@c125f765e82b09a42af3185f3214465314d75c5d # v0.5.0 + with: + identity: ${{ env.CHAINCTL_IDENTITY }} + - name: Resolve FIPS image + id: resolve-fips + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: | + docker manifest inspect "${BUILDENV_FIPS_IMAGE}:${GO_VERSION}" > /dev/null 2>&1 || \ + echo "needs-build=true" >> "${GITHUB_OUTPUT}" + - name: Build FIPS image + if: ${{ steps.resolve-fips.outputs.needs-build == 'true' }} + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: docker build -t "${BUILDENV_FIPS_IMAGE}:${GO_VERSION}" - < "${BUILDENV_FIPS_DOCKERFILE}" + - name: Save and upload FIPS image + if: ${{ steps.resolve-fips.outputs.needs-build == 'true' }} + shell: bash + env: + GO_VERSION: ${{ inputs.go-version }} + run: | + mkdir -p "${BUILDENV_TMPDIR}" + docker save "${BUILDENV_FIPS_IMAGE}:${GO_VERSION}" | gzip > "${BUILDENV_TMPDIR}/image-fips.tar.gz" + - name: Upload FIPS image artifact + if: ${{ steps.resolve-fips.outputs.needs-build == 'true' }} + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ env.BUILDENV_FIPS_ARTIFACT }} + path: ${{ env.BUILDENV_TMPDIR }}/image-fips.tar.gz + retention-days: 1 diff --git a/.github/workflows/mmctl-test-template.yml b/.github/workflows/mmctl-test-template.yml index ae048f6cfd5a..ffdddc482d81 100644 --- a/.github/workflows/mmctl-test-template.yml +++ b/.github/workflows/mmctl-test-template.yml @@ -56,19 +56,22 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Checkout mattermost project uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Setup BUILD_IMAGE - id: build + - name: buildenv/load + id: buildenv + uses: ./.github/actions/load-buildenv + with: + go-version: ${{ inputs.go-version }} + fips-enabled: ${{ inputs.fips-enabled }} + - name: Setup log artifact name + id: log-artifact run: | if [[ "$INPUT_FIPS_ENABLED" == 'true' ]]; then - echo "BUILD_IMAGE=mattermost/mattermost-build-server-fips:${INPUT_GO_VERSION}" >> "${GITHUB_OUTPUT}" echo "LOG_ARTIFACT_NAME=${INPUT_LOGSARTIFACT}-fips" >> "${GITHUB_OUTPUT}" else - echo "BUILD_IMAGE=mattermost/mattermost-build-server:${INPUT_GO_VERSION}" >> "${GITHUB_OUTPUT}" echo "LOG_ARTIFACT_NAME=${INPUT_LOGSARTIFACT}" >> "${GITHUB_OUTPUT}" fi @@ -90,7 +93,7 @@ jobs: - name: Run mmctl Tests env: - BUILD_IMAGE: ${{ steps.build.outputs.BUILD_IMAGE }} + BUILD_IMAGE: ${{ steps.buildenv.outputs.image }} run: | if [[ "$REF_NAME" == 'master' ]]; then export TESTFLAGS="-timeout 90m -race" @@ -120,13 +123,13 @@ jobs: with: report-path: server/report.xml zephyr-api-key: ${{ secrets.MM_E2E_ZEPHYR_API_KEY }} - build-image: ${{ steps.build.outputs.BUILD_IMAGE }} + build-image: ${{ steps.buildenv.outputs.image }} - name: Archive logs if: ${{ always() }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: - name: ${{ steps.build.outputs.LOG_ARTIFACT_NAME }} + name: ${{ steps.log-artifact.outputs.LOG_ARTIFACT_NAME }} path: | server/gotestsum.json server/report.xml diff --git a/.github/workflows/server-ci-nightly-race.yml b/.github/workflows/server-ci-nightly-race.yml index f9cb62afbabc..d21a978961c4 100644 --- a/.github/workflows/server-ci-nightly-race.yml +++ b/.github/workflows/server-ci-nightly-race.yml @@ -21,8 +21,8 @@ permissions: contents: read jobs: - go: - name: Compute Go Version + buildenv: + name: Build Environment runs-on: ubuntu-22.04 outputs: version: ${{ steps.calculate.outputs.GO_VERSION }} @@ -38,7 +38,7 @@ jobs: test-race: name: Race Detector - needs: go + needs: buildenv permissions: contents: read actions: write @@ -48,7 +48,7 @@ jobs: datasource: postgres://mmuser:mostest@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10 drivername: postgres logsartifact: race-detector-server-test-logs - go-version: ${{ needs.go.outputs.version }} + go-version: ${{ needs.buildenv.outputs.version }} fips-enabled: false fullyparallel: false race-enabled: true diff --git a/.github/workflows/server-ci-weekly.yml b/.github/workflows/server-ci-weekly.yml index 18aa48f1639b..e7bb3dfe4dac 100644 --- a/.github/workflows/server-ci-weekly.yml +++ b/.github/workflows/server-ci-weekly.yml @@ -15,15 +15,15 @@ on: - cron: "0 5 * * 1" # Monday 5am UTC (~1am ET) push: branches: - - 'release-*' + - "release-*" workflow_dispatch: # Allow manual trigger for urgent FIPS/binary verification permissions: contents: read jobs: - go: - name: Compute Go Version + buildenv: + name: Build Environment runs-on: ubuntu-22.04 outputs: version: ${{ steps.calculate.outputs.GO_VERSION }} @@ -39,7 +39,7 @@ jobs: test-postgres-binary: name: Postgres with binary parameters - needs: go + needs: buildenv permissions: contents: read actions: write @@ -49,7 +49,7 @@ jobs: datasource: postgres://mmuser:mostest@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10&binary_parameters=yes drivername: postgres logsartifact: postgres-binary-server-test-logs - go-version: ${{ needs.go.outputs.version }} + go-version: ${{ needs.buildenv.outputs.version }} fips-enabled: false # Unsharded run on a single 8-core runner: fullyparallel=true causes # resource exhaustion (too many server instances, WebSocket hubs, and @@ -58,7 +58,7 @@ jobs: test-postgres-normal-fips: name: Postgres FIPS - needs: go + needs: buildenv permissions: contents: read actions: write @@ -71,14 +71,14 @@ jobs: datasource: postgres://mmuser:mostest-fips-test@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10 drivername: postgres logsartifact: postgres-server-fips-test-logs - go-version: ${{ needs.go.outputs.version }} + go-version: ${{ needs.buildenv.outputs.version }} fips-enabled: true # Unsharded run on a single 8-core runner: see note on test-postgres-binary. fullyparallel: false test-mmctl-fips: name: Run mmctl tests (FIPS) - needs: go + needs: buildenv permissions: contents: read actions: write @@ -92,5 +92,5 @@ jobs: datasource: postgres://mmuser:mostest-fips-test@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10 drivername: postgres logsartifact: mmctl-fips-test-logs - go-version: ${{ needs.go.outputs.version }} + go-version: ${{ needs.buildenv.outputs.version }} fips-enabled: true diff --git a/.github/workflows/server-ci.yml b/.github/workflows/server-ci.yml index a90a1f916e71..e4b194b8184d 100644 --- a/.github/workflows/server-ci.yml +++ b/.github/workflows/server-ci.yml @@ -17,8 +17,6 @@ on: - ".github/workflows/server-test-template.yml" - ".github/workflows/server-test-merge-template.yml" - ".github/workflows/mmctl-test-template.yml" - - "!server/build/Dockerfile.buildenv" - - "!server/build/Dockerfile.buildenv-fips" - "tools/mattermost-govet/**" - "!server/**/*.md" - "!server/NOTICE.txt" @@ -38,12 +36,14 @@ jobs: permissions: contents: read pull-requests: read + actions: write + id-token: write # for chainguard (FIPS base image pull) outputs: version: ${{ steps.calculate.outputs.GO_VERSION }} gomod-changed: ${{ steps.changed-files.outputs.any_changed }} steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Calculate version @@ -52,28 +52,32 @@ jobs: run: echo GO_VERSION=$(cat .go-version) >> "${GITHUB_OUTPUT}" - name: Check for go.mod changes id: changed-files - uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: | **/go.mod + - name: Setup build environment + env: + CHAINCTL_IDENTITY: ee399b4c72dd4e58e3d617f78fc47b74733c9557/922f2d48307d6f5f + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + uses: ./.github/actions/setup-buildenv + with: + go-version: ${{ steps.calculate.outputs.GO_VERSION }} check-mocks: name: Check mocks needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Generate mocks - run: make mocks + - uses: ./.github/actions/run-in-buildenv + with: + run: make mocks - name: Check mocks run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the mocks using 'make mocks'" git diff @@ -83,20 +87,16 @@ jobs: name: Check go mod tidy needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Run go mod tidy - run: make modules-tidy + - uses: ./.github/actions/run-in-buildenv + with: + run: make modules-tidy - name: Check modules run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please tidy up the Go modules using make modules-tidy" git diff @@ -106,35 +106,28 @@ jobs: name: check-style needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Run golangci - run: make check-style + - uses: ./.github/actions/run-in-buildenv + with: + run: make check-style check-gen-serialized: name: Check serialization methods for hot structs needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Run make-gen-serialized - run: make gen-serialized + - uses: ./.github/actions/run-in-buildenv + with: + run: make gen-serialized - name: Check serialized run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the serialized files using 'make gen-serialized'" git diff @@ -144,35 +137,28 @@ jobs: name: Vet API needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Run mattermost-vet-api - run: make vet-api + - uses: ./.github/actions/run-in-buildenv + with: + run: make vet-api check-migrations: name: Check migration files needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Extract migrations files - run: make migrations-extract + - uses: ./.github/actions/run-in-buildenv + with: + run: make migrations-extract - name: Check migration files run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the migrations using make migrations-extract" git diff @@ -183,33 +169,29 @@ jobs: # migrations they add must keep the exact version+name they have on # master. New migrations on master-targeted PRs are normal and skipped. if: startsWith(github.base_ref, 'release-') - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - git fetch --no-tags --depth=1 origin master "$GITHUB_BASE_REF" - make check-migration-changes - env: - MM_MIGRATION_CHECK_BASE_REF: origin/${{ github.base_ref }} - MM_MIGRATION_CHECK_CANONICAL_REF: origin/master + uses: ./.github/actions/run-in-buildenv + with: + run: | + git fetch --no-tags --depth=1 origin master "${{ github.base_ref }}" + export MM_MIGRATION_CHECK_BASE_REF="origin/${{ github.base_ref }}" + export MM_MIGRATION_CHECK_CANONICAL_REF="origin/master" + make check-migration-changes check-email-templates: name: Generate email templates needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Generate email templates - run: | - npm install -g mjml@4.9.0 - make build-templates + - uses: ./.github/actions/run-in-buildenv + with: + run: | + npm install -g mjml@4.9.0 + make build-templates - name: Check generated email templates run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the email templates using 'make build-templates'" git diff @@ -219,20 +201,16 @@ jobs: name: Check store layers needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Generate store layers - run: make store-layers + - uses: ./.github/actions/run-in-buildenv + with: + run: make store-layers - name: Check generated code run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the store layers using make store-layers" git diff @@ -242,7 +220,6 @@ jobs: name: Check default roles permissions needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} permissions: contents: read services: @@ -251,26 +228,27 @@ jobs: env: POSTGRES_USER: mmuser POSTGRES_PASSWORD: mostest + POSTGRES_DB: mattermost_test + ports: + - 5432:5432 options: >- --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 5 - defaults: - run: - working-directory: server steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: Generate default roles permissions - env: - IS_CI: "true" - run: make default-roles-permissions + - uses: ./.github/actions/run-in-buildenv + with: + run: | + export IS_CI=true + export TEST_DATABASE_POSTGRESQL_DSN="postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable&connect_timeout=10" + make default-roles-permissions - name: Check generated code run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the default roles permissions using make default-roles-permissions" git diff @@ -280,20 +258,16 @@ jobs: name: Check mmctl docs needs: go runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server steps: - name: Checkout mattermost-server - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - uses: ./.github/actions/run-in-buildenv + with: + run: make mmctl-docs - name: Check docs run: | - echo "Making sure docs are updated" - make mmctl-docs - git config --global --add safe.directory "$GITHUB_WORKSPACE" if [ -n "$(git status --porcelain)" ]; then echo "Please update the mmctl docs using make mmctl-docs" git diff @@ -308,7 +282,7 @@ jobs: name: Postgres (shard ${{ matrix.shard }}) needs: go strategy: - fail-fast: false # Let all shards complete so we get full test results + fail-fast: false # Let all shards complete so we get full test results matrix: shard: [0, 1, 2, 3] permissions: @@ -458,32 +432,23 @@ jobs: contents: read actions: write runs-on: ubuntu-22.04 - container: mattermost/mattermost-build-server:${{ needs.go.outputs.version }} - defaults: - run: - working-directory: server - env: - BUILD_NUMBER: "${GITHUB_HEAD_REF}-${GITHUB_RUN_ID}" - FIPS_ENABLED: false steps: - name: Checkout mattermost project - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: ci/setup-node - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version-file: ".nvmrc" - cache: "npm" - cache-dependency-path: "webapp/package-lock.json" - name: Build - run: | - make config-reset - make build-cmd - make package + uses: ./.github/actions/run-in-buildenv + with: + run: | + export BUILD_NUMBER="$(printf '%s' "${HEAD_REF:-${REF_NAME}}" | tr -c 'A-Za-z0-9._-' '-')-${RUN_ID}" + export FIPS_ENABLED=false + make config-reset + make build-cmd + make package - name: Persist dist artifacts if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: server-dist-artifact path: server/dist/ @@ -492,7 +457,7 @@ jobs: retention-days: 2 - name: Persist build artifacts if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: server-build-artifact path: server/build/ diff --git a/.github/workflows/server-test-template.yml b/.github/workflows/server-test-template.yml index 62ba9357a4b4..6bb4569c47a7 100644 --- a/.github/workflows/server-test-template.yml +++ b/.github/workflows/server-test-template.yml @@ -76,7 +76,7 @@ on: permissions: contents: read - actions: write + actions: read # for load-buildenv artifact listing jobs: test: @@ -110,6 +110,12 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: buildenv/load + id: buildenv + uses: ./.github/actions/load-buildenv + with: + go-version: ${{ inputs.go-version }} + fips-enabled: ${{ inputs.fips-enabled }} - name: Restore test timing data if: inputs.shard-total > 1 @@ -131,14 +137,12 @@ jobs: restore-keys: | server-test-timing-v2- - - name: Setup BUILD_IMAGE - id: build + - name: Setup log artifact name + id: log-artifact run: | if [[ "$INPUT_FIPS_ENABLED" == 'true' ]]; then - echo "BUILD_IMAGE=mattermost/mattermost-build-server-fips:${INPUT_GO_VERSION}" >> "${GITHUB_OUTPUT}" echo "LOG_ARTIFACT_NAME=${INPUT_LOGSARTIFACT}-fips" >> "${GITHUB_OUTPUT}" else - echo "BUILD_IMAGE=mattermost/mattermost-build-server:${INPUT_GO_VERSION}" >> "${GITHUB_OUTPUT}" echo "LOG_ARTIFACT_NAME=${INPUT_LOGSARTIFACT}" >> "${GITHUB_OUTPUT}" fi @@ -225,7 +229,7 @@ jobs: - name: Run Tests env: - BUILD_IMAGE: ${{ steps.build.outputs.BUILD_IMAGE }} + BUILD_IMAGE: ${{ steps.buildenv.outputs.image }} run: | RACE_MODE="" if [[ "$INPUT_RACE_ENABLED" == "true" ]]; then @@ -279,7 +283,7 @@ jobs: if: ${{ always() }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: - name: ${{ steps.build.outputs.LOG_ARTIFACT_NAME }} + name: ${{ steps.log-artifact.outputs.LOG_ARTIFACT_NAME }} path: | server/gotestsum.json server/report.xml diff --git a/.gitignore b/.gitignore index be437655668f..8ca390779968 100644 --- a/.gitignore +++ b/.gitignore @@ -179,3 +179,11 @@ docker-compose.override.yaml server/prev-report.xml server/prev-gotestsum.json server/shard-*.txt + +# Docusaurus docs site (docs/) +docs/site/build/ +docs/site/.docusaurus/ +docs/site/node_modules/ +docs/api/reference/ +docs/pdf/build/ +docs/pdf/node_modules/ diff --git a/api/server/go.mod b/api/server/go.mod index a5da0c1ecec8..069a474ac8a9 100644 --- a/api/server/go.mod +++ b/api/server/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/api/internal -go 1.26.3 +go 1.26.4 require ( github.com/pb33f/libopenapi v0.36.4 diff --git a/api/v4/source/users.yaml b/api/v4/source/users.yaml index 8e04c19892ea..5ba9fec6d264 100644 --- a/api/v4/source/users.yaml +++ b/api/v4/source/users.yaml @@ -2611,6 +2611,82 @@ $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" + /api/v4/users/tokens/non_compliant/count: + get: + tags: + - users + summary: Count non-compliant personal access tokens + description: > + Count the active personal access tokens that violate the configured + `ServiceSettings.MaximumPersonalAccessTokenLifetimeDays` policy (tokens + that never expire or expire beyond the cap). Bot account tokens are + exempt and never counted. Returns 0 when no maximum lifetime is + configured. + + + __Minimum server version__: 11.1 + + + ##### Permissions + + Must have `manage_system` permission. + operationId: GetNonCompliantUserAccessTokenCount + responses: + "200": + description: Count retrieved successfully + content: + application/json: + schema: + type: object + properties: + count: + description: The number of non-compliant personal access tokens + type: integer + format: int64 + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + /api/v4/users/tokens/non_compliant/revoke: + post: + tags: + - users + summary: Revoke non-compliant personal access tokens + description: > + Revoke (hard-delete) every active personal access token that violates + the configured `ServiceSettings.MaximumPersonalAccessTokenLifetimeDays` + policy, along with any sessions created from them, and return the number + of tokens revoked. Bot account tokens are exempt. The request is + rejected with 400 when no maximum lifetime is configured, since there is + nothing to revoke. This is irreversible; use + `/users/tokens/non_compliant/count` first to preview the blast radius. + + + __Minimum server version__: 11.1 + + + ##### Permissions + + Must have `manage_system` permission. + operationId: RevokeNonCompliantUserAccessTokens + responses: + "200": + description: Non-compliant tokens revoked successfully + content: + application/json: + schema: + type: object + properties: + count: + description: The number of personal access tokens revoked + type: integer + format: int64 + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" "/api/v4/users/tokens/{token_id}": get: tags: diff --git a/docs/.vale.ini b/docs/.vale.ini new file mode 100644 index 000000000000..ad97b4d30b2c --- /dev/null +++ b/docs/.vale.ini @@ -0,0 +1,20 @@ +# Vale configuration for Mattermost docs. +# See PLAN.md §7 for the full style enforcement strategy. +# +# Run locally: vale docs/ develop/ api/ +# CI: vale --output=line --no-exit docs/ develop/ api/ + +StylesPath = styles + +# Vale's prebuilt vocabularies. We don't load any of the wholesale +# packages (write-good, proselint) by default — they generate too much +# noise on technical content. Add them per-rule if needed. +MinAlertLevel = suggestion + +# Lint MDX, MD, RST. .docusaurus, build, and node_modules are excluded. +[*.{md,mdx}] +BasedOnStyles = Mattermost +TokenIgnores = (\$\$.*?\$\$), \\\(.*?\\\) + +[*.rst] +BasedOnStyles = Mattermost diff --git a/docs/api/examples.mdx b/docs/api/examples.mdx new file mode 100644 index 000000000000..3ae2e50b08ba --- /dev/null +++ b/docs/api/examples.mdx @@ -0,0 +1,84 @@ +--- +id: examples +title: Quick-start with curl +description: Copy-pasteable curl quick-start for the most common Mattermost API operations. +sidebar_position: 2 +sidebar_label: Examples +--- + +Examples + +Copy-pasteable requests for the most common operations. Replace `your-mattermost-server.com` with your server URL and `` with a valid personal access token. + +## Log in and get a session token + +```bash +curl -i -X POST https://your-mattermost-server.com/api/v4/users/login \ + -H 'Content-Type: application/json' \ + -d '{ + "login_id": "user@example.com", + "password": "yourpassword" + }' +``` + +The session token is returned in the `Token` response header. + +## Post a message to a channel + +```bash +curl -X POST https://your-mattermost-server.com/api/v4/posts \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "channel_id": "", + "message": "Status update from API" + }' +``` + +## Create a channel + +```bash +curl -X POST https://your-mattermost-server.com/api/v4/channels \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "team_id": "", + "name": "ops-incident-2026-05", + "display_name": "Ops Incident — 2026-05", + "type": "O" + }' +``` + +## Add a user to a channel + +```bash +curl -X POST https://your-mattermost-server.com/api/v4/channels//members \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ "user_id": "" }' +``` + +## Upload a file + +```bash +curl -X POST https://your-mattermost-server.com/api/v4/files \ + -H 'Authorization: Bearer ' \ + -F 'channel_id=' \ + -F 'files=@./report.pdf' +``` + +## Trigger a slash command + +```bash +curl -X POST https://your-mattermost-server.com/api/v4/commands/execute \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "channel_id": "", + "command": "/echo Hello from the API" + }' +``` + + +Every endpoint page in the **[Reference](/api/reference/login)** sidebar includes the equivalent samples in **curl, PowerShell, Python, Node, and Go** — selectable via the language tab strip on the right side of the page. + diff --git a/docs/api/index.mdx b/docs/api/index.mdx new file mode 100644 index 000000000000..a17caac41848 --- /dev/null +++ b/docs/api/index.mdx @@ -0,0 +1,107 @@ +--- +slug: / +title: Mattermost API v4 +description: REST API v4 — first-class per-endpoint pages generated from the canonical OpenAPI specification. +sidebar_position: 1 +sidebar_label: Overview +--- + +API Reference + +Every endpoint is a first-class, deep-linkable page generated directly from the canonical OpenAPI spec. Per-endpoint code samples in **curl, PowerShell, Python, Node, and Go**. + + + + + +## Start here + + + +## Common workflows + + + +## How it's generated + +The canonical source is the OpenAPI specification in `mattermost/mattermost/api/v4/source/` (56 YAML fragments, one per resource). The build pipeline: + +```bash +node docs-site/scripts/build-openapi.mjs # bundle 56 fragments → one YAML, 435 paths, 550 ops +npx docusaurus gen-api-docs all # emit ~589 MDX files (one per endpoint + tag pages) +``` + +When the upstream spec changes, this regenerates automatically. AI never authors API reference content — it's deterministic from the spec. + +## Looking for something else? + + + + +The legacy ReDoc-based reference at `developers.mattermost.com/api-documentation` is being decommissioned as part of the cutover (see PLAN.md §11.1 step 10). + diff --git a/docs/develop/contribute/developer-setup/docker.md b/docs/develop/contribute/developer-setup/docker.md new file mode 100644 index 000000000000..6cdd8e8e4c73 --- /dev/null +++ b/docs/develop/contribute/developer-setup/docker.md @@ -0,0 +1,133 @@ +--- +title: "Docker Services" +sidebar_position: 1 +--- + +By default, only a small number of required Docker services are started to support basic development: + +``` +ENABLED_DOCKER_SERVICES="postgres mysql inbucket" +``` + +But there are many additional services ready to work with your local environment. Note that some services will require a Mattermost Enterprise license. + +``` +ENABLED_DOCKER_SERVICES="postgres mysql inbucket minio openldap dejavu keycloak elasticsearch grafana prometheus promtail loki" +``` + +To customize which services are started, either export the above environment variable or copy [`config.mk`](https://github.com/mattermost/mattermost/blob/master/server/config.mk) as `config.override.mk` to tune appropriately. + +## postgres + +From https://www.postgresql.org/: + +> The official site for PostgreSQL, the world's most advanced open source database. + +This is the default and recommended database to use with Mattermost. No additional configuration should be required, but the following settings apply to a Mattermost instance using Postgres: + +``` +MM_SQLSETTINGS_DRIVERNAME=postgres +MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable\u0026connect_timeout=10 +``` + +## mysql + +From https://dev.mysql.com/doc/refman/8.3/en/introduction.html: + +> The MySQL software delivers a very fast, multithreaded, multi-user, and robust SQL (Structured Query Language) database server. + +This is an alternate database supported by Mattermost, but not recommended for new deployments. + +To use with Mattermost, be sure to configure the following settings: +``` +MM_SQLSETTINGS_DRIVERNAME=mysql +MM_SQLSETTINGS_DATASOURCE=mmuser:mostest@tcp(localhost:3306)/mattermost_test?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s +``` + +## inbucket + +From https://inbucket.org/about/: + +> Inbucket is an email testing application; it will accept messages for any email address and make them available to view via a web interface. If you've ever used mailinator.com, you already have a good idea of what Inbucket does. The benefit of Inbucket is that it is an application instead of a hosted service; you may run it on your own private network, or even your desktop. + +Use this during development to "receive" email confirmations, password resets, or message notifications. + +To use with Mattermost, be sure to configure the following settings: +``` +MM_EMAILSETTINGS_ENABLESMTPAUTH=false +MM_EMAILSETTINGS_SMTPUSERNAME= +MM_EMAILSETTINGS_SMTPPASSWORD= +MM_EMAILSETTINGS_SMTPSERVER=localhost +MM_EMAILSETTINGS_SMTPPORT=10025 +``` + +When running, access the web interface at [http://localhost:9001/](http://localhost:9001/). +![inbucket](/img/docker/inbucket.png) + +## grafana + +From https://grafana.com/docs/ + +> Collect, correlate, and visualize data with beautiful dashboards using our open source data visualization and monitoring solution. + +Grafana is where all the metrics and logs collected by Prometheus, Loki and promtail come together. Panels visualize the data and are grouped into dashboards. The home dashboard links out to various performance dashboards, lists which Docker services are currently online, has quick links to various filtered log views, and panels showing the most recent Mattermost and Docker container logs. + +When running, access the web interface at [http://localhost:3000](http://localhost:3000). +![grafana](/img/docker/grafana.png) + +## prometheus + +From https://prometheus.io/docs/introduction/overview/: + +> Prometheus collects and stores its metrics as time series data, i.e. metrics information is stored with the timestamp at which it was recorded, alongside optional key-value pairs called labels. + +Mattermost exposes metrics at [http://localhost:8067/metrics](http://localhost:8067/metrics) which are scraped periodically by Prometheus to form a time series database. While you can access Prometheus directly to view and graph this collected data, typically this is used in tandem with Grafana for a rich dashboard experience. + +To use with Mattermost, be sure to install a Mattermost enterprise license and configure the following settings: + +``` +MM_METRICSSETTINGS_ENABLE=true +``` + +When running, access the web interface at [http://localhost:9090/](http://localhost:9090). +![prometheus](/img/docker/prometheus.png) + +## promtail + +From https://grafana.com/docs/loki/latest/send-data/promtail/: + +> Promtail is an agent which ships the contents of local logs to a private Grafana Loki instance or Grafana Cloud. It is usually deployed to every machine that runs applications which need to be monitored. + +To use with Mattermost, be sure to enable file logs, with the containing directory automatically mounted as a volume for promtail to scrape and relay to Loki. Promtail is automatically configured to scrape all Docker container logs for use with Loki and Grafana. + +``` +MM_LOGSETTINGS_ENABLEFILE=true +MM_LOGSETTINGS_FILELEVEL=debug +MM_LOGSETTINGS_FILEJSON=true +MM_LOGSETTINGS_FILELOCATION=logs +``` + +## loki + +From https://grafana.com/oss/loki/: + +> Loki is a log aggregation system designed to store and query logs from all your applications and infrastructure. + +Just as Prometheus is for metrics, think of Loki being for logs. Combined with promtail scraping the logs from Mattermost and all these supporting Docker containers, and Grafana for the frontend, Loki effectively provides a powerful user interface for slicing and dicing your developer logs. + +## keycloak + +From https://www.keycloak.org/documentation: + +> Keycloak is an open source identity and access management solution. + +Keycloak can be used as a SAML identity provider with your local setup. See the setup instructions [here](https://github.com/mattermost/mattermost/blob/master/server/build/docker/keycloak/README.md). + +# Other Docker services + +Other Docker services supported by the development environment include: +* minio +* openldap +* dejavu +* elasticsearch + diff --git a/docs/develop/contribute/developer-setup/index.md b/docs/develop/contribute/developer-setup/index.md new file mode 100644 index 000000000000..74f2b3135dcb --- /dev/null +++ b/docs/develop/contribute/developer-setup/index.md @@ -0,0 +1,234 @@ +--- +title: "Developer setup" +sidebar_position: 1 +--- + +Set up your development environment for building, running, and testing Mattermost. + + + +- If you're migrating from before the monorepo see the [migration notes](/developers/contribute/monorepo-migration-notes). +- If you're developing plugins, see the plugin [developer setup](/developers/integrate/plugins/developer-setup) documentation. +- If you are forking Mattermost to create a derivative version, you must comply with the AGPLv2 license in both source code and compiled versions and replace the Mattermost name and logo from the system, among other requirements, per the [Mattermost trademark policy](https://mattermost.com/trademark-standards-of-use/). + + + +# Prerequisites for Windows + +If you're using Windows, we recommend using the Windows Subsystem for Linux (WSL) for Mattermost development. Go and Node must be run from within WSL, so you'll need to install them in WSL even if you already have the Windows versions of them installed. + +1. [Install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) by running the following command as an administrator in PowerShell: `wsl --install` +2. [Install Docker Desktop for Windows](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers#install-docker-desktop) on your Windows machine. Alternatively, you can also [install](https://docs.docker.com/engine/install/) docker engine directly on your linux distribution. +3. Perform the rest of the operations (except Docker installation) within the WSL environment and not in Windows. + +# Setup the Mattermost Server + + + +The web app isn't exposed directly, it's exposed via the server. So if both server and web app are running, you can open `localhost:8065`, the server's port to access the web app. + + + +1. Install `make`. + - On Ubuntu, you can install `build essential` tools which will also take care of installing the `make`: + + ```sh + sudo apt install build-essential + ``` + +1. Install and run [Docker](https://www.docker.com/). If you don't want to use Docker, you can follow [this guide](#develop-mattermost-without-docker). + - When running `docker` commands under WSL2, if you receive the error `The command 'docker' could not be found in this WSL 2 distro.` you may need to toggle the `Use the WSL 2 based engine` off and on within Docker Settings after installation. + - Make sure that Docker has virtual file share access to the directory that you will clone the repository in + +1. Install [Go](https://go.dev/). + - Version 1.21 or higher is required. + +1. Increase the number of available file descriptors. Update your shell's initialization script (e.g. `.bashrc` or `.zshrc`), and add the following: + + ```sh + ulimit -n 8096 + ``` + +1. If you don't have it already, install libpng with your preferred package manager. + + - If you are on ARM based Mac, you'll need to install [Rosetta](https://support.apple.com/en-in/HT211861) to make `libpng` work. Rosetta can be installed by the following command- + + ```sh + softwareupdate --install-rosetta + ``` + +1. Fork https://github.com/mattermost/mattermost. + +1. Clone the Mattermost source code from your fork: + + ```sh + git clone https://github.com/YOUR_GITHUB_USERNAME/mattermost.git + ``` + +1. Install NVM and use it to install the required version of Node.js: + + 1. Install [NVM](https://github.com/nvm-sh/nvm) by following [these instructions](https://github.com/nvm-sh/nvm#installing-and-updating). + + 1. Then, use NVM to install the correct version of Node.js for the Mattermost web app (this should be run within the `webapp` directory): + ```sh + nvm install + ``` + +1. Start the server: + + ```sh + cd server + make run-server + ``` + +1. Test your environment to ensure that the server is running: + + ```sh + curl http://localhost:8065/api/v4/system/ping + ``` + + If successful, the `curl` step will return a JSON object: + ```json + {"AndroidLatestVersion":"","AndroidMinVersion":"","DesktopLatestVersion":"","DesktopMinVersion":"","IosLatestVersion":"","IosMinVersion":"","status":"OK"} + ``` + +1. Set up up your admin user using mmctl: + + ```sh + bin/mmctl user create --local --email ADMIN_EMAIL --username ADMIN_USERNAME --password ADMIN_PASSWORD --system-admin + ``` + + - Optionally, you can also populate the database with random sample data as well: + + ```sh + bin/mmctl sampledata + ``` + +1. Start the web app: + + ```sh + cd webapp + make run + ``` + +1. Open the web app by going to http://localhost:8065 in your browser or by adding it to the Mattermost desktop app. + +1. Stop the server: + + ```sh + make stop-server + ``` + + The `stop-server` make target does not stop all the docker containers started by `run-server`. To stop the running docker containers: + + ```sh + make stop-docker + ``` + +1. Set your options: + + Some behaviors can be customized such as running the server in the foreground as described in the `config.mk` file in the server directory. See that file for details. + +# Build the Mattermost Server + +The `make package` command will package the application and place it under the `./dist` directory. You can distribute the .tar.gz file if you wish the run the application elsewhere. Note that you would need to run `make build` before this to build the binaries. + +# Develop Mattermost without Docker +1. Install `make`. + - On Ubuntu, you can install `build essential` tools which will also take care of installing the `make`: + ```sh + sudo apt install build-essential + ``` +1. Copy the file `server/config.mk` as `server/config.override.mk` and set `MM_NO_DOCKER` to `true` in the copy. +1. Install [PostgreSQL](https://www.postgresql.org/download/) +1. Run `psql postgres`. Then create `mmuser` by running `CREATE ROLE mmuser WITH LOGIN PASSWORD 'mostest';` +1. Modify the role to give rights to create a database by running `ALTER ROLE mmuser CREATEDB;` +1. Confirm the role rights by running `\du` +1. Before creating the database, exit by running `\q` +1. Login again via `mmuser` by running `psql postgres -U mmuser` +1. Create the database by running `CREATE DATABASE mattermost_test;` and exit again with `\q` +1. Login again with `psql postgres` and run `GRANT ALL PRIVILEGES ON DATABASE mattermost_test TO mmuser;` to give all rights to `mmuser` +1. Install [Go](https://go.dev/). +1. Increase the number of available file descriptors. Update your shell's initialization script (e.g. `.bashrc` or `.zshrc`), and add the following: + ```sh + ulimit -n 8096 + ``` + +1. If you don't have it already, install libpng with your preferred package manager. + - If you are on ARM based Mac, you'll need to install [Rosetta](https://support.apple.com/en-in/HT211861) to make `libpng` work. Rosetta can be installed by the following command- + ```sh + softwareupdate --install-rosetta + ``` + +1. Fork https://github.com/mattermost/mattermost. +1. Clone the Mattermost source code from your fork: + ```sh + git clone https://github.com/YOUR_GITHUB_USERNAME/mattermost.git + cd mattermost + ``` + +1. Install NVM and use it to install the required version of Node.js: + - First, install [NVM](https://github.com/nvm-sh/nvm) by following [these instructions](https://github.com/nvm-sh/nvm#installing-and-updating). + - Then, use NVM to install the correct version of Node.js for the Mattermost web app (this should be run within the `webapp` directory): + ```sh + cd webapp + nvm install + cd .. + ``` + - NOTE: If you get `zsh: command not found: nvm` when running `nvm install`, you will need to add the following to your ~/.zshrc file: + ```zsh + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm + [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion + ``` + +1. Start the server: + ```sh + cd server + make run-server + ``` + +1. Test your environment to ensure that the server is running by running the following in a different terminal session: + + ```sh + curl -s http://localhost:8065/api/v4/system/ping | jq . + ``` + + If successful, the `curl` step will return a JSON object: + ```json + {"AndroidLatestVersion":"","AndroidMinVersion":"","DesktopLatestVersion":"","DesktopMinVersion":"","IosLatestVersion":"","IosMinVersion":"","status":"OK"} + ``` + + Alternately, you can enter `http://localhost:8065/api/v4/system/ping` in a web browser. + +1. Set up up your admin user using mmctl: + + ```sh + bin/mmctl user create --local --email ADMIN_EMAIL --username ADMIN_USERNAME --password ADMIN_PASSWORD --system-admin + ``` + + - Note: `ADMIN_PASSWORD` must be 8 characters or more. + + - Optionally, you can also populate the database with random sample data as well: + + ```sh + bin/mmctl --local sampledata + ``` + +1. Start the web app (in another terminal window): + + ```sh + cd PATH_TO_MATTERMOST_REPO/webapp + make run + ``` + +1. Open the web app by going to http://localhost:8065 in your browser or by adding it to the Mattermost desktop app. + +1. Stop the server: + ```sh + cd PATH_TO_MATTERMOST_REPO/server + make stop-server + ``` + +1. Set your options: + Some behaviors can be customized such as running the server in the foreground as described in the `config.mk` file in the server directory. See that file for details. diff --git a/docs/develop/contribute/expectations/index.md b/docs/develop/contribute/expectations/index.md new file mode 100644 index 000000000000..7eba4a6382a1 --- /dev/null +++ b/docs/develop/contribute/expectations/index.md @@ -0,0 +1,83 @@ +--- +title: "Contributor expectations" +sidebar_position: 3 +--- + +To contribute to Mattermost, you must sign the [Contributor License Agreement](https://mattermost.com/mattermost-contributor-agreement/). Doing so adds you to our list of [Mattermost Approved Contributors](https://docs.google.com/spreadsheets/d/1NTCeG-iL_VS9bFqtmHSfwETo5f-8MQ7oMDE5IUYJi_Y/pubhtml?gid=0&single=true). +Please also read our [community expectations](/developers/contribute/good-decisions/) and note that we all abide by the [Mattermost Code of Conduct (CoC)](https://handbook.mattermost.com/contributors/contributors/guidelines/contribution-guidelines), and by joining our contributor community, you agree to abide by it as well. + + + +Love swag? If you choose to provide us with your mailing address in the signed agreement, you'll receive a [Limited Edition Mattermost Mug](https://forum.mattermost.com/t/limited-edition-mattermost-mugs/143) as a thank you gift after your first pull request is merged. + + + + +## Before contributing + +There are many ways to contribute to Mattermost beyond a core Mattermost repository: +- You can create lightweight external applications that don’t require customizations to the Mattermost user experience by using [incoming](/developers/integrate/webhooks/incoming) and [outgoing](/developers/integrate/webhooks/outgoing) webhooks, or by using [the Mattermost API](https://api.mattermost.com/). +- You can activate external functionality within Mattermost by creating custom [slash commands](/developers/integrate/slash-commands/). +- You can extend, modify, and deeply integrate with the Mattermost server and its UI/UX by using [plugins](/developers/integrate/plugins/). However, please note that plugin development comes with the highest level of overhead and must be written in Go and React. +- You can use Mattermost from other applications, by [embedding and launching](/developers/integrate/customization/embedding/) Mattermost within other applications and mobile apps. + +To get started: + +1. Identify which repository you need to work in (see point below), then review the README located within the root of the repository to learn more about getting started with your contribution and any processes that may be unique to that repository. + + These are the Mattermost Core repositories you can contribute to: + - [Server](/developers/contribute/more-info/server/): Highly-scalable Mattermost server written in Go. + - [Web App](/developers/contribute/more-info/webapp/): JavaScript client app built on React and Redux. + - [Mobile Apps](/developers/contribute/more-info/mobile/): JavaScript client apps for Android and iOS built on React Native. + - [Desktop App](/developers/contribute/more-info/desktop/): An Electron wrapper around the web app project that runs on Windows, Linux, and macOS. + - [Core Plugins](/developers/contribute/more-info/plugins/): A core set of officially-maintained plugins that provide a variety of improvements to Mattermost. + - [Boards](/developers/contribute/more-info/focalboard/) and [Playbooks](https://github.com/mattermost/mattermost-plugin-playbooks) core integrations. + +2. To contribute to documentation, you should be able to edit any page and get to the source file in the documentation repository by selecting the **Edit on GitHub** button in the top right of its respective published page. You can read more about this process on the [why and how to contribute page](/developers/contribute/why-contribute/#you-want-to-help-with-content). You can contribute to the following Mattermost documentation sites: + + - [Product documentation](https://github.com/mattermost/docs) + - [Developer documentation](https://github.com/mattermost/mattermost-developer-documentation) + - [API reference documentation](https://github.com/mattermost/mattermost-api-reference) + - [Handbook documentation](https://github.com/mattermost/mattermost-handbook) + +## During the contribution process + +1. Check in regularly with your Pull Request (PR) to review and respond to feedback. +2. Thoroughly document what you’re doing in your PR. This way, future contributors can pick up on your work (including you!). This is especially helpful if you need to step back from a PR. +3. Each PR should represent a single project, both in code and in content. Keep unrelated tasks in separate PRs. +4. Make your PR titles and commit messages descriptive! Briefly describing the project in the PR title and in your commit messages often results in faster responses, less clarifying questions, and better feedback. + + + +If you need to take a break from an assigned issue during, for example, the Hacktoberfest project, please commit any completed work to date in a PR, and note that you're stepping away in the issue itself. These two steps help ensure that your contributions are counted and outstanding work on a given ticket can be made available to other contributors. + + + +## Writing code + +Thoroughly test your contributions! We recommend the following testing best practices for your contribution: +1. Detail exactly what you expect to happen in the product when others test your contributions. +2. Identify updates to existing [product](https://docs.mattermost.com/), [developer](https://developers.mattermost.com/), and/or [API](https://api.mattermost.com/) documentation based on your contributions, and identify documentation gaps for new features or functionality. + + + +Contributors and reviewers are strongly encouraged to work with the Mattermost Technical Writing team via the [Documentation Working Group channel](https://community.mattermost.com/core/channels/dwg-documentation-working-group) on the Mattermost Community Server before approving community contributions. See the Mattermost Handbook for additional details on [engaging the Mattermost Technical Writing team](https://handbook.mattermost.com/operations/research-and-development/product/technical-writing-team-handbook/work-with-us#how-to-engage-with-us), and for [submitting documentation with your PR](https://handbook.mattermost.com/operations/research-and-development/product/technical-writing-team-handbook/writing-community-documentation#submit-documentation-with-your-pr). + + + + +3. If your PR adds a new plugin API method or hook, please add an example to the [Plugin Starter Template](https://github.com/mattermost/mattermost-plugin-starter-template). +4. If your code adds a new user interface string, include it in the proper localization file, either for [the server](https://github.com/mattermost/mattermost/blob/master/server/i18n/en.json), [the webapp](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/i18n/en.json), or [mobile](https://github.com/mattermost/mattermost-mobile/blob/master/assets/base/i18n/en.json). + + + + +When working within the webapp repository, additionally run `make i18n-extract` from a terminal to update the list of product strings with your changes. + + + +# Writing content + +Always consider who will consume your content, and write directly to your target audience. + +Write clearly and be concise. Write informally, in the present tense, and address the reader directly. See our [voice, tone, and writing style guidelines](https://handbook.mattermost.com/operations/operations/company-processes/publishing/publishing-guidelines/voice-tone-and-writing-style-guidelines), and the [Mattermost Documentation Style Guide](https://handbook.mattermost.com/operations/operations/company-processes/publishing/publishing-guidelines/voice-tone-and-writing-style-guidelines) for details on general writing principles, syntax used to format content, and common terms used to describe product functionality. diff --git a/docs/develop/contribute/good-decisions/fixing-pr-mistakes.md b/docs/develop/contribute/good-decisions/fixing-pr-mistakes.md new file mode 100644 index 000000000000..9978fc630840 --- /dev/null +++ b/docs/develop/contribute/good-decisions/fixing-pr-mistakes.md @@ -0,0 +1,38 @@ +--- +title: "When a merged PR results in a bug" +sidebar_position: 2 +--- + +This page describes the process to follow when someone notices a mistake in a merged pull request (PR). + +1. A contributor (either staff or community member) submits a PR, it is reviewed and merged into the codebase. +2. Sometime later, the community notices a mistake with the PR. + +Question is, what should we, as a community, do? That depends on the scope of the changes in the PR that was merged. + +## Low impact issues +A low impact PR might mean that it affected: +- Some non-critical functionality. +- It doesn't affect users in a substantial way. + +If this is the case, do the following: + +1. Capture details in an issue. +2. Mark it according to its priority. +3. Would be best to assign it to the person who introduced the issue in the first place. + +## High impact issues +A high impact PR represents something that has or will result in a customer incident. + +If this is the case, there are two scenarios: + +1. The feature introduced in the PR is handled by a feature flag. +2. The feature introduced in the PR is **not** handled by a feature flag. + +For scenario 1, if it's not affecting other functionality, turn that feature flag off to disable the feature. + +For scenario 2: + +1. Revert the changes introduced in the original PR. +2. Notify the person who worked on the PR so they can work on a proper fix for their PR. +3. Reintroduce the change through the regular PR cycle. diff --git a/docs/develop/contribute/good-decisions/index.md b/docs/develop/contribute/good-decisions/index.md new file mode 100644 index 000000000000..5ece9192c448 --- /dev/null +++ b/docs/develop/contribute/good-decisions/index.md @@ -0,0 +1,37 @@ +--- +title: "Community expectations" +sidebar_position: 2 +--- +We are a welcoming and open community and we’re excited to have you join us! + +To be an open, safe, and welcoming community, we strive to be inclusive, collaborative, considerate, and respectful. We all abide by the [Mattermost Code of Conduct (CoC)](https://handbook.mattermost.com/contributors/contributors/guidelines/contribution-guidelines), and by joining our contributor community, **you agree to abide by it as well**. + +Learn more about our [company values](https://handbook.mattermost.com/company/about-mattermost#leadership-principles), and how to become a successful member of the Mattermost community by learning and following our standard operational guidelines below. Please read these sections below carefully and let us know if you have any questions or concerns. + +## We are inclusive + +We welcome all people, **but not all behavior**. + +We are a diverse community who celebrate both our differences and the things that connect us. We treat each other with respect, and aim to treat others better than they wish to be treated. + +We try our best to be clear and respectful. We remember that others may not communicate in the same language with the same fluency. We recognize that communication can be challenging, especially among a diverse group of people communicating in many different languages and coming from many different cultures and backgrounds. + +We all try to be mindful of our differences when we communicate and collaborate. We’re aware that misunderstandings can happen. We try to resolve them by being respectful, understanding, and by using clear and simple language. + +## We are collaborative + - We ask questions and consult others. + - We work together and help each other. + - We aim for clarity. + +## We are considerate + - We have patience with each other. + - We understand that no one has all the answers, nor are they expected to. + +## We are respectful + - We offer thanks and we’re grateful. + - We may occasionally disagree, but we resolve these disagreements in respectful ways, take breaks if things get heated, reassess, and consult others where appropriate. + - We aim to be self-aware and we take responsibility for our impact through our words and actions. + - We understand and acknowledge that [intent doesn’t equal impact](https://www.betterup.com/blog/intent-vs-impact). We can have the best of intentions, but still cause negative impact to others by our words and actions. This can happen to all of us, so we practice openness and grace. + +### Attribution +This document was heavily inspired by and adapted from the work of the [Drupal Community and its Code of Conduct](https://www.drupal.org/dcoc) and its [Values and Principles](https://www.drupal.org/about/values-and-principles) documents. diff --git a/docs/develop/contribute/index.md b/docs/develop/contribute/index.md new file mode 100644 index 000000000000..0e3c0adf729f --- /dev/null +++ b/docs/develop/contribute/index.md @@ -0,0 +1,19 @@ +--- +title: "Contributor guide" +sidebar_position: 1 +--- +This guide is your reference for all Mattermost contributions. The following is a brief summary to help you find what you're looking for: + +- **[Why and how to contribute](/why-contribute)**: + How to get started contributing to Mattermost projects. + +- **[Community expectations](/good-decisions)**: + How to communicate and interact effectively, respectfully, and inclusively with other members of the Mattermost community. + +- **[Contributor expectations](/expectations)**: + What is expected of you throughout the whole contribution process, including guidelines to follow when producing new code and content. + +- **[Where to find more information](/more-info)**: + Where to find more information on the contribution process beyond the guidance offered in this guide. + +Please consult this guide as your official reference when contributing at Mattermost. diff --git a/docs/develop/contribute/monorepo-migration-notes.md b/docs/develop/contribute/monorepo-migration-notes.md new file mode 100644 index 000000000000..b9bea1ffab2b --- /dev/null +++ b/docs/develop/contribute/monorepo-migration-notes.md @@ -0,0 +1,28 @@ +--- +title: "Monorepo migration notes" +sidebar_position: 2 +--- + +If you are transitioning from the non-monorepo ``mattermost-server`` to the monorepo, the easiest way to do so is to move the old mattermost server folder to something like ``mattermost-server-old`` then re-clone mattermost-server. +Then: + +1. Copy over your old config + + ```sh + cd server + cp ../../mattermost-server-old/config/config.json ./config/ + ``` + +1. Copy over your developer config override + + ```sh + cd server + cp ../../mattermost-server-old/config.override.mk ./ + ``` + +1. Update your development Docker containers for the new location of the server folder: + + ```sh + cd server + make update-docker + ``` diff --git a/docs/develop/contribute/more-info/containers/index.md b/docs/develop/contribute/more-info/containers/index.md new file mode 100644 index 000000000000..9f313a3ef6dd --- /dev/null +++ b/docs/develop/contribute/more-info/containers/index.md @@ -0,0 +1,55 @@ +--- +title: "Containers" +--- + +Mattermost uses the [Docker Registry](https://hub.docker.com/u/mattermost) to publish the official images for the Mattermost Server and also for other supporting images that are used for internal/public development and testing. + +This page lists all the Docker repositories currently in use. + +## Mattermost official docker images + +- [mattermost/mattermost-enterprise-edition](https://hub.docker.com/r/mattermost/mattermost-enterprise-edition) - **Official Mattermost Server** image for the **Enterprise Edition version**. To find the Dockerfile please refer to the [GitHub repo](https://github.com/mattermost/mattermost/tree/master/server/build). + +- [mattermost/mattermost-team-edition](https://hub.docker.com/r/mattermost/mattermost-team-edition) - **Official Mattermost Server** image for the **Team Edition version**. To find the Dockerfile please refer to the [GitHub repo](https://github.com/mattermost/mattermost/tree/master/server/build). + +- [mattermost/mattermost-push-proxy](https://hub.docker.com/r/mattermost/mattermost-push-proxy) - Mattermost Push Proxy. [Documentation](/developers/contribute/more-info/mobile/push-notifications/service). [GitHub repo](https://github.com/mattermost/mattermost-push-proxy). + +- [mattermost/mattermost-loadtest](https://hub.docker.com/r/mattermost/mattermost-loadtest) - Image for the Load Test application. Tools for profiling Mattermost under heavy load. [GitHub repo](https://github.com/mattermost/mattermost-load-test). + +- [mattermost/mattermost-operator](https://hub.docker.com/r/mattermost/mattermost-operator) - Official image for Mattermost Operator for Kubernetes. For more information please refer to the [GitHub repo](https://github.com/mattermost/mattermost-operator). + +- [mattermost/mattermost-cloud](https://hub.docker.com/r/mattermost/mattermost-cloud) - Mattermost Private Cloud is a SaaS offering meant to smooth and accelerate the customer journey from trial to full adoption. For more information please refer to the [GitHub repo](https://github.com/mattermost/mattermost-cloud). + +- [mattermost/mattermost-preview](https://hub.docker.com/r/mattermost/mattermost-preview) - This is a Docker image to install Mattermost in Preview Mode for exploring product functionality on a single machine using Docker. [Documentation](http://bit.ly/1W76riY). [GitHub repo](https://github.com/mattermost/mattermost-docker-preview). + +- [mattermost/platform](https://hub.docker.com/r/mattermost/platform) - Mirror of **mattermost/mattermost-preview**. This is a Docker image to install Mattermost in Preview Mode for exploring product functionality on a single machine using Docker. Preview image (mirror). [Documentation](http://bit.ly/1W76riY). [GitHub repo](https://github.com/mattermost/mattermost-docker-preview). + +## Community-maintained Docker images + +- [mattermost/mattermost-prod-app](https://hub.docker.com/r/mattermost/mattermost-prod-app) - Community driven image for Mattermost Server. **This Docker repository will be deprecated in Mattermost 6.0**. For more information and to check the Dockerfile please refer to the [GitHub repo](https://github.com/mattermost/mattermost-docker). + +- [mattermost/mattermost-prod-db](https://hub.docker.com/r/mattermost/mattermost-prod-db) - Community driven image for Database to run together with **mattermost/mattermost-prod-app**. **This Docker repository will be deprecated in Mattermost 6.0**. For more information and to check the Dockerfile please refer to the [GitHub repo](https://github.com/mattermost/mattermost-docker). + +- [mattermost/mattermost-prod-web](https://hub.docker.com/r/mattermost/mattermost-prod-web) - Community driven image for WebServer to run together with **mattermost/mattermost-prod-app**. **This Docker repository will be deprecated in Mattermost 6.0**. For more information and to check the Dockerfile please refer to the [GitHub repo](https://github.com/mattermost/mattermost-docker). + +## Mattermost internal Docker images + +- [mattermost/mattermost-test-enterprise](https://hub.docker.com/r/mattermost/mattermost-test-enterprise) - Repository where all testing images are published and available for any type of testing. These images are built from the CircleCI Pipelines from the [mattermost-server](https://github.com/mattermost/mattermost) and [mattermost-webapp](https://github.com/mattermost/mattermost-webapp). + +- [mattermost/mattermost-test-team](https://hub.docker.com/r/mattermost/mattermost-test-team) - Repository where all testing images are published and available for any type of testing. These images are built from the CircleCI Pipelines from the [mattermost-server](https://github.com/mattermost/mattermost) and [mattermost-webapp](https://github.com/mattermost/mattermost-webapp). + +- [mattermost/mattermost-elasticsearch-docker](https://hub.docker.com/r/mattermost/mattermost-elasticsearch-docker) - Used in in CI and for local development. Please refer to the [GitHub repo](https://github.com/mattermost/mattermost/blob/master/docker-compose.yaml) for more information. + +- [mattermost/mattermost-build-server](https://hub.docker.com/r/mattermost/mattermost-build-server) - Image used to build Mattermost used in CI. To check the Docker file refer to the [GitHub repo](https://github.com/mattermost/mattermost/blob/master/server/build/Dockerfile.buildenv). + +- [mattermost/mattermost-wait-for-dep](https://hub.docker.com/r/mattermost/mattermost-wait-for-dep) - Image used to wait for the other containers to start. Used in in CI and for local development. Please refer to the [GitHub repo](https://github.com/mattermost/mattermost/blob/master/docker-compose.yaml) for more information. + +- [mattermost/sync-helpwanted-tickets](https://hub.docker.com/r/mattermost/sync-helpwanted-tickets) - For internal use. This image runs the sync with Jira tickets and GitHub Issues. To check the code please refer to the [GitHub repo](https://github.com/mattermost/mattermost-utilities/tree/master/github_jira_tools). + +- [mattermost/podman](https://hub.docker.com/repository/docker/mattermost/podman) - For internal use. Contains Podman to build/tag/push container images. + +- [mattermost/chewbacca](https://hub.docker.com/repository/docker/mattermost/chewbacca-bot) - For internal use. A GitHub Bot for administrative tasks. Please refer to the [GitHub repo](https://github.com/mattermost/chewbacca) for more information. + +- [mattermost/matterwick](https://hub.docker.com/repository/docker/mattermost/matterwick) - For internal use. A GitHub Bot to spin test servers for pull requests. Please refer to the [GitHub repo](https://github.com/mattermost/matterwick) for more information. + +- [mattermost/webrtc](https://hub.docker.com/repository/docker/mattermost/webrtc) - DEPRECATED. Preview docker image of Mattermost WebRTC. diff --git a/docs/develop/contribute/more-info/desktop/architecture/configuration.md b/docs/develop/contribute/more-info/desktop/architecture/configuration.md new file mode 100644 index 000000000000..84b264e33818 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/configuration.md @@ -0,0 +1,44 @@ +--- +title: "Configuration" +sidebar_position: 1 +--- + +### Config module + +The **configuration** module in the **Common** module is responsible for facilitating reading from and writing to external configuration sources. It also consolidates, verifies, and upgrades configuration where applicable. + +#### Files + +We have a few different configuration files in the Desktop App, but the main one is `config.json`. Most of the user's configuration from the Settings Window is stored there, as well as any user-configured servers. + +The application supports different configuration versions and allows for them to be migrating to the version supported by the configuration module via the `upgradePreferences` module. When no configuration is found, the `defaultPreferences` object is copied over to the main configuration module. + +We also support a build configuration in which the packager of the application can pre-define servers and a few other configuration items. + +#### Registry + +We support reading from the Windows registry to allow system administrators to define Group Policy that will pre-define servers and potentially disable user-defined servers and automatic updates as per administrator wishes. + +Templates for these can be found under `resources\windows\gpo`. + +### Server manager + +The `ServerManager` is a singleton class that acts as a single source of truth for all server configuration, managing adding/modifying/removing servers and serving the server information to the rest of the application. + +#### Initialization + +We populate the `ServerManager` with all servers provided by the **configuration** module, marking them as pre-defined when applicable to not allow the user to modify them. Servers are given a unique UUID when the app initialized, and this UUID acts as the global way of identifying the server to the rest of the application. + +An external call is responsible for populating information about the specific Mattermost server (eg. server version, plugins installed), but the data is stored within the `ServerManager`. + +#### Modification + +The `ServerManager` is the only place that allows the persistent server configuration to be modified. Changes cannot be made directly through the **configuration** module. Once a server is modified, the `ServerManager` will update the **configuration** module with the new changes. + +When a server is added or updating, up to two events will be emitted: +- `SERVERS_UPDATE`: This event is emitted when the `ServerManager` has new changes. This could be a name, URL or an ordering change. +- `SERVERS_URL_MODIFIED`: This event is emitted specifically when a URL has changed, signifying that the application might need to fetch new remote server information or refresh any views associated with the server to reflect the new URL. + +#### Lookup + +We provide a server lookup call that allows for an arbitrary URL to be provided and potentially matched to a server. If found, the UUID will be provided. This function is useful for deep linking or for cross-server linking, when only a URL is available when the request is provided. \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/external-views.md b/docs/develop/contribute/more-info/desktop/architecture/external-views.md new file mode 100644 index 000000000000..272da63f5605 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/external-views.md @@ -0,0 +1,8 @@ +--- +title: "External views" +sidebar_position: 4 +--- + +To provide access to different servers, we create a series of `BrowserView` objects that directly render on top of the Main Window and load the Mattermost Web App directly from the server they correspond to. We wrap these `BrowserView` objects into a `MattermostView` that manages the loading of the view and handles events such as navigation and notifications. + +These views are also contained within and managed by the `viewManager` class. The class is responsible for adding and removing the views from the Main Window when the user needs them and handling IPC calls from the renderer processes and passing them to the child objects. \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/index.md b/docs/develop/contribute/more-info/desktop/architecture/index.md new file mode 100644 index 000000000000..fad9a45aaba7 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/index.md @@ -0,0 +1,35 @@ +--- +title: "Architecture" +sidebar_position: 1 +--- + +#### Electron +The Desktop App, like all Electron apps, is broken into two pieces: the **main** process and the **renderer** process. + +- The **main** process is a NodeJS process that has access to operating system functions, and governs the creation and management of several renderer processes. +- The **renderer** processes are Chromium instances that perform different functions. In our app, each Mattermost server is its own renderer process. + +![Process diagram](process-diagram.png) + +In order to facilitate communication between the two processes, there's a communication layer in which information can be sent between. We expose *ONLY* the communication API to the renderer process so that we don't allow any malicious server to wreak havoc on a user's computer. + +You can read more about the Process Model [here](https://www.electronjs.org/docs/latest/tutorial/process-model). + +#### Directory structure +The directory structure is broken down into a few pieces to best organize the code: + +``` +Mattermost Desktop +├── docs/ - Documentation for working on the Desktop App +├── e2e/ - E2E tests +│ ├── modules/ - Setup code for the E2E tests +│ └── specs/ - E2E tests themselves +├── resources/ - Assets such as images or sound files that the Desktop App uses +├── scripts/ - Automated scripts used for building or packaging the Desktop App +└── src/ - Application source code + ├── assets/ - Assets such as images or sound files that the Desktop App uses + ├── common/ - Common objects and utility functions that aren't specifically tied to Electron + ├── main/ - The majority of the main process code, including setup for the Electron app + ├── renderer/ - The web code for all of the main application wrapper, modals. and server dropdown views that are used by the renderer process + └── types/ - Common types for use between all of the individual modules +``` \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/internal-views.md b/docs/develop/contribute/more-info/desktop/architecture/internal-views.md new file mode 100644 index 000000000000..a96f97bd7ac3 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/internal-views.md @@ -0,0 +1,59 @@ +--- +title: "Internal views" +sidebar_position: 3 +--- + +There are several renderer processes that make up the internal interface of the Desktop App. These are all represented by singleton objects that reside in the Main Module. These classes are in charge of holding the corresponding `BrowserWindow` or `BrowserView` object, initializing any handlers specific to that view, and exposing any special functionality that other modules may need to either read or affect the view. + +As all of these views only load trusted scripts in the renderer process, all of these views are given full access to the `desktopAPI` module, allowing them to perform basically any action that we allow for in the Desktop App via the IPC layer. + +### Windows + +These are the internally-managed windows acting as the main user interface points for the user. Each of these views are represented by a `BrowserWindow` object. + +#### Main window + +![Main Window screenshot](main-window.png) + +This is the primary view that encapsulates the core of the Desktop App interface. Most `BrowserView` objects are rendered using this window as their parent, and are affected by the behavior of this window. Most other controls, including the tray icon and taskbar/dock icon, interact with this window, and most of their functionality is tied to it as well. + +This window is managed by the `MainWindow` module located at [main/windows/mainWindow](https://github.com/mattermost/desktop/blob/master/src/main/windows/mainWindow.ts). + +##### Hooks +- `init()`: Creates the `BrowserWindow` object for the Main Window and adds all appropriate listeners. +- `get()`: Returns the `BrowserWindow` object for the Main Window. This is directly exposed as there are many different functions affecting the behavior of the window, and thus the encapsulating module often needs to pass that control to other modules. If `true` is passed as an argument, `init()` will be called if the window does not exist, otherwise `undefined` is returned. +- `getBounds()`: Returns the current size and location of the `BrowserWindow`, used for resize functionality, and to ensure that child windows/views are positioned correctly. +- `focusThreeDotMenu()`: Sends a message to the Main process that focuses the view and highlights and focuses the 3-dot menu on Windows/Linux. This is used when the `ALT` key is pressed as a shortcut to focus the menu. + +#### Settings window + +![Settings Window screenshot](settings-window.png) + +This window is created when the user opens **Preferences** from the **File** menu. It contains an interface where the user can change settings specific to the Desktop App client that do not affect their Mattermost servers. This window is a child window of the Main Window and will close/hide when the Main Window is closed/hidden. + +This window is managed by the `SettingsWindow` module located at [main/windows/settingsWindow](https://github.com/mattermost/desktop/blob/master/src/main/windows/settingsWindow.ts). + +##### Hooks +- `show()`: Shows the Settings Window if it exists and will create it if does not. When the window is closed, the `BrowserWindow` object is dereferenced. +- `get()`: Retrieves the Settings Window `BrowserWindow` object if it exists and returns `undefined` if it does not. + +### Views + +These are the internally managed views that are rendered on top of existing windows, adding additional functionality. Each of these views are represented by a `BrowserView` object. + +Most of these views exist as they act as augments to the existing interface and must be rendered over top of the external sandbox Mattermost `BrowserViews`. + +#### Loading screen + +![Loading Screen screenshot](loading-screen.png) + +This is a `BrowserView` that renders over top of external Mattermost views that are loading. It is a cosmetic view that avoids the user having a white screen while the application is loading. The view is ephemeral should only be visible while the current external Mattermost view is loading. + +This view is managed by the `LoadingScreen` module located at [main/views/loadingScreen](https://github.com/mattermost/desktop/blob/master/src/main/views/loadingScreen.ts). Its parent is the Main Window. + +##### Hooks +- `show()`: Displays the Loading Screen over top of any other `BrowserView` currently rendered in the Main Window and begins the animation. +- `fade()`: Starts the process of removing the Loading Screen. First a signal is sent to the renderer to fade the screen and stop the animation. When that finishes, the view is removed from the window. +- `setBounds()`: Calls when the Main Window resizes while the Loading Screen is still visible and the view needs to change its size as well. +- `setDarkMode()`: Calls when the application's dark mode flag is changed, to ensure a consistent color scheme. +- `isHidden()`: Helper method to check whether the view is hidden or not. \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/internal-views/calls-widget.png b/docs/develop/contribute/more-info/desktop/architecture/internal-views/calls-widget.png new file mode 100644 index 000000000000..33a5073c9e95 Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/internal-views/calls-widget.png differ diff --git a/docs/develop/contribute/more-info/desktop/architecture/internal-views/loading-screen.png b/docs/develop/contribute/more-info/desktop/architecture/internal-views/loading-screen.png new file mode 100644 index 000000000000..c790c56a63e3 Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/internal-views/loading-screen.png differ diff --git a/docs/develop/contribute/more-info/desktop/architecture/internal-views/main-window.png b/docs/develop/contribute/more-info/desktop/architecture/internal-views/main-window.png new file mode 100644 index 000000000000..4fff45d34916 Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/internal-views/main-window.png differ diff --git a/docs/develop/contribute/more-info/desktop/architecture/internal-views/settings-window.png b/docs/develop/contribute/more-info/desktop/architecture/internal-views/settings-window.png new file mode 100644 index 000000000000..521548db03fa Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/internal-views/settings-window.png differ diff --git a/docs/develop/contribute/more-info/desktop/architecture/logging.md b/docs/develop/contribute/more-info/desktop/architecture/logging.md new file mode 100644 index 000000000000..7e13cc9bff1b --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/logging.md @@ -0,0 +1,34 @@ +--- +title: "Logging" +sidebar_position: 5 +--- + +Our application uses the `electron-log` module to do most of our logging. It facilitates both file and console logging. +For file logging, you can find the location of the log files by going to **Help** > **View Logs** from within the application. + +Our app supports the following log levels: `error`, `warn`, `info`, `verbose`, `debug`, and `silly`. + +In addition to the library, we provide a **Logger** object that simplifies and streamlines setting up logging for an individual module. +To create a **Logger** object, simply create a new one: + +```js +import {Logger} from 'common/log'; + +const log = new Logger('MyModuleName'); +``` + +You can then use the resulting *log* object to call any of the provided `electron-log` functions, and each log entry with be automatically prefixed with your module name. + +```js +// Will print out "[MyModuleName] a long entry" +log.debug('a log entry'); +``` + +If you need to add additional prefixing, for example to log events on a specific object instance, we provide the `withPrefix()` method which allows you to add additional prefixes. + +```js +// Will print out "[MyModuleName] [some-id] a long entry" +const myObjectId = 'some-id'; +log.withPrefix(myObjectId).debug('a log entry'); +``` + \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/navigation.md b/docs/develop/contribute/more-info/desktop/architecture/navigation.md new file mode 100644 index 000000000000..86376197d379 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/architecture/navigation.md @@ -0,0 +1,71 @@ +--- +title: "Navigation" +sidebar_position: 2 +--- + +The Desktop App exercises relatively strict control over the user's ability to navigate through the web. This is done for a few reasons: +- **Security:** Since we expose certain Electron (and therefore NodeJS) APIs to the front-end application, we want to be in control of what scripts are run in the front-end. We make a concerted effort to lock down the exposed APIs to only what is necessary; however, to avoid any privacy or security breaches, it's best to avoid allowing the user to navigate to any page that isn't explicitly trusted. +- **User Experience:** Our application is ONLY designed to work with the Mattermost Web App and thus allowing the user to navigate to other places that are not the Web App is not a supported use case, and could create some undesirable effects. + +![Navigation diagram](navigation-diagram.png) + +### Internal navigation + +The Mattermost Web App is self-contained, with the majority of links provided by `react-router` and thus most navigation is handled by that module. However, in the Desktop App, we have a major feature that allows users to navigate between distinct tabs bound to the same server. There are two ways that this style of navigation happens in the Web App: +- A user clicks on a link provided by the `react-router` `Link` component +- The application calls `browserHistory.push` directly within the Web App based on the user action +Both of these methods will make use of the `browserHistory` module within the Web App. + +When one of the above methods is used, normally the Web App would update the browser's URL and change the state of the page. In the Desktop App, we instead send the arguments of the call to `browserHistory.push` up to the Electron Main Process. The information is received at the method `WindowManager.handleBrowserHistoryPush`, where we perform the following actions: +- **Clean the path name by removing any part of the server's subpath pathname.** + - When the arguments are sent up to the Desktop App, it includes the subpath of the server hosting it. + - As an example, if the server URL is `http://server-1.com/mattermost`, any path that is received will start with `/mattermost` and we will need to remove that component. The same would be true for any other path following the origin `http://server-1.com`. +- **Retrieve the view matching the path name** + - After removing the leading subpath (if applicable), we check to see if a portion of the path matches one of the other tabs, signally that we will need to switch to that tab. + - For server `http://server-1.com/mattermost`, if the pathname is `/mattermost/boards/board1`, we would get the *Boards* view matching the server. +- **Display the correct view and send the cleaned path to its renderer process** + - We then explicitly display the new view if it's not currently in focus. If it's closed, we open it and load the corresponding URL with the provided path. + - *Exception*: If we're redirecting to the root of the application and the user is not logged in, it will generate an unnecessary refresh. In this case, we do not send the path name down. + +### External navigation + +For the cases where a user wants to navigate away from the Web App to an external site, we generally want to direct the user outside of the Desktop App and have them open their default web browser and use the external site in that application. + +In order to achieve this, we need to explicitly handle every other link and method of navigation that is available to an Electron renderer process. Fortunately, Electron provides a few listeners that help us with that: +- [**will-navigate**](https://www.electronjs.org/docs/latest/api/web-contents#event-will-navigate) is an event that fires when the URL is changed for a given renderer process. Attaching a listener for this event allows us to prevent the navigation if desired. + - NOTE: The event will not fire for in-page navigations or updating `window.location.hash`. +- [**did-start-navigation**](https://www.electronjs.org/docs/latest/api/web-contents#event-did-start-navigation) is another renderer process event that will fire once the page has started navigating. We can use this event to perform any actions when a certain URL is visited. +- [**new-window**](https://www.electronjs.org/docs/latest/breaking-changes#removed-webcontents-new-window-event) is an event that will fire when the user tries to open a new window or tab. This commonly will fire when the user clicks on a link marked `target=_blank`. We attach this listener using the `setWindowOpenHandler` and will allow us to `allow` or `deny` the opening as we desire. + +In our application, we define all of these listeners in the `webContentEvents` module, and we attach them whenever a new [webContents](https://www.electronjs.org/docs/latest/api/web-contents) object is create to make sure that all renderer processes are correctly secured and set up correctly. + +#### New window handling +Our new window handler will *deny* the opening of a new Electron window if any of the following cases are true: +- **Malformed URL:** Depending on the case, it will outright ignore it (if the URL could not be parsed), or it will open the user's default browser if it is somehow invalid in another way. +- **Untrusted Protocol:** If the URL does not match an allowed protocol (allowed protocols include `http`, `https`, and any other protocol that was explicitly allowed by the user). + - In this case, it will ask the user whether the protocol should be allowed, and if so will open the URL in the user's default application that corresponds to that protocol. +- **Unknown Site:** If the URL does not match the root of a configured server, it will always try to open the link in the user's default browser. + - If the URL DOES match the root of a configured server, we still will deny the window opening for a few cases: + - If the URL matches the public files route (`/api/v4/public/files/*`) + - If the URL matches the image proxy route (`/api/v4/image/*`) + - If the URL matches the help route (`/help/*`) + - For these cases, we will open the link in the user's browser. +- **Deep Link Case**: If the URL doesn't match any of the above routes, but is still a valid configured server, we will generally treat is as the deep link cause, and will instead attempt to show the correct tab as well as navigate to the corresponding URL within the app. + +There are two cases where we do allow the application to open a new window: +- If the URL matches the `devtools:` protocol, so that we can open the Chrome Developer Tools. +- If the URL is a valid configured server URL that corresponds to the plugins route (`/plugins/*`). In these cases we allow a single popup per tab to be opened for certain plugins to do things like OAuth (e.g. GitHub or JIRA). + +Any other case will be automatically denied for security reasons. + +#### Links within the same window +By default, the Mattermost Web App marks any link external to its application as `target=_blank`, so that the application doesn't try to open it in the same window. Any other links should therefore be internal to the application. + +We *deny* any sort of in-window navigation with the following exceptions: if the link is a `mailto:` link (which always opens the default mail program), OR if we are in the custom login flow. + +#### Custom login flow +In order to facilitate logging into to the app using an external provider (e.g. Okta) in the same way that one would in the browser, we add an exception to the navigation flow that bypasses the `will-navigate` check. + +When a user clicks on a login link that redirects them to a matching URL scheme (listed [here](https://github.com/mattermost/desktop/blob/master/src/common/utils/constants.ts#L48)), we will activate the custom login flow. The URL *MUST* still be internal to the application before we activate this flow, or any URL matching this pattern would allow the app to circumvent the navigation protection. + +While the current window is in the custom login flow, all links that emit the `will-navigate` event will be allowed. Anything that opens a new window will still be restricted based on the rules for new windows. We leave the custom login flow once the app has navigated back to an URL internal to the application \ No newline at end of file diff --git a/docs/develop/contribute/more-info/desktop/architecture/navigation/navigation-diagram.png b/docs/develop/contribute/more-info/desktop/architecture/navigation/navigation-diagram.png new file mode 100644 index 000000000000..f3535995ad6d Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/navigation/navigation-diagram.png differ diff --git a/docs/develop/contribute/more-info/desktop/architecture/process-diagram.png b/docs/develop/contribute/more-info/desktop/architecture/process-diagram.png new file mode 100644 index 000000000000..4423f3a7f8c1 Binary files /dev/null and b/docs/develop/contribute/more-info/desktop/architecture/process-diagram.png differ diff --git a/docs/develop/contribute/more-info/desktop/build-commands.md b/docs/develop/contribute/more-info/desktop/build-commands.md new file mode 100644 index 000000000000..e9012641b55f --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/build-commands.md @@ -0,0 +1,83 @@ +--- +title: "Build and CLI commands" +sidebar_position: 2 +--- + +## Build + +Here's a list of all the commands used by the Desktop App. These can all be found in `package.json`, and should be run using `npm`, using the following syntax: ```npm run ```. + +#### Testing and Verification + +* `check` - Runs ESLint, checks types, validates the build config and runs the unit tests + * `check-build-config` - Builds and validates the build config + * `check-types` - Runs the TypeScript compiler against the code to check the types for errors +* `lint:js` - Runs ESLint against the code and displays results + * `lint:js-quiet` - Same as above, but with the --quiet option + * `fix:js` - Save as above, but attempts to fix some of the issues +* `test` - Builds and runs all of the automated tests for the Desktop App + * `test:e2e` - Builds and runs the E2E tests for the Desktop App + * `test:e2e:no-rebuild` - Runs the E2E tests without rebuilding the entire app + * `test:e2e:run` - Runs the E2E tests without building them + * `test:e2e:send-report` - Uploads E2E results + * `test:unit` - Runs the unit tests for the main module + * `test:unit-coverage` - Runs the unit tests and displays a coverage breakdown + +#### Building and Running + +* `build` - An amalgam of the following build commands, used to build the Desktop App: + * `build:main` - Builds the source code used by the Electron Main process + * `build:renderer` - Builds the source code used by the Electron Renderer process + * `build:preload` - Builds the source code used by the preload scripts run in the preload context of the Electron Renderer process +* `build-prod` - Builds the app in production mode + * `build-prod-mas` - Builds the app in production mode for Mac App Store distribution + * `build-prod-upgrade` - Builds the app in production mode with auto-update functionality +* `build-test`- Builds the app for E2E testing + * `build-test:e2e` - Builds only the E2E tests and not the app + * `build-test:robotjs` - Builds the RobotJS test module for the current Electron version +* `start` - Runs the Desktop App using the current code built in the dist/ folder +* `restart` - Re-runs the build process and then starts the app (amalgam of build and start) +* `watch` - Runs the app, but watches for code changes and re-compiles on the fly when a file is changed + +#### Packaging + +* `package` - Builds and creates distributable packages for all OSes + * `package:windows` - Builds and creates distributable packages for Windows + * `package:windows-zip` - Builds and create distributable ZIP packages for Windows + * `package:windows-installers` - Builds and creates distributable MSI and EXE packages for Windows + * `package:mac` - Builds and creates distributable packages for macOS + * `package:mac-with-universal` - Same as above, but includes a universal binary + * `package:mas` - Builds and creates distributable packages for Mac App Store + * `package:mas-dev` - Same as above, but builds the development version for testing + * `package:linux` - Builds and creates distributable packages for Linux + * `package:linux-tar` - Builds and creates distributable .tar.gz packagesfor Linux + * `package:linux-pkg` - Builds and creates distributable .deb packages for Ubuntu/Debian and .rpm for Red Hat/Fedora + * `package:linux-appImage` - Builds and creates distributable .AppImage packages for Linux + +#### Workspace Utility + +* `clean` - Removes all installed Node modules and built code + * `clean-install` - Same as above, but then runs npm install to reinstall the Node modules + * `clean-dist` - Only removes the built code +* `prune` - Runs ts-prune to display unused code +* `i18n-extract` - Scrape the codebase and adds missing translations to the translation file +* `create-linux-dev-shortcut`: Creates a shortcut for Linux developers to ensure deep linking works + +## CLI options +Some useful CLI options the desktop app uses are shown below. You can also display these options by running: `npm run start help`. + +``` +--version, -v: Prints the application version +--dataDir, -d: Set the path to where user data is stored +--disableDevMode, -p: Disable development mode to allow for testing as if it was Production +``` + +## Environment variables + +Some common environment variables that are used include: + +- `NODE_ENV`: Defines the Node environment + - `PRODUCTION`: Used for Production mode + - `DEVELOPMENT`: Development mode + - `TEST`: Used when running automated tests +- `MM_DEBUG_MODALS`: Used for debugging modals, set to `1` to show Developer Tools when a modal is opened diff --git a/docs/develop/contribute/more-info/desktop/debugging.md b/docs/develop/contribute/more-info/desktop/debugging.md new file mode 100644 index 000000000000..e4b74ac4c9e8 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/debugging.md @@ -0,0 +1,65 @@ +--- +title: "Debug the desktop app" +sidebar_position: 3 +--- + +## Debug the main process + +The simplest way to debug the main process is to simply insert logging statements wherever needed and have the application output logs of whatever is necessary. + +For already built applications (or bugs that only appear in the packaged version of the application), you can view the Logs by going to Help > Show Logs in the 3-dot menu, which will open a file manager window showing the location of the log file. + +If you'd like to make use of better debugging tools, you can use the Chrome Dev Tools or the debugger in VSCode by following the steps here: https://www.electronjs.org/docs/latest/tutorial/debugging-main-process + +## Debug the renderer process + +The renderer processes are controller by Chrome instances, so each of them will have their own Developer Tools instance. + +You can access these instances by going to the **View > Developer Tools** menu (under the 3-dot menu on Windows/Linux, and in the top bar on macOS) and selecting: +- **Developer Tools for Application Wrapper** for anything involving the top bar. +- **Developer Tools for Current Tab** for anything involving the Mattermost view or the preload script. + + +For this one, make sure you're currently on the tab where you want to load the Developer Tools. You can have instances open for tabs you aren't currently viewing, but to open them in the first place requires it to be opened. + + +- **Developer Tools for Call Widget** if you are using Mattermost Calls and the calls widget is currently open. + +There are other `BrowserViews` that are governed seperately from the main application wrapper, including: +- Dropdown Menu + - You can open this one by adding a line in the `main/teamDropdownView.ts` file. In the constructor, at the end, add: + ```js + this.view.webContents.openDevTools({mode: 'detach'}); + ``` +- Modals + - You can open these by setting an environment variable when running the Desktop App called `MM_DEBUG_MODALS`. + ``` + // macOS/Linux + export MM_DEBUG_MODALS=1 + + // Windows PowerShell + $env:MM_DEBUG_MODALS = 1 + ``` +- URL View + - You can open this one by adding a line in the `main/viewManager.ts` file. In the function `showURLView`, at the end, add: + ```js + urlView.webContents.openDevTools({mode: 'detach'}); + ``` + + +This view is ephemeral and based on whether a link is hovered with the mouse, so it might be best to use some logging instead here. + + + +## Debug the Mattermost Server/webapp + +Some issues are only reproducible on the Desktop App, though the code that is causing the issue may not live in the Desktop App. + +Here are some ways of determining whether this is true: +- Does the issue reproduce on the browser? Specifically Chrome? +- Does the issue surround a piece of code on the server/webapp that only applies to the Desktop App? You can check this by seeing if there is a call to `isDesktopApp` in the webapp. + +If you have determined that the issue doesn't apply to the Desktop App code base directly, you can file a ticket in the appropriate repository, such as the [server and web app](https://github.com/mattermost/mattermost) repository. + +If you are having trouble determining where the issue lies, feel free to post in the [Developers: Desktop App](https://community.mattermost.com/core/channels/desktop-app) on Mattermost Community, or you can file a ticket in the [server and web app](https://github.com/mattermost/mattermost) repository and it will be triaged and transferred to the appropriate location. + diff --git a/docs/develop/contribute/more-info/desktop/dependencies.md b/docs/develop/contribute/more-info/desktop/dependencies.md new file mode 100644 index 000000000000..79573806dc9d --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/dependencies.md @@ -0,0 +1,33 @@ +--- +title: "Dependencies" +sidebar_position: 3 +--- + +The Desktop App uses `npm` to manage its dependencies. + +We usually try to keep each major dependency version locked such that we don't accidentally introduce any bugs or breaking changes by upgrading. + +All dependencies are locked using a `package-lock.json` file to ensure that we don't change the package versions used to build unless explicitly upgrading the package. Thus if a PR contains changes to `package-lock.json` without explicitly changing a dependency, we will usually ask the contributor to revert those changes. + +## Electron + +The most important dependency for the Desktop App is Electron, and is usually the library that can have the most impact on how the Desktop App works. The Electron dependency also contains the Chromium driver. + +Generally we try to use the **latest possible version** of Electron where applicable to ensure we have the latest security fixes and are using the latest possible version of Chromium to maintain compatibility with the Web App. + +#### Upgrading + +For **patch** releases of the Desktop App, we will generally upgrade Electron to the latest **patch version**. + +For **major and minor version** releases of the Desktop App, we will upgrade to the latest **major version**. +* This will usually require QA testing to ensure that nothing has broken between versions. + +#### Bug fixes + +Sometimes, it's necessary to upgrade the Electron version in order to resolve a bug in the app caused by the framework. If this is the case, please change the dependency according to the above guidelines, and the PR will be merged and released as per the same guidelines. + +## Other dependencies + +We try to keep the majority of dependencies up-to-date as much as possible, with a few exceptions: +- **React:** We generally keep the same version of `react` in the Desktop App for as long as possible, unless an upgrade or a new feature is required. Since the Desktop App doesn't rely too heavily on `react`, it's better for us to avoid introducing potential breaking changes unless something urgently needs to change. +- **Webpack:** Upgrading `webpack` requires us to change our configuration significantly, so we generally keep it the same unless we need to make a change. diff --git a/docs/develop/contribute/more-info/desktop/developer-setup.md b/docs/develop/contribute/more-info/desktop/developer-setup.md new file mode 100644 index 000000000000..82cc69ac56a1 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup.md @@ -0,0 +1,103 @@ +--- +title: "Developer setup" +sidebar_position: 1 +--- + +Set up your development environment for building, running, and testing the Mattermost Desktop App. + +## Dependencies + +
+ + + + + +
+ +
+ + + +This section's content used to be transcluded from `contribute/more-info/desktop/developer-setup/macos.md` via Hugo's `{/* TODO: unconverted Hugo shortcode {{% content %}} (sources/mattermost-developer-documentation/site/content/contribute/more-info/desktop/developer-setup.md) */}` shortcode. In the new IA each include is its own page — see the sidebar. + + + +
+ +
+ + + +This section's content used to be transcluded from `contribute/more-info/desktop/developer-setup/ubuntu.md` via Hugo's `{/* TODO: unconverted Hugo shortcode {{% content %}} (sources/mattermost-developer-documentation/site/content/contribute/more-info/desktop/developer-setup.md) */}` shortcode. In the new IA each include is its own page — see the sidebar. + + + +
+ +
+ + + +This section's content used to be transcluded from `contribute/more-info/desktop/developer-setup/windows.md` via Hugo's `{/* TODO: unconverted Hugo shortcode {{% content %}} (sources/mattermost-developer-documentation/site/content/contribute/more-info/desktop/developer-setup.md) */}` shortcode. In the new IA each include is its own page — see the sidebar. + + + +
+ +
+ + + +This section's content used to be transcluded from `contribute/more-info/desktop/developer-setup/arch.md` via Hugo's `{/* TODO: unconverted Hugo shortcode {{% content %}} (sources/mattermost-developer-documentation/site/content/contribute/more-info/desktop/developer-setup.md) */}` shortcode. In the new IA each include is its own page — see the sidebar. + + + +
+ +
+ + + +This section's content used to be transcluded from `contribute/more-info/desktop/developer-setup/redhat.md` via Hugo's `{/* TODO: unconverted Hugo shortcode {{% content %}} (sources/mattermost-developer-documentation/site/content/contribute/more-info/desktop/developer-setup.md) */}` shortcode. In the new IA each include is its own page — see the sidebar. + + + +
+ +#### Mattermost Server + +To develop with the Desktop App, we recommend that you set up a Mattermost server specifically for this purpose. This lets you customize it as needed in cases where there are specific integration requirements needed for testing. + +You can find information on setting that up here: + +[Developer Setup](/developers/contribute/developer-setup) + +Alternatively, for some changes you may be able to test using an existing Mattermost instance, or one that has been deployed on platforms like Docker, Linux, Kubernetes, Heroku, or others. Please refer to the [Mattermost Deployment Guide](https://docs.mattermost.com/guides/deployment.html) for more info. + +## Repo setup + +1. Fork GitHub Repository: https://github.com/mattermost/desktop +2. Clone from your repo: + + ```sh + git clone https://github.com//desktop.git + ``` + +3. Open the desktop directory + + ```sh + cd desktop + ``` + +4. Install Node Modules + + ```sh + npm i + ``` + +5. Run the application + + ```sh + npm run watch + ``` diff --git a/docs/develop/contribute/more-info/desktop/developer-setup/arch.md b/docs/develop/contribute/more-info/desktop/developer-setup/arch.md new file mode 100644 index 000000000000..df0dac9d53c2 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup/arch.md @@ -0,0 +1,34 @@ +--- +--- +**NOTE:** We don't officially support Arch Linux for use with the Mattermost Desktop App. The provided guide is unofficial. + +1. Open a terminal +2. Install nvm via + 1. [nvm-sh](https://github.com/nvm-sh/nvm#installing-and-updating): + ```sh + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash + ``` + OR + 2. [AUR](https://aur.archlinux.org/) (possibly using [a helper](https://wiki.archlinux.org/title/AUR_helpers)): + ```sh + yay -S nvm + ``` +4. Install NodeJS via + ```sh + nvm install --lts + ``` +6. Install other dependencies: + + Linux requires the X11 development libraries and `libpng` to build native Node modules. + Arch requires `libffi` since it's not installed by default. + + ```sh + sudo pacman -S npm git python3 gcc make libx11 libxtst libpng libffi + ``` + +#### Notes +* To build RPMs, you need `rpmbuild` + + ```sh + sudo pacman -S rpm + ``` diff --git a/docs/develop/contribute/more-info/desktop/developer-setup/macos.md b/docs/develop/contribute/more-info/desktop/developer-setup/macos.md new file mode 100644 index 000000000000..52ec1165db01 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup/macos.md @@ -0,0 +1,17 @@ +--- +--- +1. Install Homebrew: http://brew.sh +2. Open Terminal +3. Install dependencies + + ```sh + brew install git python3 + ``` + +4. Install [NVM](https://github.com/nvm-sh/nvm) by following [these instructions](https://github.com/nvm-sh/nvm#installing-and-updating). + + After installing, follow the post-install steps shown by the installer to add the necessary lines to your shell profile (for example `~/.zshrc` or `~/.bash_profile`). Then open a new terminal and run: + + ```sh + nvm install --lts + ``` diff --git a/docs/develop/contribute/more-info/desktop/developer-setup/redhat.md b/docs/develop/contribute/more-info/desktop/developer-setup/redhat.md new file mode 100644 index 000000000000..8033a3b5d54f --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup/redhat.md @@ -0,0 +1,26 @@ +--- +--- +**NOTE:** We don't officially support Fedora/Red Hat/CentOS Linux for use with the Mattermost Desktop App. The provided guide is unofficial. + +1. Open Terminal +2. Install NodeJS via [nvm](https://github.com/nvm-sh/nvm#installing-and-updating): + + ```sh + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash + nvm install --lts + ``` + +3. Install other dependencies: + + Linux requires the X11 developement libraries and `libpng` to build native Node modules. + + ```sh + sudo yum install git python3 g++ libX11-devel libXtst-devel libpng-devel + ``` + +#### Notes +* To build RPMs, you need `rpmbuild`: + + ```sh + sudo dnf install rpm-build + ``` diff --git a/docs/develop/contribute/more-info/desktop/developer-setup/ubuntu.md b/docs/develop/contribute/more-info/desktop/developer-setup/ubuntu.md new file mode 100644 index 000000000000..6f59514a9739 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup/ubuntu.md @@ -0,0 +1,44 @@ +--- +--- +1. Open Terminal +2. Install NodeJS from one of the following sources: + + 1. [nvm](https://github.com/nvm-sh/nvm#installing-and-updating): + + ```sh + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash + nvm install --lts + ``` + + 2. [NodeSource](https://github.com/nodesource/distributions#installation-instructions): + + ```sh + sudo apt-get update + sudo apt-get install -y ca-certificates curl gnupg + sudo mkdir -p /etc/apt/keyrings + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_16.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list + sudo apt-get update + sudo apt-get install -y nodejs + ``` + + * You might need to install `curl` as well: + + ```sh + sudo apt install curl + ``` + +3. Install other dependencies: + + Linux requires the X11 developement libraries and `libpng` to build native Node modules. + + ```sh + sudo apt install git python3 make g++ libx11-dev libxtst-dev libpng-dev + ``` + +#### Notes +* To build RPMs, you need `rpmbuild`: + + ```sh + sudo apt install rpm + ``` diff --git a/docs/develop/contribute/more-info/desktop/developer-setup/windows.md b/docs/develop/contribute/more-info/desktop/developer-setup/windows.md new file mode 100644 index 000000000000..fd8254c0a8cb --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/developer-setup/windows.md @@ -0,0 +1,15 @@ +--- +--- +1. Install Chocolatey: https://chocolatey.org/install +2. Install Visual Studio Community: https://visualstudio.microsoft.com/vs/community/ + - Include **Desktop development with C++** when installing +3. If you are on Windows 11, you may need to install `wmic` via the system settings > Optional Features. +4. Open PowerShell +5. Install dependencies + + ```sh + choco install nvm git python3 + ``` + +6. Restart PowerShell (to refresh the environment variables) +7. Run `nvm install lts` and `nvm use lts` to install and use the latest NodeJS LTS version. diff --git a/docs/develop/contribute/more-info/desktop/index.md b/docs/develop/contribute/more-info/desktop/index.md new file mode 100644 index 000000000000..1209c256c699 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/index.md @@ -0,0 +1,23 @@ +--- +title: "Desktop app" +sidebar_position: 7 +--- + +The Mattermost Desktop App is an [Electron](https://electronjs.org/) wrapper around the [web app](/developers/contribute/more-info/webapp) project. It lives in the [mattermost/desktop](https://github.com/mattermost/desktop) repository. The desktop app runs on Windows, Linux, and macOS. + +## Desktop app contributor resources + - [GitHub Repository](https://github.com/mattermost/desktop) - Get the code, report issues, or submit PRs. + - [Help Wanted](https://mattermost.com/pl/help-wanted-desktop) - This is a good place to start if you're looking for a way to contribute code. Many issues are labeled by difficulty level to make it easier to find ways to get involved. + - [Developer Setup](/developers/contribute/more-info/desktop/developer-setup) - Setup your development environment to start work on the desktop app. + - [Build and CLI Commands](/developers/contribute/more-info/desktop/build-commands) - Useful commands to help build, debug, test, and modify the desktop app on your local machine. + - [Debugging](/developers/contribute/more-info/desktop/debugging) - Identify issues in the desktop app and debug the rendering process. + - [Dependencies](/developers/contribute/more-info/desktop/dependencies) - Information about including dependencies in the desktop app. + - [Style and Code Quality](/developers/contribute/more-info/desktop/style-and-code-quality) - Information about linting, type checking, and submitting great PRs + - [Unit and End-to-End (E2E) Tests](/developers/contribute/more-info/desktop/testing) - Find out how we incorporate unit and end-to-end testing into the desktop app development process. + - [Packaging for Release](/developers/contribute/more-info/desktop/packaging-and-releasing) - Build and package the app into a distributable version. + - [General Contributor Guidelines](/developers/contribute/more-info/getting-started) - Everything you need to know about contributing code to Mattermost. + + +## Where to get help + +If you have any questions related to development of the Desktop App, you can ask us in the [Developers: Desktop App](https://community.mattermost.com/core/channels/desktop-app) channel on our [community Mattermost](https://docs.mattermost.com/guides/community-chat.html). If you need help deploying, administering, or using Mattermost, refer to our [Get Help guide](https://docs.mattermost.com/guides/get-help.html) to find all of the resources that are availalbe to support your journey. diff --git a/docs/develop/contribute/more-info/desktop/packaging-and-releasing.md b/docs/develop/contribute/more-info/desktop/packaging-and-releasing.md new file mode 100644 index 000000000000..8dd569c69b90 --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/packaging-and-releasing.md @@ -0,0 +1,79 @@ +--- +title: "Package and release" +sidebar_position: 4 +--- + +## Build + +You can build the Desktop App by running the following command: + +```text +npm run build +``` + +You can build the Desktop App for development and watch for changes in the main process with this command: + +```text +npm run watch +``` + +Our application uses `webpack` to bundle the scripts together for the main and renderer process. +There are bundles generated for each page used the renderer process, and one bundle for the main process. +A bundle is also generated for the E2E tests when needed. + +You can predefine certain variables in the app before building, by editing the build config under `src/common/config/buildConfig.ts`. For example, you can predefine servers, or disable server management. + +## Package + +Our app uses `electron-builder` to package the app into a distributable format for release. +You can find the configuration for the builder in the `electron-builder.json` file in the root directory. + +You can run the packager using this command: + +```text +npm run package: +``` + +where **\<os\>** is one of the following values: `windows, mac, mac-with-universal, mas, linux` + +All of the above values will generate builds for `x64` and `arm64` architectures: +- `windows`: `exe`, `zip` and `msi` formats +- `mac`: `dmg` and `zip` formats +- `mac-with-universal`: universal binary for all architectures - `dmg` +- `mas`: universal Mac App Store-compliant build +- `linux`: `deb`, `rpm` and `tar.gz` formats + +You can build for more specific targets using the commands [here](/developers/contribute/more-info/desktop/build-commands#packaging) + +#### After pack script + +We include an `afterPack` script to run functions after the application is built into a binary. This is a good place to inject code and make any modifications to the binary after build. + +#### Code sign + +In order to generate signed builds of the application for Windows and macOS, you'll need a certificate file for each of the operating systems. + +These files are under control of Mattermost and aren't generally distributed, but you can obtain your own certificate and sign the app yourself if necessary. + +For macOS, you'll need a valid `Mac Developer` or `Developer ID Application` certificate from the Apple Developer Program. + +For Windows, you'll need a valid code signing certificate. + +More information on Code Signing can be found here: https://www.electron.build/code-signing + +## Release + +Releasing a new version of the Desktop App can be done by running the shell script `release.sh` under the `scripts/` folder. +It will increment the version number in `package.json` for you, create a tag and generate a commit for you. It will also give you the `git` command to run to push all these changes to your repository. + +It has the following options: +``` +// generates a patch version release candidate, will increment x of v0.0.x (so v5.0.1 becomes v5.0.2-rc1) +$ ./scripts/release.sh patch + +// generates a release candidate version, on top of a current release candidate (so v5.0.2-rc1 becomes v5.0.2-rc2) +$ ./scripts/release.sh rc + +// generates a final version, on top of a current release candidate (so v5.0.2-rc2 becomes v5.0.2) +$ ./scripts/release.sh final +``` diff --git a/docs/develop/contribute/more-info/desktop/style-and-code-quality.md b/docs/develop/contribute/more-info/desktop/style-and-code-quality.md new file mode 100644 index 000000000000..0a257b98610e --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/style-and-code-quality.md @@ -0,0 +1,33 @@ +--- +title: "Style and code quality" +sidebar_position: 3 +--- + +We run automated style and type-checking against every new PR that is created and the new code must pass before it can be merged. +In some rare cases you can override these, but this is strongly discouraged. + +#### Linter + +We make use of `eslint` to enforce good coding style in the Desktop App. + +You can run the linter using the following command: + +```text +npm run lint:js +``` + +Outside of the linter, we generally allow for a loose coding style, although the reviewer of the PR has the final say. + +#### Type checker + +We make use of TypeScript in our application to help reduce errors when coding. + +You can run the type checker by running the following command: + +```text +npm run check-types +``` + +#### Submitting great PRs + +Jesse Hallam has written an excellent blog post entitled "Submitting Great PRs" that can be found [here](https://mattermost.com/blog/submitting-great-prs/) diff --git a/docs/develop/contribute/more-info/desktop/testing.md b/docs/develop/contribute/more-info/desktop/testing.md new file mode 100644 index 000000000000..31a2345c595c --- /dev/null +++ b/docs/develop/contribute/more-info/desktop/testing.md @@ -0,0 +1,33 @@ +--- +title: "Unit and End-to-End (E2E) Tests" +sidebar_position: 4 +--- + +For most changes that happen to the desktop app, consider writing an automated test to ensure that the change or fix is maintained in the codebase. Depending on the nature of the change, you will write either a unit test or an E2E test. + +### Unit tests +The [Jest](https://jestjs.io/en/) test runner is used to run unit tests in the desktop app. You can run the following command to run the tests: `npm run test:unit`. You can also run subsets of the tests by filtering using `testNamePattern` or `testPathPattern` on the `spec` files. + +Unit tests are usually written for parts of the `common` and `main` modules, and usually cover individual functions or classes. +We should endeavor to write our code such that it allows for simple testing, and any new features or bug fixes should likely have an associated unit test if possible. Check out [\[MM-40146\]\[MM-40147\] Unit tests for authManager and certificateManager #1874](https://github.com/mattermost/desktop/pull/1874), which is an example of a unit test pull request (PR). + +In order to ensure that most of the app is covered, we try to maintain 70% coverage of the `common` and `main` modules. +You can view a coverage map by running this command: `npm run test:coverage`. + +### E2E tests +We use a combination of two technologies to facilitate E2E testing in the desktop app: +- **[Playwright](https://playwright.dev/):** A testing framework similar to Cypress or Selenium that acts as a Chromium driver for testing. It's used to simulate interactions with the various web environments that make up the Desktop App, including the top bar (servers and tabs) and the individual Mattermost views. +- **[RobotJS](https://robotjs.io/):** A multi-platform OS level automation framework written in NodeJS, used for simulating arbitrary keyboard and mouse inputs. It's generally used to mock actions involving keyboard shortcuts and the Electron menu, as those are not web environments. + +To build the app and run the E2E tests, you can run the following command: `npm run test:e2e`. You can also run this command to build the tests without rebuilding the app: `npm run test:e2e:nobuild`. You can also run subsets of the tests by filtering using `grep`, for example: `npm run test:e2e:run -- --grep back_button`. + +E2E tests are usually written to cover parts of the `renderer` module and should generally cover complete workflows, such as creating and editing a server. You will generally need a combination of both Playwright and RobotJS APIs to test most workflows. + +An example of an E2E test PR is [ \[MM-39680\] E2E Test for Deep Linking #1843](https://github.com/mattermost/desktop/pull/1843). + +#### Notes + +There are many interactions (i.e. things that integrate with the operating system), such as notifications, that cannot be adequately tested using the automation frameworks we have. If this is the case, we will generally create a script to test in [Rainforest](https://handbook.mattermost.com/operations/research-and-development/quality/rainforest-process), our crowd-sourced QA platform to perform these tests manually. + +Check out the page on [web app unit testing](/developers/contribute/more-info/webapp/unit-testing) to see more of Jest in action. For other CLI commands related to testing, go to [Build and CLI commands](/developers/contribute/more-info/desktop/build-commands). + diff --git a/docs/develop/contribute/more-info/focalboard/index.md b/docs/develop/contribute/more-info/focalboard/index.md new file mode 100644 index 000000000000..48258cacb076 --- /dev/null +++ b/docs/develop/contribute/more-info/focalboard/index.md @@ -0,0 +1,32 @@ +--- +title: "Focalboard" +sidebar_position: 9 +--- + +The [Focalboard](https://www.focalboard.com) project is written in [TypeScript](https://www.typescriptlang.org/) and [Go](https://go.dev/). + +Here's the process for contributing to Focalboard: + +1. Fork the [Focalboard repository](https://github.com/mattermost/focalboard), clone it locally, and follow the steps in the [Personal Server Setup Guide](personal-server-setup-guide) to build it. You can read the [CHANGELOG](https://github.com/mattermost/focalboard/blob/main/CHANGELOG.md) to learn about recent updates. + +2. Find [help wanted tickets that are up for grabs in GitHub](https://github.com/mattermost/focalboard/issues?q=is%3Aopen+is%3Aissue+label%3A%22Up+for+grabs%22+label%3A%22Help+Wanted%22). Comment to let everyone know you’re working on it and let a core contributor assign the issue to you. If there’s no ticket for what you want to work on, read about [contributions without a ticket](/developers/contribute/more-info/getting-started/contributions-without-ticket). + +3. When your changes are checked in to your fork, follow the steps on our [contribution checklist](/developers/contribute/more-info/getting-started/contribution-checklist). If this will be your first contribution, there is a standard [CLA](https://www.mattermost.org/mattermost-contributor-agreement/) that you will need to sign as part of this checklist. + +4. Submit your pull request for a [code review](/developers/contribute/more-info/getting-started/code-review#if-you-are-a-community-member-seeking-a-review) and [wait](/developers/contribute/more-info/getting-started/code-review#if-you-are-awaiting-a-review) for a [Focalboard core committer](https://github.com/mattermost/focalboard/blob/main/CONTRIBUTING.md#contributors) to review it. When in doubt, ask for help in the [Focalboard channel](https://community.mattermost.com/core/channels/focalboard) on our community server. If you are still stuck, please message Chen Lim ([@chenilim](https://github.com/chenilim) on GitHub). + +5. After a noteable bug fix or improvement is merged, submit a pull request to the [CHANGELOG](https://github.com/mattermost/focalboard/blob/main/CHANGELOG.md) under the next release section. + +We're glad ❤️ you're here! Good luck and have fun! + +## Repository + +https://github.com/mattermost/focalboard + +## Community + +You can join the [public Focalboard channel](https://community.mattermost.com/core/channels/focalboard) on our Mattermost community server. You can also [file a bug](https://github.com/mattermost/focalboard/issues/new/choose) for an issue or [start a discussion](https://github.com/mattermost/focalboard/discussions) on the repository. + +## Help wanted + +You can find help wanted tickets [here](https://github.com/mattermost/focalboard/issues?q=is%3Aopen+is%3Aissue+label%3A%22Up+for+grabs%22+label%3A%22Help+Wanted%22). diff --git a/docs/develop/contribute/more-info/focalboard/mattermost-boards-setup-guide.md b/docs/develop/contribute/more-info/focalboard/mattermost-boards-setup-guide.md new file mode 100644 index 000000000000..f935424edc39 --- /dev/null +++ b/docs/develop/contribute/more-info/focalboard/mattermost-boards-setup-guide.md @@ -0,0 +1,58 @@ +--- +title: "Mattermost Boards plugin guide" +sidebar_position: 2 +--- + + + +From Mattermost v7.11, Mattermost Boards is a core part of the product that cannot be disabled or built separately. Developers should read the updated [Developer Guide](/developers/contribute/developer-setup) for details. + + + +In Mattermost v7.10 and earlier releases, **[Mattermost Boards](https://mattermost.com/boards/)** is the Mattermost plugin version of Focalboard that combines project management tools with messaging and collaboration for teams of all sizes. It is installed and enabled by default in Mattermost v6.0 and later. For working with Focalboard as a standalone application, please refer to the [Personal Server Setup Guide](/developers/contribute/more-info/focalboard/personal-server-setup-guide). + +## Build the plugin + + +1. Fork the [Focalboard repository](https://github.com/mattermost/focalboard) and clone it locally. Clone [Mattermost](https://github.com/mattermost/mattermost) in a sibling directory. +2. Define an environment variable ``EXCLUDE_ENTERPRISE`` with a value of ``1``. +3. To install the dependencies: +``` +cd mattermost-plugin/webapp +npm install --no-optional +cd ../.. +make prebuild +``` +4. To build the plugin: +``` +make webapp +cd mattermost-plugin +make dist +``` + +Refer to the [dev-release.yml](https://github.com/mattermost/focalboard/blob/main/.github/workflows/dev-release.yml#L168) workflow for the up-to-date commands that are run as part of CI. + +## Upload and install the plugin + +1. Enable [custom plugins](/developers/integrate/plugins/using-and-managing-plugins#custom-plugins) by setting `PluginSettings.EnableUploads` to `true` and set `FileSettings.MaxFileSize` to a number larger than the size of the packed`.tar.gz` plugin file in bytes (e.g., `524288000`) in the Mattermost `config.json` file. +2. Navigate to **System Console > Plugins > Management** and upload the packed `.tar.gz` file from your `mattermost-plugin/dist` directory. +3. Enable the plugin. + +## Deploy the plugin to a local Mattermost server + +Instead of following the steps above, you can also set up a `mattermost-server` in local mode and automatically deploy `mattermost-plugin` via `make deploy`. + +* Follow the steps in the [`mattermost-webapp` developer setup guide](/developers/contribute/developer-setup) and then: + * Open a new terminal window. In this terminal window, add an environmental variable to your bash via `MM_SERVICESETTINGS_SITEURL='http://localhost:8065'` ([docs](https://developers.mattermost.com/blog/subpath/#using-subpaths-in-development)) + * Build the web app via `make build` +* Follow the steps in the [`mattermost-server` developer setup guide](/developers/contribute/developer-setup) and then: + * Make sure Docker is running. + * Run `make config-reset` to generate the `config/config.json` file: + * Edit `config/config.json`: + * Set `ServiceSettings > SiteURL` to `http://localhost:8065` ([docs](https://docs.mattermost.com/configure/configuration-settings.html#site-url)) + * Set `ServiceSettings > EnableLocalMode` to `true` ([docs](https://docs.mattermost.com/configure/configuration-settings.html#enable-local-mode)) + * Set `PluginSettings > EnableUploads` to `true` ([docs](/developers/integrate/plugins/using-and-managing-plugins#custom-plugins)) + * In this terminal window, add an environmental variable to your bash via `MM_SERVICESETTINGS_SITEURL='http://localhost:8065'` ([docs](https://developers.mattermost.com/blog/subpath/#using-subpaths-in-development)) + * Build and run the server via `make run-server` +* Follow the [steps above](#build-the-plugin) to install the dependencies. +* Run `make deploy` in the `mattermost-plugin` folder to automatically deploy your plugin to your local Mattermost server. diff --git a/docs/develop/contribute/more-info/focalboard/personal-server-setup-guide.md b/docs/develop/contribute/more-info/focalboard/personal-server-setup-guide.md new file mode 100644 index 000000000000..ee514954c228 --- /dev/null +++ b/docs/develop/contribute/more-info/focalboard/personal-server-setup-guide.md @@ -0,0 +1,137 @@ +--- +title: "Personal server setup guide" +sidebar_position: 1 +--- + +This guide will help you configure your developer environment for the Focalboard **Personal Server**. For most features, this is the easiest way to get started working against code that ships across editions. For working with **Mattermost Boards** (Focalboard as a plugin), please refer to the [Mattermost Boards Plugin Guide](/developers/contribute/more-info/focalboard/mattermost-boards-setup-guide). + +## Install prerequisites +### All +* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) (if using Windows, see below) +* [Go](https://golang.org/doc/install) +* [Node.js](https://nodejs.org/en/download/) (v10+) +* [npm](https://www.npmjs.com/get-npm) + +### Windows +* Install [MinGW-w64](https://community.chocolatey.org/packages/mingw) via [Chocolatey](https://chocolatey.org/) +* Install [Git for Windows](https://gitforwindows.org/) and use the `git-bash` terminal shell + +### Mac +* Install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12) (v12+) +* Install the Xcode Command Line Tools via `xcode-select --install` + +### Linux +* `sudo apt-get install libgtk-3-dev` +* `sudo apt-get install libwebkit2gtk-4.0-dev` +* `sudo apt-get install autoconf dh-autoreconf` + +## Fork the project repositories + +Fork the [Focalboard GitHub repository](https://github.com/mattermost/focalboard) and [Mattermost GitHub repository](https://github.com/mattermost/mattermost). Clone both repositories locally in sibling directories. + +## Build via the terminal + +To build the server: + +``` +make prebuild +make +``` + +To run the server: + +``` + ./bin/focalboard-server +``` + +Then navigate your browser to [`http://localhost:8000`](http://localhost:8000) to access your Focalboard server. The port is configured in `config.json`. + +Once the server is running, you can rebuild just the web app via `make webapp` in a separate terminal window. Reload your browser to see the changes. + +## Build and run standalone desktop apps + +You can build standalone apps that package the server to run locally against [SQLite](https://www.sqlite.org/index.html): + +* **Windows**: + * *Requires Windows 10, [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/sdk-archive/) 10.0.19041.0, and .NET 4.8 developer pack* + * Open a `git-bash` prompt. + * Run `make prebuild` + * The above prebuild step needs to be run only when you make changes to or want to install your npm dependencies, etc. + * Once the prebuild is completed, you can keep repeating the below steps to build the app & see the changes. + * Run `make win-wpf-app` + * Run `cd win-wpf/msix && focalboard.exe` +* **Mac**: + * *Requires macOS 11.3+ and Xcode 13.2.1+* + * Run `make prebuild` + * The above prebuild step needs to be run only when you make changes to or want to install your npm dependencies, etc. + * Once the prebuild is completed, you can keep repeating the below steps to build the app & see the changes. + * Run `make mac-app` + * Run `open mac/dist/Focalboard.app` +* **Linux**: + * *Tested on Ubuntu 18.04* + * Install `webgtk` dependencies + * Run `sudo apt-get install libgtk-3-dev` + * Run `sudo apt-get install libwebkit2gtk-4.0-dev` + * Run `make prebuild` + * The above prebuild step needs to be run only when you make changes to or want to install your npm dependencies, etc. + * Once the prebuild is completed, you can keep repeating the below steps to build the app & see the changes. + * Run `make linux-app` + * Uncompress `linux/dist/focalboard-linux.tar.gz` to a directory of your choice + * Run `focalboard-app` from the directory you have chosen +* **Docker**: + * To run it locally from offical image: + * `docker run -it -p 80:8000 mattermost/focalboard` + * To build it for your current architecture: + * `docker build -f docker/Dockerfile .` + * To build it for a custom architecture (experimental): + * `docker build -f docker/Dockerfile --platform linux/arm64 .` + +Cross-compilation currently isn't fully supported, so please build on the appropriate platform. Refer to the GitHub Actions workflows (`build-mac.yml`, `build-win.yml`, `build-ubuntu.yml`) for the detailed list of steps on each platform. + +## Set up VS Code + +* Open a [VS Code](https://code.visualstudio.com/) terminal window in the project folder. +* Run `make prebuild` to install packages. *Do this whenever dependencies change in `webapp/package.json`.* +* Run `cd webapp && npm run watchdev` to automatically rebuild the web app when files are changed. It also includes source maps from JavaScript to TypeScript. +* Install the [Go](https://marketplace.visualstudio.com/items?itemName=golang.Go) and [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) VS Code extensions (if you haven't already). +* Launch the server: + * **Windows**: Ctrl+P, type `debug`, press the Space key, and select `Go: Launch Server`. + * **Mac**: Cmd+P, type `debug`, press the Space key, and select `Go: Launch Server`. + * *If you do not see `Go: Launch Server` as an option, check your `./.vscode/launch.json` file and make sure you are not using a VS Code workspace.* +* Navigate a browser to `http://localhost:8000` + +You can now edit the web app code and refresh the browser to see your changes efficiently. + +**Debugging the web app**: As a starting point, add a breakpoint to the `render()` function in `BoardPage.tsx` and refresh the browser to walk through page rendering. + +**Debugging the server**: As a starting point, add a breakpoint to `handleGetBlocks()` in `server/api/api.go` and refresh the browser to see how data is retrieved. + +## Rebuild translations + +We use `i18n` to localize the web app. Localized string generally use `intl.formatMessage`. When adding or modifying localized strings, run `npm run i18n-extract` in `webapp` to rebuild `webapp/i18n/en.json`. + +Translated strings are stored in other json files under `webapp/i18n`, (e.g. `es.json` for Spanish). + +## Access the database + +By default, data is stored in a sqlite database `focalboard.db`. You can view and edit this directly using `sqlite3 focalboard.db`. + +## Unit tests + +Run `make ci`, which is similar to the `.gitlab-ci.yml` workflow and includes: + +* **Server unit tests**: `make server-test` +* **Web app ESLint**: `cd webapp; npm run check` +* **Web app unit tests**: `cd webapp; npm run test` +* **Web app UI tests**: `cd webapp; npm run cypress:ci` + +Unit tests for Focalboard are similar to the [web app and server testing](/developers/contribute/more-info/getting-started/test-guideline) requirements. + +## Staying informed + +Are you interested in influencing the future of the Focalboard open source project? Please read the [Focalboard Contribution Guide](/developers/contribute/more-info/focalboard/). We welcome everyone and appreciate any feedback. ❤️ There are several ways you can get involved: + +* **Changes**: See the [CHANGELOG](https://github.com/mattermost/focalboard/blob/main/CHANGELOG.md) for the latest updates +* **GitHub Discussions**: Join the [Developer Discussion](https://github.com/mattermost/focalboard/discussions) board +* **Bug Reports**: [ title=](https://github.com/mattermost/focalboard/issues/new?assignees=&labels=bug&template=bug_report.md&title=) +* **Chat**: Join the [Focalboard community channel](https://community.mattermost.com/core/channels/focalboard) diff --git a/docs/develop/contribute/more-info/getting-started/branching-overview.png b/docs/develop/contribute/more-info/getting-started/branching-overview.png new file mode 100644 index 000000000000..f9a1ca468e94 Binary files /dev/null and b/docs/develop/contribute/more-info/getting-started/branching-overview.png differ diff --git a/docs/develop/contribute/more-info/getting-started/branching.md b/docs/develop/contribute/more-info/getting-started/branching.md new file mode 100644 index 000000000000..e80d2a1d74f6 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/branching.md @@ -0,0 +1,64 @@ +--- +title: "Mattermost cherry-pick process" +sidebar_position: 20 +--- + +The self-managed releases are cut based off of the Mattermost Cloud release tags (e.g Mattermost Server v6.3 release was based off of ``cloud-2021-12-08-1`` Cloud release tag) in the server, webapp, enterprise, and api-reference repos. See [the Handbook release process](https://handbook.mattermost.com/operations/research-and-development/product/release-process/release-overview#cloud-release-branch-processes) for more details. + +The Mobile and Desktop app release branches are based off of ``master`` branch. + +## Developer process + +When your PR is required on a release branch (e.g. for a dot release or to fix a regression for an upcoming release), you will follow the cherry-picking process. + +1. Make a PR to 'master' like normal. +2. Add the appropriate milestone and the `CherryPick/Approved` label. +3. When your PR is approved, it will be assigned back to you to perform the merge and any cherry picking if necessary. +4. Merge the PR. +5. An automated cherry-pick process will try to cherry-pick the PR. If the automatic process succeeds, a new PR pointing to the correct release branch will open with all the appropriate labels. If there are no additional changes from the original PR for the cherry-pick, it can be merged without further review. +6. If the automated cherry-pick fails, the developer will need to cherry-pick the PR manually. Cherry-pick the master commit back to the appropriate releases. If the release branches have not been cut yet, leave the labels as-is and cherry-pick once the branch has been cut. The release manager will remind you to finish your cherry-pick. +7. Set the `CherryPick/Done` label when completed. + + * If the cherry-pick fails, the developer needs to apply the cherry-pick manually. + * Cherry-pick the commit from `master` to the affected releases. See the steps below: +8. Run the checks for lint and tests. +9. Push your changes directly to the remote branch if the check style and tests passed. +10. No new pull request is required unless there are substantial merge conflicts. +11. Remove the `CherryPick/Approved` label and apply the `CherryPick/Done` label. + + + +If the PR needs to go to other release branches, you can run the command `/cherry-pick release-x.yz` in the PR comments and it will try to cherry-pick it to the branch you specified. + + + +### Manual cherry-pick + +If conflicts appear between your pull request (PR) and the cherry-pick target branch, the automated cherry-pick process will fail and will let you know that you need to do a manual cherry-pick. Here are the steps to do so: + +1. Fetch the latest updates from origin: +```sh +git fetch origin +``` +2. Create a new branch starting at the release branch on origin. +```sh +git checkout -b manual-cherry-pick-pr-[PR_NUMBER] origin/release-[VERSION] +``` +3. Find the SHA of the pull request merge commit, and cherry-pick this commit in your new branch: +```sh +git log origin/master +git cherry-pick [SHA] +``` +4. You're likely to face the conflict that prevented the automated cherry-pick now. Fix the conflict, and then run the following: +```sh +git add [path/to/conflicted/files] +git cherry-pick --continue +``` +5. Finally, push your new branch as usual and create a PR. Make sure you select `release-[VERSION]` as the base branch, and not the default (master). +```sh +git push -u origin manual-cherry-pick-pr-[PR_NUMBER] +``` + +## Reviewer process + +If you are the second reviewer reviewing a PR that needs to be cherry-picked, do not merge the PR. If the submitter is a core team member, you should set the `Reviews Complete` label and assign it to the submitter to cherry-pick. If the submitter is a community member who is not available to cherry-pick their PR or can not do it themselves, you should follow the cherry-pick process above. diff --git a/docs/develop/contribute/more-info/getting-started/code-review.md b/docs/develop/contribute/more-info/getting-started/code-review.md new file mode 100644 index 000000000000..9a835fd97232 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/code-review.md @@ -0,0 +1,140 @@ +--- +title: "Code review" +sidebar_position: 5 +--- + +All changes to the product should be reviewed. Every team will have its own workflow, but in general: + +* User experience changes should be reviewed by a product manager or designer. +* Code changes should be reviewed by at least two core committers. +* Documentation changes should be reviewed by a product manager or technical writer. + +Staff should consult the internal [organization chart](https://docs.google.com/spreadsheets/d/1lH8QIjQGEoGospDUdVs_LQ_i2b82I1ce6W7z18vhPTQ/edit#gid=1730823498) as needed when finding the right reviewer. + +If you are a community member seeking a review +---------------------------------------------- + +1. Submit your pull request. + * Follow the [contribution checklist](/developers/contribute/more-info/getting-started/contribution-checklist). +2. Wait for a reviewer to be assigned. + * Product managers are on the lookout for new pull requests and usually handle this for you automatically. + * If you have been working alongside a core committer, feel free to message them for help. + * When in doubt, ask for help in the [Developers](https://community.mattermost.com/core/channels/developers) channel on our community server. + * If you are still stuck, message Jason Blais ([@jasonblais](https://github.com/jasonblais) on GitHub) or Jason Frerich ([@jfrerich](https://github.com/jfrerich) on GitHub). +3. [Wait for a review](#if-you-are-awaiting-a-review). + * Expect some interaction with at least one reviewer within 5 business days. (Business days are typically Monday to Friday, excluding [statutory holidays](https://handbook.mattermost.com/operations/workplace/people/working-at-mattermost/paid-time-off#typical-public-holidays-in-canada-germany-uk-us).) + * Keep in mind that core committers are geographically distributed around the world and likely in a different time zone than your own. + * If no interaction has occurred after 5 business days, at-mention a reviewer with a comment on your PR. +4. Make any necessary changes. + * If a reviewer requests changes, your pull request will disappear from their queue of reviews. + * Once you've addressed the concerns, re-request a review from any reviewer requesting changes. + * [Avoid force pushing](https://mattermost.com/blog/submitting-great-prs/#4-avoid-force-pushing). +5. Wait for your code to be merged. + * Larger pull requests may require more time to review. + * Once all reviewers have approved your changes, they will handle merging your code. + +If you are a core committer seeking a review +-------------------------------------------- + +1. Submit your pull request. + * Follow the [contribution checklist](/developers/contribute/more-info/getting-started/contribution-checklist). +2. Immediately add the `1: UX Review`, `2: Dev Review`, and `3: QA Review` labels. + * Your pull request should not be merged until these labels are later removed in the review process. +3. Apply additional labels as necessary: + * `CherryPick/Approved`: Apply this if the pull request is meant for a quality or patch release. + * `Do Not Merge/Awaiting PR`: Apply this if the pull request depends on another (e.g. server changes) + * `Setup Test Server`: Apply this to create a test server with your changes for review. + * See [labels](/developers/contribute/more-info/getting-started/labels) for additional documentation. +4. Assign a milestone as necessary. + * Most pull requests do not require a milestone, but will simply ship once merged. + * Some reviewers may prioritize reviews for known upcoming milestones. + * The milestone is mandatory for bug fixes that must be cherry-picked. +5. Request a review from a Product Manager and/or a Designer. + * The choice of Product Manager or Designer is up to you. + - In most cases, choose the individual embedded with your team. + - If your change primarily touches another team's codebase, assign the individual from that team. + - If in doubt, assign any Product Manager or Designer and comment about the uncertainty. They may reassign as appropriate. + * [Wait](#if-you-are-awaiting-a-review) for their review to complete before continuing so as to avoid churn if changes are requested. + * Remove the `1: UX Review` label only when these reviews are done and they accept the changes. + - Product Managers and Designers ensure the changes meet [user experience guidelines](https://docs.mattermost.com/developer/fx-guidelines.html). + * If your changes do not affect the user experience, you may remove `1: UX Review` immediately. +6. After UX review, request a review from two core committers. + * The choice of core committers is up to you. + - When picking your first core committer, consider someone with domain expertise relative to your changes. Sometimes GitHub will recommend a recent editor of the code, but often you must rely on your own intuition from past interactions. + - When picking your second core committer, consider someone who may have expertise in the language you're using or the problem you're solving, even if they aren't intricately familiar with the codebase. This can provide a fresh set of eyes on the code to reveal blindspots that are not biased by hitting deadlines, and helps expose the team to new parts of the code to help spread out domain knowledge. This may not make sense for every pull request but is a practice to keep in mind. If you don't have someone specific in mind, consider using the [`@core-reviewers`](https://github.com/orgs/mattermost/teams/core-reviewers) group to assign an available reviewer automatically. + - Don't be afraid to pick someone who gives "hard" reviews. Code review feedback is never a personal attack: it should "sharpen" the skills of both the author and the reviewers, not to mention improving the quality of the product. + - Try to avoid assigning the same person to all of your reviews unless they are related. + - When in doubt, ask for recommendations on our community server. + * [Wait](#if-you-are-awaiting-a-review) for their review to complete before continuing so as to avoid churn if changes are requested. + * Remove the `2: Dev Review` label only when these reviews are done and they accept the changes. +7. After Dev review, assign a QA tester. + * Ensure that your PR includes test steps or expected results for QA reference if the QA Test Steps in the Jira ticket have not already been filled in. + * The choice of QA tester is up to you. + - In most cases, choose the individual embedded with your team. + - If your change primarily touches another team's codebase, assign the individual from that team. + - If in doubt, assign any QA tester and comment about the uncertainty. They may reassign as appropriate. + * [Wait](#if-you-are-awaiting-a-review) for their review to complete before continuing. + - It is the QA tester's responsibility to determine the scope of required testing, if any. + * Remove the `3: QA Review` label only when their review is done and they accept the changes. + * In the rare event your changes do not require QA review, you may remove `3: QA Review` immediately. + - Comment on the pull request clearly explaining the rationale. +8. Merge the pull request. + * Do not merge until the labels `1: UX Review`, `2: Dev Review` and `3: QA Review` labels have been removed. + * Add the `4: Reviews Complete` label if the last reviewer did not already add it. + * Do not merge if there are outstanding changes requested. + * Merge your pull request and delete the branch if not from a fork. + - Note that any core committer is free to merge on your behalf. + - If your pull request depends on other pull requests, consider assigning the `Do Not Merge/Awaiting PR` label to avoid merging prematurely. +9. Handle any cherry-picks. + * There is an automated cherry-pick process. + * As the author of the pull request, you should make sure the cherry-pick succeeds. + * [Check here](/developers/contribute/more-info/getting-started/branching#cherry-pick-process---developer) for details. +10. After a pull request is merged (and cherry-picked where needed), update the Jira ticket. + * Resolve the ticket for QA from "Ready for QA" button with QA test steps (or "No Testing Required" if no QA testing is needed). + +If you are awaiting a review +---------------------------- + +1. Wait patiently for reviews to complete. + * Expect some interaction with each of your reviewers within 2 business days. + * There is no need to explicitly mention them on the pull request or to explicitly reach out on our community server. + * Core committers and QA testers are expected to have the GitHub plugin installed to automate notifications and to trigger a daily review of their outstanding requested reviews. +2. Make any necessary changes. + * If a reviewer requests changes, your pull request will disappear from their queue of reviews. + * Once you've addressed the concerns, assign them as a reviewer again to put your pull request back in their queue. + +If you are a core committer asked to give a review +-------------------------------------------------- + +1. Respond promptly to requested reviews. + * Assume the requested review is urgent and blocking unless explicitly stated otherwise. + * Try to interact with the author within 2 business days. + * Configure the GitHub plugin to automate notifications. + * Review your outstanding requested reviews daily to avoid blocking authors. + * Prioritize earlier milestones when reviewing to help with the release process. + * Responding quickly doesn't necessarily mean reviewing quickly! Just don't leave the author hanging. +2. Feel free to clarify expectations with the author. + * If the PR adds a substantial feature, check that a feature flag is included. Please see [criteria here](/developers/contribute/more-info/server/feature-flags#when-to-use). + * If the code is experimental, they may need only a cursory glance and thumbs up to proceed with productizing their changes. + * If the review is large or complex, additional time may be required to complete your review. Be upfront with the author. + * If you are not comfortable reviewing the code, avoid "rubber stamping" the review. Be honest with the author and ask them to consider another core committer. +3. Never rush a review. + * Take the time necessary to review the code thoroughly. + * Don't be afraid to ask for changes repeatedly until all concerns are addressed. + * Feel free to challenge assumptions and timelines. Rushing a change into a patch release may cause more harm than good. +4. Avoid leaving a review hanging. + * Try to accept or reject the review instead of just leaving comments. + * If you are the last developer to approve the changes, consider requesting a review from the appropriate QA tester to speed up the process. +6. Run the E2E tests against the PR code + * After the PR has been reviewed, the reviewer should trigger an E2E test run on it by using [one of the available mechanisms](https://mattermost.atlassian.net/wiki/spaces/CLOUD/pages/2627371043/E2E+Tests). The E2E Test result will be posted back to the PR as a comment. + * It's the PR author's responsibility to address the E2E test failures, with the assistance of the reviewers. + * Core committers can refer to [this Confluence page](https://mattermost.atlassian.net/wiki/spaces/CLOUD/pages/2627371043/E2E+Tests) for additional informations on E2E testing and related processes. +7. Merge the pull request. + * Do not merge until the labels `1: UX Review`, `2: Dev Review` and `3: QA Review` labels have been removed. + * Add the `4: Reviews Complete` label if the last reviewer did not already add it. + * Do not merge if there are outstanding changes requested. + * Do not merge if there are any `Do Not Merge` labels applied. + - When in doubt, leave the merging of the pull request to the author. + * Merge the pull request, and delete the branch if not from a fork. +8. Handle any cherry-picks. + * There is an automated cherry-pick process and the author of the pull request should make sure the cherry-pick succeeds. Assume this is the case unless you are explicitly asked to help cherry-pick. diff --git a/docs/develop/contribute/more-info/getting-started/contribution-checklist.md b/docs/develop/contribute/more-info/getting-started/contribution-checklist.md new file mode 100644 index 000000000000..905343e7540b --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/contribution-checklist.md @@ -0,0 +1,35 @@ +--- +title: "Contribution checklist" +sidebar_position: 2 +--- + +Thanks for your interest in contributing to Mattermost! Come join our [Contributors community channel](https://community.mattermost.com/core/channels/tickets) on the community server, where you can discuss questions with community members and the Mattermost core team. + +To help with translations, [see the localization process](https://docs.mattermost.com/developer/localization.html). + +Follow this checklist for submitting a pull request (PR): + +1. You've signed the [Contributor License Agreement](https://mattermost.com/mattermost-contributor-agreement/), so you can be added to the Mattermost [Approved Contributor List](https://docs.google.com/spreadsheets/d/1NTCeG-iL_VS9bFqtmHSfwETo5f-8MQ7oMDE5IUYJi_Y/pubhtml?gid=0&single=true). + - If you've included your mailing address in the signed [Contributor License Agreement](https://mattermost.com/mattermost-contributor-agreement/), you may receive a [Limited Edition Mattermost Mug](https://forum.mattermost.com/t/limited-edition-mattermost-mugs/143) as a thank you gift after your first pull request is merged. +2. You have claimed the ticket that you wish to work on by asking for an assignment from the Mattermost team. + - Tickets are assigned on a first-come-first-serve basis. +3. Your ticket is a Help Wanted GitHub issue for the Mattermost project you're contributing to. + - If not, follow the process [here](/developers/contribute/more-info/getting-started/contributions-without-ticket). +4. Your code is thoroughly tested, including appropriate [unit, end-to-end, and integration tests for webapp](/developers/contribute/more-info/getting-started/test-guideline). +5. If applicable, user interface strings are included in localization files: + - [mattermost/server/en.json](https://github.com/mattermost/mattermost/blob/master/server/i18n/en.json) + - [mattermost/webapp/channels/src/i18n/en.json](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/i18n/en.json) + - [mattermost-mobile/assets/base/i18n/en.json](https://github.com/mattermost/mattermost-mobile/blob/master/assets/base/i18n/en.json) + + 5.1. In the webapp/channels repository run `npm run i18n-extract` to generate the new/updated strings. +6. The PR is submitted against the Mattermost `master` branch from your fork. +7. The PR title begins with the Jira or GitHub ticket ID (e.g. `[MM-394]` or `[GH-394]`) and summary template is filled out. +8. If your PR adds or changes a RESTful API endpoint, please update the [API documentation](https://github.com/mattermost/mattermost/tree/master/api). +9. If your PR adds a new plugin API method or hook, please add an example to the [Plugin Starter Template](https://github.com/mattermost/mattermost-plugin-starter-template). +10. If QA review is applicable, your PR includes test steps or expected results. +11. If the PR adds a substantial feature, a feature flag is included. Please see [criteria here](/developers/contribute/more-info/server/feature-flags#when-to-use). +12. Your PR includes basic documentation about the change/addition you're submitting. View our [guidelines](https://handbook.mattermost.com/operations/research-and-development/product/technical-writing-team-handbook#submit-documentation-with-your-pr-community) for more information about submitting documentation and the review process. + +Once submitted, the automated build process must pass in order for the PR to be accepted. Any errors or failures need to be addressed in order for the PR to be accepted. Next, the PR goes through [code review](/developers/contribute/more-info/getting-started/code-review). To learn about the review process for each project, read the `CONTRIBUTING.md` file of that GitHub repository. + +That's all! If you have any feedback about this checklist, let us know in the [Contributors channel](https://community.mattermost.com/core/channels/tickets). diff --git a/docs/develop/contribute/more-info/getting-started/contributions-without-ticket.md b/docs/develop/contribute/more-info/getting-started/contributions-without-ticket.md new file mode 100644 index 000000000000..b435ececab0b --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/contributions-without-ticket.md @@ -0,0 +1,29 @@ +--- +title: "Contributions without ticket" +sidebar_position: 1 +--- + +Contributions for minor corrections and improvements without a corresponding `Help Wanted` ticket are welcome. For example, a pull request for a bug or incremental improvement, with less than 20 lines of code change, is usually accepted if the change to existing behaviour is minor. + +All pull requests submitted without a corresponding ticket will first be reviewed by a core team product manager. Some examples of minor corrections and improvements include: + +- [Fix a formatting error in help text](https://github.com/mattermost/mattermost/pull/5640) +- [Fix success typo in Makefile](https://github.com/mattermost/mattermost/pull/5809) +- [Fix broken Cancel button in Edit Webhooks screen](https://github.com/mattermost/mattermost/pull/5612) +- [Fix Android app crashing when saving user notification settings](https://github.com/mattermost/mattermost-mobile/pull/364) +- [Fix recent mentions search not working](https://github.com/mattermost/mattermost/pull/5878) + + + +For pull requests greater than 20 lines of code, a `Help Wanted` ticket should be opened by the core team. This helps ensure that everything going into the project aligns with a unified vision. Core committers who review the PR are entitled to reject it if there isn't a `Help Wanted` ticket and feel it significantly changes behavior or user expectations. + + + + + +Please use [our translation server](https://translate.mattermost.com) to correct errors in translation. + + + + +The best way to discuss opening a `Help Wanted` ticket with the core team is by [starting a conversation in the feature idea forum](https://mattermost.uservoice.com/forums/306457-general) or [opening an issue in the GitHub repository](https://github.com/mattermost/mattermost/issues/new). Alternatively, don't hesitate to come chat about it in the [Contributors](https://community.mattermost.com/core/channels/tickets) or [Developers](https://community.mattermost.com/core/channels/developers) channels. diff --git a/docs/develop/contribute/more-info/getting-started/core-committers.md b/docs/develop/contribute/more-info/getting-started/core-committers.md new file mode 100644 index 000000000000..140230b8f0df --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/core-committers.md @@ -0,0 +1,6 @@ +--- +title: "Core committers" +sidebar_position: 4 +--- + +A core committer is a maintainer on the Mattermost project that has merge access to Mattermost repositories. They are responsible for reviewing pull requests, cultivating the Mattermost developer community, and guiding the technical vision of Mattermost. diff --git a/docs/develop/contribute/more-info/getting-started/guilds.md b/docs/develop/contribute/more-info/getting-started/guilds.md new file mode 100644 index 000000000000..fbc276b56deb --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/guilds.md @@ -0,0 +1,41 @@ +--- +title: "Engineering guilds" +sidebar_position: 50 +--- + +Our Engineering Guilds are a forum for sharing knowledge, discussing and agreeing on plans, and disseminating information related to a particular subject or technical topic. Many (although not all) Engineering Guilds are affiliated to a particular "platform" that forms a part of Mattermost, and are therefore associated with a particular Platform Team. However, the participants in each Guild span many engineering teams at Mattermost in order to get people together to share knowledge and disseminate decisions across the Engineering organization. + +The main activity of Guilds is a regular meeting. These meetings are public, and anyone within Mattermost and the wider community is welcome to attend. Details are provided below on each of the Guilds, including how to participate. + +## Web platform guild + +The Web Platform Guild covers all areas related to front-end web development and Electron desktop app development at Mattermost. + +- **Guild Lead:** Harrison Healey +- **Guild channel:** [~Developers: WebApp](https://community.mattermost.com/core/channels/webapp) +- **Guild meeting time:** *(see header of Guild channel for meeting invite)* + +## Mobile guild + +The Mobile Guild covers all areas related to mobile application development and React Native. + +- **Guild Lead:** Elias Nahum +- **Guild channel:** [~Developers: Mobile](https://community.mattermost.com/core/channels/native-mobile-apps) +- **Guild meeting time:** *(see header of Guild channel for meeting invite)* + +## Server guild + +The Server Guild covers all areas related to our server codebase and general Go development at Mattermost. + +- **Guild Lead:** Agniva De Sarker +- **Guild channel:** [~Developers: Server](https://community.mattermost.com/core/channels/developers-server) +- **Guild meeting time:** *(see header of Guild channel for meeting invite)* + +## QA guild + +The QA Guild covers all areas related to Quality Assurance and automated testing infrastructure at Mattermost. + +- **Guild Lead:** Saturnino Abril +- **Guild channel:** [~QA: Weekly Meetings](https://community.mattermost.com/core/channels/qa-weekly-meetings) +- **Guild meeting time:** *(see header of Guild channel for meeting invite)* + diff --git a/docs/develop/contribute/more-info/getting-started/inactive-contributions.md b/docs/develop/contribute/more-info/getting-started/inactive-contributions.md new file mode 100644 index 000000000000..a385fa54bcd4 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/inactive-contributions.md @@ -0,0 +1,26 @@ +--- +title: "Inactive contributions" +sidebar_position: 3 +--- + +This process describes how inactive contributions are managed at Mattermost, inspired by the [Kubernetes project](https://github.com/kubernetes/kubernetes): + +1. After 10 days of inactivity, a contribution becomes stale and a bot will add the `lifecycle/1:stale` label to the contribution. + - If action is required from submitter, Community Coordinator asks if the team can help clarify previous feedback or provide guidance on next steps. + - If action is required from reviewers, Community Coordinator asks reviewers to share feedback or help answer questions. The Coordinator will follow up with reviewers until a response is received. + +2. After 20 days of inactivity, a contribution becomes inactive. + - Community Coordinator asks the submitter if the team can help with questions. They acknowledge that after another 30 days of inactivity the contribution will be closed. They also add a `lifecycle/2:inactive` label to the contribution. + + +Contributions should never become orphaned because of reviewers. The Coordinator will be responsible for receiving a response from the reviewers during the stale period, which may be that the maintainers aren't able to accept the contribution in its current form. + + +3. After 30 days of inactivity, a contribution becomes orphaned. + - Community Coordinator notes that the contribution has been inactive for 60 days, thanks for the contribution and closes the contribution. They also add an `lifecycle/3:orphaned` label to the contribution, and adds an `Up For Grabs` label to the associated help wanted ticket, if appropriate. + +Exceptions: + +1. If the contribution is inactive but shouldn't be closed, the Coordinator adds a `lifecycle/frozen` label to the contribution. An example of this is when a design decision is being discussed but no decision has been arrived at yet. +2. Once the contribution reaches the `lifecycle/2:inactive` state, it is eligible to be assumed by another community member interested in working on the ticket. +3. Invalid PRs may be closed immediately without advancing through this lifecycle, especially if the contributor is unresponsive. diff --git a/docs/develop/contribute/more-info/getting-started/index.md b/docs/develop/contribute/more-info/getting-started/index.md new file mode 100644 index 000000000000..c78df91c8314 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/index.md @@ -0,0 +1,31 @@ +--- +title: "Contribute code" +sidebar_position: 1 +--- + +This site is for developers who want to contribute code to the core Mattermost project. If you’re looking for other ways to contribute, [head over to our website](https://mattermost.com/contribute/). Before getting started, it’s a good idea to review our guide on [integrating and extending Mattermost](/developers/integrate/getting-started) because you might be able to build the improvements you want without needing to contribute them upstream. + + +## Technical overview + +The Mattermost core repositories include: +* [Server](/developers/contribute/more-info/server) - Highly-scalable Mattermost installation written in Go +* [Web App](/developers/contribute/more-info/webapp) - JavaScript client app built on React and Redux +* [Mobile Apps](/developers/contribute/more-info/mobile) - JavaScript client apps for Android and iOS built on React Native +* [Desktop App](/developers/contribute/more-info/desktop) - An Electron wrapper around the web app project that runs on Windows, Linux, and macOS +* [Core Plugins](/developers/contribute/more-info/plugins) - A core set of officially-maintained plugins that provide a variety of improvements to Mattermost. +* Core Integrations - Major Mattermost features including [Focalboard](/developers/contribute/more-info/focalboard) and [Playbooks](https://github.com/mattermost/mattermost-plugin-playbooks). + +Improvements to Mattermost may require you to contribute to multiple projects; if you’re unsure where to start, the server repository is generally the best way to get introduced to the codebase. + + +## How to contribute code + +If you’re looking for an existing issue to help with, check out the [help wanted tickets on GitHub](https://mattermost.com/pl/help-wanted). If you see any that you’re interested in working on, comment on it to let everyone know you’re working on it. If there’s no ticket for what you want to contribute, see our guide on [contributing without a ticket.](/contributions-without-ticket) + +Once you’ve created some code that you want to contribute, follow our [pull request checklist](/contribution-checklist) to submit your contribution for [review](/code-review), and one of our [core committers](/developers/contribute/more-info/getting-started/core-committers) will reach out with any feedback, questions, or requests they have. + + +## How to get help with your contribution + +Our contributor community is segmented into [guilds](/developers/contribute/more-info/getting-started/guilds) that focus on specific components within the Mattermost ecosystem. Each guild has a leader and a channel on our [community chat server](https://docs.mattermost.com/guides/community-chat.html) where you can ask questions about your contribution. diff --git a/docs/develop/contribute/more-info/getting-started/labels.md b/docs/develop/contribute/more-info/getting-started/labels.md new file mode 100644 index 000000000000..15afa82ce9e0 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/labels.md @@ -0,0 +1,61 @@ +--- +title: "Labels" +sidebar_position: 7 +--- + +We leverage [GitHub labels](https://help.github.com/en/articles/about-labels) to track the details and lifecycle of issues and pull requests. + +# Issue labels + +* `Area/`: Involves changes to the named area (APIv4, E2E Tests, Localization, Plugins, etc.) +* `Bug Report/Open`: Bug report unresolved, awaiting for more information or in development backlog. +* `Bug Report/Scheduled for Release`: Bug report resolved and scheduled for an upcoming release. Milestone indicates scheduled release version. +* `Difficulty/1:easy`: Easy ticket. +* `Difficulty/2:medium`: Medium ticket. +* `Difficulty/3:hard`: Hard ticket. +* `Good First Issue`: Suitable for first-time contributors. +* `Help Wanted`: Community help wanted. +* `Move to Feature Ideas forum`: Marked for relocation to the feature ideas forum. +* `Move to Troubleshooting`: Marked for relocation to the troubleshooting section of the documentation. +* `PR Submitted`: A pull request has been opened for this issue. +* `Tech/`: Requires using the named technology (Go, JavaScript, ReactJS, Redux, etc.) +* `Up for Grabs`: Ready for help from the community. Removed when someone volunteers. + +# Pull request labels + +* `1: PM Review`: Requires review by a [product manager](https://handbook.mattermost.com/contributors/contributors/core-committers#product-managers). +* `1: UX Review`: Requires review by a UX designer. +* `1: SME Review`: Requires review by a subject matter expert (used in the Handbook). +* `2: Dev Review`: Requires review by a [core committer](https://handbook.mattermost.com/contributors/contributors/core-committers#core-committers). +* `2: Editor Review`: Requires review by a [technical writer](https://handbook.mattermost.com/contributors/contributors/core-committers#technical-writers). +* `3: QA Review`: Requires review by a [QA tester](https://handbook.mattermost.com/contributors/contributors/core-committers#qa-testers). May occur at the same time as Dev Review. +* `4: Reviews Complete`: All reviewers have approved the pull request. +* `Awaiting Submitter Action`: Blocked on the author. +* `AutoMerge`: If all checks and approvals pass and the user adds this label, it will be in the queue to get merge automatically without a human intervention. +* `Changelog/Done`: Required changelog entry has been written. +* `Changelog/Not Needed`: Does not require a changelog entry. +* `CherryPick/Approved`: Meant for the quality or patch release tracked in the milestone. +* `CherryPick/Candidate`: A candidate for a quality or patch release, but not yet approved. +* `CherryPick/Done`: Successfully cherry-picked to the quality or patch release tracked in the milestone. +* `Demo Plugin Changes/Needed`: Requires changes to the demo plugin. +* `Demo Plugin Changes/Done`: Required changes to the demo plugin have been submitted. +* `Do Not Merge/Awaiting Loadtest`: Must be loadtested before it can be merged. +* `Do Not Merge/Awaiting Next Release`: To be merged with the next release (e.g. API documentation updates). +* `Do Not Merge/Awaiting PR`: Awaiting another pull request before merging (e.g. server changes). +* `Do Not Merge`: Should not be merged until this label is removed. +* `Docs/Done`: Required documentation has been written. +* `Docs/Needed`: Requires documentation. +* `Docs/Not Needed`: Does not require documentation. +* `Hackfest`: Related to a Mattermost hackathon. +* `Hacktoberfest`: Related to [Hacktoberfest](https://hacktoberfest.digitalocean.com/). +* `Lifecycle/`: An [inactive contribution](/developers/contribute/more-info/getting-started/inactive-contributions). +* `Loadtest`: Triggers an automatic load test. +* `Major Change`: The pull request is a major feature or affects large areas of the code base (e.g. [moving channel store and actions to Redux](https://github.com/mattermost/platform/pull/6235)). +* `QA Deferred`: Testing of this PR is expected to be completed after merge, likely when it is available on Community. Apply this in lieu of asking for `3: QA Review`. +* `Setup Cloud Test Server`: Triggers the creation of a Enterprise Edition test server. +* `Setup HA Cloud Test Server`: Triggers the creation of a test server that has high availability. +* `Setup Cloud + CWS Test Server`: Triggers the creation of a test server that connects to our test Customer Web Server. +* `Setup Upgrade Test Server`: Triggers the creation a test server and performs an upgrade. +* `Tests/Done`: Required tests have been written. +* `Tests/Not Needed`: Does not require tests. +* `Work in Progress`: Not yet ready for review. diff --git a/docs/develop/contribute/more-info/getting-started/slash-commands.md b/docs/develop/contribute/more-info/getting-started/slash-commands.md new file mode 100644 index 000000000000..bbc619fa3385 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/slash-commands.md @@ -0,0 +1,13 @@ +--- +title: "Slash commands" +sidebar_position: 30 +--- + +There are a couple of slash-commands available on GitHub which are implemented via [Mattermod](https://github.com/mattermost/mattermost-mattermod). They only work on PRs. + +The commands are: + +- `/cherry-pick $BRANCH_NAME`, e.g. `/cherry-pick release-5.10`: Opens a PR to cherry-pick a change into the branch `$BRANCH_NAME`. This command only works for the submitter of the PR and members of the Mattermost organization. +- `/check-cla`: Checks if the PR contributor has signed the CLA. +- `/autoassign`: Automatically assigns reviewers to a PR. +- `/update-branch`: Updates the pull request branch with the latest upstream changes by merging HEAD from the base branch into the pull request branch. This command only works for members of the Mattermost organization. diff --git a/docs/develop/contribute/more-info/getting-started/test-guideline.md b/docs/develop/contribute/more-info/getting-started/test-guideline.md new file mode 100644 index 000000000000..9f2ecfba27e2 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/test-guideline.md @@ -0,0 +1,72 @@ +--- +title: "Test guidelines" +sidebar_position: 6 +--- + +At Mattermost, we write tests because we want to be confident that our product works as expected for our users. As developers, we write tests as a gift to our future selves or to be confident that changes won't cause regressions or unintended behaviors. We value contributors who write tests as much as any others, and we want the process to be integrated in our core development workflow rather than being an afterthought or follow-up action. + +This page stresses the importance of tests, including for every pull request being submitted. It is the foundation of our test guidelines, and serves as a reference on why we do not merge code without tests. This is not to meet higher code coverage but rather to write effective and well-planned use cases depending on the changes being made. But of course, there's always an exception. If, for some reason, it isn't possible to write a test, let the reviewers know by writing a description to start a discussion and to fully understand the situation you are facing. + +Test categories +--------------- +Not all test types are required in a single pull request. Only write whichever test types are most effective and appropriate. +1. __Unit tests__ - Unit tests verify that individual, isolated parts work as expected. +2. __Integration tests__ - Integration tests verify that several units work together in harmony. +3. __End-to-End (E2E) tests__ - End-to-End tests exercise most of the parts of a large application. + + + +Wisdom and definitions mostly taken from [Martin Fowler's Software Testing Guide](https://martinfowler.com/testing/) and [Kent C. Dodds's personal site](https://kentcdodds.com/). + + + +In general, when are tests necessary? +------------------------------------- +- For all files written in the main language(s) of the repository; this could be JavaScript/Typescript and JSX/TSX files, Go files, or both which are exported such as functions, modules, or components used in various places. +- Un-exported functions or methods, which have low or no test coverage from the parent exported function/method, that affect critical functionality or behavior of the application. +- New features and bug fixes, especially those originating from customer and community bugs. + +When is it fine not to have tests? +-------------------------------------------- +- For implementation details of standard libraries or external packages that are implicitly covered by the standard library or external package itself. +- Where the situation may require external services running to effectively test the functionality, such as dependencies on feature flags via [Split](https://split.io), OAuth with third-party providers such as Google, etc. +- Tests should be made at the most effective and lowest possible level, but if it requires too much effort or complicated setup to accomplish at a unit test level, it would be best to skip and assess feasibility on the next level such as integration or end-to-end testing. +- Mocks and test helpers. +- Types only. +- Interfaces only or interfaces to other repositories, such as with private Enterprise via “interfaces”. +- End-to-end tests codebase. +- Automatically generated code for database migrations, store layers, etc. +- External dependencies, modules, imports, or vendors. + +How to run and write tests +------------------ +### Server +For writing and running **unit tests** in general, see the [Server workflow](/developers/contribute/more-info/server/developer-workflow) page. If you have written a new endpoint or changed an endpoint for the Mattermost REST API, check out the [REST API](/developers/contribute/more-info/server/rest-api) page. + +### Web App +For writing and running **unit tests** in general, see the [Unit tests](/developers/contribute/more-info/webapp/unit-testing) page. For writing and running **E2E tests** in general, see the [End-to-End testing](/developers/contribute/more-info/webapp/e2e-testing) section, and the [End-to-End cheatsheets](/developers/contribute/more-info/webapp/e2e-cheatsheets) section. + +For writing and running **E2E (and unit) tests for Redux** components, see the [Redux Unit and E2E Testing](/developers/contribute/more-info/webapp/redux/testing) page. + +### Mobile Apps +For writing and running **E2E tests** for both Android and iOS systems, take a look at the [Mobile End-to-End (E2E) Tests](/developers/contribute/more-info/mobile/e2e) page. + +### Desktop App +For writing and running **unit and E2E tests** for the desktop app, check out the [Unit and End-to-End (E2E) Tests in the desktop app](/developers/contribute/more-info/desktop/testing) page. + +# How to Contribute E2E Tests +If you're looking to improve your development skills or improve your familiarity with the Mattermost code base, issues for E2E tests that are marked Help Wanted are a great place to start. + +* Look for [issues in the mattermost](https://github.com/mattermost/mattermost/issues?q=is%3Aissue+is%3Aopen+e2e) repository that have the `Help Wanted` label and either the `Area/E2E Tests` label or something related to E2E in the issue title. + * Once you find an issue you would like to work on, comment on the issue to claim it. +* Each issue is filled with specific test steps and verifications that need to be accomplished as a minimum requirement. Additional steps and assertions for robust test implementation are very welcome. The contents of an E2E issue follow this general format: + * **Steps**: What the code in the test should do and/or emulate. + * **Expected**: What the results of the test should be. + * **Test Folder**: Where the file that holds the test code should be located. + * **Test code arrangement**: Starter code for the test. + * **Notes**: Comments on what to add and not to add to the test file, plus resources for contributions, asking questions, etc. + +If you'd like to see an example of an ideal E2E test contribution, please view these issues and their associated PRs: +* [Write Webapp E2E with Cypress: "MM-T642 Attachment does not collapse"](https://github.com/mattermost/mattermost/issues/18184) +* [Cypress test: "CTRL/CMD+K - Open private channel using arrow keys and Enter"](https://github.com/mattermost/mattermost/issues/14078) + diff --git a/docs/develop/contribute/more-info/getting-started/test-servers.md b/docs/develop/contribute/more-info/getting-started/test-servers.md new file mode 100644 index 000000000000..580ddf0812e9 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/test-servers.md @@ -0,0 +1,31 @@ +--- +title: "Test servers" +sidebar_position: 8 +--- + +As part of the pull request review process, reviewers may need to test and verify proposed changes. Leveraging our Cloud infrastructure, we can spin up full environments on demand to test code submitted in PRs. + +Core committers and staff can trigger test server creation on a PR by adding one of the following labels to the PR: + +* `Setup Cloud Test Server`: Triggers the creation of a standard test server using the latest commit on the PR and a PostgreSQL database. +* `Setup HA Cloud Test Server`: Triggers the creation of a test server that has high availability. +* `Setup Cloud + CWS Test Server`: Triggers the creation of a test server that connects to our test Customer Web Server. + +After adding these labels, a bot will comment on the PR notifying you that a test server is being created. It should take approximately 3-5 minutes for the server to create it. Once it's ready, the bot will comment on the PR again with a link and credentials to the test server for both an admin and a regular user. + +If the bot comments that an error has occurred, try removing the label and then re-adding it again. If that still fails, please ask for help in [~Developers: Cloud](https://community.mattermost.com/core/channels/cloud). If you need urgent help, please mention `@sresupport` in your message. + +Once testing is complete, remove the label and the test server will be destroyed. + +Test servers are available on any repositories that have the labels. + +# Tips and tricks + +* Avoid adding and removing the labels quickly in succession - this can confuse the bot and result in issues. Please be patient. :) +* Pushing new commits to PRs will trigger the bot to automatically update the test server. +* When submitting a new PR or pushing an update to a PR, the docker build/push CI step must complete before a test server can be created/updated. +* Please make sure to remove labels when testing is complete since there is a limited capacity for test servers. +* If you want a test server to have the changes from two different PRs across the webapp and server repositories, ensure: + * Both server and webapp branches are named the same and are on the main repos and not from forks. + * The server build completes before the webapp build runs (you can re-trigger the webapp build if it didn't). + * The test server was created after the webapp build is complete (that included the server build) and present on the PR for the web app. diff --git a/docs/develop/contribute/more-info/getting-started/using-gitpod.md b/docs/develop/contribute/more-info/getting-started/using-gitpod.md new file mode 100644 index 000000000000..2422d9a8a4c7 --- /dev/null +++ b/docs/develop/contribute/more-info/getting-started/using-gitpod.md @@ -0,0 +1,112 @@ +--- +title: "Using Gitpod" +sidebar_position: 6 +--- + +### What is Gitpod? +[Gitpod](https://www.gitpod.io/) is a cloud development environment. The following instructions have been adapted from comments on this issue: [Document general usage of Gitpod #18 ](https://github.com/mattermost/mattermost-gitpod-config/issues/18). You can also check out these videos to learn how to work with Gitpod (and write an E2E test): [How to set up a developer environment for Mattermost with Gitpod](https://www.youtube.com/watch?v=LgQ2Z_GelYQ) and [Writing your first E2E test for Mattermost](https://www.youtube.com/watch?v=mLbzKSGZv4A). + +#### :cyclone: Spinning up an environment + +1. Create a new workspace for a ticket/issue that you've claimed by going to the [mattermost-gitpod-config](https://github.com/mattermost/mattermost-gitpod-config/tree/master) repository and clicking the "Open in Gitpod" badge. + + * You can also use the [Gitpod browser extension](https://www.gitpod.io/docs/configure/user-settings/browser-extension) to open up a repository in Gitpod, or manually prefix GitHub repository URLs with `gitpod.io/#`. What the extension does is add a green Gitpod button to repository pages on GitHub, and clicking it spins up a new environment for the repository on Gitpod. + ![mattermost-gitpod-config-repo](https://user-images.githubusercontent.com/43153413/194467192-675a6b15-bb3b-4a4d-be05-f1df0fbdd524.jpeg) + +2. You may need to sign in (through GitHub) to access the workspace on Gitpod. Once Gitpod has done loading, the user interface presented is that of VSCode. +![mattermost-gitpod-intro](https://user-images.githubusercontent.com/43153413/194467255-98b5a9be-85a5-4da8-b519-279011882384.jpeg) + +#### :pencil2: Working on an issue/ticket + +3. Make changes to one of the projects. For example, you could be working on writing an End-to-End (E2E) test, like this issue [Write Webapp E2E with Cypress: "MM-T642 Attachment does not collapse" #18184](https://github.com/mattermost/mattermost/issues/18184). The development process is very similar to how you would work locally. + +#### :herb: Making branches and forks + +4. You most likely won't have direct write access to the repository you are working on. Thus, you will need to bring the changes you've made over from the `master` or `main` branch to a new branch on your own fork of the repository. + +5. Click the "Source Control" icon on the left sidebar. On the panel next to the side bar, you will see a list of the repositories in the workspace, and under each repository a list of the files that have changed (if any). Next to the label for `mattermost-webapp`, click the button with the branch name and the source control icon. + +6. A dropdown will appear via the command palette. Click the option that says: "+ Create new branch..." +![mattermost-gitpod-new-branch](https://user-images.githubusercontent.com/43153413/194467696-498917fe-14a3-4cbc-ac35-1b201ce3c730.jpeg) + +7. In the box that appears, name your new branch. A good name idea is to name it after the code that refers to your issue - in this case, this is the "Test Key", so a suitable name for the branch is `MM-T642`. Then, hit `Enter` on your keyboard. +![mattermost-gitpod-branch-name](https://user-images.githubusercontent.com/43153413/194467742-e7312d5d-dbb3-4bcc-a5af-b67941bbf4f2.jpeg) + +8. Now that the branch has changed, you can commit your changes to it. Back in the source control panel, you can make a commit message in the text box above the "commit button" in the section for the `mattermost-webapp` repository. Then, press the "commit button". A modal may appear asking you to first stage your changes. +![mattermost-gitpod-commit-message](https://user-images.githubusercontent.com/43153413/194467789-0f588a7c-ff8b-4bc9-adaf-5d224726b2a5.jpeg) + +9. You can now publish your branch to the remote. However, as you will not have access to the main repository itself, you will be prompted to first create a fork. Click on the "publish branch button" on the source control panel. A popup will appear, asking if you would like to make a fork and push to that instead. On the popup, select the "create fork" button. +![mattermost-gitpod-make-fork](https://user-images.githubusercontent.com/43153413/194468420-14564230-fb63-442c-b0e6-815aeb799da5.jpeg) + +10. During the process of fork creation, you may be prompted to grant GitHub access to Gitpod's GitHub extension (you should allow this). +![mattermost-gitpod-sign-into-GitHub](https://user-images.githubusercontent.com/43153413/194468466-79cf2804-5393-4a1c-994f-9c087ff42b1d.jpeg) + +11. You may also be asked to update the permissions you give Gitpod to access GitHub through a popup. If this happens, you will have to restart the fork creation process (publish branch -> say yes to creating a fork). Click the "open access control" button on the popup. +![mattermost-gitpod-need-perms](https://user-images.githubusercontent.com/43153413/194468523-f7c7ce87-3586-48bf-b779-38253de0059e.jpeg) + +12. You will get taken to the Integration section of Gitpod's settings. In the list of Git Providers on the page, find GitHub, click the three dots next to the listing, and select "Edit Permissions" from the dropdown menu. +![mattermost-gitpod-open-perms](https://user-images.githubusercontent.com/43153413/194468548-7b31a634-dd4a-49bb-a697-a8b3e5aa39db.jpeg) + +13. A popup will appear with a list of permission checkboxes. It's a good idea to check all of them off so you don't need to go through this process again. When you're done checking off the permissions, click the "Update Permissions" button. +![mattermost-gitpod-select-perms](https://user-images.githubusercontent.com/43153413/194468567-fba1fc58-f4db-4787-8dcd-d594472d7692.jpeg) + +14. Another tab might also appear where on GitHub's end you accept the additional permissions Gitpod is requesting. Click on the "authorize gitpod-io" button. +![mattermost-gitpod-confirm-perms](https://user-images.githubusercontent.com/43153413/194468598-1866b681-ae3b-42a0-b94c-c02735776e02.jpeg) + +15. Once the forking process is done, there will be a couple of popups that appear on Gitpod: one asking if you'd like to periodically run `git fetch` (which will periodically download content from the remote), another one asking if you'd like to create a pull request for the branch you're on right inside Gitpod/the VSCode editor, and finally one informing that the fork was successfully created. On the successful fork creation popup, click the `open on GitHub` option. +![mattermost-gitpod-open-fork-on-GitHub](https://user-images.githubusercontent.com/43153413/194468614-a89701c4-8b09-4b80-b84e-a0beaca8431c.jpeg) + +#### :mag: Creating a Pull Request (PR) + +16. You'll get taken to GitHub, to the fork of the repository you've worked on in your account instead of the main one in the Mattermost organization. Navigate to the branch you've made on your fork if you're not there already. + + * Near the top of the page will be a bar mentioning how many commits ahead/behind your branch is from the `master`/`main` branch of the main repository. There will also be two buttons: "contribute" and "sync fork". Click on the "contribute" button, and in the dropdown that appears, click the "open pull request" button. +![mattermost-gitpod-create-PR-on-GitHub](https://user-images.githubusercontent.com/43153413/194468644-8c625663-17d4-4187-92be-171b683d298f.jpeg) + +17. You'll be taken to another page on GitHub called "Open a pull request". +![mattermost-gitpod-PR-creation-page](https://user-images.githubusercontent.com/43153413/194468667-aace5ac5-4bbe-4e93-9902-e210964e00c8.jpeg) + +```text +* The first section of the page compares whether the branches (your branch on your fork - the "head repository" vs. the master/main branch on the main repository - the "base repository") can be merged automatically. +* The second section of the page will show other PRs that are based on your same branch, if any. +* The third section is where you create a write-up for your pull request - giving it a title, and filling out the template. At the bottom of this section is a "Create pull request" button. This button will be faded out until you make a title for the PR. + * If you haven't already, give Mattermost's [Contribution Checklist](https://developers.mattermost.com/contribute/more-info/getting-started/contribution-checklist/) a read. An important takeaway is that you will need to sign the [Contributor License Agreement](https://mattermost.com/mattermost-contributor-agreement/) - this will be another check on the pull request and if you haven't signed it, this will also block merging. + * Also check out this blog post about [Submitting Great PRs](https://developers.mattermost.com/blog/2019-01-24-submitting-great-prs), and other repository specific information [here](https://developers.mattermost.com/contribute). + * **Parts of a PR body**: + * _Title_: a good title will refer back to the issue; and it should begin with the related Jira or GitHub ticket ID (e.g. [MM-394] or [GH-394]). In the context of the E2E issue example: `MM-T642: Attachment does not collapse - Cypress Webapp E2E Test`. + * _Summary_: description of what the PR does, as well as QA test steps (if applicable and if not already added to the Jira ticket). For example: `Verifies that attachments on posts do not collapse after entering the slash command collapse`. + * _Ticket Link_: Either link the relevant Jira ticket or if you picked up an issue/ticket with a `Helped Wanted` label, link to the GitHub issue. For example: [Write Webapp E2E with Cypress: "MM-T642 Attachment does not collapse" #18184](https://github.com/mattermost/mattermost/issues/18184). + * _Related Pull Requests_: Link other PRs here if they are related to this PR. + * _Screenshots_: Illustrate what your changes have done. + * _Release Note_: There are certain conditions that require release notes: + * Config changes (additions, deletions, updates). + * API additions—new endpoints, new response fields, or newly accepted request parameters. + * Database changes (any). + * Schema migration changes. Use the [Schema Migration Template](https://docs.google.com/document/d/18lD7N32oyMtYjFrJKwsNv8yn6Fe5QtF-eMm8nn0O8tk/edit?usp=sharing) as a starting point to capture these details as release notes. + * Websocket additions or changes. + * Anything noteworthy to a Mattermost instance administrator (err on the side of over-communicating). + * New features and improvements, including behavioral changes, UI changes, and CLI changes. + * Bug fixes and fixes of previous known issues. + * Deprecation warnings, breaking changes, or compatibility notes. +

+ If no release notes are required, write NONE. Use past-tense. For E2E tests, having `NONE` as a release note suffices. If you do not end up writing a release note at all, you'll get a warning on your PR like this: `Adding the "do-not-merge/release-note-label-needed" label [to the PR] because no release-note block was detected, please follow our release note process to remove it.` If this happens, you can just edit the body of the PR, and add it back in. + +* The last section details the code changes on your branch, including information on the commits on the branch, the files changed, and the contributors. +``` + +18. Once you've created your pull request, you'll get taken to its page, like this one: [MM-T642: Attachment does not collapse - Cypress Webapp E2E Test #11231](https://github.com/mattermost/mattermost/pull/11231). Below your initial body text of the PR will be a list of commits and other comments. At the end of this list is a checklist which notes the status of reviews required for the pull request, and the checks that the pull request must pass, plus a place to write your own additional comments. +![mattermost-gitpod-real-PR-1](https://user-images.githubusercontent.com/43153413/194468726-afddf66f-eaf1-4dab-a6bf-7ddf39db78bf.jpeg) + +19. if you need to make any changes to your PR, you can return to Gitpod and stage and commit your changes from there onto your branch; and this will be reflected in GitHub. + +### :white_check_mark: Code Review + +Information from this section comes from: [Code review at Mattermost](https://developers.mattermost.com/contribute/more-info/getting-started/code-review/). + +20. Wait for a reviewer to be assigned - normally this is handled automatically, but if you need help feel free to ask for help in the [Developers channel](https://community.mattermost.com/core/channels/developers) of the Mattermost community server. + +21. Wait for a review - if a reviewer requests changes, your PR will disappear from their queue of reviews. Once you've addressed the concerns, re-request a review from any person requesting changes. Avoid force pushing, which is the act of overwriting the commit history on the remote with what you have on local. + +22. Once all reviewers approve your pull request, they will handle the merging of your code. + + \ No newline at end of file diff --git a/docs/develop/contribute/more-info/index.md b/docs/develop/contribute/more-info/index.md new file mode 100644 index 000000000000..cb1f1f891dd7 --- /dev/null +++ b/docs/develop/contribute/more-info/index.md @@ -0,0 +1,28 @@ +--- +title: "Where to find more information?" +sidebar_position: 4 +--- + +Here are a few links to Mattermost content that you might find helpful depending on the specific area where you’ll be contributing. + +## Mattermost resources + +1. Specific localization guides (coming soon!) +2. [Mattermost contributor agreement](https://mattermost.com/mattermost-contributor-agreement/) +3. [Approved contributor list](https://docs.google.com/spreadsheets/d/1NTCeG-iL_VS9bFqtmHSfwETo5f-8MQ7oMDE5IUYJi_Y/pubhtml?gid=0&single=true) +4. [The API](https://api.mattermost.com) +5. [Incoming](/developers/integrate/webhooks/incoming) and [outgoing](/developers/integrate/webhooks/outgoing) webhooks +6. [Plugins](/developers/integrate/plugins), also [Plugins](/developers/contribute/more-info/plugins) +7. [Making slash commands](/developers/integrate/slash-commands) +8. [Embedding Mattermost in other places](/developers/integrate/customization/embedding) +9. [Server project](/developers/contribute/more-info/server) +10. [Webapp project](/developers/contribute/more-info/webapp) +11. [Mobile apps](/developers/contribute/more-info/mobile) +12. [Desktop app](/developers/contribute/more-info/desktop) +13. [Focalboard](/developers/contribute/more-info/focalboard) +14. [Playbooks](https://github.com/mattermost/mattermost-plugin-playbooks) + +## External resources + +1. [How ICU syntax works](https://formatjs.io/docs/core-concepts/icu-syntax/) +2. [Use gender-neutral language in communications and in content](https://apastyle.apa.org/style-grammar-guidelines/grammar/singular-they) diff --git a/docs/develop/contribute/more-info/mobile/build-your-own/android.md b/docs/develop/contribute/more-info/mobile/build-your-own/android.md new file mode 100644 index 000000000000..5dc1d7067fae --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/build-your-own/android.md @@ -0,0 +1,136 @@ +--- +title: "Build the Android mobile app" +sidebar_position: 1 +--- + +At times, you may want to build your own Mattermost mobile app. The most common use cases are: + +* To white label the Mattermost mobile app. +* To use your own deployment of the Mattermost Push Notification Service (always required if you are building your own version of the mobile app). + +# Build preparations + +### 1. Package name and source files + +* Ensure the package ID of the mobile app remains the same as the one in the original [mattermost-mobile GitHub repository](https://github.com/mattermost/mattermost-mobile) in `com.mattermost.rnbeta`. +* Source files for the main package remain under the `android/app/src/main/java/com/mattermost/rnbeta` folder. + +### 2. Generate a signing key + +As Android requires all apps to be digitally signed with a certificate before they can be installed building the Android app for distribution requires the release APK to be signed. + +To generate the signed key, use **keytool** which comes with the JDK required to develop the Android app. (see [Developer Setup](/developers/contribute/more-info/mobile/developer-setup#additional-setup-for-android)). + +```sh +$ keytool -genkey -v -keystore .keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 +``` + +The above command prompts you for passwords for the keystore and key (make sure you use the same password for both), and asks you to provide the Distinguished Name fields for your key. It then generates the keystore as a file called `.keystore`. + +The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take a note of the alias. + +--- + + +* Replace `` with the filename you want to specify. +* Remember to keep your keystore file private and never commit it to version control. + + + +--- + +### 3. Create a new app in Google Play + +Create a new application using the [Google Play console](https://play.google.com/console/developers). If you already have an app registered in the Google Play console you can skip this step. + +### 4. Set up Gradle variables +Now that we have created the keystore file we can tell the build process to use that file: + +- Copy or move the `my-release-key.keystore` file under a directory that you can access. It can be in your home directory or anywhere in the file system. +- Edit the `gradle.properties` file in your `$HOME` directory (e.g. `$HOME/.gradle/gradle.properties`), or create it if one does not exist, and add the following: + + ```sh + MATTERMOST_RELEASE_STORE_FILE=/full/path/to/directory/containing/my-release-key.keystore + MATTERMOST_RELEASE_KEY_ALIAS=my-key-alias + MATTERMOST_RELEASE_PASSWORD=***** + ``` +--- + + +* Replace `/full/path/to/directory/containing/my-release-key.keystore` with the full path to the actual keystore file and `********` with the actual keystore password. +* Back up your keystore and don't forget the password. + + + +--- +--- +**Important:** + +Once you publish the app on the Play Store, the app needs to be signed with the same key every time you want to distribute a new build. If you lose this key, you will need to republish your app under a different package id (losing all downloads and ratings). + +--- + +### 5. Configure environment variables + +To make it easier to customize your build, we've defined a few environment variables that are going to be used by Fastlane during the build process. + +| Variable | Description | Default | Required | +|----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|----------| +| `COMMIT_CHANGES_TO_GIT` | Should the Fastlane script ensure that there are no changes to Git before building the app and that every change made during the build is committed back to Git.

Valid values are: `true`, `false` | `false` | No | +| `BRANCH_TO_BUILD` | Defines the Git branch that is going to be used for generating the build.

**Make sure that, if this value is set, the branch it is set to exists**. | `$GIT_BRANCH` | No | +| `GIT_LOCAL_BRANCH` | Defines the local branch to be created from `BRANCH_TO_BUILD` to ensure the base branch does not get any new commits on it.

**Make sure a branch with this name does not yet exist in your local Git repository**. | build | No | +| `RESET_GIT_BRANCH` | Defines if, once the build is done, the branch should be reset to the initial state before building and whether to also delete the branch created to build the app.

Valid values are: `true`, `false` | `false` | No | +| `VERSION_NUMBER ` | Set the version of the app at build time to a specific value, rather than using the one set in the project. | | No | +| `INCREMENT_VERSION_NUMBER_MESSAGE` | Set the commit message when changing the app version number. | Bump app version number to | No | +| `INCREMENT_BUILD_NUMBER` | Defines if the app build number should be incremented.

Valid values are: `true`, `false` | `false` | No | +| `BUILD_NUMBER` | Set the build number of the app at build time to a specific value, rather than incrementing the last build number. | | No | +| `INCREMENT_BUILD_NUMBER_MESSAGE` | Set the commit message when changing the app build number. | Bump app build number to | No | +| `ANDROID_BUILD_TASK` | The build tasks for Android. This is a comma-separated list of tasks that can have two values: 'assemble' and 'bundle'.

`assemble` is used for building `APK` file and `bundle` is used for building `AAB` file. | assemble | No | +| `APP_NAME` | The name of the app as it is going to be shown on the device home screen. | Mattermost Beta | Yes | +| `APP_SCHEME` | The URL naming scheme for the app as used in direct deep links to app content from outside the app. | mattermost | No | +| `REPLACE_ASSETS` | Override the assets as described in [White Labeling](/developers/contribute/more-info/mobile/build-your-own/white-label).

Valid values are: `true`, `false` | `false` | No | +| `MAIN_APP_IDENTIFIER` | The package identifier for the app. | | Yes | +| `BUILD_FOR_RELEASE` | Defines if the app should be built in release mode.

Valid values are: `true`, `false`

**Make sure you set this value to true if you plan to submit this app Google Play or distribute it in any other way**. | `false` | Yes | +| `SEPARATE_APKS` | Build one APK per achitecture (armeabi-v7a, x86, arm64-v8a and x86_64) as well as a universal APK. The advantage is the size of the APK is reduced by about 4MB.

People will download the correct APK from the Play Store based on the CPU architecture of their device. | `false` | Yes | +| `SUBMIT_ANDROID_TO_GOOGLE_PLAY` | Should the app be submitted to the Play Store once it finishes building, use along with `SUPPLY_TRACK`.

Valid values are: `true`, `false` | `false` | Yes | +| `SUPPLY_TRACK` | The track of the application to use when submitting the app to Google Play Store. Valid values are: `alpha`, `beta`, `production`

**RIt is not recommended to submit the app to production. First try any of the other tracks and then promote your app using the Google Play console**. | `alpha` | Yes | +| `SUPPLY_PACKAGE_NAME` | The package Id of your application, make sure it matches `MAIN_APP_IDENTIFIER`. | | Yes | +| `SUPPLY_JSON_KEY` | The path to the service account `json` file used to authenticate with Google.

See the [Supply documentation]( https://docs.fastlane.tools/actions/supply/#setup) to learn more. | | Yes | + +--- + + +To configure your variables create the file `./mattermost-mobile/fastlane/.env` where `.env` is the filename. You can find the sample file `env_vars_example` [here](https://github.com/mattermost/mattermost-mobile/blob/master/fastlane/env_vars_example). + + + + +--- + +### 6. Google services + +Replace the `google-services.json` file as instructed in the [Android Push Notification Guide](/developers/contribute/more-info/mobile/push-notifications/android) before you build the app. + +## Build the mobile app + +Once all the previous steps are done, execute the following command from within the project's directory: + +```sh +$ npm run build:android +``` + +This will start the build process following the environment variables you've set. Once it finishes, it will create the `.apk` file(s) with the `APP_NAME` as the filename in the project's root directory. If you have not set Fastlane to submit the app to the Play Store, you can use this file to manually publish and distribute the app. + +## Frequently Asked Questions +### How do I update the lock file? +We use lockfiles to lock dependencies and make sure the builds are reproductible. If we want to update the lockfile to update all dependencies to the latest, we can run these commands: +``` +cd android +./gradlew app:dependencies --update-locks "*:*" +``` + +In case we want to regenerate the lockfile from the scratch, we can delete the `android/buildscript-gradle.lockfile` and then run the following commands: +``` +cd android +./gradlew app:dependencies --write-locks +``` diff --git a/docs/develop/contribute/more-info/mobile/build-your-own/index.md b/docs/develop/contribute/more-info/mobile/build-your-own/index.md new file mode 100644 index 000000000000..69705c129930 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/build-your-own/index.md @@ -0,0 +1,27 @@ +--- +title: "Build your own mobile app" +sidebar_position: 2 +--- + +You can build the app from source and distribute it within your team or company either using the App Stores, Enterprise App Stores or EMM providers, or another way of your choosing. + +At Mattermost, we build and deploy the Apps using a CI pipeline. The pipeline has different jobs and steps that run on specific contexts based on what we want to accomplish. You can check it out [here](https://github.com/mattermost/mattermost-mobile/blob/main/.github/workflows). + +As an alternative we've also created a set of **scripts** to help automate build tasks. Learn more about the scripts by reviewing the [package.json](https://github.com/mattermost/mattermost-mobile/blob/master/package.json) file. + + + +By using the **scripts**, [Fastlane](https://docs.fastlane.tools/#choose-your-installation-method) and other dependencies will be installed in your system. + + + + + +- [Build the Android app](/developers/contribute/more-info/mobile/build-your-own/android) +- [Build the iOS app](/developers/contribute/more-info/mobile/build-your-own/ios) + +### Push notifications with your own mobile app + +When building your own Mattermost mobile app, you will also need to host the [Mattermost Push Notification Service](https://github.com/mattermost/mattermost-push-proxy) in order to receive push notifications. + +See [Setup Push Notifications](/developers/contribute/more-info/mobile/push-notifications) for more details. diff --git a/docs/develop/contribute/more-info/mobile/build-your-own/ios.md b/docs/develop/contribute/more-info/mobile/build-your-own/ios.md new file mode 100644 index 000000000000..01e6ce05a8f5 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/build-your-own/ios.md @@ -0,0 +1,91 @@ +--- +title: "Build the iOS mobile app" +sidebar_position: 2 +--- + +At times, you may want to build your own Mattermost mobile app. The most common use cases are: + +* To white label the Mattermost mobile app. +* To use your own deployment of the Mattermost Push Notification Service (always required if you are building your own version of the mobile app). + +# Build preparations + +### 1. Prerequisites + +The Mattermost mobile app for iOS needs to be built on a macOS computer with Xcode and the Xcode command line tools installed. + +```sh +$ xcode-select --install +``` + +### 2. Bundle ID and entitlements + +* Follow the steps 1, 2, and 3 for [Run on iOS Devices](/developers/contribute/more-info/mobile/developer-setup/run#run-on-ios-devices) in the Developer Setup. +* After configuring the app in the previous step, **ensure** the bundle ID for each target of the mobile app remains the same as the one in the original [mattermost-mobile GitHub repository](https://github.com/mattermost/mattermost-mobile) (`com.mattermost.rnbeta`, `com.mattermost.rnbeta.MattermostShare`, and `com.mattermost.rnbeta.NotificationService`). + +### 3. Code sign + +Apple requires all apps to be digitally signed with a certificate before they can be installed. + +The build script will make use of [Match](https://docs.fastlane.tools/actions/match/) to sync your provisioning profiles (the profiles will be created for you if needed). The provisioning profiles will be created based on the environment variables. + +### 4. Configure environment variables + +To make it easier to customize your build, we've defined a few environment variables that are going to be used by Fastlane during the build process. + +| Variable | Description | Default | Required | +|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------| +| `COMMIT_CHANGES_TO_GIT` | Should the fastlane script ensure that there are no changes to Git before building the app and that every change made during the build is committed back to Git.

Valid values are: `true`, `false` | `false` | No | +| `BRANCH_TO_BUILD` | Defines the Git branch that is going to be used for generating the build.

**Make sure that, if this value is set, the branch it is set to exists**. | `$GIT_BRANCH` | No | +| `GIT_LOCAL_BRANCH` | Defines the local branch to be created from BRANCH\_TO\_BUILD to ensure the base branch does not get any new commits on it.

**Make sure a branch with this name does not yet exist in your local git**. | build | No | +| `RESET_GIT_BRANCH` | Defines if, once the build is done, the branch should be reset to the initial state before building and whether to also delete the branch created to build the app.

Valid values are: `true`, `false` | `false` | No | +| `VERSION_NUMBER` | Set the version of the app at build time to a specific value, rather than using the one set in the project. | | No | +| `INCREMENT_VERSION_NUMBER_MESSAGE` | Set the commit message when changing the app version number. | Bump app version number to | No | +| `INCREMENT_BUILD_NUMBER` | Defines if the app build number should be incremented.

Valid values are: `true`, `false` | `false` | No | +| `BUILD_NUMBER` | Set the build number of the app at build time to a specific value, rather than incrementing the last build number. | | No | +| `INCREMENT_BUILD_NUMBER_MESSAGE` | Set the commit message when changing the app build number. | Bump app build number to | No | +| `APP_NAME` | The name of the app as it is going to be shown in the device home screen. | Mattermost Beta | Yes | +| `APP_SCHEME` | The URL naming scheme for the app as used in direct deep links to app content from outside the app. | mattermost | No | +| `REPLACE_ASSETS` | Override the assets as described in [White Labeling](/developers/contribute/more-info/mobile/build-your-own/white-label).

Valid values are: `true`, `false` | `false` | No | +| `MAIN_APP_IDENTIFIER` | The bundle identifier for the app. | | Yes | +| `BUILD_FOR_RELEASE` | Defines if the app should be built in release mode.

Valid values are: `true`, `false`

**Make sure you set this value to true if you plan to submit this app to TestFlight, the Apple App Store or distribute it in any other way**. | `false` | Yes | +| `NOTIFICATION_SERVICE_IDENTIFIER` | The bundle identifier for the notification service extension. | | Yes | +| `EXTENSION_APP_IDENTIFIER` | The bundle identifier for the share extension. | | Yes | +| `FASTLANE_TEAM_ID` | The ID of your Apple Developer Portal Team. | | Yes | +| `IOS_ICLOUD_CONTAINER` | The iOS iCloud container identifier used to support iCloud storage. | | Yes | +| `IOS_APP_GROUP` | The iOS App Group identifier used to share data between the app and the share extension. | | Yes | +| `SYNC_PROVISIONING_PROFILES` | Should we run **match** to sync the provisioning profiles. **Note**: Not syncing the provisioning profiles, will cause the singing to fail. Valid values are: `true`, `false` | `false` | Yes | +| `MATCH_USERNAME` | Your Apple ID Username. | | Yes | +| `MATCH_PASSWORD` | Your Apple ID Password. | | Yes | +| `MATCH_KEYCHAIN_PASSWORD` | Your Mac user password used to install the certificates in the build computer KeyChain. | | No | +| `MATCH_GIT_URL` | URL to the Git repo containing all the certificates.

**Make sure this Git repo is set to private. Remember this repo will be used to sync the provisioning profiles and other certificates**. | | Yes | +| `MATCH_APP_IDENTIFIER` | The Bundle Identifiers for the app (comma-separated).

**List the identifiers for each target of the app**. | for example:
`com.mattermost.rnbeta`,
`com.mattermost.rnbeta.MattermostShare`,
`com.mattermost.rnbeta.NotificationService` | Yes | +| `MATCH_TYPE` | Define the provisioning profile type to sync. Valid values are: `appstore`, `adhoc`, `development`, `enterprise`

**Make sure you set this value to the same type as the `IOS_BUILD_EXPORT_METHOD` as you want to have the same provisioning profiles installed in the machine so they are found when signing the app**. | `adhoc` | Yes | +| `SUBMIT_IOS_TO_TESTFLIGHT` | Submit the app to TestFlight once the build finishes. Valid values are: `true`, `false` | `false` | No | +| `PILOT_USERNAME` | Your Apple ID Username used to deploy the app to TestFlight. | | No | +| `PILOT_SKIP_WAITING_FOR_BUILD_PROCESSING` | Do not wait until TestFlight finishes processing the app.

Valid values are: `true`, `false` | `true` | No | + +--- + + +To configure your variables create the file `./mattermost-mobile/fastlane/.env` where `.env` is the filename. You can find the sample file `env_vars_example` [here](https://github.com/mattermost/mattermost-mobile/blob/master/fastlane/env_vars_example). + + + +--- + +## Build the mobile app + +Once all the previous steps are complete, execute the following command from within the project's directory: + +```sh +$ npm run build:ios +``` + +This will start the build process following the environment variables you've set. Once it finishes, it will create an `.ipa` file with the `APP_NAME` as the filename in the project's root directory. If you have not set Fastlane to submit the app to TestFlight, you can use this file to manually publish and distribute the app. + +# Troubleshooting + +## I keep receiving `Invalid username and password combination.` but the user and password are correct + +Apple IDs must be lowercase. A username like "Example@icloud.com" may not work properly, while "example@icloud.com" will. Also ensure you have recently changed your Apple ID password. "Old" passwords may be blocked by Apple when not connecting through a browser, so Apple may block Fastlane. Resetting your password may solve this issue. diff --git a/docs/develop/contribute/more-info/mobile/build-your-own/ssl-pinning.md b/docs/develop/contribute/more-info/mobile/build-your-own/ssl-pinning.md new file mode 100644 index 000000000000..ad3ad5999232 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/build-your-own/ssl-pinning.md @@ -0,0 +1,57 @@ +--- +title: "Enable SSL Pinning certificates" +sidebar_position: 2 +--- + +##### What is SSL Pinning? + +SSL (Secure Sockets Layer) pinning is a technique used in mobile app development to ensure that the app communicates only with a server that has a specific certificate. This is done by embedding the server’s certificate in the app itself and then validating the server’s certificate against this embedded certificate during communication. If the server's certificate does not match the pinned certificate, the connection is rejected. + +##### Advantages of SSL Pinning + +1. **Increased Security**: Protects against man-in-the-middle (MITM) attacks by ensuring that the app only communicates with trusted servers. +2. **Trustworthiness**: Guarantees that the data sent and received is from the expected server. +3. **Prevention of Certificate Spoofing**: Ensures that the server’s certificate is exactly what is expected, preventing spoofing attempts. + +##### Disadvantages of SSL Pinning + +1. **Certificate Management**: Requires regular updates to the app when the server’s certificate is renewed or changed. +2. **Deployment Complexity**: Coordination between development and deployment teams is necessary to avoid disruptions during certificate rotations. +3. **Maintenance Overhead**: Adds additional steps and complexity to the app’s maintenance process. + + + +SSL pinning requires that both development and deployment teams understand and follow best practices for cryptographic key management, certificate rotation, and incident response. +- Coordinating the timing of certificate updates and app updates is crucial to minimize impact on end-users. When the server's SSL certificate is renewed or rotated, the hardcoded public key in the app no longer matches the server's new certificate, leading to connection failures until the app is updated with the new key. +- Both development and deployment teams need to align on a deployment window that considers factors like user downtime, mobile app store review timelines, and peak usage times, as well as a coordinated rollback plan. + + + +### Steps to Enable SSL Pinning in Your Mobile App + +#### 1. Obtain the Certificate from the Server + +Use `openssl` to retrieve the certificate from your server and save it to a file. This can be done with the following command: + +```sh +openssl s_client -connect yourserver.com:443 -showcerts < /dev/null | openssl x509 -outform DER -out yourserver.cer +``` + +Alternatively, to save it in PEM format: + +```sh +openssl s_client -connect yourserver.com:443 -showcerts < /dev/null | openssl x509 -outform PEM -out yourserver.crt +``` + +#### 2. Naming the Certificate Files + +Name the certificate files using the domain name as the filename with either `.cer` or `.crt` as the extension. For example, if your server’s domain is `example.com`, your files should be named `example.com.cer` and/or `example.com.crt`. + +Optionally you can have both file types (`.cer` and `.crt`) to match the server trust and to ensure continued app functionality during certificate rotations. **Coordinate certificate rotations with the deployment teams** to avoid disruptions between the app and the server. + +#### 3. Copy the Certificate Files to the Assets Folder + +Place the certificate files in the `assets/certs` folder of your project. This is necessary for the app to access and use the certificates during runtime. + +#### 4. Build Your App +Follow the instructions in the [Build the iOS app](/developers/contribute/more-info/mobile/build-your-own/ios) or [Build the Android app](/developers/contribute/more-info/mobile/build-your-own/android) sections to build your app with SSL pinning enabled. diff --git a/docs/develop/contribute/more-info/mobile/build-your-own/white-label.md b/docs/develop/contribute/more-info/mobile/build-your-own/white-label.md new file mode 100644 index 000000000000..2e8a291a6903 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/build-your-own/white-label.md @@ -0,0 +1,69 @@ +--- +title: "White label" +sidebar_position: 3 +--- + +We've made it easy to white label the mobile app and to replace and override the assets used, however, you have to [Build Your Own App](/developers/contribute/more-info/mobile/build-your-own) from source. + +If you look at the [Project Folder Structure](/developers/contribute/more-info/mobile/developer-setup/structure), you'll see that there is an assets folder containing a base folder with assets provided by Mattermost. These include localization files and images as well as a release folder that optionally contains the icons and the splash screen of the app when building in release mode. + +To replace these with your own assets, create a sub-directory called `override` in the `assets` folder. The assets that you add using the same directory structure and file names as in the `base` directory, will be used instead of the original ones. + +### Localization strings + +To replace these with your own assets, create a sub-directory called `override` in the `assets` folder. Using the same directory structure and file names as in the `base` directory, you can add assets to the override folder to be used instead. + +For example, to override `assets/base/images/logo.png` you would replace your own `logo.png` file in `assets/override/images/logo.png`. + +### Images + +To replace an image, copy the image to `assets/override/images/` with the same location and file name as in the `base` folder. + +--- + + +Make sure the images have the same height, width, and DPI as the images that you are overriding. + + + +--- + +### App splash screen and launch icons + +In the `assets` directory you will find a folder named `assets/base/release` which contains an `icons` folder and a `splash_screen` folder under each platform directory. + +Copy the full `release` directory under `assets/override/release` and then replace each image with the same name. Make sure you replace all the icon images for the platform you are building the app - the same applies to the splash screen. + +The splash screen's background color is white by default and the image is centered. If you need to change the color or the layout to improve the experience of your new splash screen make sure that you also override the file `launch_screen.xml` for Android and `LaunchScreen.storyboard` for iOS. Both can be found under `assets/base/release/splash_screen//`. + +Splash screen and launch icons assets are replaced at build time when the environment variable `REPLACE_ASSETS` is set to true (default is false). + +--- + + +Make sure the images have the same height, width, and DPI as the images that you are overriding. + + + +--- + +### Configuration + +The `config.json` file handles custom configuration for the app for settings that cannot be controlled by the Mattermost server. Like with localization strings, create a `config.json` file under `assets/override` and just include the keys and values that you wish to change that are present in `assets/base/config.json`. + +For example, if you want the app to automatically provide a server URL and skip the screen to input it, you would add the following to `assets/override/config.json`: + +```json +{ + "DefaultServerUrl": "http://192.168.0.13:8065", + "AutoSelectServerUrl": true +} +``` +--- + + +The above key/value pairs are taken from the original `config.json` file. Since we don’t need to change anything else, we only included these two settings. + + + +--- diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/dependecies.md b/docs/develop/contribute/more-info/mobile/developer-setup/dependecies.md new file mode 100644 index 000000000000..8e68467df480 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/developer-setup/dependecies.md @@ -0,0 +1,31 @@ +--- +title: "Add new dependencies" +sidebar_position: 4 +--- + +If you need to add a new dependency to the project, it is important to add them in the right way. Instructions for adding different types of dependencies are described below. + +#### JavaScript only + +If you need to add a new JavaScript dependency that is not related to React Native, **use npm, not yarn**. Be sure to save the exact version number to avoid conflicts in the future. + +```sh +$ npm i --save-exact +``` + +If the dependency is only for development +```sh +$ npm i --save-exact --save-dev +``` + +#### React Native + +As with [JavaScript only](#javascript-only), **use npm** to add your dependency and include an exact version. + +If the library contains iOS native code, make sure to run: + +```sh +$ npm run pod-install +``` + +Most of the time linking the library to React Native is done automatically, but at times some libraries need to be manually linked. In this case follow the library's documentation. diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/index.md b/docs/develop/contribute/more-info/mobile/developer-setup/index.md new file mode 100644 index 000000000000..79b20e1833d7 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/developer-setup/index.md @@ -0,0 +1,259 @@ +--- +title: "Developer setup" +sidebar_position: 1 +--- + +The following instructions apply to the mobile apps for iOS and Android built in React Native. +Download the iOS version [here](https://apps.apple.com/us/app/mattermost/id1257222717) and the Android version [here](https://play.google.com/store/apps/details?id=com.mattermost.rn). +Source code can be found at the [GitHub Mattermost Mobile app repository](https://github.com/mattermost/mattermost-mobile). + +If you run into any issues getting your environment set up, check the [Troubleshooting](https://docs.mattermost.com/deploy/mobile-troubleshoot.html) section of the product docs for common solutions. + + + +A macOS computer is required to build the Mattermost iOS mobile app. + + + + + +Version 17 of the Java SE Development Kit (JDK) is required to develop the Mattermost Android mobile app. You can download the latest OpenJDK release of Java from Oracle, for free, under an open source license. + + + +## Environment setup + +The following instructions apply to both iOS and Android mobile apps. +On macOS, we recommend using [Homebrew](https://brew.sh) as a package manager. + +### Install NodeJS and NPM + +We recommend using NodeJS v22 and npm v10. Many of our team use [nvm](https://github.com/nvm-sh/nvm) to manage npm and NodeJS versions. + + + +To install [NVM](https://github.com/nvm-sh/nvm), follow [these instructions](https://github.com/nvm-sh/nvm#installing-and-updating). + +After installing, follow the post-install steps shown by the installer to add the necessary lines to your shell profile (for example `~/.zshrc` or `~/.bash_profile`). Then open a new terminal and run: + +```sh +nvm install --lts +``` + + + +There are three available options for installing NodeJS on Linux: + +- Using NVM by following the instructions [here](https://github.com/nvm-sh/nvm#install-script). +- Install using your distribution's package manager. +- Download and install the package from the [NodeJS website](https://nodejs.org/en). + + +The version of NodeJS that your distribution's package manager supports may not be the recommended version to build Mattermost mobile apps. +Please make sure that NodeJS installed by the package manager is at the recommended version. + + + + +### Install Watchman + +[Watchman](https://facebook.github.io/watchman) is a file watching program. +When a file changes, Watchman triggers an action, such as re-running a build command if a source file has changed. + +The minimum required version of Watchman is 4.9.0. + + + +To install Watchman using Homebrew, open a terminal and execute: + +```sh +brew install watchman +``` + + + +Download the latest package from [here](https://github.com/facebook/watchman/releases). + + +Note that you need to increase your `inotify` limits for Watchman to work properly. + + + + +### Install `react-native-cli` tools + +```sh +npm -g install react-native-cli +``` + +### Install Git + + + +To install Git using Homebrew, open a terminal and execute: + +```sh +brew install git +``` + + + +Some distributions come with Git preinstalled but you'll most likely have to install it yourself. For most distributions the package is simply called `git`. + + + +## Additional setup for iOS (macOS) + +### Install XCode + +Install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?ls=1&mt=12) to build and run the app on iOS. The minimum required version is 11.0. + +### Install Ruby + +A version of Ruby is automatically installed on macOS, but Mattermost React Native app development requires Ruby 3.2.0. You can check the current version of Ruby by running the following command. +```sh +ruby --version +``` + +If it isn't, we recommend using [Ruby Version Manager](https://rvm.io) or your preferred package manager to install the required version. The steps below are for using RVM. + +1. Install the GPG keys for RVM using the command found [here](https://rvm.io/rvm/install#install-gpg-keys). + 1. If you don't have the `gpg` command, you can install it using Homebrew by running. + ```sh + brew install gnupg + ``` +2. Install the stable version of RVM using the following command. + ```sh + \curl -sSL https://get.rvm.io | bash -s stable --ruby + ``` +3. To load RVM, either open a new terminal or run the following command. + ```sh + source ~/.rvm/scripts/rvm + ``` +4. Install the required version of Ruby + ```sh + rvm install 3.2.0 + ``` +5. (Optional) If you don't need to use a different version of Ruby for anything else, you'll want to change the default version of Ruby. Without this, you'll need to run `rvm use 3.2.0` any time you want to work on the mobile app. + ```sh + rvm alias create default 3.2.0 + ``` + +## Additional setup for Android + +### Download and install Android Studio or Android SDK CLI tools + +Download and install the [Android Studio app or the Android SDK command line tools](https://developer.android.com/studio/index.html#downloads) + + + +This documentation assumes you chose the default path for your Android SDK installation. If you chose a different path, adjust the environment variables below accordingly. + + + +#### Environment variables + +Make sure you have the following environment variables configured for your platform: + + + +- Set `ANDROID_HOME` to where Android SDK is located (likely `/Users//Library/Android/sdk` or `/home//Android/Sdk`) +- Make sure your `PATH` includes `ANDROID_HOME/tools` and `ANDROID_HOME/platform-tools` + + + +On Mac, this usually requires adding the following lines to your `~/.bash_profile` file: + +```sh +export ANDROID_HOME=$HOME/Library/Android/sdk +export PATH=$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH +``` + +Then reload your bash configuration: + +```sh +source ~/.bash_profile +``` + + + +Depending on the shell you're using, this might need to be put into a different file such as `~/.zshrc`. Adjust this accordingly. + + + + +On Linux the home folder is located under `/home/` which results in a slightly different path: + +```sh +export ANDROID_HOME=/home//Android/Sdk +export PATH=$ANDROID_HOME/platform-tools:$PATH +export PATH=$ANDROID_HOME/tools:$PATH +``` + +Then reload your configuration + +```sh +source ~/.bash_profile +``` + + + +Depending on the shell you're using, this might need to be put into a different file such as `~/.zshrc`. Adjust this accordingly. + + + + +### Install the SDKs and SDK tools + +In the SDK Manager using Android Studio or the [Android SDK command line tool](https://developer.android.com/studio/command-line/sdkmanager.html), ensure the following are installed: + +- SDK Tools (you may have to select **Show Package Details** to expand packages): + - Android SDK Build-Tools 31 + - Android Emulator + - Android SDK Platform-Tools + - Android SDK Tools + - Google Play services + - Intel x86 Emulator Accelerator (HAXM installer) + - Support Repository + - Android Support Repository + - Google Repository + + ![image](sdk_tools.png) + +- SDK Platforms (you may have to select **Show Package Details** to expand packages) + - Android 12 or above + - Google APIs + - SDK Platform + - Android SDK Platform 31 or above + - Intel or Google Play Intel x86 Atom\_64 System Image + - Any other API version that you want to test + + ![image](sdk_platforms.png) + +## Obtain the source code + +In order to develop and build the Mattermost mobile apps, you'll need to get a copy of the source code. Forking the `mattermost-mobile` repository will also make it easy to contribute your work back to the project in the future. + +1. Fork the [mattermost-mobile](https://github.com/mattermost/mattermost-mobile) repository on GitHub. + +2. Clone your fork locally: + + a. Open a terminal + + b. Change to a directory you want to hold your local copy + + c. Run `git clone https://github.com//mattermost-mobile.git` if you want to use HTTPS, or `git clone git@github.com:/mattermost-mobile.git` if you want to use SSH + + + +`` refers to the username or organization in GitHub that forked the repository + + + +3. Change the directory to `mattermost-mobile`. + + ```sh + cd mattermost-mobile + ``` + +4. Install the project dependencies with `npm install` diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/run/index.md b/docs/develop/contribute/more-info/mobile/developer-setup/run/index.md new file mode 100644 index 000000000000..89d6ec774611 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/developer-setup/run/index.md @@ -0,0 +1,123 @@ +--- +title: "Run the mobile app" +sidebar_position: 2 +--- + +We provide a set of scripts to help you run the app for the different platforms that are executed with `npm`: + +* **npm start**: Start the React Native packager. The packager has to be running in order to build the JavaScript code that powers the app. +* **npm run android**: Compile and run the mobile app on Android. +* **npm run ios**: Compile and run the mobile app on iOS. + + + +To speed up development, only compile and run the apps in the following cases: +- You have not deployed the app to a device or simulator with the `npm run ` command. +- There have been changes in the native code. +- A new library has been added or updated that has native code. + +If none of the above cases apply, you could just simply start the React Native packager with `npm start` and launch the app you have already deployed to the device or simulator. + + + +The above commands are shortcuts for the `react-native` CLI. You can append `-- --help` to the above commands to see available options, for example: + +```sh +npm run android -- --help +``` + +Make sure you are adding `--` before the options you want to include or run the `react-native` CLI directly: + +```sh +npx react-native run-android --help +``` + +## Run on a device + +By default, running the app will launch an Android emulator (if you created one) or an iOS simulator. + +If you want to test the performance of the app or if you want to make a contribution it is always a good idea to run the app on an actual device. +This will let you ensure that the app is working correctly and in a performant way before submitting a pull request. + + + +To be able to run the app on an Android device you'll need to follow these steps: + +1. **Enable debugging over USB** + + Most Android devices can only install and run apps downloaded from Google Play by default. In order to be able to install the Mattermost Mobile app in the device during development you will need to enable USB Debugging on your device in the **Developer options** menu by going to **Settings > About phone** and then tap the Build number row at the bottom seven times, then go back to **Settings > Developer options** and enable **USB debugging**. + +2. **Plug in your device via USB** + + Plug in your Android device in any available USB port in your development machine (try to avoid hubs and plug it directly into your computer) and check that your device is properly connecting to ADB (Android Debug Bridge) by running `adb devices`. + + ``` + $ adb devices + List of devices attached + 42006fb3e4fb25b8 device + ``` + + If you see **device** in the right column that means that the device is connected. You can have multiple devices attached and the app will be deployed to **all of them**. + +3. **Compile and run** + + With your device connected to the USB port execute the following in your command prompt to install and launch the app on the device: + + ```sh + npm run android + ``` + + + +If you don't see a bar at the top loading the JavaScript code then it's possible that the device is not connected to the development server. See [Using adb reverse](http://reactnative.dev/docs/running-on-device.html#method-1-using-adb-reverse-recommended). + + + + +To be able to run the app on an iOS device you'll need to have [Xcode](https://developer.apple.com/xcode/) installed on a Mac computer and follow this steps: + +1. **Get an Apple Developer account** + + The apps that run on an iOS device must be signed. To sign it, you'll need a set of provisioning profiles. If you already have an Apple Developer account enrolled in the Apple Developer program you can skip this step. If you don't have an account yet you'll need to [create one](https://appleid.apple.com/account?appId=632&returnUrl=https%3A%2F%2Fdeveloper.apple.com%2Faccount%2F#!&page=create) and enroll in the [Apple Developer Program](https://developer.apple.com/programs/). + +2. **Open the project in Xcode** + + Navigate to the `ios` folder in your `mattermost-mobile` project, then open the file `Mattermost.xcworkspace` in Xcode. + +3. **Configure code signing and capabilities** + + Select the **Mattermost** project in the Xcode Project Navigator, then select the **Mattermost** target. Look for the **Signing & Capabilities** tab. + + - Go to the **Signing** section and make sure your Apple developer account or team is selected under the Team dropdown and change the [Bundle Identifier](https://developer.apple.com/documentation/appstoreconnectapi/bundle_ids). + Xcode will register your provisioning profiles in your account for the Bundle Identifier you've entered if it doesn't exist. + - Go to the **App Groups** section and change the [App Groups](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups?language=objc). + Xcode will register your AppGroupId and update the provision profile. + - Go to the **iCloud** section and change the [Containers](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_icloud-container-identifiers?language=objc). + Xcode will register your iCloud container and update the provision profile. + - Go to the **Keychain Sharing** section and change the [Keychain Groups](https://developer.apple.com/documentation/bundleresources/entitlements/keychain-access-groups?language=objc). + Xcode will register your Keychain access groups and update the provision profile. + + + +Repeat the steps for the `MattermostShare` and `NotificationService` targets. Each target must use a **different** *Bundle Identifier*. + + + +4. **Compile and run** + + Plug in your iOS device in any available USB port in your development computer. + + If everything is set up correctly, your device will be listed as the build target in the Xcode toolbar, and it will also appear in the Devices Pane (2). You can press the **Build and run** button (R) or select **Run** from the Product menu to run the app. + + ![image](running_ios.png) + + As an alternative you can select the targeted device by opening the **Product** menu in Xcode menu bar, then go to **Destination** and look for your device to select from the list. + + + +If you run into any issues, please take a look at Apple's [Launching Your App on a Device](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/LaunchingYourApponDevices/LaunchingYourApponDevices.html#//apple_ref/doc/uid/TP40012582-CH27-SW4) documentation. +If the app fails to build, go to the **Product** menu and select **Clean Build Folder** before trying to build the app again. +Also, be sure that your iOS device is trusted so app deployments can proceed. + + + diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/run/running_ios.png b/docs/develop/contribute/more-info/mobile/developer-setup/run/running_ios.png new file mode 100644 index 000000000000..7551791a2b72 Binary files /dev/null and b/docs/develop/contribute/more-info/mobile/developer-setup/run/running_ios.png differ diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/sdk_platforms.png b/docs/develop/contribute/more-info/mobile/developer-setup/sdk_platforms.png new file mode 100644 index 000000000000..0bf01e5cfc4b Binary files /dev/null and b/docs/develop/contribute/more-info/mobile/developer-setup/sdk_platforms.png differ diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/sdk_tools.png b/docs/develop/contribute/more-info/mobile/developer-setup/sdk_tools.png new file mode 100644 index 000000000000..85e2a2591774 Binary files /dev/null and b/docs/develop/contribute/more-info/mobile/developer-setup/sdk_tools.png differ diff --git a/docs/develop/contribute/more-info/mobile/developer-setup/structure.md b/docs/develop/contribute/more-info/mobile/developer-setup/structure.md new file mode 100644 index 000000000000..ac883ef8c92f --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/developer-setup/structure.md @@ -0,0 +1,56 @@ +--- +title: "Folder structure" +sidebar_position: 1 +--- +The following is an overview of the Mobile app repository file structure: + +```goat +| ++-- .circleci # Circle CI workflow to build the apps ++-- .github # GitHub actions ++-- .husky ++-- android # Android specific code ++-- app # React Native code +| | +| +-- actions +| +-- client +| +-- components +| +-- constants +| +-- context +| +-- database +| +-- helpers +| +-- hooks +| +-- i18n +| +-- init +| +-- managers +| +-- notifications +| +-- products +| +-- queries +| +-- screens +| +-- store +| +-- utils +| ++-- assets +| | +| +-- base +| | | +| | +-- i18n +| | +-- images +| | +-- release +| +-- fonts +| ++-- build +| | +| +-- notice-file +| ++-- detox ++-- docs ++-- eslint ++-- fastlane # Fastlane scripts to build the app ++-- ios # iOS specific code ++-- patches # Patches for various dependencies ++-- scripts ++-- share_extension # Android's share extension app ++-- test ++-- types +``` diff --git a/docs/develop/contribute/more-info/mobile/e2e.md b/docs/develop/contribute/more-info/mobile/e2e.md new file mode 100644 index 000000000000..40777cc7304c --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/e2e.md @@ -0,0 +1,148 @@ +--- +title: "Mobile End-to-End (E2E) Tests" +sidebar_position: 5 +--- + +This page describes how to write and run End-to-End (E2E) testing for Mobile Apps for both iOS and Android. Mobile products use [Detox](https://github.com/wix/Detox), which is a "gray box end-to-end testing and automation library for mobile apps." See its [documentation](https://github.com/wix/Detox/tree/master/docs) to learn more. + +### File Structure + +The folder structure is as follows: +``` +|-- detox + |-- e2e + |-- support + |-- test + |-- config.json + |-- environment.js + |-- init.js + |-- .babelrc + |-- .detoxrc.json + |-- package-lock.json + |-- package.json +``` + +* `/detox/e2e/support` is the support folder, which is a place to put reusable behavior such as Server API and UI commands, or global overrides that should be available to all test files. +* `/detox/e2e/test`: To start writing tests, create a new file (e.g. `login.e2e.js`) in the `/detox/e2e/test` folder. + - The subfolder naming convention depends on the test grouping, which is usually based on the general functional area (e.g. `/detox/e2e/test/messaging/` for "Messaging"). + - Test cases that require an Enterprise license should fall under `/detox/e2e/test/enterprise/`. This is to easily identify license requirements, both during local development and production testing for Enterprise features. +* `/detox/.detoxrc.json`: for Detox configuration. +* `/detox/package.json` : for all dependencies related to Detox end-to-end testing. + +### Writing an E2E Test +This process has many similarities to [writing an E2E test for the mattermost-webapp project](/developers/contribute/more-info/webapp/e2e-testing). +Before writing a script, ensure that it has a corresponding test case in Zephyr. All test cases may be found in this [link](https://mattermost.atlassian.net/projects/MM?selectedItem=com.atlassian.plugins.atlassian-connect-plugin%3Acom.kanoah.test-manager__main-project-page#!/design?projectId=10302). If test case is not available, feel free to prompt the QA team who will either search from an existing Zephyr entry or if it's a new one, it will be created for you. + +1. Create a test file based on the file structure aforementioned above. +2. Include Zephyr identification (ID) and title in the test description, following the format of `it('[Zephyr_id] [title]')` or `it('[Zephyr_id]_[step] [title]')` if the test case has multiple steps. For test case "[MM-T109 RN apps: User can't send the same message repeatedly](https://mattermost.atlassian.net/projects/MM?selectedItem=com.atlassian.plugins.atlassian-connect-plugin%3Acom.kanoah.test-manager__main-project-page#!/testCase/MM-T109)", it should be: + ```javascript + describe('Messaging', () => { + it('MM-T109 User can\'t send the same message repeatedly', () => { + // Test steps and assertion here + } + } + ``` +4. Target an element using available matchers. For best results, it is recommended to match elements by unique identifiers using `testID`. The identifier should follow the following format to avoid duplication, `...`, where: + + +Not all fields are required. When assigning a `testID`, carefully inspect the actual render structure and pick up the minimum fields combination to create a unique value. Some examples include: `send.button` and `post.`. + + + +```text +* `location` - can be a parent component, a main section, or a UI screen. +* `modifier` - adds meaning to the `element`. +* `element` - common terms like `button`, `text_input`, `image`, and the like. +* `identifier` - could be unique ID of a post, channel, team or user, or a number to represent order. +``` + +5. Prefix each comment line with appropriate indicator. Each line in a multi-line comment should be prefixed accordingly. Separate and group test step comments and assertion comments for better readability. + - `#` indicates a test step (e.g. `// # Go to a screen`) + - `*` indicates an assertion (e.g. `// * Check the title`) +6. Simulate user interaction using available actions, and verify user interface (UI) expectations using `expect`. When using `action`, `match`, or another API specific to a particular platform, verify that the equivalent logic is applied so that the API does not impact other platforms. Always run tests in applicable platforms. + +### Running E2E Tests +#### Testing Android Locally +##### Local setup + +1. Install the latest Android SDK: + + ``` + sdkmanager "system-images;android-30;google_apis;x86" + sdkmanager --licenses + ``` +2. Create the emulator using `npm run e2e:android-create-emulator` from the `/detox` folder. Android testing requires an emulator named `detox_pixel_4_xl_api_30` and the script helps to create it automatically. + +##### Complete a test run in debug mode +This is the typical flow for local development and test writing: + +1. Open a terminal window and run react-native packager by `npm install && npm start` from the root folder. +2. Open a second terminal window and: + * Change directory to `/detox` folder. + * Install npm packages by `npm install`. + * Build the app together with the android test using `npm run e2e:android-build`. + * Run the test using `npm run e2e:android-test`. + * For running a single test, follow this example command: `npm run e2e:android-test -- connect_to_server.e2e.ts`. + +##### Complete a test run in release mode +This is the typical flow for CI test run: + +1. Build a release app by running `npm install && npm run e2e:android-build-release` from the `/detox` folder. +2. Run a test using `npm run e2e:android-test-release` from the `/detox` folder. + +#### Testing iOS Locally +##### Local setup + +1. Install [applesimutils](https://github.com/wix/AppleSimulatorUtils): + ``` + brew tap wix/brew + brew install applesimutils + ``` +2. Set XCode's build location so that the built app, especially debug, is expected at the project's location instead of the Library's folder which is unique/hashed. +3. Open XCode, then go to **XCode > Settings > Locations**. +4. Under **Derived Data**, click **Advanced...**. +5. Select **Custom > Relative to Workspace**, then set **Products** as **Build/Products**. +6. Click **Done** to save the changes. + +##### Complete a test run in debug mode + +1. In one terminal window, from the root folder run `npm run start` and on another `npm run ios` from the root folder. +2. Once the build is complete and installed, there will be a message informing of the path where the app is installed. Copy that path. Sample output: + ```log + info Building (using "xcodebuild -workspace Mattermost.xcworkspace -configuration Debug -scheme Mattermost -destination id=00008110-00040CA10263801E") + info Installing "/Users/myuser/Proyectos/mattermost-mobile/ios/Build/Products/Debug-iphonesimulator/Mattermost.app + info Launching "com.mattermost.rnbeta" + success Successfully launched the app + ``` +3. Edit `/detox/.detoxrc` and + - In **apps > ios.debug**, substitute `binaryPath` by that value. + - In **devices > ios.simulator > device**, substitute `type` and `os` with the values corresponding to the ones being used by the simulator. If unsure wich ones, either open the simulator or go to Xcode to see where it is being built. +4. Export the values for `ADMIN_USERNAME` and `ADMIN_PASSWORD` with the appropiate values for your test server. Check the Environment Variables section below to learn more about default values and other variables available. + ```sh + export SITE_1_URL="http://localhost:8065" + export ADMIN_USERNAME="sysadmin" + export ADMIN_PASSWORD="Sys@dmin-sample1" + ``` +5. In another terminal window, run `npm i` then `npm run e2e:ios-test` from the `/detox` folder. + * For running a single test, follow this example command: `npm run e2e:ios-test -- connect_to_server.e2e.ts`. + ```sh + cd detox + npm i + npm run e2e:ios-test + ``` + +##### Complete a test run in release mode + +1. Build the release app by running `npm run build:ios-sim` from the root folder or `npm run e2e:ios-build-release` from within the `/detox` folder. +2. Run the test using `npm run e2e:ios-test-release` from the `/detox` folder. + +#### Environment variables +Test configurations are [defined at test_config.js](https://github.com/mattermost/mattermost-mobile/blob/master/detox/e2e/support/test_config.js) and environment variables are used to override default values. In most cases you don't need to change the values, because it makes use of the default local developer setup. If you do need to make changes, you may override by exporting, e.g. `export SITE_URL=`. + +| Variable | Description | +|----------------|---------------------------------------------------------------------------------------------------------------------| +| SITE_URL | Host of test server.

*Default*: `http://localhost:8065` for iOS or `http://10.0.2.2:8065` for Android. | +| ADMIN_USERNAME | Admin's username for the test server.

*Default*: `sysadmin` when server is seeded by `make test-data`. | +| ADMIN_PASSWORD | Admin's password for the test server.

*Default*: `Sys@dmin-sample1` when server is seeded by `make test-data`. | +| LDAP_SERVER | Host of LDAP server.

*Default*: `localhost` | +| LDAP_PORT | Port of LDAP server.

*Default*: `389` | diff --git a/docs/develop/contribute/more-info/mobile/index.md b/docs/develop/contribute/more-info/mobile/index.md new file mode 100644 index 000000000000..e6b90ea48f09 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/index.md @@ -0,0 +1,25 @@ +--- +title: "Mobile apps" +sidebar_position: 4 +--- + +The Mattermost mobile apps are written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) using [React Native](https://facebook.github.io/react-native/). + +## Repository +Further explanation of the file structure can be found in [the Developer Setup](/developers/contribute/more-info/mobile/developer-setup/structure). For more information about E2E testing on the Android and iOS apps, check out [Mobile End-to-End (E2E) tests](/developers/contribute/more-info/mobile/e2e) + +## Mobile app contributor resources + - [GitHub Repository](https://github.com/mattermost/mattermost-mobile) - Get the code, report issues, or submit PRs. + - [Running the app](/developers/contribute/more-info/mobile/developer-setup/run) - Compile recommendations. + - [Channel](https://community.mattermost.com/core/channels/native-mobile-apps) - Use the channel to interact with other Mattermost Mobile developers. + - [Help Wanted](https://mattermost.com/pl/help-wanted-mattermost-mobile) - Find help wanted tickets here. + +### Android specific documentation + - [Build guide](/developers/contribute/more-info/mobile/build-your-own/android) + - [Push Notifications](/developers/contribute/more-info/mobile/push-notifications/android) + - [Sign Unsigned Builds](/developers/contribute/more-info/mobile/unsigned/android) + +### iOS specific documentation + - [Build guide](/developers/contribute/more-info/mobile/build-your-own/ios) + - [Push Notifications](/developers/contribute/more-info/mobile/push-notifications/ios) + - [Sign Unsigned Builds](/developers/contribute/more-info/mobile/unsigned/ios) diff --git a/docs/develop/contribute/more-info/mobile/push-notifications/android.md b/docs/develop/contribute/more-info/mobile/push-notifications/android.md new file mode 100644 index 000000000000..0cd76ee6ead0 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/push-notifications/android.md @@ -0,0 +1,42 @@ +--- +title: "Android push notifications" +sidebar_position: 1 +--- + +Push notifications on Android are managed and dispatched using [Firebase Cloud Messaging (FCM)](http://firebase.google.com/docs/cloud-messaging/) + +- Create a Firebase project within the [Firebase Console](https://console.firebase.google.com). + +- Click **Add Project** + ![image](/img/mobile/firebase_console.png) + +- Enter the project name, project ID and Country + +- Click **CREATE PROJECT** + + ![image](/img/mobile/firebase_project.png) + +Once the project is created you'll be redirected to the Firebase project +dashboard + +![image](/img/mobile/firebase_dashboard.png) + +- Click **Add Firebase to your Android App** +- Enter the package ID of your custom Mattermost app as the **Android package name**. +- Enter an **App nickname** so you can identify it with ease +- Click **REGISTER APP** +- Once the app has been registered, download the **google-services.json** file which will be used later + +- Click **CONTINUE** and then **FINISH** + ![image](/img/mobile/firebase_register_app.png) + ![image](/img/mobile/firebase_google_services.png) + ![image](/img/mobile/firebase_sdk.png) + +Now that you have created the Firebase project and the app and +downloaded the *google-services.json* file, you need to make some +changes in the project. + +- Replace `android/app/google-services.json` with the one you downloaded earlier + +At this point, you can build the Mattermost app for Android and setup the [Mattermost Push Notification Service](/developers/contribute/more-info/mobile/push-notifications/service). + diff --git a/docs/develop/contribute/more-info/mobile/push-notifications/corporate-proxy.md b/docs/develop/contribute/more-info/mobile/push-notifications/corporate-proxy.md new file mode 100644 index 000000000000..a5311226d993 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/push-notifications/corporate-proxy.md @@ -0,0 +1,33 @@ +--- +title: "Corporate proxy" +sidebar_position: 4 +--- + +When your IT policy requires a corporate proxy to scan and audit all outbound traffic the following options are available: + +###### 1. Deploy Mattermost with connection restricted post-proxy relay in DMZ or a trusted cloud environment + +Some legacy corporate proxy configurations may be incompatible with the requirements of modern mobile architectures, such as the requirement of HTTP/2 requests from Apple to send push notifications to iOS devices. + +In this case, a **post-proxy relay** (which accepts network traffic from a corporate proxy such as NGINX, and transmits it to the final destination) can be deployed to take messages from the Mattermost server passing through your corporate IT proxy in the incompatible format, e.g. HTTP/1.1, transform it to HTTP/2 and relay it to its final destination, either to the [Apple Push Notification Service (APNS)](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1) and [Google Fire Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) services. + +The **post-proxy relay** [can be configured using the Mattermost Push Proxy installation guide](/developers/contribute/more-info/mobile/push-notifications/service) with connection restrictions to meet your custom security and compliance requirements. + +You can also host in a trusted cloud environment such as AWS or Azure in place of a DMZ (this option may depend on your organization's internal policies). + +![image](/img/mobile/post-proxy-relay.png) + +###### 2. Whitelist Mattermost push notification proxy to bypass your corporate proxy server + +Depending on your internal IT policy and approved waivers/exceptions, you may choose to deploy the [Mattermost Push Proxy](/developers/contribute/more-info/mobile/push-notifications/service) to connect directly to [Apple Push Notification Service (APNS)](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1) without your corporate proxy. + +You will need to [whitelist one subdomain and one port from Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1) for this option: + + - Development server: `api.development.push.apple.com:443` + - Production server: `api.push.apple.com:443` + +###### 3. Run App Store versions of the Mattermost mobile apps + +You can use the mobile applications hosted by Mattermost in the [Apple App Store](https://apps.apple.com/ca/app/mattermost/id1257222717) or [Google Play Store](https://play.google.com/store/apps/details?id=com.mattermost.rn) and connect with [Mattermost Hosted Push Notification Service (HPNS)](https://docs.mattermost.com/deploy/mobile-hpns.html) through your corporate proxy. + +The use of hosted applications by Mattermost [can be deployed with Enterprise Mobility Management solutions via AppConfig](https://docs.mattermost.com/deploy/mobile-appconfig.html). Wrapping is not supported with this option. diff --git a/docs/develop/contribute/more-info/mobile/push-notifications/index.md b/docs/develop/contribute/more-info/mobile/push-notifications/index.md new file mode 100644 index 000000000000..40d4486c8193 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/push-notifications/index.md @@ -0,0 +1,13 @@ +--- +title: "Set up push notifications" +sidebar_position: 3 +--- + +When building a custom version of the Mattermost mobile app, you will also need to host your own [Mattermost Push Notification Service](https://github.com/mattermost/mattermost-push-proxy/releases) and make a few modifications to your Mattermost mobile app to be able to get push notifications. + +1. Setup the custom mobile apps to receive push notifications + - [Android](/developers/contribute/more-info/mobile/push-notifications/android) + - [iOS](/developers/contribute/more-info/mobile/push-notifications/ios) +2. [Setup the Mattermost push notification service](/developers/contribute/more-info/mobile/push-notifications/service) + +If the use of a proxy server is required by your IT policy, see the [corporate proxy](/corporate-proxy) page. diff --git a/docs/develop/contribute/more-info/mobile/push-notifications/ios.md b/docs/develop/contribute/more-info/mobile/push-notifications/ios.md new file mode 100644 index 000000000000..deb4317ea7ad --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/push-notifications/ios.md @@ -0,0 +1,50 @@ +--- +title: "iOS push notifications" +sidebar_position: 2 +--- + +## Generate APNs Auth Key + +To deliver push notifications on iOS, you need to authenticate with **Apple Push Notification service (APNs)**. +Mattermost recommends using **token-based authentication** with an APNs Auth Key (`.p8`) instead of certificates. + +--- + +### Prerequisites + +- Apple Developer Program account +- Registered iOS app Bundle ID with **Push Notifications** capability enabled + +--- + +### 1. Create an APNs Auth Key + +1. Sign in to [Apple Developer: Keys](https://developer.apple.com/account/resources/authkeys/list). +2. Click **+** to register a new key. + ![Apple Developer register new key](/img/mobile/ios-register-key.png) +3. **Enter a Key Name** to easily identify it later (e.g., *Mattermost Push Proxy*). + ![Enter key name](/img/mobile/ios-key-name.png) +4. **Enable APNs** by checking the **Apple Push Notifications service (APNs)** box and click **Configure** to configure the key. + ![Enable APNs](/img/mobile/ios-enable-apns.png) +5. On the **Configure Key** screen: + - Select an **Environment**: *Sandbox*, *Production*, or *Sandbox & Production*. + - Choose a **Key Restriction**: *Team Scoped (All Topics)* or *Topic Specific*. + ![Configure APNs key](/img/mobile/ios-configure-apns.png) + - If you select *Topic Specific*, add the topics (App IDs) you want to associate. + ![Add topics](/img/mobile/ios-add-topics.png) +6. Click **Save**, then **Continue**. +7. Review the Key details and click **Register**. +8. Download the generated file `AuthKey_XXXXXXXXXX.p8` and store it securely. + > You can only download the file once. +9. Note the following values: + - **Key ID** (from the Keys list) + - **Team ID** (from your Apple Developer Membership) + - **Bundle ID** (your app identifier, used as the APNs topic) + +![Apple Developer key list](/img/mobile/ios-key-list.png) + +--- + +### 2. Next Steps + +Once you’ve generated your APNs Auth Key and collected the Key ID, Team ID, and Bundle ID, continue to the [Push Notification Service setup](/developers/contribute/more-info/mobile/push-notifications/service) page to configure the Mattermost Push Notification Service (MPNS). diff --git a/docs/develop/contribute/more-info/mobile/push-notifications/service.md b/docs/develop/contribute/more-info/mobile/push-notifications/service.md new file mode 100644 index 000000000000..0a6dbcac7648 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/push-notifications/service.md @@ -0,0 +1,174 @@ +--- +title: "Push notification service" +sidebar_position: 3 +--- + +Now that the app can receive push notifications, we need to make sure that the Mattermost Push Notification Service is able to send the notification to the device. This guide will focus on installing and configuring the push notification service. + +### Requirements + +- A Linux or FreeBSD box server with at least 1GB of memory. +- A copy of the [Mattermost Push Notification Service](https://github.com/mattermost/mattermost-push-proxy/releases). +- [Custom Android and/or iOS](/developers/contribute/more-info/mobile/build-your-own) Mattermost mobile apps. +- An APNs Auth Key (`.p8`) obtained by following the [iOS Push Notifications guide](/developers/contribute/more-info/mobile/push-notifications/ios). +- A Firebase Cloud Messaging Server key obtained by following the [Android Push Notifications guide](/developers/contribute/more-info/mobile/push-notifications/android). + +## Install and upgrade + +For the sake of making this guide simple we located the files at `/home/ubuntu/mattermost-push-proxy`. We've also elected to run the Push Notification Service as the `ubuntu` account for simplicity. We **recommend** setting up and running the service under a `mattermost-push-proxy` user account with limited permissions. + +1. Download the latest Mattermost Push Notification Service: + + `wget https://github.com/mattermost/mattermost-push-proxy/releases/download/vX.X.X/mattermost-push-proxy-linux-amd64.tar.gz` + or + `wget https://github.com/mattermost/mattermost-push-proxy/releases/download/vX.X.X/mattermost-push-proxy-freebsd-amd64.tar.gz` + +```text +In this command, `vX.X.X` refers to the release version you want to download. See [Mattermost Push Notification Service releases](https://github.com/mattermost/mattermost-push-proxy/releases). +``` + +2. If you're upgrading a previous version of the Mattermost Push Notification Service make sure to back up your `mattermost-push-proxy.json` file before continuing. + +3. Unzip the downloaded Mattermost Push Notification Service using: + `tar -xvzf mattermost-push-proxy-linux-amd64.tar.gz` + or + `tar -xvzf mattermost-push-proxy-freebsd-amd64.tar.gz` + +4. Configure the Mattermost Push Notification service by editing the `mattermost-push-proxy.json` file at `/home/ubuntu/mattermost-push-proxy/config`. Follow the steps in the [Android](#set-up-mattermost-push-notification-service-to-send-android-push-notifications) + and [iOS](#set-up-mattermost-push-notification-service-to-send-ios-push-notifications) sections to replace the values in the config file. + +5. Create a systemd unit file to manage the Mattermost Push Notification Services with systemd and log all output of the service to `/var/log/syslog` by running this command as root. + ```bash + echo "[Unit] + Description=Mattermost Push Notification Service + + [Service] + Type=oneshot + ExecStart=/bin/sh -c '/home/ubuntu/mattermost-push-proxy/bin/mattermost-push-proxy | logger' + WorkingDirectory=/home/ubuntu/mattermost-push-proxy + + [Install] + WantedBy=multi-user.target" >> /etc/systemd/system/mattermost-push-proxy.service + ``` + + To route the traffic through a separate proxy server, add `Environment="HTTP_PROXY="` under the `[Service]` section of the file. If you have an HTTPS server, then use `HTTPS_PROXY`. If you set both then `HTTPS_PROXY` will take higher priority than `HTTP_PROXY`. + +6. Start the service with `sudo systemctl start mattermost-push-proxy` or restart with `sudo systemctl restart mattermost-push-proxy`. Use `sudo systemctl enable mattermost-push-proxy` to have systemd start the service on boot. + +### Set up Mattermost push notification service to send Android push notifications + +- Go to the [Firebase Console](https://console.firebase.google.com) and select the project you've created. Once in the dashboard, go to the project settings and select **Service Accounts**. +![image](/img/mobile/firebase_settings.png) +![image](/img/mobile/firebase_cloud_messaging.png) + +- Click on **Generate new private key** and store the downloaded file. +![image](/img/mobile/firebase_server_key.png) + +- Open the **mattermost-push-proxy.json** file in the `mattermost-push-proxy/config` directory and look for the "ServiceFileLocation" entry under "AndroidPushSettings". Paste the location of the file as its value. + ``` + "ServiceFileLocation": "/path/to/downloaded_file" + ``` + +### Set up Mattermost push notification service to send iOS push notifications + +Instead of certificates, we now recommend using an **APNs Auth Key (`.p8`)** to authenticate with Apple Push Notification service (APNs). +If you haven’t generated your key yet, see [Generate an APNs Auth Key](/developers/contribute/more-info/mobile/push-notifications/ios). + +- Open the **mattermost-push-proxy.json** file under the `mattermost-push-proxy/config` directory and configure it with your key details: + + ```json + "ApplePushSettings":[ + { + "Type":"apple_rn", + "ApplePushUseDevelopment":true, + "ApplePushTopic":"your.bundle.id", + "AppleAuthKeyFile":"./config/beta/YourAuthKeyFile.p8", + "AppleAuthKeyID":"YourAuthKeyID", + "AppleTeamID":"YourAppleTeamID" + } + ], + ``` +- **ApplePushTopic**: Your app’s bundle ID (APNs topic). +- **AppleAuthKeyFile**: Path to the `.p8` file. +- **AppleAuthKeyID**: Key ID from Apple Developer portal. +- **AppleTeamID**: Team ID from Apple Developer Membership. +- **ApplePushUseDevelopment**: `true` for sandbox APNs, `false` for production. + + + +If you are migrating from certificate-based authentication, you can remove the `ApplePushCertPrivate` field and replace it with the new `AppleAuthKeyFile`, `AppleAuthKeyID`, and `AppleTeamID` values. + + + +### Configure the Mattermost Server to use the Mattermost push notification service + +- In your Mattermost instance, enable mobile push notifications. + * Go to **System Console > Notifications > Mobile Push**. + * Under **Send Push Notifications**, select **Manually enter Push Notification Service location**. + * Enter the location of your Mattermost Push Notification Service in the **Push Notification Server** field. + + ![image](/img/mobile/manual_mpns.png) + +- (Optional) Customize mobile push notification contents. + * Go to **System Console > Notifications > Mobile Push**. + * Select an option for **Push Notification Contents** to specify what type of information to include in the push notifications. + * Most deployments choose to include the full message snippet in push notifications unless they have policies against it to protect confidential information. + + ![image](/img/mobile/push_contents.png) + +- Finally, start your Mattermost Push Notification Service, and your app should start receiving push notifications. + +### Test the Mattermost push notification service + +* Verify that the server is functioning normally and test the push notification using curl: + `curl http://127.0.0.1:8066/api/v1/send_push -X POST -H "Content-Type: application/json" -d '{"type": "message", "message": "test", "badge": 1, "platform": "PLATFORM", "server_id": "MATTERMOST_DIAG_ID", "device_id": "DEVICE_ID", "channel_id": "CHANNEL_ID"}'` + + * Replace `MATTERMOST_DIAG_ID` with the value found by running the SQL query: + ```sql + SELECT * FROM Systems WHERE Name = 'DiagnosticId'; + ``` + * Replace `DEVICE_ID` with your device ID, which can be found using (where `your_email@example.com` is the email address of the user you are logged in as): + ```sql + SELECT + Email, DeviceId + FROM + Sessions, + Users + WHERE + Sessions.UserId = Users.Id + AND DeviceId != '' + AND Email = 'your_email@example.com'; + ``` + * Replace `CHANNEL_ID` with the Town Square channel ID, which can be found using: + ```sql + SELECT Id FROM Channels WHERE DisplayName = 'Town Square'; + ``` + + +Remove the `apple:`, `apple_rn`, `android:` or `android_rn:` prefix from your device ID before replacing `DEVICE_ID`. Use that prefix as the `PLATFORM` (make sure to remove the ":"). + + +* You can also verify push notifications are working by opening your Mattermost site and mentioning a user who has push notifications enabled in **Settings > Notifications > Mobile Push Notifications**. + +To view the log file, use: + +```bash +$ sudo tail -n 1000 /var/log/upstart/mattermost-push-proxy.log +``` + + +Note that device IDs can change somewhat frequently, as they are tied to a device session. If you're having trouble, double-check the latest device IDs by re-running the above queries. + + + +### Troubleshooting + +##### DeviceTokenNotForTopic + +**For iOS / Apple Push Notifications**: If the logs are reflecting DeviceTokenNotForTopic (error 400) this may be because you're using an older / previous Device ID. Re-run the queries you need to get device IDs and test. + +This could also be because you generated a key for the wrong bundle ID. The bundle ID used in `mattermost-push-proxy.json` should be the same one as the app, and should be for the same app it was generated for. + +### Reporting issues + +For issues with repro steps, please report to https://github.com/mattermost/mattermost/issues diff --git a/docs/develop/contribute/more-info/mobile/storybook.md b/docs/develop/contribute/more-info/mobile/storybook.md new file mode 100644 index 000000000000..df6ab540163c --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/storybook.md @@ -0,0 +1,19 @@ +--- +title: "Storybook" +sidebar_position: 6 +--- + +Storybook has been added to the `mobile` repository to help prototype components. To use Storybook: + +1. In the root of the repository, run `npm run storybook`. This step automatically scans and loads all stories, then opens a new browser tab with the Storybook interface. + + **Note**: When using a real device, you may need to configure the Storybook *Host URL* by updating the `.env` file in the root of the repository. When running in an emulator, the code tries to use the default network values. + +2. Run the usual `npm run android` (or `npm run ios`) and `npm start` commands. +3. Storybook has been integrated into the react-native dev menu. + - On Mac OS, press CMD+D to open the dev menu when your app is running in an iOS Simulator, or press CMD+M when running in an Android emulator. + - On Windows and Linux, press CTRL+M to open the dev menu, then select the "Storybook" option. + - If running on a real device, shaking the device brings up the react-native dev menu. You can also press `d` in the terminal window where you ran `npm start`. +4. The Storybook interface opens in the mobile app. The stories can be controlled either through the desktop browser Storybook UI or the mobile browser Storybook UI. Both will render the component on the device. + +>**Caveat**: Promises are currently broken in Storybook for react native. Components using promises will not work correctly. There is a temporary hacky fix to work around this issue: [storybookjs/react-native#57](https://github.com/storybookjs/react-native/issues/57#issuecomment-737931284). diff --git a/docs/develop/contribute/more-info/mobile/unsigned/android.md b/docs/develop/contribute/more-info/mobile/unsigned/android.md new file mode 100644 index 000000000000..752b81140699 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/unsigned/android.md @@ -0,0 +1,77 @@ +--- +title: "Sign unsigned Android builds" +sidebar_position: 1 +--- + +With every Mattermost mobile app release, we publish the Android unsigned apk in in the [GitHub Releases](https://github.com/mattermost/mattermost-mobile/releases) page. This guide describes the steps needed to modify and sign the app, so it can be distributed and installed on Android devices. + +#### Prerequisites + +1. [Apktool](https://ibotpeaches.github.io/Apktool/) is a tool for reverse engineering Android apk files. +2. [XMLStarlet](http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html) is a set of command line utilities (tools) which can be used to transform, query, validate, and edit XML documents and files using a simple set of shell commands in the same way it is done for plain text files using UNIX `grep`, `sed`, `awk`, `diff`, `patch`, `join`, etc., commands. +3. [JQ](https://stedolan.github.io/jq/) is like `sed` for JSON data - you can use it to slice, filter, map, and transform structured data with the same ease that `sed`, `awk`, and `grep` let you work with text. +4. Android SDK as described in the [Developer Setup](/developers/contribute/more-info/mobile/developer-setup#additional-setup-for-android). +5. Set up keys and Google Services as described in steps 2, 3, 4, and 6 of the [Build your own App guide](/developers/contribute/more-info/mobile/build-your-own/android#build-preparations). +6. [sign-android](/scripts/sign-android) script to sign the Android app. + +#### Sign tool + +```bash +Usage: sign-android + [-e|--extract path] + [-p|--package-id packageID] + [-g|--google-services path] + [-d|--display-name displayName] + outputApk +Usage: sign-android -h|--help +Options: + -e, --extract path (Optional) Path to extract the unsigned APK file. + By default the path of the unsigned APK is used. + + -p, --package-id packageID (Optional) Specify the unique Android application ID. + + -g, --google-services path (Optional) Path to the google-services.json file. + Will setup the Firebase to receive Push Notifications. + Warning: will apply only if packageID is set. + + -d, --display-name displayName (Optional) Specify new application display name. + By default "Mattermost" is used. + + -h, --help Display help message. +``` + +#### Sign the Mattermost Android app + +Now that all requirements are met, it's time to sign the Mattermost app for Android. Most of the options of the signing tool are optional but you should use your own `package identifier`, `google services settings`, and change the `display name`. + +* Create a folder that will serve as your working directory to store all the needed files. +* Download the [sign-android](/scripts/sign-android) script and save it in your working directory. +* Download the [Android unsigned build](https://github.com/mattermost/mattermost-mobile/releases) and save it in your working directory. +* Open a terminal to your working directory and make sure the `sign-android` script is executable. + + ``` + $ ls -la + total 49756 + drwxr-xr-x 4 user staff 128 Oct 2 08:12 . + drwx------@ 59 user staff 1888 Oct 1 14:12 .. + -rw-r--r-- 1 user staff 50685064 Sep 29 10:58 Mattermost-unsigned.apk + -rw-r--r-- 1 user staff 2597 Oct 2 08:19 google-services.json + -rwxr-xr-x 1 user staff 7005 Sep 30 12:47 sign-android + ``` + +* Sign the app + + ```bash + $ ./sign-android Mattermost-unsigned.apk -p com.example.test -g google-services.json -d "My App" MyApp-signed.apk + ``` + +Once the code sign is complete you should have a signed APK in the working directory with the name **MyApp-signed.apk**. + +--- + + +The app name can be anything but be sure to use double quotes if the name includes white spaces. If you are using a `Google Services` JSON file, you need to specify a `package identifier` that has a corresponding client in the JSON configuration file. + + + +--- diff --git a/docs/develop/contribute/more-info/mobile/unsigned/index.md b/docs/develop/contribute/more-info/mobile/unsigned/index.md new file mode 100644 index 000000000000..c7353eae198a --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/unsigned/index.md @@ -0,0 +1,22 @@ +--- +title: "Sign unsigned builds" +sidebar_position: 4 +--- + +Mattermost publishes an unsigned build of the mobile app in the [GitHub Releases](https://github.com/mattermost/mattermost-mobile/releases) page with every version that gets released. + +These unsigned builds cannot be distributed nor installed directly on devices until they are properly signed. + +--- + + +Android and Apple require all apps to be digitally signed with a certificate before they can be installed. + + + +--- + +To avoid rebuilding the apps from scratch, you could just **sign** the unsigned builds published by Mattermost with your certificates and keys. + +- [Sign Unsigned Android](/developers/contribute/more-info/mobile/unsigned/android) +- [Sign Unsigned iOS](/developers/contribute/more-info/mobile/unsigned/ios) diff --git a/docs/develop/contribute/more-info/mobile/unsigned/ios.md b/docs/develop/contribute/more-info/mobile/unsigned/ios.md new file mode 100644 index 000000000000..704d175f6051 --- /dev/null +++ b/docs/develop/contribute/more-info/mobile/unsigned/ios.md @@ -0,0 +1,92 @@ +--- +title: "Sign unsigned iOS builds" +sidebar_position: 2 +--- + +With every Mattermost mobile app release, we publish the iOS unsigned ipa in in the [GitHub Releases](https://github.com/mattermost/mattermost-mobile/releases) page, this guide describes the steps needed to modify and sign the app, so it can be distributed and installed on iOS devices. + +#### Requisites + +1. macOS with [Xcode](https://itunes.apple.com/us/app/xcode/id497799835?ls=1&mt=12) installed. The minimum required version is **11.0**. +2. Install the Xcode command line tools: + ```bash + $ xcode-select --install + ``` +3. Set up your Certificate and Provisioning profiles as described in steps 1 and 2 for [Run on iOS Devices](/developers/contribute/more-info/mobile/developer-setup/run#run-on-ios-devices) in the Developer Setup. +4. [sign-ios](/scripts/sign-ios) script to sign the iOS app. + +#### Sign Tool + +```bash +Usage: sign-ios + [-a|--app provisioning] + [-n|--notification provisioning] + [-s|--share provisioning] + [-c|--certificate certificateName] + [-g|--app-group-id appGroupId] + [-d|--display-name displayName] + outputIpa +Usage: sign-ios -h|--help +Options: + -a, --app provisioning Provisioning profile for the main application. + -a xxx.mobileprovision + + -n, --notification provisioning Provisioning profile for the notification extension. + -n xxx.mobileprovision + + -s, --share provisioning Provisioning profile for the share extension. + -s xxx.mobileprovision + + -d, --display-name displayName (Optional) Specify new application display name. + By default "Mattermost" is used. + Warning: will apply for all nested apps and extensions. + + -g, --app-group-id appGroupId Specify the app group identifier to use (AppGroupId). + Warning: will apply for all nested apps and extensions. + + -v, --verbose Verbose output. + + -h, --help Display help message. +``` + +#### Sign the Mattermost iOS app + +Now that all requisites are met, it's time to sign the Mattermost app for iOS. Most of the options of the signing tool are mandatory +and you should be using your own `provisioning profiles`, `certificate`, also you could change the app `display name`. + +* Create a folder that will serve as your working directory to store all the needed files. +* Download your **Apple Distribution certificate** from the [Apple Developer portal](https://developer.apple.com/account/resources/certificates/list) and save it in your working directory. +* Install the previously downloaded certificate into your macOS Keychain. [Learn more](https://developer.apple.com/support/certificates). +* Download your **Provisioning profiles** from the [Apple Developer portal](https://developer.apple.com/account/resources/profiles/list) and save it in your working directory. +* Download the [sign-ios](/scripts/sign-ios) script and save it in your working directory. +* Download the [iOS unsigned build](https://github.com/mattermost/mattermost-mobile/releases) and save it in your working directory. +* Open a terminal to your working directory and make sure the `sign-ios` script is executable. + +``` +$ ls -la +total 81472 +drwxr-xr-x 7 user staff 224 Oct 11 10:54 . +drwxr-xr-x 8 user staff 256 Oct 11 10:49 .. +-rw-r--r--@ 1 user staff 75261811 Oct 2 12:44 Mattermost-unsigned.ipa +-rw-r--r--@ 1 user staff 10746 Oct 2 10:30 app.mobileprovision +-rw-r--r--@ 1 user staff 9963 Oct 2 10:30 noti.mobileprovision +-rw-r--r--@ 1 user staff 10763 Oct 2 10:30 share.mobileprovision +-rwxr-xr-x 1 user staff 38581 Oct 11 10:54 sign-ios +``` + +* Sign the app + +```bash +$ ./sign-ios Mattermost-unsigned.ipa -c "Apple Distribution: XXXXXX. (XXXXXXXXXX)" -a app.mobileprovision -n noti.mobileprovision -s share.mobileprovision -g group.com.mattermost -d "My App Display Name" MyApp-signed.ipa +``` + +Once the code sign is complete you should have a signed IPA in the working directory with the name **MyApp-signed.ipa**. + +--- + + +The app name can be anything but be sure to use double quotes if the name includes white spaces. The name of the `certificate` should match the name in the macOS Keychain. + + + +--- diff --git a/docs/develop/contribute/more-info/mvp/index.md b/docs/develop/contribute/more-info/mvp/index.md new file mode 100644 index 000000000000..0c0ad80fadb7 --- /dev/null +++ b/docs/develop/contribute/more-info/mvp/index.md @@ -0,0 +1,121 @@ +--- +title: "MVP" +--- + +Hundreds of developers around the world contribute to Mattermost open source projects. Our Hall of Fame honors the best of the best. + +![MVP Award](/img/mvp_award.png) + +The title of “Most Valued Professional” is awarded to an outstanding contributor for a key Mattermost release. + +| Version | Release date | MVP | +|---------|--------------------|-----------------------------------------------------------------------------------| +| 11.2 | December 16, 2025 | [Angel Mendez](https://github.com/hereje) +| 11.1 | November 14, 2025 | [Vicktor](https://github.com/Victor-Nyagudi) +| 11.0 | October 16, 2025 | [Kaya Zeren](https://github.com/kayazeren) +| 10.12 | September 16, 2025 | [Lucas Reis](https://github.com/panoramix360) +| 10.11 | August 15, 2025 | [Alan Lew](https://github.com/neflyte) +| 10.10 | July 16, 2025 | [Harsh Aulakh](https://github.com/AulakhHarsh) +| 10.9 | June 16, 2025 | [Pineoak](https://translate.mattermost.com/user/pineoak-audio/) +| 10.8 | May 16, 2025 | [Lucas Reis](https://github.com/panoramix360) +| 10.7 | April 16, 2025 | [Clément Collin](https://github.com/cinlloc) +| 10.6 | March 14, 2025 | [Vicktor](https://github.com/Victor-Nyagudi) +| 10.5 | February 19, 2025 | [TheInvincible](https://github.com/TheInvincibleRalph) +| 10.4 | January 16, 2025 | [Rohan Sharma](https://github.com/RS-labhub) +| 10.3 | December 16, 2024 | [Nicolas Le Cam](https://github.com/KuSh) +| 10.2 | November 15, 2024 | [Tanmay Thole](https://github.com/tanmaythole) and [Rutam Prita Mishra](https://github.com/Rutam21) +| 10.1 | October 16, 2024 | [Ivy Gesare](https://github.com/Gesare5) +| 10.0 | September 16, 2024 | [Rita Anene](https://github.com/Camillarhi) +| 9.11 | August 16, 2024 | [Arya Khochare](https://github.com/Aryakoste) +| 9.10 | July 16, 2024 | [Frank Paul Silye](https://translate.mattermost.com/user/frankps) +| 9.9 | June 14, 2024 | [Anna Os](https://github.com/annaos) and [Ezekiel](https://github.com/ezekielchow) +| 9.8 | May 16, 2024 | [Varghese Jose](https://github.com/varghesejose2020) +| 9.7 | April 16, 2024 | [Tanmay Thole](https://github.com/tanmaythole) +| 9.6 | March 15, 2024 | [Syed Ali Abbas Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi) +| 9.5 | February 16, 2024 | [Tom De Moor](https://github.com/ctlaltdieliet) | +| 9.4 | January 16, 2024 | [Paul Stern](https://github.com/Paul-Stern) +| 9.3 | December 15, 2023 | [Rutam Prita Mishra](https://github.com/Rutam21) +| 9.2 | November 16, 2023 | [Yusuke Nemoto](https://github.com/kaakaa) +| 9.1 | October 16, 2023 | [KyeongSoo Kim](https://github.com/kyeongsoosoo) +| 9.0 | September 15, 2023 | [Kaya Zeren](https://github.com/kayazeren) +| 8.1 | August 24, 2023 | [Ben Bodenmiller](https://github.com/bbodenmiller) +| 8.0 | July 14, 2023 | [Roy Orbitson](https://github.com/Roy-Orbison) +| 7.10 | April 14, 2023 | [Matthew Dorner](https://github.com/matthewdorner) and [Alexander Griesser](https://github.com/anx-ag/) | +| 7.9 | March 16, 2023 | [Matthew Dalton](https://github.com/matthew-src) | +| 7.8 | February 16, 2023 | [Sinan Sonmez](https://github.com/sinansonmez) | +| 7.7 | January 16, 2023 | [Julien Fabre](https://github.com/jufab) | +| 7.5 | November 16, 2022 | [Ayroti Dey Sarkar](https://github.com/ayrotideysarkar) +| 7.4 | October 16, 2022 | [Sridhar](https://github.com/sridhar02) | +| 7.3 | September 16, 2022 | [Vishakha Poonia](https://github.com/VishakhaPoonia) | +| 7.2 | August 16, 2022 | [Alexander Griesser](https://github.com/anx-ag/) | +| 7.1 | July 16, 2022 | [kamre](https://github.com/kamre) | +| 7.0 | June 16, 2022 | [Tom De Moor](https://github.com/ctlaltdieliet) | +| 6.7 | May 16, 2022 | [Vishakha Poonia](https://github.com/VishakhaPoonia) | +| 6.6 | April 16, 2022 | [Sayanta Banerjee](https://github.com/Sayanta66) | +| 6.5 | March 16, 2022 | [Sinan Sonmez](https://github.com/sinansonmez) | +| 6.4 | February 16, 2022 | [Suneet Srivastava](https://github.com/codedsun) | +| 6.3 | January 16, 2022 | [Ujjwal Sharma](https://github.com/shadowshot-x) | +| 6.2 | December 16, 2021 | [Julien Fabre](https://github.com/jufab) | +| 6.1 | November 16, 2021 | [Penthaa Patel](https://github.com/penthaapatel) | +| 6.0 | October 13, 2021 | [Johannes Marbach](https://github.com/Johennes) | +| 5.39 | September 16, 2021 | [Rutam Prita Mishra](https://github.com/Rutam21) | +| 5.38 | August 16, 2021 | [kamre](https://github.com/kamre) | +| 5.37 | July 16, 2021 | [Sera Geyran](https://github.com/srgyrn) | +| 5.36 | June 16, 2021 | [Ben Bodenmiller](https://github.com/bbodenmiller) | +| 5.35 | May 16, 2021 | [Alexander Brenchev](https://github.com/TheDarkestDay) | +| 5.34 | April 16, 2021 | [darkLord19](https://github.com/darkLord19) | +| 5.33 | March 16, 2021 | [Mahmudul Haque](https://github.com/mahmud2011) | +| 5.32 | February 16, 2021 | [Yusuke Nemoto](https://github.com/kaakaa) | +| 5.31 | January 16, 2021 | [Haardik Dharma](https://github.com/haardikdharma10) | +| 5.30 | December 16, 2020 | [XxLilBoPeepsxX](https://github.com/XxLilBoPeepsxX) | +| 5.29 | November 16, 2020 | [Tom De Moor](https://github.com/ctlaltdieliet) | +| 5.28 | October 16, 2020 | [Soo Hwan Kim](https://github.com/josephk96) | +| 5.27 | September 16, 2020 | [Mohan Prasath](https://github.com/openmohan) | +| 5.26 | August 16, 2020 | [Abdu Assabri](https://github.com/abdusabri) | +| 5.25 | July 16, 2020 | [Rodrigo Villablanca](https://github.com/rvillablanca) | +| 5.24 | June 16, 2020 | [Rakesh Peela](https://github.com/rakhi2104) | +| 5.23 | May 16, 2020 | [Vladimir Lebedev](https://github.com/nadalfederer) | +| 5.22 | April 16, 2020 | [Tim Estermann](https://github.com/der-test) | +| 5.21 | March 16, 2020 | [Allan Guwatudde](https://github.com/AGMETEOR) | +| 5.20 | February 16, 2020 | [Md Zubair Ahmed](https://github.com/M-ZubairAhmed) | +| 5.19 | January 16, 2020 | [Allen Lai](https://github.com/allenlai18) | +| 5.18 | December 16, 2019 | [larkox](https://github.com/larkox) | +| 5.17 | November 16, 2019 | [Andre Vasconcelos](https://github.com/avasconcelos114) | +| 5.16 | October 16, 2019 | [Paulo Bittencourt](https://github.com/pbitty) | +| 5.15 | September 16, 2019 | [Siyuan Liu](https://github.com/liusy182) | +| 5.14 | August 16, 2019 | [Rodrigo Villablanca Vásquez](https://github.com/rvillablanca) | +| 5.13 | July 16, 2019 | [Adrian Mönnich](https://github.com/thiefmaster) | +| 5.12 | June 16, 2019 | [Scott Davis](https://github.com/scottleedavis) | +| 5.11 | May 16, 2019 | [Maneschi Romain](https://github.com/manland) | +| 5.10 | April 16, 2019 | [Grzegorz Kosik](https://github.com/kosgrz) | +| 5.9 | March 16, 2019 | [JtheBAB](https://github.com/JtheBAB) | +| 5.8 | February 16, 2019 | [Kyâne Pichou](https://github.com/pichouk) | +| 5.7 | January 16, 2019 | [sadb](https://github.com/sadb) | +| 5.6 | December 16, 2018 | [Pradeep Murugesan](https://github.com/pradeepmurugesan) | +| 5.5 | November 16, 2018 | [Mukul Rawat](https://github.com/mukulrawat1986) | +| 5.4 | October 16, 2018 | [Hanzei](https://github.com/Hanzei) | +| 5.3 | September 16, 2018 | [SmartHoneybee](https://github.com/SmartHoneybee) | +| 5.2 | August 16, 2018 | [Daniel Schalla](https://github.com/DSchalla) | +| 5.1 | July 16, 2018 | [Hyeseong Kim](https://github.com/cometkim) | +| 5.0 | June 16, 2018 | [William Gathoye](https://github.com/wget) | +| 4.10 | May 16, 2018 | [Siyuan Liu](https://github.com/liusy182) | +| 4.9 | April 16, 2018 | [Christian Hoff](https://github.com/chumbalum) | +| 4.8 | March 16, 2018 | [Pierre de La Morinerie of Codeurs en Liberté](https://github.com/kemenaran) | +| 4.7 | February 16, 2018 | [Kher Yee Ting](https://github.com/tkbky) | +| 4.6 | January 16, 2018 | [Yusuke Nemoto](https://github.com/kaakaa) | +| 4.5 | December 16, 2017 | [Ryan Wang](https://github.com/r-wang97) | +| 4.4 | November 16, 2017 | [Sudheer Timmaraju](https://github.com/sudheerDev) | +| 4.3 | October 16, 2017 | [Jesús Espino](https://github.com/jespino) | +| 4.2 | September 16, 2017 | Uber Development Team | +| 4.1 | August 16, 2017 | [Nazar Laba](https://github.com/n1aba) | +| 4.0 | July 16, 2017 | [prixone](https://github.com/prixone) and [sousapro](https://github.com/sousapro) | +| 3.10 | June 16, 2017 | [Galois, Inc.](https://github.com/matterhorn-chat) | +| 3.9 | May 16, 2017 | [Carlos Tadeu Panato Junior](https://github.com/cpanato) | +| 3.8 | April 16, 2017 | [VeraLyu](https://github.com/veralyu) | +| 3.7 | March 16, 2017 | [Saturnino Abril](https://github.com/saturninoabril) | +| 3.6 | January 16, 2017 | [Carlos Tadeu Panato Junior](https://github.com/cpanato) | +| 3.5 | November 16, 2016 | [Harshavardhana](https://github.com/harshavardhana) | +| 3.4 | September 16, 2016 | [Wim van Wemmel](https://github.com/42wim) | +| 3.3 | August 16, 2016 | [Ivan Naydonov](https://github.com/samogot) | +| 3.2 | July 16, 2016 | [Christian Arnold](https://github.com/meilon) | +| 3.1 | June 16, 2016 | [Thomas Balthazar](https://github.com/tbalthazar) | diff --git a/docs/develop/contribute/more-info/plugins/index.md b/docs/develop/contribute/more-info/plugins/index.md new file mode 100644 index 000000000000..9251d57fca53 --- /dev/null +++ b/docs/develop/contribute/more-info/plugins/index.md @@ -0,0 +1,19 @@ +--- +title: "Plugins" +sidebar_position: 10 +--- + +Mattermost plugins are isolated pieces of code written in Go and/or React. They're separate from the main repositories and are used to extend the functionality of the Mattermost server and webapp. + +- The Go portions run directly on the Mattermost server, and are managed by the server at runtime. +- The React portions run in each user's browser, allowing developers to modify the user interface in [several ways](/developers/integrate/plugins/components/webapp/best-practices). + +The plugin Help Wanted tickets are located in each plugin's respective GitHub repository. In order to browse all of the open tickets, see the plugin [Help Wanted tickets](https://mattermost.com/pl/help-wanted-plugins/) page with links to specific plugin repositories, as well as queries for Help Wanted tickets in all repositories. The [All Plugins Up for Grabs](https://github.com/issues?utf8=%E2%9C%93&q=repo%3Amattermost%2Fmattermost-plugin-agenda+repo%3Amattermost%2Fmattermost-plugin-antivirus+repo%3Amattermost%2Fmattermost-plugin-autolink+repo%3Amattermost%2Fmattermost-plugin-aws-SNS+repo%3Amattermost%2Fmattermost-plugin-custom-attributes+repo%3Amattermost%2Fmattermost-oembed-plugin+repo%3Amattermost%2Fmattermost-plugin-giphy+repo%3Amattermost%2Fmattermost-plugin-github+repo%3Amattermost%2Fmattermost-plugin-gitlab+repo%3Amattermost%2Fmattermost-plugin-google-calendar+repo%3Amattermost%2Fmattermost-plugin-jenkins+repo%3Amattermost%2Fmattermost-plugin-jira+repo%3Amattermost%2Fmattermost-plugin-msoffice+repo%3Amattermost%2Fmattermost-plugin-solar-lottery+repo%3Amattermost%2Fmattermost-plugin-suggestions+repo%3Amattermost%2Fmattermost-plugin-todo+repo%3Amattermost%2Fmattermost-plugin-webex+repo%3Amattermost%2Fmattermost-plugin-welcomebot+repo%3Amattermost%2Fmattermost-plugin-zoom+repo%3Amattermost%2Fmattermost-plugin-msteams-meetings+is%3Aopen+is%3Aissue+archived%3Afalse+label%3A%22help%20wanted%22%20label%3A%22up%20for%20grabs%22%20) link is useful to browse all repositories at once. + +The plugin [developer setup](/developers/integrate/plugins/developer-setup) and [developer workflow](/developers/integrate/plugins/developer-workflow) pages are useful to learn about the plugin development environment. You can find more information about plugins in general [here](/developers/integrate/plugins). + + + +The `make` commands listed in the [developer workflow](/developers/integrate/plugins/developer-workflow#common-make-commands-for-working-with-plugins) page (specifically `make test` and `make check-style`) should be used locally to run certain tests before submitting a PR. This makes the PR review process much more streamlined overall. + + diff --git a/docs/develop/contribute/more-info/server/ESR-diagram.png b/docs/develop/contribute/more-info/server/ESR-diagram.png new file mode 100644 index 000000000000..979a90288ac1 Binary files /dev/null and b/docs/develop/contribute/more-info/server/ESR-diagram.png differ diff --git a/docs/develop/contribute/more-info/server/cli-commands.md b/docs/develop/contribute/more-info/server/cli-commands.md new file mode 100644 index 000000000000..2803465f125c --- /dev/null +++ b/docs/develop/contribute/more-info/server/cli-commands.md @@ -0,0 +1,100 @@ +--- +title: "CLI commands" +sidebar_position: 5 +--- + +As of 6.0, Mattermost CLI has been replaced by [mmctl](https://github.com/mattermost/mmctl). `mmctl` is built to enable access to Mattermost server from the command line. The tool leverages the public API so that administrator and user tasks can be performed. + +Since `mmctl` uses the public API, an authorization mechanism is required. Which means the access rights are managed on the server side. There is a pre-run check to read credentials and use it in the client. In addition to authentication via credentials, `mmctl` can communicate to a local server without any authentication. This must be enabled via server configuration and both `mmctl` and `mattermost/server` needs to be running in the same machine. + +In addition to provide more functionality towards testing and development, `db` subcommand has been added Mattermost server binary. + +The CLI interface is written using [Cobra](https://github.com/spf13/cobra), a +powerful and modern CLI creation library. If you have never used Cobra before, it is +well documented in its [GitHub Repository](https://github.com/spf13/cobra). + +The source code used to build our CLI interface is written in the `commands` directory of the [mmctl](https://github.com/mattermost/mmctl) repository. + +Each "command" of the CLI is stored in a different file of the +`commands` directory. Within each file, you can find +multiple "subcommands". + +## Add a new subcommand + +If you want to add a new subcommand in an existing mattermost command, first find the relevant file. For example, if you want to add a `show` command to +the `channel` command, go to `commands/channel.go` and add your subcommand there. + +To add the subcommand, start by creating a new `Command` instance, for example: + +```go +var ChannelShowCmd = &cobra.Command{ + Use: "show", + Short: "Show channel info", + Long: "Show channel information, including the name, header, purpose and the number of members.", + Example: " channel show --team myteam --channel mychannel" + RunE: showChannelCmdF, +} +``` + +Then implement the subcommand function, in this example `showChannelCmdF`. + +```go +func showChannelCmdF(c client.Client, cmd *cobra.Command, args []string) error { + // Your code implementing the command itself + newChannel, _, err := c.ShowChannel(channel) + if err != nil { + return err + } + + return nil +} +``` + +Now, you set the flags of your subcommand and register it in the command. In our case we register our new `ChannelShowCmd` flag in `ChannelCmd`. + +```go +func init() { + ... + + ChannelShowCmd.Flags().String("team", "", "Team name or ID") + ChannelShowCmd.Flags().String("channel", "", "Channel name or ID") + ... + ChannelCmd.AddCommand( + ... + ChannelShowCmd, + ) + ... +} +``` + +Finally, implement unit tests in `commands/channel_test.go` and end-to-end tests to commands/channel_e2e_test.go`. + +## Add a new command + +If you want to add a new command to `mmctl`, first create a file for the command. +For example, if you want to add a new `emoji` command to manage emojis in +Mattermost from the CLI, create `commands/emoji.go` +and add your command and your subcommands there. + +A command is exactly the same as a subcommand, so you can follow the same +steps of the previous section. However, you must also register the new command in the +"Root" command as follows: + +```go +var EmojiCmd = &cobra.Command{ + Use: "emoji", + Short: "Emoji management", + Long: "Lists, creates and deletes custom emoji", +} +func init() { + ... + RootCmd.AddCommand(EmojiCmd) + ... +} +``` + +Usually, you would then add several subcommands to perform various tasks. + +## Submit your pull request + +Please submit a pull request against the [mattermost/mmctl](https://github.com/mattermost/mmctl) repository by [following these instructions](/developers/contribute/more-info/server/developer-workflow). diff --git a/docs/develop/contribute/more-info/server/dependencies.md b/docs/develop/contribute/more-info/server/dependencies.md new file mode 100644 index 000000000000..1d1883de957b --- /dev/null +++ b/docs/develop/contribute/more-info/server/dependencies.md @@ -0,0 +1,31 @@ +--- +title: "Dependencies" +sidebar_position: 5 +--- + + +The Mattermost server uses [Go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. + +## Add or update a new dependency + +Adding a dependency is easy. All you have to do is import the dependency in the code and recompile. The dependency will be automatically added for you. Updating uses the same procedure. + +Before committing the code with your new dependency added, be sure to run `go mod tidy` to maintain a consistent format and `go mod vendor` to synchronize the vendor directory. + +If you want to add or update to a specific version of a dependency you can use a command of the form: +```bash +go get -u github.com/pkg/errors@v0.8.1 +go mod tidy +go mod vendor +``` + +If you just want whatever the latest version is, you can leave off the `@version` tag. + +## Remove a dependency + +Be sure you have enabled go modules support. After removing all references to the dependency in the code, you run: +```bash +go mod tidy +go mod vendor +``` +to remove it from the `go.mod` file and the `vendor` directory. diff --git a/docs/develop/contribute/more-info/server/developer-workflow.md b/docs/develop/contribute/more-info/server/developer-workflow.md new file mode 100644 index 000000000000..d89c982bca44 --- /dev/null +++ b/docs/develop/contribute/more-info/server/developer-workflow.md @@ -0,0 +1,113 @@ +--- +title: "Server workflow" +sidebar_position: 3 +--- + +If you haven't [set up your developer environment](/developers/contribute/developer-setup), please do so before continuing with this section. + +Join the [Developers community channel](https://community.mattermost.com/core/channels/developers) to ask questions from community members and the Mattermost core team. + +### Workflow + +Here's a general workflow for a Mattermost developer working on the [mattermost](https://github.com/mattermost/mattermost) repository: + +#### Making code changes +1. Review the repository structure to familiarize yourself with the project: + + * [./server/channels/api4/](https://github.com/mattermost/mattermost/tree/master/server/channels/api4) holds all API and application related code. + * [./server/public/model/](https://github.com/mattermost/mattermost/tree/master/server/public/model) holds all data model definitions and the Go driver. + * [./server/channels/store/](https://github.com/mattermost/mattermost/tree/master/server/channels/store) holds all database querying code. + * [./server/channels/utils/](https://github.com/mattermost/mattermost/tree/master/server/channels/utils) holds all utilities, such as the mail utility. + * [./server/i18n/](https://github.com/mattermost/mattermost/tree/master/server/i18n) holds all localization files for the server. +2. On your fork, create a feature branch for your changes. Name it `MM-$NUMBER_$DESCRIPTION` where `$NUMBER` is the [Jira](https://mattermost.atlassian.net) ticket number you are working on and `$DESCRIPTION` is a short description of your changes. Example branch names are `MM-18150_plugin-panic-log` and `MM-22037_uppercase-email`. +3. Make the code changes required to complete your ticket. +#### Running and writing tests +4. Ensure that unit tests are written or modified where appropriate. For the server repository in general, Mattermost follows the opinionated way of testing in Go. You can learn more about this process in [DigitalOcean's How To Write Unit Tests in Go tutorial](https://www.digitalocean.com/community/tutorials/how-to-write-unit-tests-in-go-using-go-test-and-the-testing-package). Test files must always end with `_test.go`, and should be located in the same folder where the code they are checking lives. For example, check out [download.go](https://github.com/mattermost/mattermost/blob/master/server/channels/app/download.go) and [download_test.go](https://github.com/mattermost/mattermost/blob/master/server/channels/app/download_test.go), which are both located in the `app` folder. Please also use [testify](https://github.com/stretchr/testify) for new tests. +5. If you made changes to the store, run `make store-mocks` and `make store-layers` to update test mocks and timing layer. +6. To test your changes, run `make run-server` from the root directory of the server repository. This will start up the server at `http://localhost:8065`. To get changes to the server it must be restarted with `make restart-server`. If you want to test with the web app, you may also run `make run` which will start the server and a watcher for changes to the web app. +7. Once everything works to meet the ticket requirements, stop Mattermost by running `make stop` in the server repository, then run `make check-style` to check your syntax. +8. Run the tests using one or more of the following options: + * Run `make test` to run all the tests in the project. This may take a long time and provides very little feedback while it's running. + * Run individual tests by name executing `go test -run "TestName" ./`. + * Run all the tests in a package where changes were made executing `go test app`. + * Create a draft PR with your changes and let our CI servers run the tests for you. +9. Running every single unit test takes a lot of time while making changes, so you can run a subset of the server-side unit tests by using the following: + ``` + go test -v -run='' ./ + ``` + For example, if you want to run `TestUpdatePost` in `app/post_test.go`, you would execute the following: + + ``` + go test -v -run='TestUpdatePost' ./app + ``` +10. If you added or changed any localization strings you will need to run `make i18n-extract` to generate the new/updated strings. +#### Testing email notifications + +11. When Docker starts, the SMTP server is available on port 2500. A username and password are not required. You can access the Inbucket webmail on port 9000. For additional information on configuring an SMTP email server, including troubleshooting steps, see the [SMTP email setup page in the Mattermost user documentation](https://docs.mattermost.com/install/smtp-email-setup.html). +#### Testing with GitLab Omnibus + +12. To test a locally compiled version of Mattermost with GitLab Omnibus, replace the following GitLab files: + * The compiled `mattermost` binary in `/opt/gitlab/embedded/bin/mattermost`. + * The assets (templates, i18n, fonts, webapp) in `/opt/gitlab/embedded/service/mattermost`. +#### Creating a pull request (PR) +13. Commit your changes, push your branch, and [create a pull request](/developers/contribute/more-info/getting-started/contribution-checklist). +14. Once a PR is submitted it's best practice to avoid rebasing on the base branch or force-pushing. Jesse, a developer at Mattermost, mentions this in his blog article [Submitting Great PRs](https://mattermost.com/blog/submitting-great-prs/). When the PR is merged, all the PR's commits are automatically squashed into one commit, so you don't need to worry about having multiple commits on the PR. +15. That's it! Rejoice that you've helped make Mattermost better. + +### Useful Server makefile commands + +Some useful `make` commands include: + +* `make run` runs the server, creates a symlink for your mattermost-webapp folder, and starts a watcher for the web app. +* `make stop` stops the server and the web app watcher. +* `make run-server` runs only the server and not the client. +* `make debug-server` will run the server in the `delve` debugger. +* `make stop-server` stops only the server. +* `make update-docker` stops and updates your Docker images. This is needed if any changes are made to `docker-compose.yaml`. +* `make clean-docker` stops and removes your Docker images and is a good way to wipe your database. +* `make clean` cleans your local environment of temporary files. +* `make config-reset` resets the `config/config.json` file to the default. +* `make nuke` wipes your local environment back to a completely fresh start. +* `make package` creates packages for distributing your builds and puts them in the `./dist` directory. You will first need to run `make build` and `make build-client`. + +If you would like to run the development environment without Docker you can set the `MM_NO_DOCKER` environment variable. If you do this, you will need to set up your own database and any of the other services needed to run Mattermost. + +### Useful Mattermost and mmctl commands + +During development you may want to reset the database and generate random data for testing your changes. For this purpose, Mattermost has the following commands in the Mattermost CLI: + +1. First, install the server with `go install ./cmd/mattermost` in the server repository. +2. You can reset your database to the initial state using: + + ``` + mattermost db reset + ``` +3. The following commands need to be run via the [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) tool. + + * You can generate random data to populate the Mattermost database using: + + ``` + mmctl sampledata + ``` + + * Create an account using the following command: + + ``` + mmctl user create --email user@example.com --username test1 --password mypassword + ``` + + * Optionally, you can assign that account System Admin rights with the following command: + + ``` + mmctl user create --email user@example.com --username test1 --password mypassword --system-admin + ``` + +### Customize your workflow + +#### Makefile variables + +You can customize variables of the Makefile by creating a `config.override.mk` file or setting environment variables. To get started, you can copy the `config.mk` file to `config.override.mk` and change the values in your newly copied file. + +#### Docker-compose configurations + +If you create a `docker-compose.override.yaml` file at the root of the project, it will be automatically loaded by all the `Makefile` tasks using `docker-compose`, allowing you to define your own services or change the configuration of the ones Mattermost provides. diff --git a/docs/develop/contribute/more-info/server/feature-flags.md b/docs/develop/contribute/more-info/server/feature-flags.md new file mode 100644 index 000000000000..16baafb5297f --- /dev/null +++ b/docs/develop/contribute/more-info/server/feature-flags.md @@ -0,0 +1,122 @@ +--- +title: "Feature flags" +sidebar_position: 3 +--- + +# What are feature flags + +Feature flag is a software development technique that turns functionality on and off without deploying new code. Feature flags allow us to be more confident in shipping features continuously to Mattermost Cloud. Feature flags also allow us to control which features are enabled on a cluster level. + +# How to use feature flags + +## When to use + +There are no hard rules on when a feature flag should be used. It is left up to the best judgement of the responsible engineers to determine if a feature flag is required. The following are guidelines designed to help the determination: + +- Any "substantial" feature should have a flag +- Features that are probably substantial: + - Features with new UI or changes to existing UI + - Features with a risk of regression +- Features that are probably not substantial: + - Small bug fixes + - Refactoring + - Changes that are not user facing and can be completely verified by unit and E2E testing. + +In all cases, ask yourself: Why do I need to add a feature flag? If I don't add one, what options do I have to control the impact on user experience (e.g. a config setting or System Console setting)? + +## Add the feature flag in code + +1. Add the new flag to the feature flag struct located in `model/feature_flags.go`. +2. Set a default value in the `SetDefaults` function in the same file. +3. Use the feature flag in code as you would use a regular configuration setting. In tests, manipulate the configuration value to test value changes, such as activation and deactivation of the feature flag. +4. Code may be merged regardless of setup in the management system. In this case it will always take the default value supplied in the `SetDefaults` function. +5. Create a removal ticket for the feature flag. All feature flags should be removed as soon as they have been verified by Cloud. The ticket should encompass removal of the supporting code and archiving in the management system. + +### Feature flag code guidelines + +- A ticket should be created when a feature flag is added to remove the feature flag as soon as it isn't required anymore. +- Tests should be written to verify the feature flag works as expected. Note that in cases where there may be a migration or new data, off to on and on to off should both be tested. +- Log messages by the feature should include the feature flag tag, with the feature flag name as a value, in order to ease debugging. + +# Changing Feature Flag Values + +## Self Hosted (and local development) + +Feature flag values can be changed via environment variables. The environment variable set follows the pattern `MM_FEATUREFLAGS_` where `` is the uppercase key of the feature flag you added to model/feature_flags.go + +## Cloud + +Feature flag adjustments (ie, turning something on or off) in the Mattermost Cloud environment are owned and controlled by the Cloud team. To change the value for a feature flag, please open a ticket. + +## Timelines for rollouts + +Typically feature flag will initially disable the feature. It's a good idea to test the feature during a safe time or on a subset of instances. Each team can decide what's best and there's no need to request the flag value changes from the Cloud team. If you think there might be a performance impact there's no harm in communicating your plan beforehand. + + + +The steps below are an initial guideline and will be iterated on over time. + + - 1st week after feature is merged (T-30): 10% rollout; only to test servers, no rollout to customers. + - 2nd week (T-22): 50% rollout; rollout to some customers (excluding big customers and newly signed-up customers); no major bugs in test servers. + - 3rd week (T-15): 100% rollout; no major bugs from customers or test servers. + - End of 3rd week (T-8): Remove flag. Feature is production ready and not experimental. + + + +For smaller, non-risky features, the above process can be more fast tracked as needed, such as starting with a 10% rollout to test servers, then 100%. +Features have to soak on Cloud for at least two weeks for testing. Focus is on severity and number of bugs found; if there are major bugs found at any stage, the feature flag can be turned off to roll back the feature. + +When the feature is rolled out to customers, logs will show if there are crashes, and normally users will report feedback on the feature (e.g. bugs). + +## Self-hosted releases + +For self-hosted releases, typically a flagged feature will be released in an enabled state. That said, you can release a feature to self-hosted disabled, [it's not unprecedented](https://github.com/mattermost/mattermost/blob/master/server/public/model/feature_flags.go#L75). + +## Tests + +Tests should be written to verify all states of the feature flag. Tests should cover any migrations that may take place in both directions (i.e., from "off" to "on" and from "on" to "off"). Ideally E2E tests should be written before the feature is merged, or at least before the feature flag is removed. + +## Examples of feature flags + +Some [examples are here](https://github.com/mattermost/mattermost/blob/master/server/public/model/feature_flags.go#L75). + +## FAQ + +1. What are the expected values for boolean feature flags? + - Normally ``true`` or ``false``, but this may not always equate to enabled/disabled. A feature flag that introduces three new sorting algorithms can also be written: + - "selection" (default, the existing strategy in production) + - "bubble" + - "quick" + +2. Is it possible to use a plugin feature flag such as `PluginIncidentManagement` to "prepackage" a plugin only on Cloud by only setting a plugin version to that flag on Cloud? Can self-hosted customers manually set that flag to install the said plugin? + - Yes. If you leave the default "" then nothing will happen for self-hosted installations. + +3. How do feature flags work on webapp? + - To add a feature flag that affects frontend, the following is needed: + 1. PR to server code to add the new feature flag. + 2. PR to redux to update the types. + 3. PR to webapp to actually use the feature flag. + +4. How do feature flags work on mobile? + - To add a feature flag that affects mobile, the following is needed: + 1. PR to server code to add the new feature flag. + 2. PR to mobile to update the types and to actually use the feature flag. + +5. What is the environment variable to set a feature flag? + - It is `MM_FEATUREFLAGS_`. + +6. Can plugins use feature flags to enable small features aside of the version forcing feature flag? + - Yes. You can create feature flags as if they were added for the core product, and they'll get included in the plugin through the config. + + +7. Do feature flag changes require the server to be restarted? + - Feature flags don’t require a server restart unless the feature being flagged requires a restart itself. + +8. For features that are requested by self-hosted customers, why do we have to deploy to Cloud first, rather than having the customer who has the test case test it? + - Cloud is the way to validate the stability of the feature before it goes to self-hosted customers. In exceptional cases we can let the self-hosted customer know that they can use environment variables to enable the feature flag (but specify that the feature is experimental). + +9. How does the current process take into account bugs that may arise on self-hosted specifically? + - The process hasn’t changed much from the old release process: Features can still be tested on self-hosted servers once they have been rolled out to Cloud. The primary goal is that bugs are first identified on Cloud servers. + +10. How can self-hosted installations set feature flags? + - Self-hosted installations can set environment variables to set feature flag values. However, users should recognize that the feature is still considered "experimental" and should not be enabled on production servers. diff --git a/docs/develop/contribute/more-info/server/index.md b/docs/develop/contribute/more-info/server/index.md new file mode 100644 index 000000000000..7734df1420ad --- /dev/null +++ b/docs/develop/contribute/more-info/server/index.md @@ -0,0 +1,28 @@ +--- +title: "Server" +sidebar_position: 2 +--- + +The server is the highly scalable backbone of the Mattermost project. Written in Go, it compiles to a single, standalone binary. It's generally stateless except for the WebSocket connections and some in-memory caches. + +Communication with Mattermost clients and integrations mainly occurs through the RESTful JSON web API and WebSocket connections primarily used for event delivery. + +Data storage is done with MySQL or PostgreSQL for non-binary data. Files are stored locally, on network drives or in a service such as S3 or Minio. + +## Repository + +https://github.com/mattermost/mattermost + +## Server packages + +The server consists of several different Go packages: + +* `api4` - Version 4 of the RESTful JSON Web Service +* `app` - Logic layer for getting, modifying, and interacting with models +* `cmd` - Command line interface +* `einterfaces` - Interfaces for Enterprise Edition features +* `jobs` - Job server and scheduling +* `model` - Definitions and helper functions for data models +* `store` - Storage layer for interacting with caches and databases +* `utils` - Utility functions for various tasks +* `web` - Serves static pages diff --git a/docs/develop/contribute/more-info/server/migrations_pie.png b/docs/develop/contribute/more-info/server/migrations_pie.png new file mode 100644 index 000000000000..0c88203478e9 Binary files /dev/null and b/docs/develop/contribute/more-info/server/migrations_pie.png differ diff --git a/docs/develop/contribute/more-info/server/plugins.md b/docs/develop/contribute/more-info/server/plugins.md new file mode 100644 index 000000000000..e8c2d1d16326 --- /dev/null +++ b/docs/develop/contribute/more-info/server/plugins.md @@ -0,0 +1,36 @@ +--- +title: "Plugins" +sidebar_position: 5 +--- + +Mattermost supports plugins that offer powerful features for extending and deeply integrating with both the server and web/desktop apps. + +This document covers the plugin infrastructure and how to contribute to it. + +## Build plugins + +Looking to build a plugin? [Then you want the plugin author documentation.](/developers/integrate/plugins) + +## Overview + +Plugins are generally made of at least two parts: a manifest and a server binary and/or a JavaScript bundle. + +The manifest tells Mattermost what the plugin is and provides a set of metadata used by the server to install and run the plugin. Please see the [manifest reference](/developers/integrate/plugins/manifest-reference) for more information. Manifests may be defined in JSON or YAML. + +The server binary is a compiled Go program that extends the [MattermostPlugin](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin#MattermostPlugin) struct of the [plugin](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin) package. When enabled, the plugin's server binary is started as a process by the Mattermost server. Plugin developers then have access to interact with the Mattermost server over RPC through the plugin [API](/developers/integrate/reference/server/server-reference#API) and [Hooks](/developers/integrate/reference/server/server-reference#Hooks). The server-side of plugins is built using the [go-plugin](https://github.com/hashicorp/go-plugin) library from Hashicorp. More information is available in the [server side of the plugin author documentation](/developers/integrate/plugins/components/server). + +The JavaScript bundle is a webpack-built collection of JavaScript code that will be run on the Mattermost web/desktop apps. When a plugin is enabled, the client is notified and it makes a request to add the JS bundle to the document. The plugin's client code then registers itself and its components with the Mattermost client through the client's [plugin registry](/developers/integrate/reference/webapp/webapp-reference#registry). The registry contains many methods for registering different components and callbacks. These are all stored as part of the app's [plugin reducer](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/reducers/plugins/index.ts). The [Pluggable](https://github.com/mattermost/mattermost/tree/master/webapp/channels/src/plugins/pluggable) component is then inserted into various places in the app, allowing plugins to insert components into these locations in the UI. In some special cases, the Pluggable component is not used and we instead implement the plugs manually. More information is available in the [webapp side of the plugin author documentation](/developers/integrate/plugins/components/webapp). + +All these different components of a plugin are compressed into a .tar.gz bundle. Installing a plugin is the process of uploading this bundle to the Mattermost server (via the UI, REST API or CLI). The server then unpacks the bundle, performs some validation and extracts it into the configured directory for storing installed plugins. Installed plugins are not yet running. To start a plugin it must be enabled (again via the UI, REST API or CLI). Once it is enabled, the server will then start the server process and prepare the web app bundle for serving to the client. Plugin settings, configuration and enabled/disabled status are managed by the Mattermost `config.json` using a [PluginSettings](https://godoc.org/github.com/mattermost/mattermost/server/public/model#PluginSettings) struct. + +Check out the [`plugin` package](https://github.com/mattermost/mattermost/tree/master/server/public/plugin) and the [plugin_* files in the `app` package](https://github.com/mattermost/mattermost/tree/master/server/channels/app) for the code, and [mattermost-plugin-demo](https://github.com/mattermost/mattermost-plugin-demo) for an example plugin. To start developing your own plugin, please follow the instructions [here](/developers/integrate/plugins/developer-setup). + +## Add an API + +To add a plugin API you need to add the signature of your new method to the [API interface](https://github.com/mattermost/mattermost/blob/master/server/public/plugin/api.go). You then need to implement the API in the [plugin_api.go](https://github.com/mattermost/mattermost/blob/master/server/channels/app/plugin_api.go) of the `app` package. Finally, you need to run `make pluginapi` to generate the RPC glue code needed for your new API and `make plugin-mocks` to generate the mocks used for plugin testing. + +That's it! Submit your pull request. + +## Questions? + +If you have any questions, feel free to ask in the [Toolkit channel](https://community.mattermost.com/core/channels/developer-toolkit) of our Mattermost community instance. diff --git a/docs/develop/contribute/more-info/server/rest-api.md b/docs/develop/contribute/more-info/server/rest-api.md new file mode 100644 index 000000000000..2f9f002ef060 --- /dev/null +++ b/docs/develop/contribute/more-info/server/rest-api.md @@ -0,0 +1,101 @@ +--- +title: "REST API" +sidebar_position: 4 +--- + +The REST API is a JSON web service that facilitates communication between Mattermost clients, as well as integrations, and the server. The server is currently on API version 4. + +### Reference + +Looking for the API reference? You can find it here: [https://api.mattermost.com](https://api.mattermost.com). + +### Add an endpoint + +To add an endpoint to API version 4, all of the following must be completed: + +- [Reference](#reference) +- [Add an endpoint](#add-an-endpoint) + - [Document the endpoint](#document-the-endpoint) + - [Implement the API handler](#implement-the-api-handler) + - [Update the Golang driver](#update-the-golang-driver) + - [Write a unit test](#write-a-unit-test) + - [Submit your pull request (PR)](#submit-your-pull-request-pr) +- [Legacy Notes](#legacy-notes) + +#### Document the endpoint +At Mattermost, the [OpenAPI specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) is used for API documentation. The API documentation lives in the main Mattermost repository alongside the server: [api](https://github.com/mattermost/mattermost/tree/master/api). + +To document an endpoint, follow these steps: + +1. Find the `.yaml` file in the [api/v4/source](https://github.com/mattermost/mattermost/tree/master/api/v4/source) directory that fits your endpoint. + - For example, if you were adding the `GET /users/{user_id}` endpoint you would be looking for the [users.yaml](https://github.com/mattermost/mattermost/blob/master/api/v4/source/users.yaml) file. + - If the file doesn't exist yet, you may need to create it and then update the [Makefile](https://github.com/mattermost/mattermost/tree/master/api/Makefile) to include the file. + +2. Copy an existing endpoint from the same or a different file. + +3. Update the documentation you copied with the correct information for your endpoint, including: + - `Tag` - the resource type + - `Summary` - a summary of few words + - `Description` - a brief 1-2 sentence description + - `Permissions` - the permission(s) required + - `Parameters` - the URL and body parameters + - `Responses` - the success and error responses + +4. Confirm you don't have any syntax errors by running `make build` within the [api](https://github.com/mattermost/mattermost/tree/master/api/) directory. + +5. Continue with the implementation of your API handler, updating this documentation as needed. + +#### Implement the API handler +To implement the API handler, you'll first need to [setup your developer environment](/developers/contribute/developer-setup), and then follow these steps: + +1. Add the declaration for your endpoint. For an example, check out the [/api4/user.go](https://github.com/mattermost/mattermost/blob/master/server/channels/api4/user.go) file. + +2. Implement the handler for your endpoint. Follow this general pattern for handlers: + + ```Go + func handlerName(c *Context, w http.ResponseWriter, r *http.Request) { + // 1. Parse the request URL and body. + // 2. Do a permissions check if required. + // 3. Invoke handler logic through the app package. + // 4. (Optional) Check the Etag. + // 5. Format the response and write the response. + } + ``` + For examples, see the [createUser()](https://github.com/mattermost/mattermost/blob/d693f880431741e3e1482503c4e80d6148b0f1bf/server/channels/api4/user.go#L111) and the [getUser()](https://github.com/mattermost/mattermost/blob/d693f880431741e3e1482503c4e80d6148b0f1bf/server/channels/api4/user.go#L177) handlers. + +3. Run the server by runing `make run-server` within the [server](https://github.com/mattermost/mattermost/tree/master/server/) directory. + +4. Use `curl` or [Postman](https://www.getpostman.com/) to test the basics of your endpoint. + +#### Update the Golang driver +The Go driver for APIv4 is in [/model/client4.go](https://github.com/mattermost/mattermost/blob/master/server/public/model/client4.go). To add a function to support your new endpoint: + +1. Copy over an existing driver function, such as [CreateUser](https://github.com/mattermost/mattermost/blob/master/server/public/model/client4.go#L827). + +2. Paste the function into the section for your endpoint. For example, `POST /teams` would go in the Teams section. + +3. Modify the function to correctly hit your endpoint. Make sure to update the request method to match your endpoint's HTTP method. + +#### Write a unit test +The most important part of this process is to make sure the new endpoint works correctly. Follow these steps to write a unit test: + +1. Open the test Go file related to your endpoint, or create one if necessary. For example, if you put your handler in [/api4/user.go](https://github.com/mattermost/mattermost/blob/master/server/channels/api4/user.go), your test will go in [/api4/user\_test.go](https://github.com/mattermost/mattermost/blob/master/server/channels/api4/user_test.go). + +2. Write your test based on the other tests in your file (or folder). There are several helper functions in [/api4/apitestlib.go](https://github.com/mattermost/mattermost/blob/master/server/channels/api4/apitestlib.go) that you may use. + +3. Ensure that your test covers the following: + - All combinations of correct inputs to your endpoint. + - Etags for your endpoint, if applicable. + - Incorrect URL or body parameters return a **400 Bad Request** status code. + - Requests without a token return a **401 Unauthorized** status code (for endpoints requiring a session). + - Requests with insufficient permissions return a **403 Forbidden** status code (for endpoints requiring permission). + - Requests to non-existent resources or URLs return a **404 Not Found** status code. + +Returning the correct error code might require investigation in the [app](https://github.com/mattermost/mattermost/tree/master/server/channels/app) or [store](https://github.com/mattermost/mattermost/tree/master/server/channels/store) to find the source of errors. Status codes on errors should be set at the creation of the error. + +#### Submit your pull request (PR) +Submit your pull request against the [mattermost/mattermost](https://github.com/mattermost/mattermost) repository by [following these instructions](/developers/contribute/more-info/server/developer-workflow). + +### Legacy Notes + +The Mattermost API used to be defined in https://github.com/mattermost/mattermost-api-reference, but the source has since been moved to the [mattermost/mattermost](https://github.com/mattermost/mattermost) to streamline making code and documentation changes at the same time. diff --git a/docs/develop/contribute/more-info/server/schema-migration-guide.md b/docs/develop/contribute/more-info/server/schema-migration-guide.md new file mode 100644 index 000000000000..77dd02f7e9be --- /dev/null +++ b/docs/develop/contribute/more-info/server/schema-migration-guide.md @@ -0,0 +1,301 @@ +--- +title: "DB migration guide" +sidebar_position: 3 +--- + +## Overview + +This document aims to do an analysis of the types of schema migrations we do in Mattermost and ways to make them non-blocking so as to improve the Mattermost upgrade experience. +Historically, we have never put a lot of thought to the migration process. Developers would simply add a DDL statement and call it a day. But that causes a significant impact to large customers for whom downtime is not an option. This causes them to push back on upgrading their Mattermost version for a long time (sometimes for several years). This in turn, has some cascading effects like customers not able to get new features, performance improvements etc. + +We want to improve the situation and make upgrades a worry-free experience for our customers. It definitely comes at a cost of writing more code and delaying some features to avoid breaking changes. This document will aim to uncover all those cases and provide best practices to follow so that we can hit the right balance. + +## Goals + +We have two overarching goals and a third auxiliary goal. + +1. Schema migrations should **ALWAYS** be backwards compatible until the last ESR. +2. Schema migrations should **NEVER** lock the entire table. +3. Reduce migration time where possible. + +We want to strictly follow this as much as possible (even at the cost of slower feature development). + +### Background + +Schema changes are always made synchronously when Mattermost starts up. This means the application won't be ready to serve requests until all schema changes are applied. In most cases, the new application won't be able to work until those schema changes are in place. + +In a high availability environment, multiple instances will try to run migrations. To prevent this, a lock table is used in the migration system. Until migrations are completed, none of the instances will start. Once the lock is released by a node, another instance will obtain the lock, and check the migrations table. Since the previous node already applied the migrations, the remaining nodes won't re-apply the migrations. + +From Mattermost release v6.4, we have started using a schema-based migration system. We are now creating SQL statement files to run migrations. A developer must create migration files for each database driver. Since we want our migrations to be reversible, the developer must create one `up` script along with a `down` script. For instance, a single migration would have the following files: + +- `000066_upgrade_posts_v6.0.down.sql` +- `000066_upgrade_posts_v6.0.up.sql` + +A file naming convention is used to determine the order in which the migrations should be applied that appends `up|down.sql` suffix to the migration name. We were using a database version before the new migration system which is why the versions exist in the migration file name in the example. Going forward, using version identifiers for future next migration files is not mandatory. A developer can add any information to the name if they think it's going to be helpful. + +We are using [morph](https://github.com/go-morph/morph) for the migration engine. The tool has a library and also a CLI. Mattermost server imports the library to have programmatic access to morph functions. A developer can use the morph CLI tool to test whether their migrations are working properly. Please follow instructions in the morph documentation to use the morph CLI tool. + +### Analysis + +A rough analysis of our past schema migrations shows the following (some very early migrations were skipped which would be considered as base Mattermost): + +``` +CREATE INDEX - 489 +ALTER TABLE - 195 + ADD COLUMN - 113 + ALTER COLUMN - 51 + DROP COLUMN - 25 + ADD CONSTRAINT - 6 +DROP INDEX - 124 +CREATE TABLE - 60 +UPDATE - 19 +DELETE - 2 +``` + +![Migrations distribution](/contribute/more-info/server/migrations_pie.png) + +We will go through each of these migration types and discuss how we can make it non-blocking. This is a lengthy document, so for those wanting to directly look at the executive summary, we present it right now. And then expand on each section in detail later. + +### Conclusions + + +| Operation | Table rewrite | Concurrent DML allowed | +| ----------- | ------------- | ---------------------- | +| CREATE INDEX | NO | YES | +| DROP INDEX | NO | YES | +| ADD COLUMN | NO | YES1 | +| ALTER COLUMN | YES | NO | +| DROP COLUMN | YES | YES1 | +| ADD FK CONSTRAINT| NO | YES (only selects)2 | +| ADD UNIQUE CONSTRAINT | NO | YES | + + + + +1. Technically it takes an ACCESS EXCLUSIVE LOCK, however it is only to add/remove the metadata. The command returns instantly. +2. Adding FK constraint takes a SHARE ROW EXCLUSIVE [lock](https://www.postgresql.org/docs/11/sql-altertable.html). + + + +### Recommendations + +- **Try to avoid FK constraints**. +- **Strongly avoid trying to alter column types**. + +However, if you MUST do it, take a look into the following sections. + +### Details + +1. CREATE INDEX + +CREATE INDEX CONCURRENTLY does not take any locks. + +2. ALTER TABLE ADD COLUMN + +Adding nullable columns happens in constant time from version 10. And from version 11 onwards, adding non-null columns with a default value also happens in constant time. + +The catch here is to be able to handle denormalization optimizations which typically adds a new column but needs to backfill that with data before using the column. Take a look at the next section on how to achieve that. + +3. ALTER TABLE ALTER COLUMN + +This takes an exclusive lock. We strongly recommend you avoid doing this. + +To give some context, we have this particular migration `ALTER TABLE posts ALTER COLUMN props TYPE jsonb USING props::jsonb;` which has caused us more pain than it was worth. Several large customers have faced problems with this migration where in some cases, it has been observed to take 8+ hrs. Therefore, we strongly suggest to avoid making any `ALTER COLUMN` changes until absolutely unavoidable (for example, security issues). + +However, if you MUST do this, then see the example later. + +4. ALTER TABLE DROP COLUMN + +Only a metadata lock is taken. No table rewrite takes place. The space is just marked as unused and later taken up by future DB writes. + +5. ALTER TABLE ADD CONSTRAINT + +Relatively rare, but out of those 6 cases, 2 are adding unique constraints. For example: + +```sql +ALTER TABLE oauthaccessdata ADD CONSTRAINT oauthaccessdata_clientid_userid_key UNIQUE (clientid, userid); +``` + +This can be improved by first adding the index concurrently, and then attaching the index to the constraint. See example later. + +Adding a foreign key in PostgreSQL takes a share row exclusive lock, which means only SELECT queries are allowed. It is possible to bypass the table scanning by adding a “NOT VALID” suffix, but then it defeats the purpose of having a foreign key. We recommend against doing it. + +6. DROP INDEX + +DROP INDEX CONCURRENTLY does not take any locks. + +7. CREATE TABLE + +Does not lock any existing data so no issues. + +8. UPDATE + +An analysis shows that UPDATE statements roughly fall into one of these three categories: + +- **Data migrations**: + +```sql +UPDATE channelmembers SET MentionCountRoot = .. +UPDATE Channels SET TotalMsgCountRoot = .. +UPDATE ChannelMembers CM SET MsgCountRoot .. +``` + +In these cases, rather than operating on the entire table, we need to operate on batches at a time. See the example later on how to achieve that. + +- **Changing NULL columns to NON-NULL** + +```sql +UPDATE Channels SET LastRootPostAt=0 WHERE LastRootPostAt IS NULL; +UPDATE OAuthApps SET MattermostAppID = '' WHERE MattermostAppID IS NULL; +``` + +This is possible to handle from the code itself using a `COALESCE` function. It makes the code more complicated, but it’s a cost we have to pay to reduce migration overhead. + +- **Denormalization optimizations**: + +```sql +UPDATE threads SET threaddeleteat = posts.deleteat FROM posts WHERE threads.threaddeleteat IS NULL AND posts.id = threads.postid; +UPDATE reactions SET channelid = COALESCE((select channelid from posts where posts.id = reactions.postid), '') WHERE channelid=''; +UPDATE threads SET threadteamid = channels.teamid FROM channels WHERE threads.threadteamid IS NULL AND channels.id = threads.channelid; +UPDATE fileinfo SET channelid = posts.channelid FROM posts WHERE fileinfo.channelid IS NULL AND fileinfo.postid = posts.id; +``` + +We can take the same approach as in data migrations. + +9. DELETE + +So far, there have been only a handful of DELETE statements in schema migrations. And mostly they have been for security issues. The general recommendation is to avoid running a full-blown DELETE statement that operates on the entire table, but rather operate on batches so as to avoid taking a lock on the entire table. This could either be done in a job since there is no new code waiting for this to be executed. (See above) + +## Examples + +### How do I change a column type if I MUST + +Follow this long-winded procedure: +- Create a new column. +- Migrate existing data. +- From next ESR, start using the new column. +- Next ESR, drop the old column. + +For example, let’s say the next upcoming version is 8.4, and the next ESR is 8.6. So step 1 and 2, goes in 8.4. And in 8.7 onwards, we add the code to start using the new column, which will eventually be part of 8.12 (ESR after that). And then from 8.13 onwards, we can drop the column. + +The following diagram should explain things better: + +![ESR migrations](/contribute/more-info/server/ESR-diagram.png) + +The reasoning behind this is some customers will only upgrade from ESR to ESR. So we need to ensure backwards compatibility with the previous version. + +Following shows an example where we are adding a channel_count column to the status table. This is not exactly altering a column, but the idea remains the same, and you can extend this to fit your use-case. + +1. ALTER TABLE status ADD COLUMN channel_count integer; + +2. Our next objective is to migrate existing data. We do this in a 2-phase approach where we set up triggers to migrate all new data and in the background migrate old data in batches. + +```sql +CREATE OR REPLACE FUNCTION public.update_status_channel_count() + RETURNS trigger + LANGUAGE plpgsql +AS $function$ +DECLARE + member_count integer; +BEGIN + select count(*) into member_count from channelmembers where userid=NEW.userid; + NEW.channel_count := member_count; + RETURN NEW; +END +$function$ + +CREATE TRIGGER tr_update_status_channel_count +BEFORE INSERT OR UPDATE ON status +FOR EACH ROW EXECUTE PROCEDURE update_status_channel_count(); +``` + +After this is taken care of, we need to create a job, which will migrate existing data in batches. + +```sql +UPDATE status s SET channel_count=(SELECT count(*) FROM channelmembers cm WHERE cm.userid=s.userid) WHERE channel_count IS NOT NULL AND s.userid in (SELECT userid FROM status WHERE userid > '' ORDER BY userid ASC limit 10); +``` + +Then store the user id offset in the job metadata. + +```sql +UPDATE status s SET channel_count=(SELECT count(*) FROM channelmembers cm WHERE cm.userid=s.userid) WHERE channel_count IS NOT NULL AND s.userid in (SELECT userid FROM status WHERE userid > ORDER BY userid ASC limit 10); +``` + +At this point, when the job finishes, the new column would be ready to use. And the triggers would take care of always keeping the data up to date. + +3. Now we can start using the new column from the next ESR version. But we cannot yet drop the existing column because of backwards compatibility guarantees. The old column would still be in use by older app nodes in the cluster during upgrade. We also would want to drop the trigger since its use is finished. + +```sql +DROP TRIGGER tr_update_status_channel_count on status +``` + +4. And in the ESR after that, now we can finally drop the old column. + +This deliberately skips renaming the column for simplicity. Depending on your use-case, you can do that if you want to. It is a fast operation that does not rebuild the table, so there are no issues. + +### How do I add a unique constraint to a table + +```sql +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS oauthaccessdata_clientid_userid_key on oauthaccessdata(clientid, userid); +ALTER TABLE oauthaccessdata ADD UNIQUE USING INDEX oauthaccessdata_clientid_userid_key; -- This is instantaneous +``` + +### How do I run UPDATE statements in data migrations/denormalizations + +The idea would be to run the UPDATE statements in batches so as to avoid taking a large lock. This is similar to the second part in the column change example. + +Following is an example where I update the channels table in batches setting a new column. + +```sql +CREATE OR REPLACE FUNCTION public.update_in_batches() +RETURNS INTEGER +LANGUAGE plpgsql +AS $function$ +DECLARE + id_offset text := ''; + rows_updated integer; +BEGIN + LOOP + WITH table_holder AS ( + SELECT id FROM channels + WHERE id > id_offset + ORDER BY id ASC limit 100 + ) + UPDATE channels c SET new='improved' WHERE c.id in (SELECT id FROM table_holder); -- change this query to whatever your requirement is + GET DIAGNOSTICS rows_updated = ROW_COUNT; + + -- We have to run the select query again + -- becaue "select into" isn't allowed inside a CTE + -- and without CTE, we have to use a temp table (because you can't select into a table) + -- and with a temp table, you run into max_locks_inside_transaction limit. + -- Probably there is a better way but keeping things simple for now. + select id into id_offset from (select id from channels where id > id_offset ORDER BY id ASC limit 100) as temp order by id desc limit 1; + EXIT WHEN rows_updated = 0; + END LOOP; + return 1; +END +$function$; +``` + +## FAQ + +### I need to make a schema change. What do I do? + +1. Add the appropriate SQL script file containing the statements you want to run into the migrations directory. This directory is located in `{project_dir}/db/migrations/{driver_name}/`. +2. Run `make migrations-extract` to add your new migrations to the `db/migrations/migrations.list` file. This will ensure that there will be merge conflicts in case there is a conflict on migration sequence numbers with the master branch. Since we don't want to have a collision on version numbers of the migration files, the developer should merge the upstream branch to the feature branch just before merging so that we can be sure that there are no versioning issues. In case of a version number collision, the build process will fail and main branch will be broken until it gets fixed. +3. When you run the mattermost/server binary, the tool will automatically apply the migration if it's required. The migration name will be saved in the `db_migrations` table. +4. Lastly, please also measure the time taken for the migration with an eye towards resource usage. Please use the DB dumps from the ~developers-performance channel in our Community server. You will find the links in the channel header. +5. In your PR, make sure to add release notes following the [Developer Schema Migration Template](https://docs.google.com/document/d/18lD7N32oyMtYjFrJKwsNv8yn6Fe5QtF-eMm8nn0O8tk/edit?tab=t.0). + +### My migration has failed. What do I do? +1. If you think your migration is applied, and you want to revert changes, you can run the down script to roll back in a clean way. You can use morph CLI to apply down migrations. + - Before rolling down the script, check the `db_migrations` table whether the migration is applied or not. + - If it's applied you can revert it using morph CLI command. An example command would look like `morph apply down --driver {your-driver} --dsn "{your-dsn}" --path {path-to-your-driver-specific-migration-files} --number 1` +2. If the migration has been shipped in a release and you want to apply fixes, instead of changing the existing script, you should add a new one so that `db_migrations` will stay consistent. You can edit the existing migration to be a no-op for future releases in this case. + +## GLOSSARY + +- **DDL** - short form of Data Definition Language, which deals with database schema changes. For example: `CREATE TABLE`, `ALTER TABLE` etc. +- **DML** - short form of Data Manipulation Language, which deals with SQL queries that read/update/delete tables. For example: `SELECT`, `UPDATE`, `INSERT` etc. +- **FK** - Foreign Key + diff --git a/docs/develop/contribute/more-info/server/style-guide.md b/docs/develop/contribute/more-info/server/style-guide.md new file mode 100644 index 000000000000..2b85557b960c --- /dev/null +++ b/docs/develop/contribute/more-info/server/style-guide.md @@ -0,0 +1,344 @@ +--- +title: "Golang style guide" +sidebar_position: 3 +--- + +Golang ("go") is a more opinionated language than many others when it comes to coding style. The compiler enforces some basic stylistic elements, such as the removal of unused variables and imports. Many others are enforced by the `gofmt` tool, such as usage of white-space, semicolons, indentation, and alignment. The `gofmt` tool is run over all code in the Mattermost Server CI pipeline. Any code which is not consistent with the formatting enforced by `gofmt` will not be accepted into the repository. + +Despite this, there are still many areas of coding style which are not dictated by these tools. Rather than reinventing the wheel, we are adopting [Effective Go](https://golang.org/doc/effective_go.html) as a basis for our style guide. On top of that, we also follow the guidelines laid out by the Go project at [CodeReviewComments](https://go.dev/wiki/CodeReviewComments). + +However, at present, some of the guidelines from these sources come into conflict with existing patterns that are present in our codebase which cannot immediately be corrected due to the need to maintain backward compatibility. + +This document, which should be read in conjunction with [Effective Go](https://golang.org/doc/effective_go.html) and [CodeReviewComments](https://go.dev/wiki/CodeReviewComments), outlines the small number of exceptions we make to maintain backward compatibility, as well as a number of additional stylistic rules we have adopted on top of those external recommendations. + +### Application of guidelines + +The following guidelines should be applied to both new and existing code. However, this does not mean that a developer is *required* to fix any surrounding code that contravenes the rules in the style guide. It's encouraged to keep fixing things as you go, but it's not compulsory to do so. Reviewers should refrain from asking for stylistic changes in surrounding code if the submitter has not included them in their pull request. + +## Guidelines + +### Project layout + +When creating a new Go module, please follow the [standardized guidelines](https://go.dev/doc/modules/layout) of the Go team. + +[This blog article](https://go.dev/blog/package-names) provides additional guidance on package names. + +Following are some of the anti-patterns to keep in mind: + +- Don't use the `pkg` pattern. This is a common standard used by many projects. But it goes against the Go philosophy of naming packages that signify what they contain. From https://blog.golang.org/package-names: + +> A package's name provides context for its contents, making it easier for clients to understand what the package is for and how to use it. + +The `pkg` directory was used long ago in the Go project when there weren't any well-defined standards. But it was later removed to just have normal packages. + +- Same for `util` or `misc` packages. Don't use them. Instead break out related `util` functionalities into its own package or if it's not used by a lot of packages, make it part of the original package itself. + +- Don't have too many small packages with only one file. It's usually a sign of splitting packages without giving thought into them. Look at the API boundaries and group the packages into bigger chunks. + +### Functional + +#### Default to sync instead of async + +Always prefer synchronous functions by default. Async calls are hard to get right. They have no control over goroutine lifetimes and introduce data races. If you think something needs to be asynchronous, measure it and prove it. Ask these questions: + +- Does it improve performance? If so, by how much? +- What’s the tradeoff of the happy path vs. slow path? +- How do I propagate errors? +- What about back-pressure? +- What should be my concurrency model? + +Do not create one-off goroutines without knowing when/how they exit. They cause problems that are hard to debug, and can often cause performance degradation rather than an improvement. Have a look at: + +- https://go.dev/wiki/CodeReviewComments#goroutine-lifetimes +- https://go.dev/wiki/CodeReviewComments#synchronous-functions + +#### Pointers to slices + +Do not use pointers to slices. Slices are already reference types which point to an underlying array. If you want a function to modify a slice, then return that slice from the function, rather than passing a pointer. + +#### Avoid creating more ToJSON methods + +Do not create new `ToJSON` methods for model structs. Instead, just use `json.Marshal` at the call site. This has two major benefits: + +- It avoids bugs due to the suppression of the JSON error which happens with `ToJSON` methods (we've had a number of bugs caused by this). +- It's a common pattern to pass the output to something (like a network call) which accepts a byte-slice, leading to a double conversion from byte-slice to string to a byte-slice again if `ToJSON` methods are used. + +#### [Interfaces](https://go.dev/wiki/CodeReviewComments#interfaces) + +- Return structs, accept interfaces. +- Interface names should end with “-er”. This is not a strict rule. Just a guideline which indicates the fact that interface functionalities are designed around the concept of “doing” something. +- Try not to define interfaces on the implementer side of an API "for mocking"; instead, design the API so that it can be tested using the public API of the real implementation. + +As an example, if you're trying to integrate with a third-party service, it's tempting to create an interface and use that in the code so that it can be easily mocked in the test. This is an anti-pattern and masks real bugs. Instead, you should try to use the real implementation via a docker container or if that's not feasible, mock the network response coming from the external process. + +Another common pattern is to preemptively declare the interface in the source package itself, so that the consumer can just directly import the interface. Instead, try to declare the interface in the package which is going to consume the functionality. Often, different packages have non-overlapping set of functionalities to consume. If you do find several consumers of the package, remember that interfaces can be composed. So define small chunks of functionalities in different interfaces, and let consumers compose them as needed. Take a look at the set of interfaces in the [io](https://golang.org/pkg/io/) package. + +These are just guidelines and not strict rules. Understand your use case and apply them appropriately. + +### Stylistic + +#### [CamelCase variables/constants](https://go.dev/wiki/CodeReviewComments#mixed-caps) + +We use CamelCase names like WebsocketEventPostEdited, not WEBSOCKET_EVENT_POST_EDITED. + +#### Empty string check + +Use `foo == ""` to check for empty strings, not `len(foo) == 0`. + +#### [Reduce indentation](https://go.dev/wiki/CodeReviewComments#indent-error-flow) + +If there are multiple return statements in an if-else statement, remove the else block and outdent it. + +This is an example from `mlog/human/parser.go`: + +```go +// Look for an initial "{" +if token, err := dec.Token(); err != nil { + return result, err +} else { + d, ok := token.(json.Delim) + if !ok || d != '{' { + return result, fmt.Errorf("input is not a JSON object, found: %v", token) + } +} +``` + +This can be simplified to: + +```go +// Look for an initial "{" +if token, err := dec.Token(); err != nil { + return result, err +} +d, ok := token.(json.Delim) +if !ok || d != '{' { + return result, fmt.Errorf("input is not a JSON object, found: %v", token) +} +``` + +#### [Initialisms](https://go.dev/wiki/CodeReviewComments#initialisms) + +Use `userID` rather than `userId`. Same for abbreviations; `HTTP` is preferred over `Http` or `http`. + +#### [Receiver names](https://go.dev/wiki/CodeReviewComments#receiver-names) + +The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client"). Don't use generic names such as "me", "this", or "self" identifiers typical of object-oriented languages that give the variable a special meaning. + +#### Error variable names + +The name of any `error` variable must be `err` or prefixed with `err`. The name of any `*model.AppError` variable must be `appErr` or prefixed with `appErr`. This allows us to avoid confusion about how to handle different kind of errors inside Mattermost. If you are storing the error value from a function that returns an `error` type in its signature, it's considered an `error`, regardless of whether the function, internally, is returning a `*model.AppError` instance. + +For example, when the function signature returns an `error`, we use the `err` variable name: + +```go +func MyFunction() error { + return model.NewAppError(...) +} + +func OtherFunction() { + ... + err := MyFunction() + ... +} +``` + +When the function signature returns an `*model.AppError`, we use the `appErr` variable name: + +```go +func MyFunction() *model.AppError { + return model.NewAppError(...) +} + +func OtherFunction() { + ... + appErr := MyFunction() + ... +} +``` + +### Errors + +Always add proper context to errors. + +#### Include the user input for validation errors. + +For example: + +`return fmt.Errorf("invalid export type, must be one of: csv, actiance, globalrelay")` does not include what was the input value entered by the user. A better way might be: + +```diff +- return fmt.Errorf("invalid export type, must be one of: csv, actiance, globalrelay") ++ return fmt.Errorf("invalid export type: %s, must be one of: csv, actiance, globalrelay", exportType) +``` + +Another example: + +```diff +if r.Start > r.End { +- return fmt.Errorf("report timestamps are erroneous") ++ return fmt.Errorf("report timestamps are erroneous: start_timestamp %f is greater than end_timestamp %f", r.Start, r.End) +} +``` +#### Return errors instead of boolean for ID validation errors + +A validation function can check various properties of an object. But if we simply return true or false, and then log that object is invalid, the user will have no idea why it is invalid or how to fix it. + +For example: + +```diff +- func IsValidId(value string) bool { ++ func IsValidId(value string) error { + if len(value) != 26 { +- return false ++ return fmt.Errorf("Invalid length. Found: %d; expected: %d", len(value), 26) + } + + for _, r := range value { + if !unicode.IsLetter(r) && !unicode.IsNumber(r) { +- return false ++ return fmt.Errorf("Rune %c in %s is not an unicode letter or number", r, value) + } + } + +- return true ++ return nil +} +``` + +### Logging + +Log messages should be annotated with contextual information in the form of key-value pairs to make it easier to identify the context they originated from. The keys should use snake_case. Refer to the corresponding JSON struct tags for key names. + +```go +func (a *App) SendNotifications(...) { + .. + _, err := a.sendOutOfChannelMentions(c, sender, post, channel, ...) + if err != nil { + c.Logger().Error( + "Failed to send warning for out of channel mentions", + mlog.String("user_id", sender.Id), + mlog.String("post_id", post.Id), + mlog.Err(err), + ) + } + .. +} +``` + +#### Avoid double-logging + +Double-logging is when you immediately log something after an error, and also return an error at the same time. This creates two log lines with the same error and is confusing to the admin. The best practice is to always pass the error upwards adding context and log it in the upper-most layer correct. Logging the error at the lowest layer does not give any additional context as to from where it was called, and what path did the code take to reach there. + +For example: + +```diff +if err != nil { +- mlog.Error("Failed to generate SQL query", +- mlog.String("user_id", userID), +- mlog.Int("timestamp", int(syncTime)), +- mlog.Err(err), +- ) +- return errors.Wrap(err, "failed to generate SQL query") ++ return errors.Wrapf(err, "failed to generate SQL query: user_id: %s, timestamp: %d", userID, int(syncTime)) +} +``` + +#### Log levels + +The purpose of logging is to provide observability - it enables the application communicate back to the administrator about what is happening. To communicate effectively logs should be meaningful and concise. To achieve this, log lines should conform to one of the definitions below: + +**Critical:** This log-level represents the most severe situations when the service is entirely unable to continue operating. After emitting a _critical_ log line, it is expected that the service will terminate. + +For example, the code block below demonstrates a _critical_ situation where the server startup routine fails, meaning the service is unable to start and must terminate. + +```go +func runServer(..) { + .. + server, err := app.NewServer(options...) + if err != nil { + mlog.Critical(err.Error()) + return + } + .. +} +``` + +**Error:** This log-level is used when something unexpected has happened to the service, but it does not result in a total loss of service. Log lines using the _error_ level must be actionable, so that the system administrator can investigate and resolve the incident. The _error_ log level may indicate a loss of service for an individual user or request or it may indicate a total failure of a non-critical subsystem within the service. + +For example, the _error_ log level is used in the code snippet below as it represents a partial failure of one non-critical subsystem of the service. Administrator intervention is required to resolve this situation, but the rest of the service is able to continue operating in the meantime. + +```go +func (a *App) SyncPlugins(..) { + .. + reader, appErr := a.FileReader(plugin.path) + if appErr != nil { + mlog.Error("Failed to open plugin bundle from file store.", mlog.String("bundle", plugin.path), mlog.Err(appErr)) + return + } + .. +} +``` + +**Warn:** This log level is used to indicate that something unexpected has happened, but the server is able to continue operating and it has not suffered any loss of functionality as a consequence of this failure. System administrators may wish to investigate the cause of log lines at this level, but the need is typically less pressing than for those at _error_ level. System administrators may also wish to monitor the rate of occurrence of individual log-lines at this level as this may be indicative of a wider problem. Log lines at the _warning_ level should be as detailed as possible, since these are often the least clear-cut category of message. + +For example, the _warning_ log level may be used to indicate that something went wrong but the overall operation was still able to complete successfully. + +```go +func (a *App) UpdateUserRoles(..) { + .. + if result := <-schan; result.NErr != nil { + // soft error since the user roles were still updated + mlog.Warn("Error during updating user roles", mlog.Err(result.NErr)) + } + + a.InvalidateCacheForUser(userId) + .. +} +``` + +**Info:** This log level should be used to record normal, expected application behavior, even if it results in an error for the end user. They are not actionable individually, but the significant changes in the frequency of occurrence of individual log lines at this level may be indicative of a possible problem. + +For example, the _info_ log level may be used to communicate to administrators that certain subsystems within the service have been started or stopped. + +```go +func (s *Schedulers) Start(..) { + s.startOnce.Do(func() { + mlog.Info("Starting schedulers.") + .. + }) + .. +} +``` + +**Debug:** This log-level is used for diagnostic information which may be used to debug issues but is not necessary for normal production system logging, nor actionable by system administrators. + +```go +func (worker *Worker) Run() { + mlog.Debug("Worker started", mlog.String("worker", worker.name)) + .. +``` + +### Performance sensitive areas + +Any PR that can potentially have a performance impact on the `mattermost/server` codebase is encouraged to have a performance review. For more information, please see this [link](https://docs.google.com/document/d/1Uzt3XHyKhDKipkuCmESkHoPio7vz7VYS4N_5_9ffgNU/edit). The following is a brief list of indicators that should to undergo a performance review: + +- New features that might require benchmarks and/or are missing load-test coverage. +- PRs touching performance of critical parts of the codebase (e.g. `Hub`/`WebConn`). +- PRs adding or updating SQL queries. +- Creating goroutines. +- Doing potentially expensive allocations: `bytes.Buffer` and `[]byte`: + - Use of `Buffer.Grow`, `Buffer.ReadFrom`, `ioutil.ReadAll`. + - Creating big slices and maps without capacity when size is known in advance. +- Recursion, unbounded, and deeply nested `for` loops. +- Use of locks and/or other synchronization primitives. +- Regular expressions, especially when creating `regexp.MustCompile` dynamically every time. +- Use of the `reflect` package. + +## Propose a new rule + +To propose a new rule, follow the process below: + +- Add it to the agenda in the [Server](https://community.mattermost.com/core/channels/developers-server) Guild meeting, and propose it. +- If it gets accepted, create a go-vet rule (if possible), or a golangci-lint rule to prevent new regressions from creeping in. +- Fix all existing issues. +- Add it to this guide. diff --git a/docs/develop/contribute/more-info/server/system_console.md b/docs/develop/contribute/more-info/server/system_console.md new file mode 100644 index 000000000000..3a235460c14f --- /dev/null +++ b/docs/develop/contribute/more-info/server/system_console.md @@ -0,0 +1,21 @@ +--- +title: "System Console" +sidebar_position: 5 +--- + +## Add fields to the configuration + +In order to add fields to the configuration, you need to modify `model/config.go` in the server by adding the desired field to one of the structs such as `ServiceSettings` and setting its default value in the corresponding `SetDefaults` method. + +Note that some of the configuration values are collected as telemetries. The telemetry definitions are defined in the `services/telemetry` package. Once a configuration is added, it should be added to the telemetry package. If the configuration value is not going to be collected as a telemetry, a `// telemetry: none` comment must be added to prevent the [configtelemetry](https://github.com/mattermost/mattermost-govet#included-analyzers) check from failing. + +Also we use struct tags to identify access level for configuration values. If the value requires a restriction, please use this tag accordingly. + +### Expose settings in the System Console + +To expose the newly-added field in the System Console, you need to add that same setting to the `AdminDefinition` JS object in `webapp/channels/src/components/admin_console/admin_definition.jsx`. This object defines most of the settings in the System Console. + + +### Make settings available for non-admin users + +To make the newly added setting accessible to non-admin users in the apps, you'll need to add it to the `GenerateClientConfig` method in `config/client.go` in the server. Note that this always encodes the setting as a string, so anywhere that you would want to use this value in the client, you have to look for a string. diff --git a/docs/develop/contribute/more-info/server/tests.md b/docs/develop/contribute/more-info/server/tests.md new file mode 100644 index 000000000000..4bcf388415f4 --- /dev/null +++ b/docs/develop/contribute/more-info/server/tests.md @@ -0,0 +1,122 @@ +--- +title: "Tests" +sidebar_position: 2 +--- + +## Handling Flaky Tests + +A flaky test is one that exhibits both passing and failing results when run multiple times without any code changes. When our automation detects a flaky test on your PR: + +1. **Check if the Test is Newly Introduced** + - Review your PR changes to determine if the flaky test was introduced by your changes + - If the test is new, fix the flakiness in your PR before merging + +2. **For Existing Flaky Tests** + - Create a JIRA ticket titled "Flaky Test: \{TestName\}", e.g. "Flaky Test: TestGetMattermostLog" + - Copy the test failure message into the JIRA ticket description + - Add the `flaky-test` and `triage-global` labels + - Create a PR to skip the test by adding: + + ```go + t.Skip("https://mattermost.atlassian.net/browse/MM-XXXXX") + ``` + + where MM-XXXXX is your JIRA ticket number + - Link the JIRA ticket in the skip message for tracking + +This process helps us track and systematically address flaky tests while preventing them from blocking development work. + +## Writing Parallel Tests + +Leveraging parallel tests can drastically reduce execution time for entire test packages, such as [`api4`](https://github.com/mattermost/mattermost/tree/master/server/channels/api4) and [`app`](https://github.com/mattermost/mattermost/tree/master/server/channels/app), which are notably heavy with hundreds of tests. However, careful implementation is essential to ensure reliability and prevent flakiness. Follow these guidelines when writing parallel tests: + +### Enabling Parallel Tests + +In [`api4`](https://github.com/mattermost/mattermost/tree/master/server/channels/api4), [`app`](https://github.com/mattermost/mattermost/tree/master/server/channels/app), [`platform`](https://github.com/mattermost/mattermost/tree/master/server/channels/app/platform), [`email`](https://github.com/mattermost/mattermost/tree/master/server/channels/app/email), [`jobs`](https://github.com/mattermost/mattermost/tree/master/server/channels/jobs) packages: + +```go +func TestExample(t *testing.T) { + mainHelper.Parallel(t) + + ... +} + +// OR + +func TestExample(t *testing.T) { + th := Setup(t) + th.Parallel(t) + + ... +} + +// OR + +func TestExample(t *testing.T) { + if mainHelper.Options.RunParallel { + t.Parallel() + } + + ... +} + +``` + +If [`sqlstore`](https://github.com/mattermost/mattermost/tree/master/server/channels/store/sqlstore) package: + +```go +func TestExample(t *testing.T) { + if enableFullyParallelTests { + t.Parallel() + } + + ... +} +``` + +To enable parallel execution, you should set the `ENABLE_FULLY_PARALLEL_TESTS` environment variable. Example: + +```bash +ENABLE_FULLY_PARALLEL_TESTS=true go test -v ./api4/... +``` + +### When to Use Parallel Tests + +- **Generally Safe**: Tests with dedicated setup functions that ensure independence from other tests. +- **Subtests**: Only safe if each subtest features its own setup function, ensuring they are decoupled and independent of execution order. +- **Unsafe**: When a subtest depends on state changes made by another subtest, thus coupling their execution order. + +### Common Issues That Break Parallel Safety + +#### Global State + +Avoid reliance on global variables and registrations such as: + +- `LicenseValidator` +- `platform.RegisterMetricsInterface` +- `platform.PurgeLinkCache` +- `model.BuildEnterpriseReady` +- `jobs.DefaultWatcherPollingInterval` + +#### Filesystem Operations + +Avoid using `os.Chdir` (or `t.Chdir`) and relative paths tied to the test executable, as they may introduce inconsistencies when tests run in parallel. When possible, rely on temporary directories such as `th.tempWorkspace` which are dedicated to the test. + +#### Environment Variables + +Using `os.Setenv` for feature flags and other settings can cause interference between parallel tests. Instead, use the configuration API: + +```go +// UNSAFE for parallel tests: +os.Setenv("MM_FEATUREFLAGS_CUSTOMFEATURE", "true") +defer os.Unsetenv("MM_FEATUREFLAGS_CUSTOMFEATURE") + +// SAFE for parallel tests: +th.App.UpdateConfig(func(cfg *model.Config) { + cfg.FeatureFlags.CustomFeature = true +}) +``` + +#### Process-Level Methods + +Be cautious with methods affecting the entire process, such as `pprof.StartCPUProfile`, which can introduce contention between tests. diff --git a/docs/develop/contribute/more-info/server/tooling.md b/docs/develop/contribute/more-info/server/tooling.md new file mode 100644 index 000000000000..0e0d681804f7 --- /dev/null +++ b/docs/develop/contribute/more-info/server/tooling.md @@ -0,0 +1,23 @@ +--- +title: "Tools" +sidebar_position: 10 +--- + +## Mattermost Server + +In the [mattermost repository](https://github.com/mattermost/mattermost), we are using [Docker](https://www.docker.com/) images and [Docker Compose](https://docs.docker.com/compose/) to set up the development enviroment. The following are required images: + +- [MySQL](https://www.mysql.com/) +- [PostgreSQL](https://www.postgresql.org/) +- [MinIO](https://min.io/) +- [Inbucket](https://www.inbucket.org/) +- [OpenLDAP](https://www.openldap.org/) +- [Elasticsearch](https://www.elastic.co) + +We also have added optional tools to help with your development: + +### Dejavu + +[Dejavu](https://opensource.appbase.io/dejavu/) is a user interface for Elasticsearch when no UI is provided to visualize or modify the data you're storing inside Elasticsearch. + +To use Dejavu, execute `docker-compose up -d dejavu`. It will run at `http://localhost:1358`. diff --git a/docs/develop/contribute/more-info/webapp/build-component.md b/docs/develop/contribute/more-info/webapp/build-component.md new file mode 100644 index 000000000000..d18700d786ee --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/build-component.md @@ -0,0 +1,163 @@ +--- +title: "Build a component" +sidebar_position: 4 +--- + +This page describes how to build a new React component in the Mattermost web app. A new component must meet the following requirements: + +1. Is pure, meaning that all information required to render is passed in by props. +2. Has no direct store interaction. Use `connect` to wrap the component if needed. +3. Has component tests. +4. Is generic and re-usable when possible. +5. Has documented props. + +If none of those make any sense to you or you're new to React and Redux, then check out these links: + +- https://react.dev/learn/ +- http://redux.js.org/ + +These requirements are discussed in more detail in the following sections. + +## Design the component + +The most important part of designing your component is deciding on what the props will be. Props are very much the API for your component. Think of them as a contract between your component and the users. + +Props are read-only variables that get passed down to your component either directly from a parent component or from an `index.ts` container that connects the component to the Redux store. + +How do you decide what props your component should have? Think about what your component is trying to display to the user. Any data you need to accomplish that should be part of the props. + +As an example, let's imagine we're building an `ItemList` component with the purpose of displaying a list of items. The props for such a component might look like: + +```typescript +type Props = { + /** + * The title of the list + */ + title?: string; + + /** + * An array of items to display + */ + items: ListItem[]; +} +``` + +The `title` prop is a string that's displayed as the title of the list, and `items` is an array of objects that make up the contents of the list. Note that `items` is required while `title` is optional. + +Make sure you add brief but clear comments to each prop type as shown in the example. + +Our ItemList component would live in a file named `item_list.tsx`. + +## Use a Redux container component + +The next question to ask yourself is whether you're going to need a container component. This is the `index.ts` file mentioned above. If your component needs either of the following, then you'll need a container: + +1. Needs some data injected into its props that the parent component doesn't have access to +2. Needs to be able to perform some sort of action that affects the state of the store + +Continuing the `ItemList` example above, maybe our parent component doesn't care about our list of items and doesn't have access to them. Let's also imagine that we want to let the user remove items from the list by clicking on them. This means our component now needs a container for both criteria above and our props will change slightly: + +```typescript +type Props = { + /** + * The title of the list + */ + title?: string; + + /** + * An array of item components to display + */ + items: ListItem[]; + + actions: { + /** + * An action to remove an item from the list + */ + removeItem: (item: ListItem) => void; + }; +} +``` + +Note that the type definition for actions passed from Redux won't include the any reference to Redux's `dispatch` or Redux Thunk's `getState`. This is intentional as `connect` hides those details from the component. + +The container will then handle getting data from the Redux state in `mapStateToProps` and passing Redux actions to the component using `mapDispatchToProps`. Note that either of these are optional if only one is needed. + +```typescript +import {connect} from 'react-redux'; +import {bindActionCreators, Dispatch} from 'redux'; + +import {removeItem} from 'mattermost-redux/actions/items'; +import {getItems} from 'mattermost-redux/selectors/entities/items'; + +import {GlobalState} from 'types/store'; + +import ItemList from './item_list'; + +function mapStateToProps(state: GlobalState) { + return { + items: getItems(state), + }; +} + +function mapDispatchToProps(dispatch: Dispatch) { + return { + actions: bindActionCreators({ + removeItem, + }, dispatch), + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ItemList); +``` + +If the selectors and/or actions you need don't yet exist in Redux then you should go add those first by following the [guide to adding actions and selectors](/developers/contribute/more-info/webapp/redux/actions). + +Your `index.ts` and `item_list.ts` files will live together in an `item_list/` directory. + +## Implement the component + +With the props defined and, if necessary, the container built, you're ready to implement the rest of your component. For the most part, implementing a component for the web app is no different than building any other React component. While older code tends to use class components which extend `React.PureComponent`, most newer code should use functional components. + +Our `ItemList` example might look something like this: + +```tsx +type Props = { + /** + * The title of the list + */ + title?: string; + + /** + * An array of item components to display + */ + items: ListItem[]; + + actions: { + /** + * An action to remove an item from the list + */ + removeItem: (item: ListItem) => void; + }; +} + +export default function ItemList(props: Props) { + const title = this.props.title ?

{this.props.title}

: null; + const items = this.props.items.map((item: ListItem) => ( + + )); + + return ( +
+ {title} + {items} +
+ ); +} +``` + +--- +To test your component, [follow the guide here](/developers/contribute/more-info/webapp/unit-testing). diff --git a/docs/develop/contribute/more-info/webapp/developer-workflow.md b/docs/develop/contribute/more-info/webapp/developer-workflow.md new file mode 100644 index 000000000000..d7bddd455ae3 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/developer-workflow.md @@ -0,0 +1,40 @@ +--- +title: "Web app workflow" +sidebar_position: 3 +--- + +This page contains most of the information required for a developer to work with the Mattermost web app. Note that everything in this document will refer to working in the `webapp` directory of [the main Mattermost repository](https://github.com/mattermost/mattermost) unless otherwise stated. + +### Workflow + +1. If you haven't done so already, [set up your developer environment](/developers/contribute/developer-setup). + +2. On your fork, create a feature branch for your changes. Name it `MM-$NUMBER_$DESCRIPTION` where `$NUMBER` is the [Jira](https://mattermost.atlassian.net) ticket number you are working on and `$DESCRIPTION` is a short description of your changes. Example branch names are `MM-18150_plugin-panic-log` and `MM-22037_uppercase-email`. You can also use the name `GH-$NUMBER_$DESCRIPTION` for tickets come from [GitHub Issues](https://github.com/mattermost/mattermost/issues). + +3. Make the code changes required to complete your ticket, making sure to write or modify unit tests where appropriate. Use `make test` to run the unit tests. + +4. To run your changes locally, you'll need to run both the client and server. The server and client can either be run together or separately as follows: + * You can run both together by using `make run` from the server directory. Both server and web app will be run together and can be stopped by using `make stop`. If you run into problems getting the server running this way, you may want to consider running them separately in case the output from one is hiding errors from the other. + + * You can run the server independently by running `make run-server` from its directory and, using another terminal, you can run the web app by running `make run` from the web app directory. Each can be stopped by running `make stop-server` or `make stop` from their respective directories. + + Once you've done either of those, your server will be available at `http://localhost:8065` by default. Changes to the web app will be built automatically, but changes to the server will only be applied if you restart the server by running `make restart-server` from the server directory. + +5. If you added or changed any translatable text, you will need to update the English translation files to make them available to translators for other languages. You can do that by navigating to `channels` and running `make i18n-extract` to update `src/i18n/en.json`. + * Remember to double check that any newly added strings have the correct values in case they weren't detected correctly. + * Generally, only `en.json` should be modified directly from this repository. Other languages' translation files are updated using [Weblate](https://translate.mattermost.com). + +6. Before submitting a PR, make sure to check your coding style and run the automated tests on your changes. These are checked automatically by CI, but they should be run manually before submitting changes to ensure the review process goes smoothly. + * To check the code style and run the linter, run `make check-style`. If any problems are encountered, they may be able to be automatically fixed by using `make fix-style`. + * To run the type checker, use `make check-types`. + * To run the unit tests, run `make test`. + +7. Commit your changes, push your branch and [create a pull request](https://developers.mattermost.com/blog/submitting-great-prs/). + +8. Respond to feedback on your pull request and make changes as necessary by committing to your branch and pushing it. Your branch should be kept roughly up to date by [merging](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merging) master into it periodically. This can either be done using [`git merge`](https://git-scm.com/docs/git-merge) or, as long as there are no conflicts, by commenting `/update-branch` on the PR. + +9. That's it! Rejoice that you've helped make Mattermost better. + +### Useful Mattermost commands + +During development you may want to reset the database and generate random data for testing your changes. See [the corresponding section of the server developer workflow](/developers/contribute/more-info/server/developer-workflow#useful-mattermost-commands) for how to do that. diff --git a/docs/develop/contribute/more-info/webapp/e2e-cheatsheets.md b/docs/develop/contribute/more-info/webapp/e2e-cheatsheets.md new file mode 100644 index 000000000000..ecc945579705 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/e2e-cheatsheets.md @@ -0,0 +1,161 @@ +--- +title: "End-to-End (E2E) cheatsheets" +sidebar_position: 7 +--- + +This page compiles all Cypress custom commands based on specific sections of the web app, as well as other general examples. The examples provided showcase the best and conventions on how to write great automated test scripts. +We encourage everyone to read this information, ask questions if something is not clear, and challenge the mentioned practices so that we can continuously refine and improve. + +If you need to add more custom commands, add them to `/e2e-tests/cypress/tests/support`, and check out the [Cypress custom commands](https://docs.cypress.io/api/cypress-api/custom-commands.html) documentation. For ease of use, in-code documentation functionality, and making custom commands more discoverable, add type definitions. See this example of a [declaration file](https://github.com/mattermost/mattermost/blob/master/e2e-tests/cypress/tests/support/api/user.d.ts) for reference on how to include and make type definitions. +_____ +### General Queries with the Testing Library + +The [Testing Library](https://testing-library.com/) is used through the package `@testing-library/cypress`, and it provides simple and complete custom Cypress commands and utilities that encourage such good testing practices. To decide on the queries from the Testing Library you should be using while writing Cypress tests, check out this [article](https://testing-library.com/docs/guide-which-query/) to learn more. For instance, you can select something with test ID using: `cy.findByTestId`. + +If you need more help, check out the [online Testing Playground](https://testing-playground.com/)—no install required, always up-to-date, and it teaches you the exact Testing-Library queries you should be using as you click through the DOM. And if you’d rather stay in a VSCode editor, check out the [VS Code Testing Playground](https://marketplace.visualstudio.com/items?itemName=aganglada.vscode-testing-playground) extension, which brings the same interactive query suggestions and best-practice guidance right into your IDE. + +The following is a short summary of the recommended order of priority for queries: + +#### :white_check_mark: Queries Accessible to Everyone +These reflect the experience of visual/mouse users as well as those that use assistive technology. Examples include: `cy.findByRole`, `cy.findByLabelText`, `cy.findByPlaceholderText`, `cy.findByText`, and `cy.findByDisplayValue`. + +#### :white_check_mark: Semantic Queries +These use HTML5 and ARIA–compliant selectors. Note that the user experience of interacting with these attributes varies greatly across browsers and assistive technology. Some examples include: `cy.findByAltText` and `cy.findByTitle`. + +#### :warning: Base Queries +These are considered part of implementation details and are discouraged to be used. You will still find base queries in the codebase but they will be replaced soon. Therefore, please refrain from reusing the existing base query patterns. However, you may want to use them only to limit the scope of selection. Examples include: `cy.get('#elementId')` and `cy.get('.class-name')`. Below is an acceptable use case of base queries: + +```javascript +// limit the scope but chained with recommended query +cy.get('#elementId').should('be.visible').findByRole('button', {name: 'Save'}).click(); + +// limit the scope then use the recommended queries within the scope +cy.get('.class-name').should('be.visible').within(() => { + cy.findByRole('input', {name: 'Position'}).type('Software Developer'); + cy.findByRole('button', {name: 'Save'}).click(); +}); +``` + +#### :white_check_mark: Query Variants + +Note that `cy.findBy*` are shown but other variants are `cy.findAllBy*`, `cy.queryBy*`, and `cy.queryAllBy*`. See the [Queries](https://testing-library.com/docs/dom-testing-library/api-queries) section from `testing-library`. + +#### :x: Off-limits Queries +Please do not use any `Xpath` selectors such as the descendant selector. Do not use the `ul > li` and order selectors either, like `ul > li:nth-child(2)`. If an element can only be queried with this approach, then you may modify the application codebase, improve it, and make it "accessible to everyone". +_____ +### Settings Modal +![settings modal image](../../../../img/e2e/settings-modal.png) + +#### Opening the settings modal +The function `cy.uiOpenSettingsModal(section)` opens the settings modal when viewing a channel. `section` is of the +< string > type. Possible values for `section` are: `'Notifications'`, `'Display'`, `'Sidebar'`, and `'Advanced'`. + + * **Open 'Settings' modal and view the default 'General Settings'**: `cy.uiOpenSettingsModal();` + * **Open the Settings modal and view a specific section (like the 'Advanced' section)**: `cy.uiOpenSettingsModal('Advanced');` + * **Open the Settings modal, view a specific section, and change a setting**: + ```javascript + // # Open 'Advanced' section of 'Settings' modal + cy.uiOpenSettingsModal('Advanced').within(() => { + // # Open 'Enable Join/Leave Messages' and turn it off + cy.findByRole('heading', {name: 'Enable Join/Leave Messages'}).click(); + cy.findByRole('radio', {name: 'Off'}).click(); + // # Save and close the modal + cy.uiSave(); + cy.uiClose(); + }); + ``` + +#### Selecting a section's button within a modal +Use the function `cy.findByRoleExtended('button', {name})`. `name` is of the < string > type. Possible values for `name` are: `'Notifications'`, `'Display'`, `'Sidebar'`, and `'Advanced'`. + + * **Clicking a button within the Settings modal**: + ```javascript + // # Open 'Advanced' section of 'Settings' modal + cy.uiOpenSettingsModal().within(() => { + // # Click 'Notifications' button + cy.findByRoleExtended('button', {name: 'Notifications'}).should('be.visible').click(); + }); + ``` +#### Select a section's setting within a modal via the name of the section +Use the function `cy.findByRole('heading', {name})`. `name` is of the < string > type. Possible values for `name` are: `'Full Name'`, `'Username'`, and others depending on the sections in the modal. + + * **Open a section within the Settings modal**: + ```javascript + // # Open 'Notifications' of 'Settings' modal + cy.uiOpenSettingsModal('Notifications').within(() => { + // # Open 'Words That Trigger Mentions' setting + cy.findByRole('heading', {name: 'Words That Trigger Mentions'}).should('be.visible').click(); + }); + ``` + +#### Select a section's setting within a modal via role +Use the function `cy.findByRole(role, {name})`. `role` is of the < string > type. Possible values for `role` are: `'textbox'`, `'radio'`, `'checkbox'` and other roles. `name` is of the < string > type. Possible values for `name` are: `'On'`, `'Off'`, and others depending on a section's settings. + * **Change value of a section's setting in the Settings modal**: + ```javascript + // # Open 'Notifications' of 'Settings' modal + cy.uiOpenSettingsModal('Notifications').within(() => { + // # Open 'Words That Trigger Mentions' setting + cy.findByRole('heading', {name: 'Words That Trigger Mentions'}).should('be.visible').click(); + // # Check channel-wide mentions + cy.findByRole('checkbox', {name: 'Channel-wide mentions "@channel", "@all", "@here"'}).click(); + }); + ``` + +#### Saving and closing a modal +`cy.uiSave` and `cy.uiClose` are common functions that can be used to save things and close modals. + + * **Saving and closing in the Settings modal**: + ```javascript + // # Open 'Notifications' of 'Settings' modal + cy.uiOpenSettingsModal('Notifications').within(() => { + // # Open 'Words That Trigger Mentions' setting + cy.findByRole('heading', {name: 'Words That Trigger Mentions'}).should('be.visible').click(); + // # Check channel-wide mentions + cy.findByRole('checkbox', {name: 'Channel-wide mentions "@channel", "@all", "@here"'}).click(); + // # Save then close the modal + cy.uiSave(); + cy.uiClose(); + }); + ``` +_____ +### Channel Menu +![channel menu image](../../../../img/e2e/channel-menu.png) + +#### Opening the channel menu +Use the function `cy.uiOpenChannelMenu(item)`. This will open the channel menu by clicking the channel header title or dropdown icon when viewing a channel. `item` is of the type < string >. Possible values for `item` are: `'View Info'`, `'Move to...'`,`'Notification Preferences'`, `'Mute Channel'`, `'Add Members'`, `'Manage Members'`,`'Edit Channel Header'`, `'Edit Channel Purpose'`, `'Rename Channel'`, and `'Convert to Private Channel'`, `'Archive Channel'`, and `'Leave Channel'`. + + * **Open the channel menu normally**: + ```javascript + // # Open 'Channel Menu' + cy.uiOpenChannelMenu(); + ``` + * **Open the channel menu and click on a specific item**: + ```javascript + // # Open 'Advanced' section of 'Settings' modal + cy.uiOpenChannelMenu('View Info'); + ``` +#### Closing the channel menu +Use the function `cy.uiCloseChannelMenu()`. This will close the channel menu by clicking the channel header title or dropdown icon again at the center channel view, given that the menu is already open. + +#### Get the DOM elements of the channel menu +Use the function `cy.uiGetChannelMenu()`. +_____ +### Product Menu +![product menu image](../../../../img/e2e/product-menu.png) + +#### Opening the product menu +Use the function `cy.uiOpenProductMenu(item)`. `item` is of the type < string >. Possible values for `item` are: `'Channels'`, `'Boards'`, `'Playbooks'`, `'System Console'`, `'Integrations'`, `'Marketplace'`, `'Download Apps'`, and `'About Mattermost'`. + +* **Open the product menu normally**: + ```javascript + // # Open 'Product menu' + cy.uiOpenProductMenu(); + ``` +* **Open the product menu and click on a specific item**: + ```javascript + // # Open 'Integrations' section of 'Product Menu' modal + cy.uiOpenProductMenu('Integrations'); + ``` +#### Get the DOM elements of the product menu +Use the function `cy.uiGetProductMenu()`. +_____ diff --git a/docs/develop/contribute/more-info/webapp/e2e-testing.md b/docs/develop/contribute/more-info/webapp/e2e-testing.md new file mode 100644 index 000000000000..9d3366846a46 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/e2e-testing.md @@ -0,0 +1,300 @@ +--- +title: "End-to-End (E2E) tests" +sidebar_position: 6 +--- + +End-to-end tests for the Mattermost web app in general use [Cypress](https://www.cypress.io/) and [Playwright](https://playwright.dev/). If you're not familiar with Cypress, check out the Cypress [Developer Guide](https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshell) and [API Reference](https://docs.cypress.io/api/api/table-of-contents.html). Feel free to also join us on the Mattermost Community server if you'd like to ask questions and collaborate with us! + + +Playwright is a new framework getting added to the Mattermost web app for test automation (and is currently being used for visual tests). Documentation about Playwright in the web app is in development, so all other content about E2E testing will be related to Cypress. + +If you're looking for information related to E2E tests and Redux, please check out [Redux Unit and E2E Testing](/developers/contribute/more-info/webapp/redux/testing). + + + +### What requires an E2E test? + +* Test cases that are defined in [help-wanted E2E issues](https://github.com/mattermost/mattermost/issues?q=label%3A%22Area%2FE2E+Tests%22+label%3A%22Help+Wanted%22+is%3Aopen+is%3Aissue+). +* New features and stories - For example, check out [MM-19922 Add E2E tests for Mark as Unread #4243](https://github.com/mattermost/mattermost-webapp/pull/4243) which contains E2E tests for the `Mark As Unread` feature. +* Bug fixes - For example, see [MM-26751: Fix highlighting of at-mentions of self #5908](https://github.com/mattermost/mattermost-webapp/pull/5908), which fixes a highlighting issue and adds a related test. +* Test cases from [Zephyr](https://support.smartbear.com/zephyr-scale-cloud/docs/) - For example, see [Added Cypress tests MM-T1410, MM-T1415 and MM-T1419 #5850](https://github.com/mattermost/mattermost-webapp/pull/5850) which adds automated tests for `Guest Accounts`. + +### File Structure for E2E Testing +E2E tests are located at the root of the repository in [the `e2e-tests` folder](https://github.com/mattermost/mattermost/tree/master/e2e-tests). The file structure is mostly based on the [Cypress scaffold](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests#Folder-Structure). Here is an overview of some important folders and files: + +``` +|-- e2e-tests + |-- cypress + |-- tests + |-- fixtures + |-- integration + |-- plugins + |-- support + |-- utils + |-- cypress.config.ts + |-- package.json +``` + +* `/e2e-tests/cypress/tests/fixtures` or [Fixture Files](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Fixture-Files): + - Fixtures are used as external pieces of static data that can be used by tests. + - Typically used with the `cy.fixture()` command and most often when stubbing network requests. +* `/e2e-tests/cypress/tests/integration` or [Test Files](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Test-files): + - Subfolder naming convention depends on test grouping, which is usually based on the general functional area (e.g. `/e2e/cypress/tests/integration/messaging/` for "Messaging"). +* `/e2e-tests/cypress/tests/plugins` or [Plugin Files](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Plugins-file): + - A convenience mechanism that automatically includes plugins before running every single `spec` file. +* `/e2e-tests/cypress/tests/support` or [Support Files](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Support-file): + - A support file is a place for reusable behaviour such as custom commands or global overrides that are available and can be applied to all `spec` files. +* `/e2e-tests/cypress/tests/utils`: this folder contains common utility functions. +* `/e2e-tests/cypress/cypress.config.ts`: this file is for Cypress [configuration](https://docs.cypress.io/guides/references/configuration.html#Options). +* `/e2e-tests/cypress/package.json`: this file is for all the dependencies related to Cypress end-to-end testing. + +### Writing End-to-End Tests + +#### Where should a new test go? +You will need to either add the new test to an existing `spec` file, or create a new file. Sometimes, you will be informed (for example through issue descriptions) of the specific folder the test file should go in, or the actual test file being amended. As aforementioned, the `e2e-tests/cypress/tests/integration` folder is where all of the tests live, with subdirectories that roughly divide the tests by functional areas. Cypress is configured to look for and run tests that match the pattern of `*_spec.ts`, so a good new test file name for an issue like [Write Web App E2E with Cypress: "MM-T642 Attachment does not collapse" #18184](https://github.com/mattermost/mattermost/issues/18184) would be `attachment_does_not_collapse_spec.ts`, to ensure that it gets picked up. +> *Note*: There may be some JavaScript `spec` files, but new tests should be written in TypeScript. If you are adding a test to an existing `spec` file, convert that file to TypeScript if necessary. + +If you don't know where a test should go, first check the names of the subdirectories, and select a folder that describes the functional area of the test best. From there, look to see if there is already a `spec` file that may be similar to what you are testing; if there is one, it would be possible to add the test to the pre-existing file. + +#### Test metadata on spec files +Test metadata is used to identify each `spec` file before it is forwarded for a Cypress run, and the metadata is located at the start of a `spec` file. Currently, supported test metadata fields include the following: + +* **Stage** - Indicates the environment for testing; valid values for this include `@prod`, `@smoke`, `@pull_request`. "Stage" metadata in `spec` files are owned and controlled by the Quality Assurance (QA) team who carefully analyze the stability of tests and promote/demote them into certain stages. This is not required when submitting a `spec` file and it should be removed when modifying an existing `spec` file. + +* **Group** - Indicates test group or category, which is primarily based on functional areas and existing release testing groups. Valid values for this include: `@settings` for Settings, `@playbooks` for Playbooks, etc. This is required when submitting a `spec` file. + +* **Skip** - This is a way to skip running a `spec` file depending on the capabilities of the test environment. This is required when submitting a `spec` file if there is a test that has certain limitations or requirements. Forms of capabilities include: + - **Platform-related**: valid values include - `@darwin` for Mac, `@linux` for Linux flavors like Ubuntu, `@win32` for Windows, etc. + - **Browser-related**: valid values include - `@electron`, `@chrome`, `@firefox`, `@edge`, etc. + - **User interface-related**: valid values include `@headless` or `@headed`. + +A `spec` file can have zero or more metadata values separated by spaces (for example, `// Stage: @prod @smoke`). A more full example of what metadata would look like at the start of a `spec` file (for example, `attachment_does_not_collapse_spec.ts`) would be: + +``` +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element ID when selecting an element. Create one if none. +// *************************************************************** + +// Stage: @prod +// Group: @incoming_webhook +``` + +The metadata is part of a comment block that also includes information on copyright and license, and a section to explain how to tag comments in your code appropriately. + +#### Setting up test code + +Underneath the comment header, we can add the starter code as defined from the "Test code arrangement" part of the issue. Each test (no matter the situation you're writing a test for) should have a corresponding test case in Zephyr. Therefore, the `describe` block encompassing the test code should correspond to folder name in Zephyr (e.g. "Incoming webhook"), and the `it` block should contain `Zephyr test case number` as `Test Key`, and then the test title. For [Write Web App E2E with Cypress: "MM-T642 Attachment does not collapse" #18184](https://github.com/mattermost/mattermost/issues/18184), in the spec file made for it (`attachment_does_not_collapse_spec.ts`), the starter code would be: + ```javascript + describe('Integrations/Incoming Webhook', () => { + it('MM-T642 Attachment does not collapse', () => { + // Put test steps and assertions here + }); + }); + ``` +For those writing E2E from Help Wanted tickets with `Area/E2E Tests` label, the `Test Key` is available in the Github issue itself. The `Test Key` is used for mapping test cases per Release Testing specification. It will be used to measure coverage between manual and automated tests. In case the `Test Key` is not available, feel free to prompt the QA team who will either search for an existing Zephyr entry or if it's a new one, it will be created for you. + +#### Using Cypress Hooks + +Before writing the main body of the test in the `it` block, it can help to write some setup code for test isolation using [hooks](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests#Hooks). In a `before()` hook, you can run tests in isolation using the custom command `cy.apiInitSetup()`. This command creates a new team, channel, and user which can only be used by the spec file itself. Make use of the `cy.apiInitSetup()` function as much as possible, as it is recommended to log in as a new user and visit the generated team and/or channel. Avoid the use of `sysadmin` user or default `ad-1` team if possible. + +For `attachment_does_not_collapse_spec.ts` for example: + ```javascript + let incomingWebhook; + let testChannel; + + before(() => { + // # Create and visit new channel and create incoming webhook + cy.apiInitSetup().then(({team, channel}) => { + testChannel = channel; + + const newIncomingHook = { + channel_id: channel.id, + channel_locked: true, + description: 'Incoming webhook - attachment does not collapse', + display_name: 'attachment-does-not-collapse', + }; + + cy.apiCreateWebhook(newIncomingHook).then((hook) => { + incomingWebhook = hook; + }); + + cy.visit(`/${team.name}/channels/${channel.name}`); + }); + }); + ``` +The `before()` hook is also a good place to add checks if a test requires a certain kind of server license. If test(s) require a certain licensed feature, use the function `cy.apiRequireLicenseForFeature('')`. To check if the server has a license in general, use `cy.apiRequireLicense()`. You can also add hard requirements in the `before()` hook, such as: `cy.shouldNotRunOnCloudEdition()`, `cy.shouldRunOnTeamEdition()`, `cy.shouldHavePluginUploadEnabled()`, `cy.shouldHaveElasticsearchDisabled()`, and `cy.requireWebhookServer()`. For more information on custom commands and how to select elements, check out the [End-to-End (E2E) cheatsheets](/developers/contribute/more-info/webapp/e2e-cheatsheets). + +Putting what you've gone through so far all together, you should have code that looks similar to this template: + +```javascript +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ********************************************************************** +// - Use [#] in comment to indicate a test step (e.g. # Go to a page) +// - Use [*] in comment to indicate an assertion (e.g. * Check the title) +// - Query an element with @testing-library/cypress as much as possible +// ********************************************************************** + +// Group: @change_group + +describe('Change to Functional Group', () => { + before(() => { + // Add hard requirement(s) to immediately fail and throw a descriptive error if not met + // cy.shouldNotRunOnCloudEdition(); + + // Add license requirement(s) + // cy.apiRequireLicense(); + + // Init basic setup for test isolation + cy.apiInitSetup({loginAfter: true}).then(({team, channel, user}) => { + // Assign return values to variable/s + // # Visit a channel + // Do other setup per test data preconditions + }); + }); + + // Add a title of "[Zephyr_id] - [Zephyr title]" for test case with single step, + // or "[Zephyr_id]_[step_number] - [Zephyr title]" for test case with multiple steps + it('[Zephyr_id] - [Zephyr title]', () => { + // Put test steps and assertions here + }); +}); +``` + +#### Main body of the test + + + +Use `camelCase` when assigning to `data-testid` or element ID. Also, watch out for potential breaking changes in the snapshot from [unit testing](/developers/contribute/more-info/webapp/unit-testing). Run `make test` to see if all unit tests are passing, and run `npm run updatesnapshot` or `npm run test -- -u` if necessary to update snapshot tests. + + + +Now, inside the body of the `it` block , we will write in code the "Steps" part of the E2E issue. The following steps and code are from [Write Web App E2E with Cypress: "MM-T642 Attachment does not collapse" #18184](https://github.com/mattermost/mattermost/issues/18184). Check out the complete file at: [`attachment_does_not_collapse_spec.ts`](https://github.com/mattermost/mattermost-webapp/pull/11231/files). + + * **Create an incoming webhook and send it through POST with attachment**: + ```javascript + // # Post the incoming webhook with a text attachment + const content = '[very long lorem ipsum test text]'; + const payload = { + channel: testChannel.name, + attachments: [{fallback: 'testing attachment does not collapse', pretext: 'testing attachment does not collapse', text: content}], + }; + cy.postIncomingWebhook({url: incomingWebhook.url, data: payload, waitFor: 'attachment-pretext'}); + ``` + * **View the webhook post that has the attachment**: you are already in the channel that has the attachment post, as specified by the line `cy.visit('/${team.name}/channels/${channel.name}')`; from the setup section of the code. + + * **Type /collapse and press Enter**: + ```javascript + // * Check "show more" button is visible and click + cy.getLastPostId().then((postId) => { + const postMessageId = `#${postId}_message`; + cy.get(postMessageId).within(() => { + cy.get('#showMoreButton').scrollIntoView().should('be.visible').and('have.text', 'Show more').click(); + }); + }); + // # Type /collapse and press Enter + const collapseCommand = 'collapse'; + cy.uiGetPostTextBox().type(`/${collapseCommand} {enter}`); + ``` + + * **Observe the integration post with the Message Attachment**: where you ascertain what is expected of the test. + ```javascript + cy.getNthPostId(-2).then((postId) => { + const postMessageId = `#${postId}_message`; + cy.get(postMessageId).within(() => { + // * Verify "show more" button says "Show less" + cy.get('#showMoreButton').scrollIntoView().should('be.visible').and('have.text', 'Show less'); + // * Verify gradient + cy.get('#collapseGradient').should('not.be.visible'); + }); + ``` + +### Running E2E Tests +#### On your local development machine / Gitpod + +1. If the server is not running, launch it by running `make run` in the `server` directory. Then, confirm that the Mattermost instance has started successfully. You can also run `make test-data` in the `server` directory to preload your server instance with initial seed data (you may need to restart the server again). + - Each test case should handle the required system or user settings, but if you encounter an unexpected error while testing, you may want to reset the configuration of the server to the default by going to the `server` directory and running `make config-reset`. +2. Change the directory to `e2e-tests/cypress`, and install dependencies by running `npm i`. +3. You can then run tests in a variety of different ways by using the following commands in the `e2e-tests/cypress` directory: + + - **Running all E2E tests**: `npm run cypress:run`. This does not include the `spec` files in the `/e2e-tests/cypress/tests/integration/enterprise` folder because they need an Enterprise license to run successfully. + - **Running tests selectively based on `spec` metadata**: For example, if you want to run all the tests in a specific group, such as those in "accessibility", the command would be: `node run_tests.js --group='@accessibility'`. + - **Using the Cypress desktop app**: `npm run cypress:open`. This will start up the Cypress desktop app, where you will be able to do partial testing depending on the `spec` selected in the app. If you are using Gitpod, the Cypress app will open up in the VNC desktop, which is accessible at port `6080`. +4. Don't forget to check your coding styles! See the [Web app workflow](/developers/contribute/more-info/webapp/developer-workflow) page for helpful commands to run. + +#### In a Continuous Integration (CI) pipeline + +All tests are run by Mattermost in a CI pipeline, and they are grouped according to test stability. + +1. __Daily production tests against development branch (master)__: Initiated on the master branch by using the command `node run_tests.js --stage='@prod'`. These production tests are selected and also labeled with `@prod` in the test metadata. See link for an example test run posted in our community channel. +2. __Daily production tests against release branch__: Same as above except the test is initiated against the release branch. See link for an example test run. +3. __Daily unstable tests against development branch (master)__: Initiated on the master branch by using the command `node run_tests.js --stage='@prod' --invert` to run all tests except production tests. These are called "unstable tests" as they either consistently or intermittently fail due to automation bugs, and not because of product bugs. + +#### Environment variables + +Several environment variables (env variables) are used when testing with Cypress in order to easily change things when running tests in CI and to cater to different values across developer machines. + +Environment variables are [defined in cypress.config.ts](https://github.com/mattermost/mattermost/blob/master/e2e-tests/cypress/cypress.config.ts) under the `env` key. In most cases you don't need to change the values, because it makes use of the default local developer setup. If you do need to make changes, the easiest method is to override by exporting `CYPRESS_*`, where `*` is the key of the variable, for example: `CYPRESS_adminUsername`. See the [Cypress documentation on environment variables](https://docs.cypress.io/guides/guides/environment-variables.html#Setting) for details. + +| Variable | Description | +|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| CYPRESS\_adminUsername | Admin's username for the test server.

*Default*: `sysadmin` when server is seeded by `make test-data`. | +| CYPRESS\_adminPassword | Admin's password for the test server.

*Default*: `Sys@dmin-sample1` when server is seeded by `make test-data`. | +| CYPRESS\_dbClient | The database of the test server. It should match the server config `SqlSettings.DriverName`.

*Default*: `postgres`
*Valid values*: `postgres` or `mysql` | +| CYPRESS\_dbConnection | The database connection string of the test server. It should match the server config `SqlSettings.DataSource`.

*Default*: `"postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable\u0026connect_timeout=10"` | +| CYPRESS\_enableVisualTest | Use for visual regression testing.

*Default*: `false`
*Valid values*: `true` or `false` | +| CYPRESS\_ldapServer | Host of the Lightweight Directory Access Protocol (LDAP) server.

*Default*: `localhost` | +| CYPRESS\_ldapPort | Port of the LDAP server.

*Default*: `389` | +| CYPRESS\_runLDAPSync | Option to run LDAP sync.

*Default*: `true`
*Valid values*: `true` or `false` | +| CYPRESS\_resetBeforeTest | When set to `true`, it deletes all teams and their channels where `sysadmin` is a member except `eligendi` team and its channels.

*Default*: `false`
*Valid values*: `true` or `false` | +| CYPRESS\_webhookBaseUrl | A server used for testing webhook integrations.

*Default*: `http://localhost:3000` when initiated with the command `npm run start:webhook` in the `e2e-tests/cypress` directory. | + +### Submitting your pull request (PR) + +Review the [Test Guidelines](/developers/contribute/more-info/getting-started/test-guideline) for details on how to submit your PR + +### Troubleshooting +#### Test(s) failing due to a known issue +If test(s) are failing due to another known issue, follow these steps to amend your test: +1. Append the Jira issue key in the test title, following the format of ` -- KNOWN ISSUE: [Jira_key]`. For example: + ```javascript + describe('Upload Files', () => { + it('MM-T2261 Upload SVG and post -- KNOWN ISSUE: MM-38982', () => { + // Test steps and assertion here + }); + }); + ``` +2. Move the test case into a separate `spec` file following the format of ``. For example: + `accessibility_account_settings_spec_1.js` and demote the spec file (i.e. remove `// Stage: @prod` from the spec file) +3. If all the test cases are failing in a spec file, update each title as mentioned above and demote the spec file. +4. Link the failed test case(s) to the Jira issue (the known issue). In the Jira bug, select the **Zephyr Scale** tab. Select the **add an existing one** link, then select test case(s), and finally select **Add**. +5. Conversely, remove the Jira issue key if the issue has been resolved and the test is passing. + +#### Cypress failed to start after running `npm run cypress:run` +In this problem, either the command line exits immediately without running any test or it logs out like the following with the error message: +```sh +✖ Verifying Cypress can run /Users/user/Library/Caches/Cypress/3.1.3/Cypress.app + → Cypress Version: 3.1.3 +Cypress failed to start. + +This is usually caused by a missing library or dependency. +``` +The solution to this problem is to clear node options by initiating `unset NODE_OPTIONS` in the command line. Running `npm run cypress:run` should then proceed with Cypress testing. + +#### Running any Cypress spec gives `ENOSPC` + +This error may occur in Ubuntu when running any Cypress spec: + +``` +code: 'ENOSPC', +errno: 'ENOSPC', +``` +The solution to this problem is to run the following command: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. + + diff --git a/docs/develop/contribute/more-info/webapp/index.md b/docs/develop/contribute/more-info/webapp/index.md new file mode 100644 index 000000000000..4334c3fa3b5a --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/index.md @@ -0,0 +1,47 @@ +--- +title: "Web app" +sidebar_position: 1 +--- + +The Mattermost web app is written in JavaScript using [React](https://react.dev/) and [Redux](https://redux.js.org/). + +## Repository + +It is located in the `webapp` directory of the [main Mattermost repository](https://github.com/mattermost/mattermost). + +https://github.com/mattermost/mattermost/tree/master/webapp + +## Help Wanted + +[Find help wanted tickets here](https://mattermost.com/pl/help-wanted-mattermost-webapp/). + +## Package structure + +The web app is set up as a monorepo which has the code broken up into multiple packages. The main packages in the web app are: + +* `channels` - The main web app which contains Channels, the System Console, login/signup pages, and most of the core infrastructure for the app. + * `src/`. Key folders include: + * `actions` - Contains Redux actions which make up much of the view logic for the web app + * `components` - Contains UI components and views written using React + * `i18n` - Contains the localization files for the web app + * `packages/mattermost-redux` - Contains most of the Redux logic used for handling data from the server + * `plugins` - Contains the plugin framework, utility functions and components + * `reducers` - Contains Redux reducers used for view state + * `selectors` - Contains Redux selectors used for view state + * `tests` - Contains setup code and mocks used for unit testing + * `utils` - Contains many widely-used utility functions +* `platform` - Packages used by the web app and related projects + * `client` - The JavaScript client for Mattermost's REST API, available on NPM as [@mattermost/client](https://www.npmjs.com/package/@mattermost/client) + * `components` - A work-in-progress package containing UI components designed to be used by different parts of Mattermost + * `types` - The TypeScript types used by Mattermost, available on NPM as [@mattermost/types](https://www.npmjs.com/package/@mattermost/types) + +### Important libraries and technologies + +- [React](https://reactjs.org/) - React is a user interface library used for React apps. Its key feature is that it uses a variation of JavaScript called JSX to declaratively define interfaces using HTML-like syntax. +- [Redux](https://redux.js.org/) - Redux is a state management library used for JavaScript apps. Its key features are a centralized data store for the entire app and a pattern for predictably modifying and displaying that application state. Notably, we're not using Redux Toolkit since a large portion of our Redux code predates its existence. +- [Redux Thunk](https://github.com/reduxjs/redux-thunk) - Redux Thunk is a middleware for Redux that's used to write async actions and logic that interacts more closely with the Redux store. +- [React Redux](https://react-redux.js.org/) - React Redux is the library used to connect React components to a Redux store. + +## Legacy Notes + +Note that the webapp was previously located at https://github.com/mattermost/mattermost-webapp/. You may find additional history in this repository that was not migrated back to https://github.com/mattermost/mattermost when forming the monorepo. diff --git a/docs/develop/contribute/more-info/webapp/migrating-to-typescript.md b/docs/develop/contribute/more-info/webapp/migrating-to-typescript.md new file mode 100644 index 000000000000..bd26033d2354 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/migrating-to-typescript.md @@ -0,0 +1,38 @@ +--- +title: "Migrate to Typescript" +sidebar_position: 9 +--- + +The Mattermost team wants to proactively improve the quality, security, and stability of [the code](https://github.com/mattermost/mattermost/tree/master/webapp), and one way to do this is by introducing the usage of type checking. Thus, we have decided to introduce Typescript in our codebase as it's a mature and feature-rich approach. + +As a first step, we have migrated the [mattermost-redux](https://github.com/mattermost/mattermost-redux) library to use Typescript, and are now in the process of migrating the [web app](https://github.com/mattermost/mattermost/tree/master/webapp) to use Typescript. + +This campaign will help with the migration by converting files written in Javascript to type-safe files written in Typescript. + +By completing this campaign, we're looking to: + +- Reduce the errors derived from changes. +- Increase the consistency of the code. +- Ensure a more defensive programming in the code. + +## Contribute + +If you're interested in contributing, please join the [Typescript Migration channel on community.mattermost.com](https://community.mattermost.com/core/channels/typescript-migration). You can also check out the [Contributors](https://community.mattermost.com/core/channels/tickets) channel, where there are several posts mentioning tickets related to this campaign, each containing the hashtag `#typescriptmigration`. You can work on migrating an individual module to Typescript by claiming a ticket that matches [this GitHub issue search](https://github.com/mattermost/mattermost/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Area%2FTechnical+Debt%22+label%3A%22Up+For+Grabs%22+Migrate+to+Typescript). + +## Component migration steps + +There are a few steps involved with migrating a file to use Typescript. Some of them may not apply to every file and they may change slightly based on the file you're working on. In general, you can follow these steps as a checklist for work that needs to be done on each file. + +1. Every React component's set of `props` needs to be converted to a new type. You can use the component's `propTypes` as a template for what `props` a given component can expect. This conversion to Typescript includes maintaining whether a given `prop` is required or not. An optional property in Typescript is noted by including a question mark at the end of the property's name. +2. A component's `state` also needs to be defined using a type. The initial `state` assignment and any call to `setState` will be indicators of what values are present in the component's state. +3. Once a component's `props` and `state` (if any) have been converted, you can define the component as `class MyComponent extends React.PureComponent`. You can omit the `State` portion if the component does not have its own `state`. +4. Avoid use of the `any` type except in test files. The components themselves should be as well-defined as possible. +5. Most objects we used are typed in the [@mattermost/types](https://github.com/mattermost/mattermost/tree/master/webapp/platform/types) library, if you can't find a type you're looking for. +6. Check that the types are all correct using the `make check-types` command. + +## Examples + +You can see example pull requests here: + +- https://github.com/mattermost/mattermost/pull/5840 +- https://github.com/mattermost/mattermost/pull/5244 diff --git a/docs/develop/contribute/more-info/webapp/redux/actions.md b/docs/develop/contribute/more-info/webapp/redux/actions.md new file mode 100644 index 000000000000..8505bb56f12a --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/actions.md @@ -0,0 +1,267 @@ +--- +title: "Actions" +sidebar_position: 4 +--- + +In Redux, actions represent an operation either performed by the user or the server that cause a change to the state of the web app which is stored in the Redux store. It's generally represented as a plain JavaScript object with a constant `type` string with other data stored in fields such as `data`. + +```typescript +{ + type: 'SELECT_CHANNEL', + data: channelId, +} +``` + +Actions are created by functions called action creators. In regular Redux, this function will take some arguments and return an action representing how the store should be changed. Something to note with Mattermost Redux is that we typically refer to the action creators as the "actions" themselves since there's often a single action creator for a given type of action. + +```typescript +function selectChannel(channelId: string) { + return { + type: 'SELECT_CHANNEL', + data: channelId, + }; +} +``` + +This action is later received by the Redux store's reducers which will know how to read the contents of the action and modify the store accordingly. + +Because we use the [Thunk middleware](https://github.com/reduxjs/redux-thunk) for Redux, we have the ability to use more powerful action creators that can read the state of the store, perform asynchronous actions like network requests, and dispatch multiple actions when needed. Instead of returning a plain object, these action creators return a function that takes the Redux store's `dispatch` and `getState` to be able to dispatch actions as needed. + +```typescript +function loadAndSelectChannel(channelId: string) { + return async (dispatch: DispatchFunc, getState: GetStateFunc) => { + const {channels} = getState().entities.channels; + + if (!channels.hasOwnProperty(channelId)) { + // Optionally call another action to asynchronously load the channel over the network + dispatch(setChannelLoading(true)); + + await dispatch(loadChannel(channelId)); + + dispatch(setChannelLoading(false)); + } + + // Switch to the channel + dispatch(selectChannel(channelId)); + }; +} +``` + +Actions live in the `src/actions` directory with the constants that define their types being in the `src/action_types` directory. + +## Use actions + +To use an action, you need to pass it into the `dispatch` method of the Redux store so that it can be passed off to the reducers. + +```typescript +const store = createReduxStore(); + +store.dispatch(loadAndSelectChannel(channelId)); +``` + +Typically, you won't have direct access to the store to get its `dispatch` method. Instead, you'll receive it from either [React Redux](https://react-redux.js.org/) or [Redux Thunk](https://github.com/reduxjs/redux-thunk) depending on what part of the code you're working on. + +### Dispatch actions from a component + +[React Redux](https://react-redux.js.org/) provides two ways of accessing dispatch, and you'll see both used throughout Mattermost. + +The first is by its `connect` higher order component. Its second parameter `mapDispatchToProps` is used to wrap action creators so that they will automatically be dispatched when called. + +```tsx +// src/components/widget/index.jsx + +import {connect} from 'react-redux'; + +import {loadAndSelectChannel} from 'src/actions/channels'; + +import Widget from './widget'; + +// mapDispatchToProps is an object containing all actions passed into the component +const mapDispatchToProps = { + loadAndSelectChannel, +}; + +export default connect(null, mapDispatchToProps)(Widget); + +// src/components/widget/widget.tsx + +type Props = { + channelId: string; + + // Notice that the type of the wrapped action omits the `getState` and `dispatch` parameters of the Thunk action + loadAndSelectChannel: (channelId: string) => void; +} + +export default function Widget(props: Props) { + const handleClick = useCallback(() => { + // We don't need to dispatch anything at this point + props.loadAndSelectChannel(props.channelId); + }, [props.loadAndSelectChannel, props.channelId]); + + return ( + + ); +} +``` + +Alternatively, you can use the `useDispatch` hook to dispatch actions directly in the component. + +```tsx +// src/components/widget/widget.tsx + +import {useDispatch} from 'react-redux'; + +import {loadAndSelectChannel} from 'src/actions/channels'; + +type Props = { + channelId: string; +} + +export default function Widget(props: Props) { + const dispatch = useDispatch(); + + const handleClick = useCallback(() => { + dispatch(loadAndSelectChannel(props.channelId)); + }, [dispatch, props.channelId]); + + return ( + + ); +} +``` + +The choice of which method to use is left up to the developer at the moment. `connect` is more widely used throughout the code base, but that's primarily because hooks are relatively new compared to it. The class-based components that make up older parts of the app also aren't compatible with hooks. + +When deciding which one to use though, try to match the area of the code that you're working in. Individual components should never mix the two. + +## Add an action + +The steps for adding a new Redux action are as follows: + +1. Decide where to the action creator will be located. Depending on where the action will be located you will want to put it in one of the following locations: + - If the action is more general and affects Redux state stored in `state.entities`, it should be put somewhere in `webapp/channels/src/packages/mattermost-redux/src/actions`. + - If the action is specific to the web app, affects `state.views` and will be used in multiple places throughout the app, it should be put in `actions`. + - If the action is very specific and will likely only be used by one or more closely related components, it should be put in an `actions.ts` located in the same directory as those components. + +2. If the action creator will have an effect on the Redux state that isn't covered by existing action types, you'll need to add a new "action type" constant that will be used by the action creator and will be handled by a reducer. These are located separate from the definition of the action creator itself to avoid having reducers import code from the action creators directly. + + Depending on where the action is located, the action creator will be located in one of the following: + - If the action is located in `mattermost-redux`, the action type should be added to one of the files in `webapp/channels/src/packages/mattermost-redux/src/action_types`. + - If the action is specific to the web app or a single component, the action type should be added to the `ActionTypes` object in `webapp/channels/src/utils/constants.tsx`. + + ```typescript + export default keyMirror({ + SOMETHING_HAPPENED: null + }); + ``` + +3. Write the action creator itself. Depending on what data is needed by the action and if it needs to perform any async operations will change whether or not a Thunk action should be used. We should generally try to use plain Redux actions wherever possible since they're a bit more complex, both to read and to process. + + ```typescript + function somethingHappened(channelId: string) { + return { + type: SOMETHING_HAPPENED, + channelId, + data: 1234, + }; + } + + function somethingAsyncHappened(channelId: string) { + return async (dispatch: DispatchFunc, getState: GetStateFunc) => { + const currentUserId = getCurrentUserId(getState()); + + let data; + try { + data = await Client4.doSomething(currentUserId, channelId); + } catch (error) { + dispatch({ + type: SOMETHING_FAILED, + channelId, + error, + }); + + return {error}; + } + + // Note that if you need to access state again after waiting for something asynchronous, you should call + // getState a second time to ensure you have an up to date version of the state + + dispatch({ + type: SOMETHING_HAPPENED, + channelId, + data, + }); + }; + } + ``` + +4. If you added a new action type, make sure to add or update existing reducers to handle the new action. More information about reducers is available [here](/developers/contribute/more-info/webapp/redux/reducers). +5. Add unit tests to make sure that the action has the intended effects on the store. More information on unit testing reducers is available on the page [Redux Unit and E2E Testing](/developers/contribute/more-info/webapp/redux/testing). + +### Add a new API action + +If your action is corresponds to an API call, there are a few extra steps required but also a helper function to simplify the error handling for the action. The additional steps are as follows: + +1. Ensure that `Client4`, the JavaScript API client for Mattermost which is located in `webapp/platform/client/src/client4.ts`, has a method that corresponds to the API endpoint that you're using. That method will likely involve simply constructing the URL for the endpoint, optionally constructing a body for the request, and then using the `doFetch` method to actually make the request. + + ```typescript + class Client4 { + doSomething = (userId: string, channelId: string) => { + return this.doFetch( + `${this.getUserRoute(userId)}/something`, + {method: 'post', body: JSON.stringify({channelId})}, + ); + } + } + ``` + +2. Depending on your use case, you'll likely want to dispatch a Redux action containing the response to the API request when it succeeds. You may optionally also want to dispatch actions when the request is made or fails to update the Redux state as the request progresses. + ```typescript + export default keyMirror({ + SOMETHING_HAPPENED: null, + + // The following actions are optional. They used to be added for every API request, but we found we were only + // rarely using their results, so we don't recommend adding them any more + SOMETHING_REQUEST: null, + SOMETHING_SUCCESS: null, + SOMETHING_FAILURE: null, + }); + ``` +3. Most actions involving an API request follow a similar pattern of calling Client4 with the provided parameters, handling any errors that may occur, and dispatching an action containing the result if successful. The `bindClientFunc` helper can help with that. + + ```typescript + function somethingAsyncHappened(channelId: string) { + return bindClientFunc({ + clientFunc: client.doSomething, + + onSuccess: SOMETHING_HAPPENED, + params: [channelId], + }; + } + + // clientFunc is the only mandatory parameter of bindClientFunc. The rest may be added as needed. + function somethingVerboseHappened(userId: string, channelId: string) { + return bindClientFunc({ + clientFunc: client.doSomething, + + // The onRequest action will be dispatched before the request is made + onRequest: SOMETHING_REQUEST, + + // The onSuccess action will be dispatched if the request succeeds. It will include a data parameter + // containing the response to the request. Additionally, onSuccess can be an array of actions if multiple + // should be dispatched when the request succeeds. + onSuccess: [SOMETHING_SUCCESS, SOMETHING_HAPPENED], + + // The onFailure action will be dispatched if the request fails due to a network issue or an invalid request. + // It will include an error parameter containing an Error object. + onFailure: SOMETHING_FAILED, + + // An array of parameters will be passed into clientFunc in the order they're received + params: [userId, channelId], + }; + } + ``` diff --git a/docs/develop/contribute/more-info/webapp/redux/index.md b/docs/develop/contribute/more-info/webapp/redux/index.md new file mode 100644 index 000000000000..d0dfff24bca9 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/index.md @@ -0,0 +1,12 @@ +--- +title: "Redux" +sidebar_position: 8 +--- + +The Mattermost web app uses [Redux](https://redux.js.org/) as its state management library. Its key features are a centralized data store for the entire app and a pattern for predictably modifying and displaying that application state. Notably, we're not using Redux Toolkit since a large portion of our Redux code predates its existence. + +In addition to Redux itself, we also use: +- [React Redux](https://react-redux.js.org/) to connect React components to the Redux store using higher-order components like `connect` or hooks like `useSelector`. +- [Redux Thunk](https://github.com/reduxjs/redux-thunk) to write async actions and logic that interacts more closely with the Redux store. + +Currently, the different packages in the web app use Redux in varying amounts. The bulk of our Redux code is in `channels` where it's split between logic that's more view-oriented, located at the root of its `src` directory, and logic that's more server-oriented, located in `channels/src/packages/mattermost-redux`. diff --git a/docs/develop/contribute/more-info/webapp/redux/react-redux.md b/docs/develop/contribute/more-info/webapp/redux/react-redux.md new file mode 100644 index 000000000000..516ae4f08830 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/react-redux.md @@ -0,0 +1,93 @@ +--- +title: "Use Redux with React" +sidebar_position: 7 +--- + +Using Redux with React is fairly straightforward thanks to the [React Redux](https://github.com/reactjs/react-redux) library. It provides the `connect` function to create higher order components that have access to the Redux store to set their props. + +A typical Redux-connected component will be in its own folder with two files: `index.jsx` containing the code to connect to the Redux store and the file where the component is actually implemented. This helps to keep the Redux logic separate from the rendering for the component which keeps it more easily readable and makes it easier to test since it can be done without the whole Redux store. + +```jsx +// components/my_component/index.jsx + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; + +import {messageUser} from 'actions/entities/users'; + +import {getCurrentUser, getUser} from 'selectors/entities/users'; + +import MyComponent from './my_component'; + +// mapStateToProps receives the Redux store state and any props passed into the connected +// component, and they are used to return any additional data from the Redux store that is +// needed to render the component. ownProps will also be passed directly to the component. +function mapStateToProps(state, ownProps) { + return { + currentUser: getCurrentUser(state), + otherUser: getUser(state, ownProps.userId), + }; +} + +// mapDispatchToProps receives the Redux store's dispatch method so that bindActionCreators +// can be used to automatically dispatch those actions as necessary. +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + messageUser, + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(MyComponent); + +// components/my_component/my_component.jsx + +import React from 'react'; + +function MyComponent(props) { + const handleClick = () => { + props.actions.messageUser(props.otherUser, props.currentUser, `Hello, ${props.otherUser.first_name}!`); + }; + + return ( + + ); +} +``` + +Both `mapStateToProps` and `mapDispatchToProps` are optional and can be omitted as necessary. + +If you're using a selector that is produced through a factory, such as `makeGetUser`, you can instead generate an individual `mapStateToProps` function for each instance of the component. + +```jsx +// component/my_component/index.jsx + +... + +import {getCurrentUser, makeGetUser} from 'selectors/entities/users'; + +// makeMapStateToProps is called once for each instance of the component on the page. Because of this +// a separate getUser selector is created for each instance, allowing them to be memoized separately. +function makeMapStateToProps() { + const getUser = makeGetUser(); + + return (state, ownProps) => { + return { + currentUser: getCurrentUser(state), + otherUser: getUser(state, ownProps.userId) + }; + }; +} + +... + +export default connect(makeMapStateToProps, mapDispatchToProps)(MyComponent); +``` + +## Performance considerations + +Something very important to note when using React with Redux is that every single `mapStateToProps` function within your application will be called whenever anything in the store changes. If any work being done in `mapStateToProps` performs any complicated calculations or returns rich objects, it should be moved into a [selector](/developers/contribute/more-info/webapp/redux/selectors) so that it can be memoized whenever possible. diff --git a/docs/develop/contribute/more-info/webapp/redux/reducers.md b/docs/develop/contribute/more-info/webapp/redux/reducers.md new file mode 100644 index 000000000000..de2b41695ae5 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/reducers.md @@ -0,0 +1,107 @@ +--- +title: "Reducers" +sidebar_position: 5 +--- + +Reducers in Redux are pure functions that describe how the data in the store changes after any given action. A reducer receives the previous state of the store and an action as a JavaScript object (see [here](/developers/contribute/more-info/webapp/redux/actions) for more information on actions) and should output the resulting state without receiving any outside data. Because reducers are pure, they will always produce the same resulting state for a given state and action. + +```javascript +const myValueDefault = ''; +function myValue(state = myValueDefault, action) { + switch(action.type) { + case SET_MY_VALUE: + // This data changes myValue, so just return the new value + return action.data; + + default: + // This action doesn't affect us, so return the previous value + return state; + } +} +``` + +Most reducers used by Mattermost Redux are simple like the one above in that they only affect a single part of the store. These can be easily composed using Redux's [`combineReducers`](https://redux.js.org/api-reference/combinereducers) function to make a more complex data store. + +```javascript +function myStringValue(state = '', action) { + ... +} + +function myNumberValue(state = 0, action) { + ... +} + +function myOtherValue(state = {}, action) { + ... +} + +// This combines the reducers so that the resulting store will look like +// { +// myStringValue: 'abc', +// myNumberValue: '1234', +// myOtherValue: {color: 'red', weather: 'rain'} +// } +export const combineReducers({ + myStringValue, + myNumberValue, + myOtherValue +}); +``` + +`combineReducers` can be nested further to make up the complex data store as used by Mattermost Redux. + +## Avoiding mutating the store + +One of the core principals of Redux is that the state of the store should never be modified. If the state changes, a completely new state tree should be returned. That's not to say the entire thing is destroyed and recreated from scratch any time anything changes, but only the parts that are modified are recreated. + +For example, if the store holds a state like: + +- entities + - channels + - channels + - users + - currentUserId + - profiles +- requests + - getUser + - getChannel + +and we make a request to get the profile for a user that we don't have, the following fields would be changed (shown in bold): + +- **entities** + - channels + - channels + - **users** + - currentUserId + - **profiles** +- **requests** + - **getUser** + - getChannel + +To do this, it is important to always return new objects from a reducer if any of its contents change. This is trivial for reducers for state that is a primitive string or number, but it can be more complicated for other types of data. You should also make sure to return the same object if nothing needs to change. As long as you do that, `combineReducers` will make sure to update the rest of the state tree accordingly. + +```javascript +function myOtherValue(state = {color: 'red', weather: 'rain'}, action) { + switch(action.type) { + case SET_OTHER_VALUE_COLOR: + // This destructuring syntax is used to create a new object that is a shallow copy of state + // with the color field updated to the new value + return { + ...state, + color: action.data + }; + case SET_OTHER_VALUE_WEATHER: + return { + ...state, + weather: action.data + }; + + default: + // There's no changes, so return the previous value + return state; + } + ... +} +``` + +If you accidentally mutate the state, you'll receive an error when Mattermost Redux is running in development mode. diff --git a/docs/develop/contribute/more-info/webapp/redux/selectors.md b/docs/develop/contribute/more-info/webapp/redux/selectors.md new file mode 100644 index 000000000000..39040261d5a7 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/selectors.md @@ -0,0 +1,82 @@ +--- +title: "Selectors" +sidebar_position: 6 +--- + +Selectors are functions used to compute data from the data in the Redux stores. This is done using [Reselect](https://github.com/reactjs/reselect), a library designed to do this efficiently by memoizing any results so that they are only recalculated if relevant parts of the store change. The code for this is in the `src/selectors` folder of the Mattermost Redux repository. + +For more information about reselect and how we use it at Mattermost, [check out this developer talk given by core developer Harrison Healey](https://www.youtube.com/watch?v=6N2X7gEwmaQ). + +## Use a selector + +Selectors are simple functions that take the state from the redux store and return some data computed from them. Most selectors take simply the state of the redux store and return some data from the store. + +```javascript +const currentUser = getCurrentUser(state); +const currentTeam = getCurrentTeam(state); +``` + +Selectors can also receive additional arguments however extra care must be taken to ensure that the extra argument doesn't prevent proper memoization. Instead of providing the selector directly, a factory function will usually be provided so that each location or component that users the selector can be memoized separately. + +```javascript +const getPostsInThread = makeGetPostsInThread(); + +const selectedPost = getSelectedPost(state); +const postsInSelectedThread = getPostsInThread(state, selectedPost.root_id); +``` + +For an example of how a selector like `makeGetPostInThread` could be used with React, see [here](/developers/contribute/more-info/webapp/redux/react-redux). + +## Add a selector + +The most basic selector is just a function that takes in the state and returns a part of it without any memoization or complicated logic. All these provide is that they make it easier to access part of the store without having to remember exactly where the data is. + +```javascript +export function getCurrentUserId(state) { + return state.entities.users.currentUserId; +} +``` + +To create a selector that actually computes some data, you need to use Reselect's [`createSelector`](https://github.com/reactjs/reselect#createselectorinputselectors--inputselectors-resultfunc) to combine simple selectors like the one above and provide some proper memoziation. + +```javascript +export const getCurrentUser = createSelector( + getCurrentUserId, + (state) => state.entities.users.profiles, + (currentUserId, profiles) => { + if (!profiles.hasOwnProperty(currentUserId)) { + // Current user not found + return {}; + } + + return profiles[currentUserId]; + } +); +``` + +The way that `createSelector` works is that it takes any number of "input selectors" followed by a single "result function". When you call the selector, it calls all of the input selectors to get the values that will be passed into the result function. If any of those have changed, it passes them to the result function to calculate and return the final result. If none of those values change, it skips the result function, and just returns the previous value. + +By keeping the input selectors simple and memoizing based on their results, we can skip recalculating the final value which saves time and keeps it so that `getCurrentUser(state) === getCurrentUser(state)` even when `getCurrentUser` returns an object that can't normally be compared with `===`. This is incredibly important when using Redux with React as your selectors will likely be called many times per second so minimizing time taken and returning new objects sparingly can have significant performance gains. + +While Reselect doesn't encourage the use of selectors with parameters, these can be passed in when calling the selector. Any arguments passed in will be provided to the input selectors, but not the result function. If necessary, you can work around this by including an extra input selector to pass the argument along. + +```javascript +export function makeGetUser() { + return createSelector( + getProfiles, + (state, userId) => userId, + (profiles, userId) => { + if (!profiles.hasOwnProperty(userId)) { + // User not found + return {}; + } + + return profiles[userId]; + } + ); +} +``` + +Note that when we make a selector that takes arguments, we typically wrap it in a factory function so that we can create multiple instances of the selector that are each memoized separately. This is because having a single instance of the above `getUser` selector and calling it with different user IDs would prevent any memoization since it would be constantly called with different IDs leading it to recalculate on each call. + +This may sound unnecessary if you're writing a one-off selector, but if you think of something like a `getPost` selector in the Mattermost app, we will frequently be rendering 100+ post components each with their own copy of the `getPost` selector. With only a single copy of that selector, it would be constantly recalculating, but with 100+ copies, each only recalculates and rerenders when their specific post changes. diff --git a/docs/develop/contribute/more-info/webapp/redux/testing.md b/docs/develop/contribute/more-info/webapp/redux/testing.md new file mode 100644 index 000000000000..4a9b43ca6ef9 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/redux/testing.md @@ -0,0 +1,102 @@ +--- +title: "Redux Testing" +sidebar_position: 7 +--- + +### Unit Testing + +#### Unit Testing for Actions + +Tests for both actions and action creators are written using [Jest](https://jestjs.io/) and will often focus on seeing how dispatching an action affects the stored state in Redux. It'll often look similar to testing a reducer except you'll be looking at the whole store state instead of a single part of it. + +There are a few different ways of testing Redux actions used throughout Mattermost, but the most common way involves: + +1. Setting up an initial store state for the test case. +2. Optionally mocking any external operations that may be required for the action. This includes API requests which are mocked using [Nock](https://github.com/nock/nock). +3. Dispatching the result of the action creator. +4. Looking at the resulting store state to ensure the required changes are made. + + ```typescript + import nock from 'nock'; + + import mockStore from 'tests/test_store'; + + import {somethingAsyncHappened, somethingHappened} from './actions'; + + describe('somethingHappened', () => { + const channelId = 'channelId'; + + test('should update state.somethingCount', () => { + const store = mockStore({ + somethingCount: 0, + }); + + // Remember to actually call your action creator since that's very easy to forget to do + store.dispatch(somethingHappened(channelId)); + + expect(store.getState().somethingCount).toBe(1234); + }); + }); + + describe('somethingAsyncHappened', () => { + // Initial state may be shared between multiple test cases and may include state that's required for both + // testing and for thunk actions + const currentUserId = 'currentUserId'; + const initialState = { + entities: { + users: { + currentUserId: 'user1', + }, + }, + somethingCount: 0, + }; + + test('should update state.somethingCount on success', async () => { + const store = mockStore(initialState); + + const expectedResult = {status: 'SomethingHappened'}; + nock(Client4.getBaseRoute()). + post(`/channels/${channelId}/something`). + reply(200, {}); + + // Remember that tests for async requests need to themselves be async and we need to wait for the dispatch + await store.dispatch(somethingAsyncHappened(channelId)); + + expect(store.getState().somethingCount).toBe(1234); + }); + + test('should update state.somethingCount on failure', async () => { + const store = mockStore(initialState); + + const expectedResult = {status: 'SomethingHappened'}; + nock(Client4.getBaseRoute()). + post(`/channels/${channelId}/something`). + reply(400, {}); + + // You can also inspect the result of the action if desired + const result = await store.dispatch(somethingAsyncHappened(channelId)); + + expect(result.error).toBeDefined(); + expect(result.data).not.toBeDefined(); + + expect(store.getState().somethingCount).toBe(0); + }); + }); + ``` +5. Add unit tests to make sure that the action has the intended effects on the store. Test location is adjacent to the file being tested. Example, for `src/actions/admin.js`, test is located at `src/actions/admin.test.js`. Add test file if necessary. More information on unit testing reducers is available below. + +Some unit tests found throughout the web app may also test the actions dispatched by a thunk action rather than testing the effects on the changes to the store state. This method isn't considered as effective. + +#### Unit Testing for Selectors + +Unit tests for selectors are located in the same directory, adjacent to the file being tested. For example, the test for `src/selectors/admin.js` is located at `src/selectors/admin.test.js`. These tests are written using [Jest Testing Framework](https://jestjs.io/). In that folder, there are many examples of how those tests should look. Most follow the same general pattern of: +1. Construct the initial test state. Note that this doesn't need to be shared between tests as it is in many other cases. +2. Pass the state into the selector and check the results. The tests for some more complicated selectors do this multiple times while changing different parts of the store to ensure that the memoization is working correctly since it can be very important in certain areas of the app. + +### End-to-End (E2E) Testing + +#### E2E Tests for Actions + +Sometimes, it's not easy to test a redux action given it contains complicated async logic or requires a large amount of Redux state to be initialized to test it out. Other times, an action may feel too simple to test, especially if it's just dispatching an action that dictates specifically how the Redux state should change. + +In cases where the action will have an effect that's visible to the end user, it's possible to rely more on [end-to-end testing](/developers/contribute/more-info/webapp/e2e-testing). While this might not test every code path of the action such as poor network conditions, end-to-end tests are often more valuble since they involve testing that the code as a whole does what is expected rather than testing just that a single piece of code works under artificial conditions which may not be realistic. \ No newline at end of file diff --git a/docs/develop/contribute/more-info/webapp/unit-testing.md b/docs/develop/contribute/more-info/webapp/unit-testing.md new file mode 100644 index 000000000000..a0357bd551a8 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/unit-testing.md @@ -0,0 +1,237 @@ +--- +title: "Unit tests" +sidebar_position: 5 +--- + +### Unit Tests for Component and Utility Files + +The last required step in building a web app component is to test it. [Jest](https://jestjs.io/en/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) are the main frameworks/testing utilities used in unit testing components and utility files in our web app. Please visit their respective documentation for detailed information on how to get started, best practices, and updates. React Testing Library is used to render and interact with React components in a way that closely mirrors how users interact with them in the browser, while Jest is used to perform snapshot testing against these components. + +With React Testing Library, you can focus on testing the behavior of your components, rather than their implementation details. This means that your tests will be more resilient to changes in your codebase, and will give you more confidence that your application is working as expected. +If you need to unit test something related to Redux, please check out [Redux Unit and E2E Testing](/developers/contribute/more-info/webapp/redux/testing). + +#### Writing unit tests +Below is a brief guide on how to do component testing: + +1. Use our [testing library helpers](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/tests/react_testing_utils.tsx) to render a component and its child components. Use `screen` to interact with the rendered component and assert on the expected results. Match snapshots using default or expected props. Note that while using snapshots is convenient, do not rely solely on this for every test case, as changes can be easily overlooked when using the command `jest --updateSnapshot` to update multiple snapshots at once. For example: + ```javascript + import {render, screen, userEvent} from 'tests/react_testing_utils'; + const baseProps = { + active: true, + onSubmit: jest.fn(), + }; + + test('should match snapshot, not send email notifications', () => { + // For components that use Redux, React Intl, or Reach Router, you can also use the renderWithFullContext helper + const {container} = render(); + + expect(container.firstChild).toMatchSnapshot(); + + // Assert on a specific element rendered by the component + const submitButton = screen.getByRole('button', { name: 'Submit' }); + expect(submitButton).toBeInTheDocument(); + }); + ``` +2. Use screen from React Testing Library to query for elements by text or role and use assertions to verify their existence and properties. + ```javascript + expect(screen.getByRole('checkbox', { id: 'emailNotificationImmediately' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: props.siteName })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: props.customDescriptionText })).toBeInTheDocument(); + ``` +3. Use toHaveClass matcher from Jest DOM to check CSS classes. + ```javascript + expect(screen.getByTestId('create_post')).toHaveClass('center'); + ``` +4. Simulate events using userEvent and verify state changes using expect. + ```javascript + test('should pass handleChange', () => { + const {getByRole} = render(); + const emailNotificationImmediately = getByRole('checkbox', { id: 'emailNotificationImmediately' }); + + userEvent.click(emailNotificationImmediately); + + expect(emailNotificationImmediately.checked).toBe(true); + expect(screen.getByTestId('emailInterval').value).toBe('30'); + }); + ``` +5. Ensure that all functions of a component are tested. This can be done via events, state changes, or just calling it directly. + ```javascript + const baseProps = { + updateSection: jest.fn(), + }; + + test('should call updateSection on handleExpand', () => { + const {getByRole} = render(); + const button = getByRole('button', { name: /expand/i }); + + userEvent.click(button); + + expect(baseProps.updateSection).toBeCalled(); + expect(baseProps.updateSection).toHaveBeenCalledTimes(1); + expect(baseProps.updateSection).toBeCalledWith('email'); + }); + ``` + +6. When a function is passed to a component via props, make sure to test if it gets called for a particular event call or its state changes. + ```javascript + const baseProps = { + onSubmit: jest.fn(), + updateSection: jest.fn(), + }; + + test('should call functions on handleSubmit', () => { + const {getByTestId} = render(); + const submitButton = getByTestId('submit-button'); + + userEvent.click(submitButton); + + expect(baseProps.onSubmit).not.toBeCalled(); + expect(baseProps.updateSection).toHaveBeenCalledTimes(1); + expect(baseProps.updateSection).toBeCalledWith('email'); + + const emailNotificationNever = getByTestId('email-notification-never'); + userEvent.change(emailNotificationNever); + + userEvent.click(submitButton); + + expect(baseProps.onSubmit).toBeCalled(); + expect(baseProps.onSubmit).toHaveBeenCalledTimes(1); + expect(baseProps.onSubmit).toBeCalledWith({enableEmail: 'false'}); + + expect(baseProps.updateSection).toHaveBeenCalledTimes(2); + expect(baseProps.updateSection).toBeCalledWith(''); + }); + ``` +7. Provide a mock for a single function imported from another file while keeping the original version of the rest of that file's exports. + ```javascript + jest.mock('utils/utils', () => { + const original = jest.requireActual('utils/utils'); + return { + ...original, + isMobileView: jest.fn(() => true), + }; + }); + ``` +8. Mock async ``redux`` actions as necessary while providing a readable action type and having them pass their arguments. + ```javascript + jest.mock('mattermost-redux/actions/channels', () => { + const original = jest.requireActual('mattermost-redux/actions/channels'); + return { + ...original, + fetchMyChannelsAndMembers: (...args) => ({type: 'MOCK_FETCH_CHANNELS_AND_MEMBERS', args}), + }; + }); + + // Then compare the dispatched actions + await testStore.dispatch(Actions.loadChannelsForCurrentUser()); + expect(testStore.getActions()).toEqual(expectedActions); + ``` +9. For utility functions, list all test cases with test description, input and output. + ```javascript + describe('stripMarkdown | RemoveMarkdown', () => { + const testCases = [{ + description: 'emoji: same', + inputText: 'Hey :smile: :+1: :)', + outputText: 'Hey :smile: :+1: :)', + }, + { + description: 'at-mention: same', + inputText: 'Hey @user and @test', + outputText: 'Hey @user and @test', + }]; + + testCases.forEach((testCase) => { + test(testCase.description, () => { + expect(stripMarkdown(testCase.inputText)).toEqual(testCase.outputText); + }); + }); + } + ``` +#### Running unit tests +10. To run all tests that have been modified or added since the last commit, run [Jest](https://jestjs.io/en/) in `watch` mode with the command: `npm run test:watch`. + * If there are new tests in the first run, test snapshots will be generated and placed in the `__snapshots__` directory in the folder where the test suite is located. + * In watch mode, you can also run specific sets of tests: + + ``` + › Press a to run all tests. + › Press f to run only failed tests. + › Press o to only run tests related to changed files. + › Press q to quit watch mode. + › Press p to filter by a filename regex pattern. + › Press t to filter by a test name regex pattern. + › Press Enter to trigger a test run. + ``` + * To see if a component test passes, select `p` in `watch` mode and enter the filename for the component test. + +#### Troubleshooting + +* If you get an error similar to `UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'filter' of undefined`: + + - Check if the code being tested uses native timer functions (i.e., `setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`). You can mock the timers and/or run fake timers (e.g. `jest.useFakeTimers()`) if necessary. Note that `jest.useFakeTimers()` is already used in the [Jest global setup](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/tests/setup.js), but there are cases where it needs to run specifically depending on how the component uses the native timer functions. +

+ +* If you get an error similar to `UnhandledPromiseRejectionWarning: TypeError: (0 , \_fff.hhh) is not a function`: + + - Check if you're mocking part of an imported module without providing other exports which are used. You can use `jest.requireActual` to get the un-mocked version of the file. + + ```javascript + // DO NOT partially mock the module + jest.mock('actions/storage', () => ({ + setGlobalItem: (...args) => ({type: 'MOCK_SET_GLOBAL_ITEM', args}), + })); + + // DO fully mock the module + jest.mock('actions/storage', () => { + const original = jest.requireActual('actions/storage'); + return { + ...original, + setGlobalItem: (...args) => ({type: 'MOCK_SET_GLOBAL_ITEM', args}), + }; + }); + ``` + +* If you get an error similar to `UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'data' of undefined`: + + - Use async mock functions with resolved values. The property in question that cannot be read can be `error`, `data`, `exists`, `match`, or whatever else the resolved value(s) contains. For example, if the file being tested contains a line where it awaits on an async value like: + + ```javascript + const {data} = await this.props.actions.addUsersToTeam(this.props.currentTeamId, userIds); + ``` + + The mocked function should return a Promise by using `mockResolvedValue`: + + ```javascript + // DO NOT assign a regular mock function. + const addUsersToTeam = jest.fn(); + + // DO NOT forget to provide a resolved value. + const addUsersToTeam: jest.fn(() => { + return new Promise((resolve) => { + process.nextTick(() => resolve()); + }); + }), + + // DO mock async function with resolved value. `mockResolvedValue` is the easiest way to do this. + const addUsersToTeam = jest.fn().mockResolvedValue({data: true}) + + // DO mock async function with several resolved values for repeated calls. + const addUsersToTeam = jest.fn(). + mockResolvedValueOnce({error: true}). + mockResolvedValue({data: true}); + ``` + + Remember to make individual test cases async when testing async functions: + + ```javascript + // DO NOT forget to wait for the async function to complete. + test('should match state when handleSubmit is called', () => { + wrapper.instance().handleSubmit(); + expect(...) + }); + + // DO remember to wait on the async function and to make the entire test case async. + test('should match state when handleSubmit is called', async () => { + await wrapper.instance().handleSubmit(); + expect(addUsersToTeam).toHaveBeenCalledTimes(1); + }); + ``` diff --git a/docs/develop/contribute/more-info/webapp/using-i18n-extract.md b/docs/develop/contribute/more-info/webapp/using-i18n-extract.md new file mode 100644 index 000000000000..99fe32394af5 --- /dev/null +++ b/docs/develop/contribute/more-info/webapp/using-i18n-extract.md @@ -0,0 +1,41 @@ +--- +title: "Use make i18n-extract" +sidebar_position: 10 +--- + +`make i18n-extract` is a command used for localization. It allows you to validate that your strings have been successfully extracted from your source code before you continue. + +This page demonstrates how to review your results and to verify if your extraction was successful or not. If the extraction was not successful this page also provides a workaround to correct for this. + + + +These steps haven't been updated since Mattermost has switched to using a [monorepo](https://github.com/mattermost/mattermost). We're in the process of updating our I18n workflow and these corresponding docs. + +In the meantime, these commands can be run from within each package (`webapp/boards`, `webapp/channels`, and `webapp/playbooks`) to update their corresponding translation files. + + + +1. After you execute `make i18n-extract` you will need to review the results and validate that the strings were either added or removed in the `i18n/en.json` file. +2. Run `git diff` and determine if your strings were added or removed in the `i18n/en.json` file correctly. If this was a successful extraction you will have output similar to below: + + ![image](/img/i18n-extract-1.jpg) + +3. However, if you have a string that was not properly extracted you will see an output similar to below. If you executed the `make i18n-extract` at this point nothing would change because the string `"new-text-id"` is not detected as a string that needs to be translated. + + ![image](/img/i18n-extract-2.jpg) + +4. The solution is to tag the string. Do this by using the `"t"` function, shown in the example below: + + ![image](/img/i18n-extract-3.jpg) + +5. At this point you will need to execute the `make i18n-extract` once again and determine if the extraction was successful. This will generate a message in the `i18n/en.json` file. However, this is not going to extract the "default message", you will have to add this yourself. See example below: + + ![image](/img/i18n-extract-4.jpg) + + + +Be aware that when you use the `"t"` function, only the translation id is extracted. You have to add the translation string in the `i18n/en.json` file manually. + + + +For further discussion about translations or to ask for help, refer to the following Mattermost channels: [Localization](https://community.mattermost.com/core/channels/localization) and [Contributors](https://community.mattermost.com/core/channels/tickets). diff --git a/docs/develop/contribute/why-contribute/contribute.png b/docs/develop/contribute/why-contribute/contribute.png new file mode 100644 index 000000000000..d67e17435535 Binary files /dev/null and b/docs/develop/contribute/why-contribute/contribute.png differ diff --git a/docs/develop/contribute/why-contribute/inactivity.png b/docs/develop/contribute/why-contribute/inactivity.png new file mode 100644 index 000000000000..c29ba583d905 Binary files /dev/null and b/docs/develop/contribute/why-contribute/inactivity.png differ diff --git a/docs/develop/contribute/why-contribute/index.md b/docs/develop/contribute/why-contribute/index.md new file mode 100644 index 000000000000..09499b92828e --- /dev/null +++ b/docs/develop/contribute/why-contribute/index.md @@ -0,0 +1,195 @@ +--- +title: "Why and how to contribute" +sidebar_position: 1 +--- +There are many reasons you might be motivated to contribute to Mattermost: + +- [You've found a bug](#youve-found-a-bug) +- [You want to help with content](#you-want-to-help-with-content) +- [You want to make something more inclusive or accessible](#you-want-to-make-something-more-inclusive-or-accessible) +- [You have a feature idea](#you-have-a-feature-idea) +- [You're looking to practice your skills or give back to the community](#youre-looking-to-practice-your-skills-or-give-back-to-the-community) +- [You want to help with product translation](#you-want-to-help-with-product-translation) +- [You want to help test new features](#you-want-to-help-test-new-features) + +## You’ve found a bug + +1. If the bug fix that you’re proposing would be larger than 20 lines of code, [create a GitHub issue](https://github.com/mattermost/mattermost/issues). + + - You can speed up the process by asking about the issue in the [Contributors](https://community.mattermost.com/core/channels/tickets) or [Developers](https://community.mattermost.com/core/channels/developers) channels on the Mattermost Community Server. + + - [Here’s a good example of a contribution](https://github.com/mattermost/mattermost-mobile/pull/364/commits/7a97451b62fee4022edac4c0395ad0a5cbf1bb66) that is small enough to not need a ticket while still being incredibly helpful. + +2. If you’ve volunteered to take the ticket once it's active, or if your fix is too small to warrant the ticket, fork the applicable repository, and start making your changes. + +3. Create a PR on the `master` branch of the applicable repository. If there is an associated [Jira](https://mattermost.atlassian.net/issues/?jql=) or GitHub issue, your PR should begin with the issue ID (e.g. `[MM-394]` or `[GH-394]`). Our GitHub PR template will walk you through the creation of your PR. + +4. If you’re a community contributor, the team at Mattermost will handle most of the review process for you. You can wait for a reviewer to be assigned and for them to review your work. + + - Generally the process works like you’d expect: they’ll make suggestions, you’ll implement them, and together you'll discuss changes in PR comments. If you’re having trouble getting a reviewer to be assigned to your PR, take a look at GitHub’s suggested reviewers and reach out to them in the [Community workspace](http://community.mattermost.com). + +![Contribute](contribute.png) + +5. Here is an overview of how our review process works listed in the order in which things happen. If you’re a core contributor, you can manage the process yourself. + + - **Labels will be added to your PR**, such as `1: UX Review`, `2: Dev Review`, and `3: QA Review`, as applicable. See [the list of labels](/developers/contribute/more-info/getting-started/labels) for details. + + - **A milestone or a `cherry-pick` label may be added to your PR**. Many PRs don’t need this step, and will simply ship once merged. However, if there are upcoming milestones, some reviewers are going to prioritize reviews attached to those milestones. Adding a milestone is mandatory for bug fixes that must be cherry-picked. + + - In many cases, you'll know whose code you’re changing and can **assign the appropriate Product Manager, Designer, or Technical Writer to review your PR** from a UI/UX perspective. When in doubt, somebody is better than nobody, as reviewers can always reassign. Once reviewers approve your PR, the `1: UX Review` label will be removed. + + - **Request two core committers to review your PR** — one with experience solving that particular type of issue or in that particular language, and another with expertise in the domain of your changes. Don’t request the same people over and over again unless they’re the only people with the necessary expertise. Once they give their approval, the `2: Dev Review` label will be removed. + + - **Request a QA tester** from the team that owns the code that you’re changing. They’ll decide the necessary scope of testing. Make sure you’ve defined what the expected results are so they know when their tests are successful. Once they give their approval, the `3: QA Review` label will be removed. The QA tester may add the `QA Review Done` label as well. + + +We recommend that you generally avoid doing QA testing yourself, unless it’s obvious that it’s not necessary. The best way to help Mattermost QA is to clearly explain your changes and expected outcomes in the PR. + + + +```text +- Once all outstanding requests are completed, and all involved have approved of the PR, **the `4: Reviews Complete` label will be added** which signals Mattermost core committers to merge the PR into `master`, and delete the old branch. If your pull request depends on other pull requests, note this as a PR comment so that the `Do Not Merge/Awaiting PR` label can be added to avoid merging prematurely. + +- If this is a cherry-picked PR, **automated processes should handle everything from here on out**. If the automated cherry-pick fails, the PR will be cherry-picked manually back to the appropriate releases. If the release branches have not been cut yet, labels are left as-is and the PR is cherry-picked once the branch has been cut. The release manager will provide reminders to finish cherry-picks. The `CherryPick/Done` label is applied the end of a cherry-pick process. + +- **Update the appropriate Jira ticket** so everybody knows where the project stands. Resolve the ticket for QA from the **Ready for QA** button, and include QA test steps, or note **No Testing Required** if no QA testing is needed. + +- If you need to test your changes on a test server, an [appropriate label](/developers/contribute/more-info/getting-started/labels) can be added to the PR. **Request this label as a comment in your PR to create a test server**. After about three to five minutes, a test server is created, and a bot will send a link and credentials in the form of a comment on the PR. The test server is destroyed when the label is removed. +``` + + ![Review-process](review.png) + +6. Once you address suggestions a reviewer has made, re-request a review from them. Their initial review was technically completed, so it’s no longer in a reviewer's queue until you re-request. + + + +Give reviewers time — they may have long queues and different schedules. If you’ve been assigned a reviewer but haven’t heard from them in five business days, you can politely bring focus back to your PR by mentioning them in a PR comment. + + + +7. Mattermost has a system to categorize the inactivity of contributions. Invalid PRs don’t need to go through this cycle at the Community Coordinator’s discretion. + + - **After ten days of inactivity**: A contribution becomes stale, and a bot will add the `lifecycle/1:stale` label to the PR. It’s the job of the Community Coordinator to nudge the right people to get a stale PR active again, even if that means clarifying requests so the contributor has more information to work with. + + - **After 20 days of inactivity**: A contribution becomes inactive, and a bot will add the `lifecycle/2:inactive` label to the PR. + + - The Community Coordinator warns everybody involved how much time they have before the contribution is closed and again tries to reach out to the blocking party to help. + + - The Community Coordinator also ensures that it’s not the reviewers taking the PR to this point — contributions should only ever be inactive because of no response from the contributor. + + - When contributions are inactive, but there's a good reason (for example, when the team is actively discussing a major design decision but they haven’t decided on anything yet), `lifecycle/frozen` would be a better label. + + - Inactive contributions are eligible to be picked up by another community member. + + - **After 30 days of inactivity**: A contribution becomes orphaned, the `lifecycle/3:orphaned` label is added to the now-closed PR. The associated `Help Wanted` ticket is given back its `Up For Grabs` status so others can pick up the issue. + + ![Inactivity](inactivity.png) + +## You want to help with content + +Good product and developer documentation content is as important as good code! If you notice and fix a content error in the documentation, in a repository README, or in another open source article describing Mattermost, we consider you to be as valued a member of our contributor community as those who contribute to core code. + +1. If you see a problem with Mattermost [developer](https://developers.mattermost.com/) or [product](https://docs.mattermost.com/) documentation, you have a few options: + + - If you have time to fix the mistake and it only affects a single page, navigate to the applicable page and select **Edit in GitHub** at the top right. You'll be walked through the process of creating a fork so that you can then follow the steps under the section titled [“You’ve found a bug”](/developers/contribute/why-contribute/#youve-found-a-bug) in this guide. + + - If you don’t have time to fix the mistake, copy the file path you’re on, and create a GitHub issue about the problem you found on the applicable repository. Make sure to include the file path and fill out the issue template completely to maximize clarity. + + - If you’re not up for creating a GitHub issue right now, that’s alright too! In the bottom-right corner of every product documentation page is the question “Did you find what you were looking for?” Use this to quickly provide direct feedback about any page you’re viewing. + + - If you want to fix a larger problem that affects multiple pages or the structure of the docs, you should first report it as an issue on the appropriate GitHub repository, and follow the steps under [“You’ve found a bug”](/developers/contribute/why-contribute/#youve-found-a-bug). The [developer](https://developers.mattermost.com/) and [product](https://docs.mattermost.com/) documentation repositories contain instructions on how to build and modify the sites locally so you can test larger changes more efficiently. + + - Find a list of the Mattermost documentation specific repos on the [Contributor expectations page](/developers/contribute/expectations/#before-contributing) of this guide. + + + +The best place to discuss problems with the writing team is in the [Documentation Working Group channel](https://community.mattermost.com/core/channels/dwg-documentation-working-group) where you can ping our technical writers with the group `@docsteam`. + + + +2. If you’d like to contribute to our blog, website, or social media content, you also have a few options: + + - You can get paid to write technical content for developers through the Mattermost [community writing program](https://mattermost.com/blog/blog-announcing-community-writing-program/). + + - If you see a problem with any webpages, blog posts, or other content on [Mattermost.com](https://mattermost.com), you can notify us via [the Content channel](https://community.mattermost.com/core/channels/mattermost-blog) on the Mattermost Community Server. + + - Share your contributor or user experience! Mention us when you promote your work within our community, and we’ll amplify the message through Mattermost social media platforms. + + - Want to lead a social community? We can provide advice and resources to help you in the [Community channel](https://community.mattermost.com/core/channels/community-team) on the Mattermost Community Server. + +## You want to make something more inclusive or accessible + +Accessibility is one of the most overlooked yet most important features of modern software development, and we’re eager to improve on the accessibility of the features in our open source project and its documentation. + +- Problems with the accessibility or the inclusivity of both features in the codebase, as well as problems with pieces of content describing Mattermost, are bugs, so we treat them as such in our development process. + +- When you contribute a change that incorporates an adjustment based on the principles of accessibility and inclusivity, please circle back to this guide to back you up in the PR, ticket, or post. + +## You have a feature idea + +Thank you for your enthusiasm! You can act on feature ideas in a few ways: + +1. Take a look at our [product roadmap](https://mattermost.com/roadmap/). There’s a chance we might already be building the thing you want. + +2. [Provide input on features](https://portal.productboard.com/mattermost/33-what-matters-to-you/tabs/117-potential-future-offerings) we’re considering to let us know what matters the most to you. + +3. [Participate in a survey](https://portal.productboard.com/mattermost/33-what-matters-to-you/tabs/115-help-us-learn-more-through-surveys) to help us better understand how to meet the needs of our users. + +4. Discuss your idea with our community in the [Feature Proposals channel](https://community.mattermost.com/core/channels/feature-ideas). + +5. Build an app! Mattermost has a rich framework full of tools to help you add the features you want that don’t quite work as core additions to Mattermost. + + - [Webhooks](/developers/integrate/webhooks) are the easiest type of app to create and enable you to integrate with the vast majority of modern web tools. + + - [Slash commands](/developers/integrate/slash-commands) are apps that respond to triggers sent as messages inside Mattermost. + + - [plugins](/developers/integrate/plugins) enable you to alter every component of the Mattermost experience. + +## You’re looking to practice your skills or give back to the community + +We love developers who are passionate about open-source! + +If you’re looking to tackle an interesting problem, we’ve got you covered! Feel free to check out the [help wanted tickets on GitHub](https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+archived%3Afalse+org%3Amattermost+label%3A%22Help+Wanted%22++label%3A%22Up+For+Grabs%22). To take one on, just comment on the issue, and follow the process outlined in [You've found a bug](#youve-found-a-bug) of this guide. You can find a list of the Mattermost repositories on the [Contributor expectations page](/developers/contribute/expectations/#before-contributing) of this guide. + +## You want to help with product translation + +We’re honored that you’d like to help people use Mattermost in their native language, so we treat all translators as full-fledged contributors alongside engineers and authors. + +Each localization community is going to have specific guidelines on how to maintain Mattermost’s distinctive voice across language barriers. Read these guides thoroughly before starting to translate [German](https://gist.github.com/der-test/6e04bff8a173e053811cb93e08838ca2), [French](https://github.com/wget/mattermost-localization-french-translation-rules), or [Dutch](https://github.com/ctlaltdieliet/mattermost-localization-dutch-translation-rules). + +To get started: + +1. Join [Mattermost translation server](https://translate.mattermost.com/) and the [localization community channel](https://community.mattermost.com/core/channels/localization) on the Mattermost Community Server. + + - If your preferred language already exists on the translation server, you can start making translations or translation suggestions immediately *there on the translation server*. Don’t try to do this manually through GitHub. + - If your language is absent from the translation server, ask on the [localization community channel](https://community.mattermost.com/core/channels/localization) for it to be added. + - Visit the [Mattermost Handbook](https://handbook.mattermost.com/contributors/join-us/localization) to learn more about getting started with product translation at Mattermost. + +2. Each language in whole is assigned one quality level, and with each release cycle, it can be upgraded or downgraded if necessary. + + - **Official** — 100% of the language’s translations are verified both by a Mattermost functionality expert and by an expert speaker of the target language. Officially supported languages have at least one official reviewer who updates all of the strings that have changed in the English source text, and they have successfully kept all of the translated strings updated since the last release cycle. The language has been in use for at least three full release cycles. + + + - **Beta** — At least 90% of the language’s translations are verified by at least one Mattermost functionality expert who is fluent in the target language. If a language is at risk for ongoing maintenance, Mattermost can raise the threshold closer to 100%. Up to 10% of the translations may not be synchronized with the latest English source text. + + - **Alpha** — The language does not meet the qualifications for the Beta level. + +3. Every Monday, PRs gets opened for all updates. These PRs will be checked for unexpected character insertions and security problems. Reviewers should always “merge commit” or “rebase and merge” into the PR, but never, ever “squash and commit”. Once approved, PRs are merged into the proper repositories. + +4. Every contribution will be written with the ICU syntax. Please read [this guide](https://formatjs.io/docs/core-concepts/icu-syntax/) so you can get familiar with how it works, and focus especially on how plural terms are handled since that topic comes up quite often. See the [Mattermost Handbook's Localization page](https://handbook.mattermost.com/contributors/join-us/localization#message-syntax) for best practice recommendations on working with ICU syntax. + +5. Don’t hesitate to use tools like the [Online ICU Message Editor](https://format-message.github.io/icu-message-format-for-translators/editor.html), which can help you see how your string will look in context. + +6. If you’re not sure how to translate a technical term, you can search for it elsewhere in your language on the translation server, check [how Microsoft has translated it](https://msit.powerbi.com/view?r=eyJrIjoiODJmYjU4Y2YtM2M0ZC00YzYxLWE1YTktNzFjYmYxNTAxNjQ0IiwidCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsImMiOjV9), and feel free to ask for additional string context in the localization channel. + +## You want to help test new features + +The QA team keeps all contributions up to Mattermost’s high standards. That big responsibility earns QA reviewers the same status as all other contributors. + +- If you’d like to earn some prizes, join our periodic bug bashes run on the [QA Contributors channel](https://community.mattermost.com/core/channels/qa-contributors) on the Mattermost Community Server. + +- Standalone [exploratory testing](https://github.com/mattermost/quality-assurance/issues/2) is highly encouraged too! Remember to report your findings in the [QA Contributors channel](https://community.mattermost.com/core/channels/qa-contributors). + +Test-writing is also a valuable part of the development process, and is a great way to start contributing to the Mattermost project. + +- Get started by learning about our testing ethos, the categories of tests that exist, situations where tests should and should not be made, and how to write tests on the [Test guidelines](/developers/contribute/more-info/getting-started/test-guideline) page. diff --git a/docs/develop/contribute/why-contribute/review.png b/docs/develop/contribute/why-contribute/review.png new file mode 100644 index 000000000000..f9e020b8685a Binary files /dev/null and b/docs/develop/contribute/why-contribute/review.png differ diff --git a/docs/develop/index.mdx b/docs/develop/index.mdx new file mode 100644 index 000000000000..874ad81293f6 --- /dev/null +++ b/docs/develop/index.mdx @@ -0,0 +1,64 @@ +--- +slug: / +title: Mattermost for Developers +description: Contribute to Mattermost, build plugins and integrations, and extend the platform. +sidebar_position: 1 +sidebar_label: Welcome +--- + +Developers + +Build with, on, and for Mattermost. Contribute to the platform, build plugins and integrations, and extend Mattermost into the rest of your operational stack. + +## Start here + + + +## What's covered here + +- **[Contribute](/developers/contribute)** — onboarding, expectations, finding good first issues, the contribution workflow. +- **[Integrate & Extend](/developers/integrate)** — apps, plugins, slash commands, incoming + outgoing webhooks, OAuth, customization, the marketplace. +- **[Internal](/developers/internal)** — Mattermost-engineering team docs (build process, infrastructure, QA). + +## Looking for something else? + + + + +Content migrated from the legacy `mattermost-developer-documentation` Hugo site. Some pages have unconverted Hugo shortcode placeholders (`{/* TODO: unconverted Hugo shortcode … */}` markers) that are scheduled for manual cleanup — see PLAN.md §11.2. + diff --git a/docs/develop/integrate/apps/authentication/oauth2/index.md b/docs/develop/integrate/apps/authentication/oauth2/index.md new file mode 100644 index 000000000000..d503b5db98db --- /dev/null +++ b/docs/develop/integrate/apps/authentication/oauth2/index.md @@ -0,0 +1,176 @@ +--- +title: "Use OAuth2.0 with Mattermost" +sidebar_position: 80 +--- + +The authorization allows: + +- Users with an account on a Mattermost server to sign in to third-party applications. You can find a [sample OAuth2 Client Application for Mattermost here](https://github.com/enahum/mattermost-oauth2-client-sample) to test the functionality. +- A Mattermost server to authenticate requests to a third-party API. One popular application is Zapier integration which allows you to integrate more than 700 applications with Mattermost through OAuth 2.0. See our [Zapier documentation](/developers/integrate/zapier-integration) to learn more. + +## Understanding client types + +Mattermost supports two types of OAuth 2.0 clients as defined in [RFC 6749](https://tools.ietf.org/html/rfc6749): + +### Confidential clients + +- **Authentication**: Have a `client_secret` that must be kept secure +- **Use cases**: Server-side applications, trusted backends +- **Token endpoint auth method**: `client_secret_post` +- **Created**: Via UI (default) or Dynamic Client Registration (DCR) +- **Security**: Can securely store credentials on the server side + +### Public clients + +- **Authentication**: No `client_secret` (uses auth method `none`) +- **Use cases**: Single-Page Applications (SPAs), mobile apps, browser-based applications that cannot securely store secrets +- **Security**: MUST use PKCE for authorization code flow +- **Token endpoint auth method**: `none` +- **Created**: Via API with `is_public: true` parameter, or via DCR with `token_endpoint_auth_method: "none"` +- **Limitations**: Do not receive refresh tokens (access tokens only) + +## Register your application in Mattermost + +You must register your application in Mattermost to generate OAuth 2.0 credentials (client ID and secret for confidential clients, or just client ID for public clients), which your application can use to authenticate API calls to Mattermost, and which Mattermost uses to authorize API requests from the application. + +If you'd like to set up a Zapier integration with OAuth 2.0, see our [Zapier documentation](/developers/integrate/zapier-integration) to learn more. + +### Enable OAuth 2.0 applications + +OAuth 2.0 applications are off by default and can be enabled by the System Admin as follows: + +1. Log in to your Mattermost server as the System Administrator. +2. Go to **System Console > Integrations > Integration Management**. +3. Set [Enable OAuth 2.0 Service Provider](https://docs.mattermost.com/administration/config-settings.html#enable-oauth-2-0-service-provider) to **True**. +4. (Optional) If you'd like to allow external applications to post with customizable usernames and profile pictures, then set [Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) and [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) to **true**. +5. (Optional) If you'd like to allow users on your system who are not System Admins to create OAuth 2.0 applications, then set [Restrict managing integrations to Admins](https://docs.mattermost.com/administration/config-settings.html#restrict-managing-integrations-to-admins) to **False**. +6. (Optional) To enable Dynamic Client Registration, set **Enable Dynamic Client Registration** to **True** in **System Console > Integrations > Integration Management**. See the [Dynamic Client Registration](#dynamic-client-registration) section for important security considerations. + +### Register an OAuth 2.0 application + +1. Go to **Product menu > Integrations**. +2. Select **OAuth 2.0 Applications**, then choose **Add OAuth 2.0 Application**. +3. Set **Is Trusted**: When set to **Yes**, your application is considered trusted by Mattermost. This means Mattermost doesn't require users to accept authorization when signing to third-party applications. When set to **No**, users will be provided with the following page to accept or deny authorization when authenticating for the first time. + + ![image](oauth2_authorization_screen.png) + +```text +Only System Admins can set OAuth 2.0 applications as trusted. +``` + +4. Set **Is Public Client**: When set to **Yes**, your application is registered as a public client (for SPAs, mobile apps, etc.). Public clients do not receive a client secret and must use PKCE for the authorization code flow. When set to **No** (default), your application is registered as a confidential client with a client secret. +5. Specify the **Display Name**: Enter a name for your application made of up to 64 characters. This is the name users will see when granting access to the application, when viewing a list of authorized applications in **Settings > Security > OAuth 2.0 Applications** and when viewing a list of OAuth 2.0 applications in the **Integrations** menu. +6. Add **Description**: This is a short description of your application that users will see when viewing a list of authorized applications in **Settings > Security > OAuth 2.0 Applications**. +7. Specify the **Homepage**: This is the homepage of the OAuth 2.0 application and lets users visit the app page to learn more what it does. The URL must be a valid URL and start with `http://` or `https://` depending on your server configuration. +8. (Optional) Add **Icon URL**: The image users will see when viewing a list of authorized applications in **Settings > Security > OAuth 2.0 Applications** and when viewing a list of OAuth 2.0 applications in the **Integrations** menu. Must be a valid URL and start with `http://` or `https://`. +9. Add **Callback URLs**: These are the URL(s) to which Mattermost will redirect users after accepting or denying authorization of your application, and which will be the only URL(s) that handle authorization codes or access tokens. If more than one URL is specified, users will be redirected to the URL used for the initial authorization of the app. Each URL must be on a separate line and start with `http://` or `https://`. +10. Select **Save** to create the application. + + ![image](oauth2_app_screen.png) + +11. You'll be provided with a **Client ID**, **Client Secret**, and the authorized redirect URLs. Save these values and use them in your application to connect it to Mattermost. + + ![image](oauth2_confirmation_screen.png) + + + +**Client Secret** can be regenerated by the application creator or System Admin. Tokens created with the old secret will remain valid and authorization of existing users will continue to work; however, new authorizations and requests for new tokens will fail until the client secret has been updated in your app configuration. + + + +```text +![image](oauth2_regenerate_secret.png) +``` + +## Grant permissions to your application + +Once you have created an OAuth 2.0 application, all users on the Mattermost server are automatically given access to it. + +The application does not automatically have permissions based on the user who registers the app - the permissions are based on which users go through the OAuth flow, which could be the user who registers the app or anyone else on the system. + +If the application was registered as a trusted OAuth 2.0 app on the Mattermost server, authorization from users is not required. Otherwise, the following page will be provided to accept or deny authorization when authenticating the app for the first time. + +![image](oauth2_authorization_screen.png) + +Once authorized, the application receives an access token to perform requests on behalf of that user. The application can then perform any action for which the user has permission. + +Users can view a list of authorized apps from **Settings > Security > OAuth 2.0 Applications**, and revoke authorization from this setting. + +![image](oauth2_deauthorize_app.png) + +## Supported OAuth flows + +Mattermost supports the [authorization code](https://oauth.net/2/grant-types/authorization-code/) and [implicit](https://oauth.net/2/grant-types/implicit/) grant flows for OAuth 2.0 applications. + +### Flow support by client type + +| Client Type | Authorization Code Flow | Implicit Flow | PKCE Required | +|---------------------|-------------------------|---------------------------------|----------------------| +| Public Client | Supported | Supported | YES (code flow only) | +| Confidential Client | Supported | Supported **(Not recommended)** | Optional | + +**Key notes:** + +- Public clients **cannot** use the refresh token grant type - they only receive access tokens, not refresh tokens +- Implicit flow does **not** require PKCE (no code exchange happens) +- Confidential clients can optionally use PKCE; if initiated with `code_challenge`, it will be enforced throughout the flow + +## PKCE (Proof Key for Code Exchange) + +[PKCE (RFC 7636)](https://tools.ietf.org/html/rfc7636) is a security extension that protects against authorization code interception attacks. It's especially important for public clients like single-page applications and mobile apps that cannot securely store client secrets. + +### When PKCE is required + +- **Public clients**: MUST use PKCE when using the authorization code flow. The Mattermost server will reject authorization requests from public clients that don't include PKCE parameters. +- **Confidential clients**: PKCE is optional. However, if you include PKCE parameters in the authorization request, you must complete the PKCE flow in the token request. + +### How PKCE works + +PKCE adds two parameters to the OAuth flow: + +1. **Authorization request**: Include a `code_challenge` (a hashed value) and `code_challenge_method` (Mattermost supports `S256` only) +2. **Token request**: Include the `code_verifier` (the original unhashed value) + +The server verifies that the `code_verifier` matches the original `code_challenge`, ensuring the same client that started the authorization is completing it. + +## Dynamic Client Registration + +Dynamic Client Registration (DCR) allows applications to programmatically register OAuth clients without requiring manual configuration by a System Admin. This follows [RFC 7591](https://tools.ietf.org/html/rfc7591). + +### Enabling DCR + +DCR is disabled by default and can be enabled by a System Admin: + +1. Go to **System Console > Integrations > Integration Management** +2. Set **Enable Dynamic Client Registration** to **True** + + + +When DCR is enabled, the registration endpoint is **publicly accessible** without authentication. This means anyone can register OAuth clients on your Mattermost server. Only enable DCR if you understand and accept this security model, or have additional network-level access controls in place. + + + +### Using DCR + +When enabled, applications can register themselves as either public or confidential clients by making a request to the registration endpoint (`/api/v4/oauth/apps/register`). The application specifies its redirect URIs and authentication method: + +- `token_endpoint_auth_method: "none"` creates a public client (no client secret) +- `token_endpoint_auth_method: "client_secret_post"` creates a confidential client (with client secret) + +### Discovery endpoint + +Mattermost provides an [OAuth 2.0 Authorization Server Metadata](https://tools.ietf.org/html/rfc8414) endpoint at `/.well-known/oauth-authorization-server` that advertises server capabilities, including whether DCR is enabled and what authentication methods are supported. + +## Refresh tokens + +**Confidential clients** receive refresh tokens and can use them to obtain new access tokens. **Public clients** do not receive refresh tokens for security reasons. + +## OAuth endpoints + +- Authorize URI `/oauth/authorize` +- Token URI `/oauth/access_token` +- User info URI `/api/v4/users/me` + +## Delete your application + +Deleting the application will revoke access from all users. Only the user who created the application or a System Admin can delete the app. diff --git a/docs/develop/integrate/apps/authentication/oauth2/oauth2_app_screen.png b/docs/develop/integrate/apps/authentication/oauth2/oauth2_app_screen.png new file mode 100644 index 000000000000..4276259281ac Binary files /dev/null and b/docs/develop/integrate/apps/authentication/oauth2/oauth2_app_screen.png differ diff --git a/docs/develop/integrate/apps/authentication/oauth2/oauth2_authorization_screen.png b/docs/develop/integrate/apps/authentication/oauth2/oauth2_authorization_screen.png new file mode 100644 index 000000000000..a74886f27cda Binary files /dev/null and b/docs/develop/integrate/apps/authentication/oauth2/oauth2_authorization_screen.png differ diff --git a/docs/develop/integrate/apps/authentication/oauth2/oauth2_confirmation_screen.png b/docs/develop/integrate/apps/authentication/oauth2/oauth2_confirmation_screen.png new file mode 100644 index 000000000000..585535df3952 Binary files /dev/null and b/docs/develop/integrate/apps/authentication/oauth2/oauth2_confirmation_screen.png differ diff --git a/docs/develop/integrate/apps/authentication/oauth2/oauth2_deauthorize_app.png b/docs/develop/integrate/apps/authentication/oauth2/oauth2_deauthorize_app.png new file mode 100644 index 000000000000..013c5ad85434 Binary files /dev/null and b/docs/develop/integrate/apps/authentication/oauth2/oauth2_deauthorize_app.png differ diff --git a/docs/develop/integrate/apps/authentication/oauth2/oauth2_regenerate_secret.png b/docs/develop/integrate/apps/authentication/oauth2/oauth2_regenerate_secret.png new file mode 100644 index 000000000000..7603e993ffd4 Binary files /dev/null and b/docs/develop/integrate/apps/authentication/oauth2/oauth2_regenerate_secret.png differ diff --git a/docs/develop/integrate/customization/customization/index.md b/docs/develop/integrate/customization/customization/index.md new file mode 100644 index 000000000000..9e72ad1c42a9 --- /dev/null +++ b/docs/develop/integrate/customization/customization/index.md @@ -0,0 +1,30 @@ +--- +title: "Customize Mattermost" +sidebar_position: 50 +--- + +Mattermost allows for a variety of customization options and modifications, making it possible to create a more adequate experience depending on the needs of each deployment. + +There are a few limitations regarding [how the re-branding of Mattermost](https://mattermost.com/trademark-standards-of-use/) must be handled, such as the fact that changes to the Enterprise Edition's source code isn't supported. However these limitations can be overcome with the utilization of [Plugins](/developers/integrate/plugins). + +# Customizable components + +## Server (Team Edition only) + +The [Mattermost server](https://github.com/mattermost/mattermost/tree/master/server)'s source code, written in Golang, may be customized to deliver additional functionalities or to meet specific security requirements. + +It's recommended that you attempt to meet such customizations by leveraging the [Plugin framework](/developers/integrate/plugins) in order to avoid creating any breaking changes, however details on how to build a custom server may be found [here](/developers/integrate/customization/customization/server-build). + +## Server files + +Some parts of server-side customizations don't require changes to the source code. View more details on which server files may be customized in [here](/developers/integrate/customization/customization/server-files). + + + +Modifications to server files can be utilized in both Team Edition and Enterprise Editions. + + + +## Web app + +Mattermost's web application runs on React, and [its codebase](https://github.com/mattermost/mattermost/tree/master/webapp) has been open-sourced (regardless of which edition your server uses). You can view details on how to customize the web app in [here](/developers/integrate/customization/customization/webapp). Keep in mind, however, that some changes to the web app can also leverage the [Plugin](/developers/integrate/plugins/components/webapp) framework, which can help reduce the necessity of rebasing your custom client to each Mattermost release. diff --git a/docs/develop/integrate/customization/customization/server-build.md b/docs/develop/integrate/customization/customization/server-build.md new file mode 100644 index 000000000000..95dca46e3674 --- /dev/null +++ b/docs/develop/integrate/customization/customization/server-build.md @@ -0,0 +1,24 @@ +--- +title: "Server build (Team Edition)" +sidebar_position: 1 +--- + +If plugin functionalities don't cover your use cases, you have the freedom to customize and build your own version of the `mattermost-server` project. + +Before proceeding with the steps below, make sure you have completed the [mattermost-server setup](/developers/contribute/developer-setup) process. + +1. Customize the project according to your requirements. + +2. Build binary files for Mattermost server. + + ```shell + make build + ``` + +3. Assemble essential files. + + ```shell + make package + ``` + +4. Transfer desired `.tar.gz` file to server for deployment. diff --git a/docs/develop/integrate/customization/customization/server-files.md b/docs/develop/integrate/customization/customization/server-files.md new file mode 100644 index 000000000000..a78622b40188 --- /dev/null +++ b/docs/develop/integrate/customization/customization/server-files.md @@ -0,0 +1,78 @@ +--- +title: "Server files" +sidebar_position: 1 +--- + +In both Mattermost Team and Enterprise editions, you have the freedom to alter how content is displayed by being able to change the contents of localized files and email templates. + +Before proceeding with the steps below, make sure you have completed the [mattermost-server](/developers/contribute/developer-setup) and [mattermost-webapp](/developers/contribute/developer-setup) setup process. + +## i18n files +The `i18n` files define many of the contents seen in email notifications and responses from the server. + +1. Edit contents of files in the `mattermost/server/i18n` directory according to your requirements. + +2. Once you're ready, create a tarball or zip the files __within__ the `i18n` directory. + + ```shell + cd i18n + tar -cvf i18n.tar * + ``` + +3. Before replacing the files, stop your Mattermost instance if it's currently running. + + ```shell + sudo service mattermost stop + ``` + +4. In your Mattermost deployment, back up and remove the files inside `i18n` that will no longer be in use. + + ```shell + cd ~/mattermost/i18n + tar -cvf i18n-yyyy-MM-dd.tar * + rm -f *.json + ``` + +5. Transfer your custom `i18n.tar` file to the deployment server and extract it in the `i18n` directory. + + ```shell + mv i18n.tar mattermost/i18n + cd ~/mattermost/i18n + tar -xvf i18n.tar + ``` + +6. Restart your Mattermost instance. + + ```shell + sudo service mattermost start + ``` + +## Email templates +Similarly to the i18n files, email templates can be edited and applied onto a running Mattermost instance in the following manner: + +1. Edit the `html` files inside of the `templates` directory. In this example we'll assume the `post_body_full.html` file has been customized. + +2. Stop your Mattermost instance if it's currently running. + + ```shell + sudo service mattermost stop + ``` + +3. (optional) Rename the template file to be replaced to keep it as a backup. + + ```shell + cd ~/mattermost/templates + mv post_body_full.html post_body_full_yyyy_MM_dd.html + ``` + +4. Transfer your custom `post_body_full.html` file to the deployment server and place it inside `templates`. + + ```shell + mv ./post_body_full.html ~/mattermost/templates/ + ``` + +5. Restart your Mattermost instance. + + ```shell + sudo service mattermost start + ``` diff --git a/docs/develop/integrate/customization/customization/webapp.md b/docs/develop/integrate/customization/customization/webapp.md new file mode 100644 index 000000000000..35b463f94871 --- /dev/null +++ b/docs/develop/integrate/customization/customization/webapp.md @@ -0,0 +1,83 @@ +--- +title: "Web app" +sidebar_position: 1 +--- + +Customizations to the Mattermost Web App can be performed in cases where you need to customize branding, alter localization strings, or fulfill security requirements that are not immediately offered out-of-the-box. + +## Customization steps +With that in mind, customizing and deploying your Mattermost Web App can be done in a few steps: + +1. Fork the [mattermost](https://github.com/mattermost/mattermost) repository and then clone your fork in your local environment. + + ```shell + git clone https://github.com//mattermost + ``` + +2. Create a separate branch for your customized version, as it's not recommended to perform them in the `master` branch (more details about that in the next section regarding rebasing). + + ```shell + git checkout -b custom_branch + ``` + +3. Perform customization tasks by replacing image assets, changing strings, altering the UI, and whatever else may be necessary. Be mindful not to violate any of the [guidelines on trademark use](https://mattermost.com/trademark-standards-of-use/) during this process. + +4. Once customization has been completed, build the files that will be used in your deployment and generate `mattermost-webapp.tar.gz` containing them. + + ```shell + make dist + ``` + +5. In a Mattermost deployment, rename `client` (assuming Mattermost was deployed in the `$HOME` directory). + + ```shell + cd ~/mattermost + mv client client-original + ``` + +6. Transfer compressed `dist` files inside Mattermost's `client` directory, and decompress it. + + ```shell + tar -xvf mattermost-webapp.tar.gz + ``` + +7. Copy the `products` subdirectory from the original deployment into the customized one. + + ```shell + cp -R client-original/products client/products + ``` + +## Rebasing to latest version +Challenges arise when creating a separate custom branch from an active open-source project like `mattermost`. As the project gets new commits and pull requests on a daily basis, your custom webapp can quickly become outdated. + +To deal with that, you'll need to leverage Git's [interactive rebasing functionality](https://git-scm.com/docs/git-rebase#_interactive_mode) in the following way: + +1. Add an upstream with the original `mattermost` repository. + + ```shell + git remote add upstream https://github.com/mattermost/mattermost.git + ``` + +2. Update `master` branch to latest upstream commit. + + ```shell + git checkout master + git pull upstream master + ``` + +3. Perform interactive rebase. + + ```shell + git checkout custom_branch + git rebase -i master + ``` + +```text +Use `git rebase --continue` after resolving any conflicts that arise during rebase process +``` + +4. Push new version back to remote (Note: Rebasing requires that you override previous remote version with a `force` push. Be sure you've tested that your rebase was successful before completing this last command). + + ```shell + git push -f origin custom_branch + ``` diff --git a/docs/develop/integrate/customization/embedding/index.md b/docs/develop/integrate/customization/embedding/index.md new file mode 100644 index 000000000000..8abf54abc314 --- /dev/null +++ b/docs/develop/integrate/customization/embedding/index.md @@ -0,0 +1,61 @@ +--- +title: "Embed Mattermost" +sidebar_position: 80 +--- + +## Launch Mattermost from a button selection + +The most common way of integrating Mattermost into another application is via a link or a button that brings up Mattermost in a new browser window or tab, with a link to a specific Mattermost channel to begin discussion. + +Optionally, single-sign-on can be added to make the experience seamless. + +### Mattermost launch button example in HTML + +Save the below HTML code in a file called `mattermost-button-example.html` then open the file in a browser as an example. + +```html + + + +
+
+ +
+
+ +
+
+ +``` + +## Embed Mattermost in web apps using an <iframe> + +Any web application embedded into another using an [<iframe>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) is at risk of security exploits, since the outer application intercepts all user input into the embedded application, an exploit known as [Click-Jacking](https://en.wikipedia.org/wiki/Clickjacking). By default, Mattermost disables embedding. If you choose to embed Mattermost we highly recommend it is done only on a private network that you control. + +See [this recipe](https://forum.mattermost.com/t/recipe-embedding-mattermost-in-web-applications-using-an-iframe-unsupported-recipe/10233) for details. + +## Embed Mattermost in mobile apps + +The open source mobile applications can serve as a guide or starter code to embed Mattermost in mobile applications. The Mattermost Javascript Driver is used to connect with the Mattermost server and product the interactivity for these applications. + +The mobile applications also provide full source code for push notifications. + +### Mobile apps offering Mattermost as a web view + +- https://github.com/mattermost/ios + +### Mobile apps offering Mattermost with React Native components + +- https://github.com/mattermost/mattermost-mobile diff --git a/docs/develop/integrate/customization/index.md b/docs/develop/integrate/customization/index.md new file mode 100644 index 000000000000..7f40a80f6c37 --- /dev/null +++ b/docs/develop/integrate/customization/index.md @@ -0,0 +1,12 @@ +--- +title: "Customize and embed" +sidebar_position: 50 +--- + +If the [API](https://api.mattermost.com) or [plugins](/developers/integrate/plugins) don't meet your your needs, take a look at the other methods for integrating and extending Mattermost: + +* Webhooks - Post to channels with [incoming webhooks](/developers/integrate/webhooks/incoming), or listen for new messages with [outgoing webhooks](/developers/integrate/webhooks/outgoing). +* Slash Commands - Enable your users to [trigger custom actions](/developers/integrate/slash-commands) from within Mattermost. +* Embed - Learn how to use the Mattermost API to [embed Mattermost](/developers/integrate/customization/embedding) into web browsers and web applications. +* Customize - Modify the source code for the server or web app to make basic [changes and customization](/developers/integrate/customization/customization). +* Interactive Messages - Create messages that include [interactive functionality](https://docs.mattermost.com/developer/interactive-messages.html). diff --git a/docs/develop/integrate/examples/index.md b/docs/develop/integrate/examples/index.md new file mode 100644 index 000000000000..cfa4f54fd979 --- /dev/null +++ b/docs/develop/integrate/examples/index.md @@ -0,0 +1,24 @@ +--- +title: "Examples" +sidebar_position: 65 +--- + +See a full list of all Mattermost integrations here. + +* [**Hubot Adapter**](https://github.com/loafoe/hubot-matteruser) + + Hubot is a "chat bot" created by GitHub that listens for commands and executes actions based on your requests. + + `hubot-matteruser` is a Hubot adapter for Mattermost written in coffee script that uses the Mattermost Web Services API and WebSockets to deliver Hubot functionality. + +* [**Bitbucket Webhooks**](https://github.com/danielkappelle/bitbucket-mattermost-bridge) + + This integration, written in Python, converts Bitbucket outgoing webhook events to be posted into Mattermost using an incoming webhook. + +* [**Interactive Poll**](https://github.com/jedfonner/MattermostOnFire) + + Backend code for powering a Mattermost slash command that creates an interactive poll. Contains Firebase Cloud Functions that connect Mattermost Interactive Buttons with the Firebase Realtime Database. + +* [**Mattermost Chat Bridge**](https://github.com/42wim/matterbridge) + + Simple bridge between Mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat, Hipchat(via xmpp), Matrix, Steam and ssh-chat. diff --git a/docs/develop/integrate/faq/images/access_token_enable.png b/docs/develop/integrate/faq/images/access_token_enable.png new file mode 100644 index 000000000000..3ad9ae16ccce Binary files /dev/null and b/docs/develop/integrate/faq/images/access_token_enable.png differ diff --git a/docs/develop/integrate/faq/images/access_token_manage_roles.png b/docs/develop/integrate/faq/images/access_token_manage_roles.png new file mode 100644 index 000000000000..80be83c5a6f5 Binary files /dev/null and b/docs/develop/integrate/faq/images/access_token_manage_roles.png differ diff --git a/docs/develop/integrate/faq/images/access_token_settings.png b/docs/develop/integrate/faq/images/access_token_settings.png new file mode 100644 index 000000000000..57ccb3519b4c Binary files /dev/null and b/docs/develop/integrate/faq/images/access_token_settings.png differ diff --git a/docs/develop/integrate/faq/images/access_tokens_additional_roles.png b/docs/develop/integrate/faq/images/access_tokens_additional_roles.png new file mode 100644 index 000000000000..c19b97dba7f5 Binary files /dev/null and b/docs/develop/integrate/faq/images/access_tokens_additional_roles.png differ diff --git a/docs/develop/integrate/faq/images/attachments-author.png b/docs/develop/integrate/faq/images/attachments-author.png new file mode 100644 index 000000000000..740080b6854c Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-author.png differ diff --git a/docs/develop/integrate/faq/images/attachments-color.png b/docs/develop/integrate/faq/images/attachments-color.png new file mode 100644 index 000000000000..5dea1019ab59 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-color.png differ diff --git a/docs/develop/integrate/faq/images/attachments-example.png b/docs/develop/integrate/faq/images/attachments-example.png new file mode 100644 index 000000000000..cc140111c9c7 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-example.png differ diff --git a/docs/develop/integrate/faq/images/attachments-fields.png b/docs/develop/integrate/faq/images/attachments-fields.png new file mode 100644 index 000000000000..beeb401fb50d Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-fields.png differ diff --git a/docs/develop/integrate/faq/images/attachments-footer.png b/docs/develop/integrate/faq/images/attachments-footer.png new file mode 100644 index 000000000000..47ff7bc4cf98 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-footer.png differ diff --git a/docs/develop/integrate/faq/images/attachments-image.png b/docs/develop/integrate/faq/images/attachments-image.png new file mode 100644 index 000000000000..d81c1ea691f1 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-image.png differ diff --git a/docs/develop/integrate/faq/images/attachments-pretext.png b/docs/develop/integrate/faq/images/attachments-pretext.png new file mode 100644 index 000000000000..968f42bdc02a Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-pretext.png differ diff --git a/docs/develop/integrate/faq/images/attachments-text.png b/docs/develop/integrate/faq/images/attachments-text.png new file mode 100644 index 000000000000..40b85d561c86 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-text.png differ diff --git a/docs/develop/integrate/faq/images/attachments-thumb.png b/docs/develop/integrate/faq/images/attachments-thumb.png new file mode 100644 index 000000000000..64bc8aea46a9 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-thumb.png differ diff --git a/docs/develop/integrate/faq/images/attachments-titles.png b/docs/develop/integrate/faq/images/attachments-titles.png new file mode 100644 index 000000000000..1c16521dfc04 Binary files /dev/null and b/docs/develop/integrate/faq/images/attachments-titles.png differ diff --git a/docs/develop/integrate/faq/images/incoming_webhooks_create_simple.png b/docs/develop/integrate/faq/images/incoming_webhooks_create_simple.png new file mode 100644 index 000000000000..ecd5b8f99b3d Binary files /dev/null and b/docs/develop/integrate/faq/images/incoming_webhooks_create_simple.png differ diff --git a/docs/develop/integrate/faq/images/incoming_webhooks_full_example.png b/docs/develop/integrate/faq/images/incoming_webhooks_full_example.png new file mode 100644 index 000000000000..57db76170769 Binary files /dev/null and b/docs/develop/integrate/faq/images/incoming_webhooks_full_example.png differ diff --git a/docs/develop/integrate/faq/images/incoming_webhooks_markdown_formatting.png b/docs/develop/integrate/faq/images/incoming_webhooks_markdown_formatting.png new file mode 100644 index 000000000000..cf78540d6ae8 Binary files /dev/null and b/docs/develop/integrate/faq/images/incoming_webhooks_markdown_formatting.png differ diff --git a/docs/develop/integrate/faq/images/incoming_webhooks_override_username.png b/docs/develop/integrate/faq/images/incoming_webhooks_override_username.png new file mode 100644 index 000000000000..2d16f2cd96e6 Binary files /dev/null and b/docs/develop/integrate/faq/images/incoming_webhooks_override_username.png differ diff --git a/docs/develop/integrate/faq/images/incoming_webhooks_sample.png b/docs/develop/integrate/faq/images/incoming_webhooks_sample.png new file mode 100644 index 000000000000..410a95878a0d Binary files /dev/null and b/docs/develop/integrate/faq/images/incoming_webhooks_sample.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-bool.png b/docs/develop/integrate/faq/images/interactive-dialog-bool.png new file mode 100644 index 000000000000..7f4d4b1f0c0c Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-bool.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-complete-example.png b/docs/develop/integrate/faq/images/interactive-dialog-complete-example.png new file mode 100644 index 000000000000..a0b7cf461d48 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-complete-example.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-error.png b/docs/develop/integrate/faq/images/interactive-dialog-error.png new file mode 100644 index 000000000000..fe73f33cbd50 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-error.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-example.png b/docs/develop/integrate/faq/images/interactive-dialog-example.png new file mode 100644 index 000000000000..71929860ee42 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-example.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-radio.png b/docs/develop/integrate/faq/images/interactive-dialog-radio.png new file mode 100644 index 000000000000..a519907ff7f8 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-radio.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-select-menu.png b/docs/develop/integrate/faq/images/interactive-dialog-select-menu.png new file mode 100644 index 000000000000..d3976235e801 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-select-menu.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-select.png b/docs/develop/integrate/faq/images/interactive-dialog-select.png new file mode 100644 index 000000000000..384bb2d8c3c7 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-select.png differ diff --git a/docs/develop/integrate/faq/images/interactive-dialog-text.png b/docs/develop/integrate/faq/images/interactive-dialog-text.png new file mode 100644 index 000000000000..f3c272a8111b Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-dialog-text.png differ diff --git a/docs/develop/integrate/faq/images/interactive-messages.png b/docs/develop/integrate/faq/images/interactive-messages.png new file mode 100644 index 000000000000..db8e3b954678 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive-messages.png differ diff --git a/docs/develop/integrate/faq/images/interactive_message.gif b/docs/develop/integrate/faq/images/interactive_message.gif new file mode 100644 index 000000000000..946352bb38d9 Binary files /dev/null and b/docs/develop/integrate/faq/images/interactive_message.gif differ diff --git a/docs/develop/integrate/faq/images/message-menus.png b/docs/develop/integrate/faq/images/message-menus.png new file mode 100644 index 000000000000..fdea56a860c7 Binary files /dev/null and b/docs/develop/integrate/faq/images/message-menus.png differ diff --git a/docs/develop/integrate/faq/images/oauth2_app_screen.png b/docs/develop/integrate/faq/images/oauth2_app_screen.png new file mode 100644 index 000000000000..4276259281ac Binary files /dev/null and b/docs/develop/integrate/faq/images/oauth2_app_screen.png differ diff --git a/docs/develop/integrate/faq/images/oauth2_authorization_screen.png b/docs/develop/integrate/faq/images/oauth2_authorization_screen.png new file mode 100644 index 000000000000..a74886f27cda Binary files /dev/null and b/docs/develop/integrate/faq/images/oauth2_authorization_screen.png differ diff --git a/docs/develop/integrate/faq/images/oauth2_confirmation_screen.png b/docs/develop/integrate/faq/images/oauth2_confirmation_screen.png new file mode 100644 index 000000000000..585535df3952 Binary files /dev/null and b/docs/develop/integrate/faq/images/oauth2_confirmation_screen.png differ diff --git a/docs/develop/integrate/faq/images/oauth2_deauthorize_app.png b/docs/develop/integrate/faq/images/oauth2_deauthorize_app.png new file mode 100644 index 000000000000..013c5ad85434 Binary files /dev/null and b/docs/develop/integrate/faq/images/oauth2_deauthorize_app.png differ diff --git a/docs/develop/integrate/faq/images/oauth2_regenerate_secret.png b/docs/develop/integrate/faq/images/oauth2_regenerate_secret.png new file mode 100644 index 000000000000..7603e993ffd4 Binary files /dev/null and b/docs/develop/integrate/faq/images/oauth2_regenerate_secret.png differ diff --git a/docs/develop/integrate/faq/images/outgoing_webhooks_token.png b/docs/develop/integrate/faq/images/outgoing_webhooks_token.png new file mode 100644 index 000000000000..50e76d518920 Binary files /dev/null and b/docs/develop/integrate/faq/images/outgoing_webhooks_token.png differ diff --git a/docs/develop/integrate/faq/images/poll.gif b/docs/develop/integrate/faq/images/poll.gif new file mode 100644 index 000000000000..c226567d90c2 Binary files /dev/null and b/docs/develop/integrate/faq/images/poll.gif differ diff --git a/docs/develop/integrate/faq/images/poll.png b/docs/develop/integrate/faq/images/poll.png new file mode 100644 index 000000000000..80784e6f9253 Binary files /dev/null and b/docs/develop/integrate/faq/images/poll.png differ diff --git a/docs/develop/integrate/faq/images/slash_commands_token.png b/docs/develop/integrate/faq/images/slash_commands_token.png new file mode 100644 index 000000000000..07ba4508144d Binary files /dev/null and b/docs/develop/integrate/faq/images/slash_commands_token.png differ diff --git a/docs/develop/integrate/faq/images/weatherBot.png b/docs/develop/integrate/faq/images/weatherBot.png new file mode 100644 index 000000000000..80b621716439 Binary files /dev/null and b/docs/develop/integrate/faq/images/weatherBot.png differ diff --git a/docs/develop/integrate/faq/images/webhooks.png b/docs/develop/integrate/faq/images/webhooks.png new file mode 100644 index 000000000000..cf954016e5c7 Binary files /dev/null and b/docs/develop/integrate/faq/images/webhooks.png differ diff --git a/docs/develop/integrate/faq/images/webhooksTable.png b/docs/develop/integrate/faq/images/webhooksTable.png new file mode 100644 index 000000000000..a0709cfb84c4 Binary files /dev/null and b/docs/develop/integrate/faq/images/webhooksTable.png differ diff --git a/docs/develop/integrate/faq/images/zapier-ch1.png b/docs/develop/integrate/faq/images/zapier-ch1.png new file mode 100644 index 000000000000..5f4e65024c40 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-ch1.png differ diff --git a/docs/develop/integrate/faq/images/zapier-ch2.png b/docs/develop/integrate/faq/images/zapier-ch2.png new file mode 100644 index 000000000000..01852194e200 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-ch2.png differ diff --git a/docs/develop/integrate/faq/images/zapier-dynamic-fields.png b/docs/develop/integrate/faq/images/zapier-dynamic-fields.png new file mode 100644 index 000000000000..fb9629b5261e Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-dynamic-fields.png differ diff --git a/docs/develop/integrate/faq/images/zapier-error1.png b/docs/develop/integrate/faq/images/zapier-error1.png new file mode 100644 index 000000000000..b185f8118d5b Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-error1.png differ diff --git a/docs/develop/integrate/faq/images/zapier-error2.png b/docs/develop/integrate/faq/images/zapier-error2.png new file mode 100644 index 000000000000..9b08b388a908 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-error2.png differ diff --git a/docs/develop/integrate/faq/images/zapier-error3.png b/docs/develop/integrate/faq/images/zapier-error3.png new file mode 100644 index 000000000000..42c9af8e5609 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-error3.png differ diff --git a/docs/develop/integrate/faq/images/zapier-error4.png b/docs/develop/integrate/faq/images/zapier-error4.png new file mode 100644 index 000000000000..4be90b6a9379 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-error4.png differ diff --git a/docs/develop/integrate/faq/images/zapier-oauth.png b/docs/develop/integrate/faq/images/zapier-oauth.png new file mode 100644 index 000000000000..2514060a1022 Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-oauth.png differ diff --git a/docs/develop/integrate/faq/images/zapier-trailing-space-error.png b/docs/develop/integrate/faq/images/zapier-trailing-space-error.png new file mode 100644 index 000000000000..693aeee5c56b Binary files /dev/null and b/docs/develop/integrate/faq/images/zapier-trailing-space-error.png differ diff --git a/docs/develop/integrate/faq/images/zoom_api_key.png b/docs/develop/integrate/faq/images/zoom_api_key.png new file mode 100644 index 000000000000..762385c5c739 Binary files /dev/null and b/docs/develop/integrate/faq/images/zoom_api_key.png differ diff --git a/docs/develop/integrate/faq/images/zoom_channel_header2.png b/docs/develop/integrate/faq/images/zoom_channel_header2.png new file mode 100644 index 000000000000..df558772bd3e Binary files /dev/null and b/docs/develop/integrate/faq/images/zoom_channel_header2.png differ diff --git a/docs/develop/integrate/faq/images/zoom_system-console_management.png b/docs/develop/integrate/faq/images/zoom_system-console_management.png new file mode 100644 index 000000000000..99bd8e1e1854 Binary files /dev/null and b/docs/develop/integrate/faq/images/zoom_system-console_management.png differ diff --git a/docs/develop/integrate/faq/images/zoom_system_console.png b/docs/develop/integrate/faq/images/zoom_system_console.png new file mode 100644 index 000000000000..f316424b28fb Binary files /dev/null and b/docs/develop/integrate/faq/images/zoom_system_console.png differ diff --git a/docs/develop/integrate/faq/images/zoom_webhook.png b/docs/develop/integrate/faq/images/zoom_webhook.png new file mode 100644 index 000000000000..3931af3a62f6 Binary files /dev/null and b/docs/develop/integrate/faq/images/zoom_webhook.png differ diff --git a/docs/develop/integrate/faq/index.md b/docs/develop/integrate/faq/index.md new file mode 100644 index 000000000000..1f34dbaf9e64 --- /dev/null +++ b/docs/develop/integrate/faq/index.md @@ -0,0 +1,137 @@ +--- +title: "Frequently asked questions (FAQ)" +sidebar_position: 80 +--- +### What's the difference between incoming and outgoing webhooks? + +A webhook is a way for one app to send real-time data to another app. + +In Mattermost, incoming webhooks receive data from external applications and make a post in a specified channel. They're great for setting up notifications when something happens in an external application. + +Outgoing webhooks take data from Mattermost, and send it to an external application. Then the outgoing webhook can post a response back in Mattermost. They're great for listening in on channels, and then notifying external applications when a trigger word is used. + +### What is a slash command? + +A slash command is similar to an outgoing webhook, but instead of listening to a channel it is used as a command tool. This means if you type in a slash command it will not be posted to a channel, whereas an outgoing webhook is only triggered by posted messages. + +### What does Slack-compatible mean? + +Slack compatible means that Mattermost accepts integrations that have a payload in the same format as Slack. + +If you have a Slack integration, you should be able to set it up in Mattermost without changing the format. + +### What if I have a webhook from somewhere other than Slack? + +If you have an integration that outputs a payload in a different format you need to write an intermediate application to act as a translation layer to change it to the format Mattermost uses. Since there’s currently no general standard for webhook formatting, this is unavoidable and just a part of how webhooks work. + +If there's no translation layer, Mattermost won't understand the data you're sending. + +### What are attachments? + +When "attachments" are mentioned in the integrations documentation, it refers to Slack's Message Attachments. These "attachments" can be optionally added as an array in the data sent by an integration, and are used to customize the formatting of the message. + +We currently don't support the ability to attach files to a post made by an integration. + +### Where can I find existing integrations? + +[Visit our app directory](https://mattermost.com/marketplace/) for dozens of open source integrations to common tools like Jira, Jenkins, GitLab, Trac, Redmine, and Bitbucket, along with interactive bot applications (Hubot, mattermost-bot), and other communication tools (Email, IRC, XMPP, Threema) that are freely available for use and customization. + +### Where should I install my integrations? + +For self-hosted deployments in small setups you might host integrations on the same server on which Mattermost is installed. For larger deployments you can setup a separate server for integrations, or add them to the server on which the external application is hosted - for example, if you're self-hosting a Jira server you could deploy a Jira integration on the Jira server itself. + +When self-hosting restrictions are less strict, AWS, Heroku, and other public cloud options could also be used. + +### How do I create a bot account with personal access tokens? + +See [bot accounts documentation](/developers/integrate/reference/bot-accounts) to learn more about how to create and manage bot accounts in Mattermost. + +### How do I create a bot account without personal access tokens or webhooks? + +Deployments that cannot create bot accounts via webhooks due to security reasons and do not want to use [personal access tokens](/developers/integrate/reference/personal-access-token) with no expiry time, can use the following approach: + +1. Create a bot account using a secure email and strong password. +2. Manually add the account to all teams and channels it needs access to. If your deployment has a lot of teams or channels, you may create a CLI script to automate the process. + - In a testing environment, you may also make the bot account a System Admin, giving the bot permissions to post to any channel. Not recommended in production due to potential security vulnerabilities. +3. Provide the email and password to your integration, and store it in a secure location with restricted access. +4. Have your integration use the email and password with an [`/api/v4/login`](https://api.mattermost.com/v4/#tag/authentication) endpoint to retrieve a session token. The session token is used to authenticate to the Mattermost system. + - Set up your bot to make an HTTP POST to `your-mattermost-url.com/api/v4/users/login` with a JSON body, including the bot account's email and password. + + ```http request + POST /api/v4/users/login HTTP/1.1 + Host: your-mattermost-url.com + Content-Length: 66 + Content-Type: application/json + + {"login_id":"someone@nowhere.com","password":"thisisabadpassword"} + ``` + + where we assume there is a Mattermost instance running at http://localhost:8065. + - If successful, the response will contain a `Token` header and a user object in the body: + + ```http request + HTTP/1.1 200 OK + Set-Cookie: MMSID=hyr5dmb1mbb49c44qmx4whniso; Path=/; Max-Age=2592000; HttpOnly + Token: hyr5dmb1mbb49c44qmx4whniso + X-Ratelimit-Limit: 10 + X-Ratelimit-Remaining: 9 + X-Ratelimit-Reset: 1 + X-Request-Id: smda55ckcfy89b6tia58shk5fh + X-Version-Id: developer + Date: Fri, 11 Sep 2015 13:21:14 GMT + Content-Length: 657 + Content-Type: application/json; charset=utf-8 + + {{user object as json}} + ``` + +```text +The bot should retrieve the session token from the `Token` header and store it in memory for use with future requests. +``` + + + +Each session token has an expiry time, set depending on the server's configuration. If the session token your bot is using expires, it will receive a `401 Unauthorized` response from requests using that token. When your bot receives this response, it should reapply the login logic (using the above steps) to get another session token. Then resend the request that received the `401` status code. + + + +5. Include the `Token` as part of the `Authorization` header on API requests from your integration. + - To confirm the token works, you can have your bot make a simple `GET` request to `/api/v4/users/me` with the `Authorization: bearer ` in the header. If it returns a `200` with the bot's user object in the response, the API request was made successfully. + + ```http request + GET /api/v4/users/me HTTP/1.1 + Authorization: bearer + Host: your-mattermost-url.com + ``` + + + +The Mattermost development team is also working on an [API developer token](https://docs.google.com/document/d/1ey4eNQmwK410pNTvlnmMWTa1fqtj8MV4d9XkCumI384), which allows you to authenticate the bot account via the API token rather than retrieving a session token from a user account. + + + +### How should I automate the install and upgrade of Mattermost when included in another application? + +Automate Mattermost installation within another application: + +1. Review the [Mattermost installation documentation](https://docs.mattermost.com/guides/install-deploy-upgrade-scale.html#install-mattermost) to understand configuration steps of the production deployment. +2. Install Mattermost files to a dedicated `/opt/mattermost` directory by decompressing the `tar.gz` file of the latest release for your target platform (for example `linux-amd64`). +3. Review [Configuration Settings](https://docs.mattermost.com/configure/configuration-settings.html) in `config.json` and set your automation to customize your Mattermost deployment based on your requirements. +4. For directory locations defined in `config.json`, such as the location of the local file storage directory (`./data/`) or logs directory (`./logs`), you can redefine those locations in your `config.json` settings and move the directories. + - All other directories should remain as they are in `/mattermost`. +5. Test that your Mattermost server is running with your new configuration. +6. Also, from the command line run `./bin/mattermost -version` to test that the command line interface is functioning properly. + +Automate Mattermost upgrade within another application: + +1. Review the [upgrade guide](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) for an overview of the upgrade procedure. +2. Create automation to upgrade to the next Mattermost versions: + - Back up the `config.json` file to preserve any settings a user may have made. + - Back up the `./data` directory if local storage is used for files. + - Replace the contents of `/mattermost` directory with the decompressed contents of the latest release. + - Restore `config.json` and `./data` to their previous locations (which may have been overwritten). + - If you need to overwrite any `config.json` parameters use a [`sed` command](https://stackoverflow.com/questions/20568515/how-to-use-sed-to-replace-a-config-files-variable) or similar tool to update `config.json` + - Starting the Mattermost server to upgrade the database, `config.json` file, and `./data` as necessary. +3. Optionally the upgrade procedure can be chained so users can upgrade across an arbitrary number of Mattermost versions rather than to just the latest release. + +Come [join our Contributors community channel](https://community.mattermost.com/core/channels/tickets) on our daily build server, where you can discuss questions with community members and the Mattermost core team. Join our [Developers channel](https://community.mattermost.com/core/channels/developers) for technical discussions and our [Integrations channel](https://community.mattermost.com/core/channels/integrations) for all integrations and plugins discussions. diff --git a/docs/develop/integrate/getting-started/index.md b/docs/develop/integrate/getting-started/index.md new file mode 100644 index 000000000000..62111f125dab --- /dev/null +++ b/docs/develop/integrate/getting-started/index.md @@ -0,0 +1,41 @@ +--- +title: "Get started" +sidebar_position: 10 +--- +Mattermost offers a wealth of methods to add functionality and customize the experience to suit your needs, whether you want to add new user capabilities with slash commands, build an advanced chatbot, or completely change the functionality of your server. + +## Webhooks + +Webhooks provide a simple way to post messages to a channel and trigger external actions. + +[Create your Webhook now](/developers/integrate/webhooks) + +## Slash commands + +Slash commands are messages that begin with `/` and trigger an HTTP request to a web service that can in turn post one or more messages in response. + +[Create your Slash command now](/developers/integrate/slash-commands) + +## Plugins + +Plugins are the most comprehensive way to add new features and customization, but come with additional development overhead and must be written in Go. They’re for developers who need tightly integrated services or want to improve the server, mobile, desktop, and web apps without making contributions to the core codebase. + +[Get started with plugins](/developers/integrate/plugins) + + + +See the [Mattermost Server SDK Reference](/developers/integrate/reference/server/server-reference) and [Mattermost Client UI SDK Reference](/developers/integrate/reference/webapp/webapp-reference) documentation for details on available server API endpoints and client methods. + + + +## API + +Interact with users, channels, and everything else that happens on your Mattermost server via a modern REST API that meets the OpenAPI specification. The API is for developers who want to build bots and other interactions that don’t rely on customizing the Mattermost user experience. + +[View the REST API Reference](https://api.mattermost.com)
+ +## Other ways to integrate and extend + +* Embed - Learn how to use the Mattermost API to [embed Mattermost](/developers/integrate/customization/embedding) into web browsers and web applications. +* Customize - Modify the source code for the server or web app to make basic [changes and customization](/developers/integrate/customization/customization). +* Interactive Messages - Create messages that include [interactive functionality](https://docs.mattermost.com/developer/interactive-messages.html). diff --git a/docs/develop/integrate/marketplace-submissions/index.md b/docs/develop/integrate/marketplace-submissions/index.md new file mode 100644 index 000000000000..23cabaeafa6b --- /dev/null +++ b/docs/develop/integrate/marketplace-submissions/index.md @@ -0,0 +1,37 @@ +--- +title: "Contribute to the Marketplace" +sidebar_position: 100 +--- + +The [Mattermost web Marketplace](https://mattermost.com/marketplace/) supports discovery, installation, and updates of extensions of the Mattermost platform. If you have built a plugin, app, playbook, integration, or tool that helps other users get more from Mattermost, the web Marketplace is a great way to get feedback on your contribution and help make it more popular. Once your submission is accepted to the web Marketplace, Mattermost will also send you swag! All contributions are eligible following a review from our team. + +## Types of integrations to submit to the web Marketplace + +- [Plugins](/developers/integrate/plugins) +- [Webhook](/developers/integrate/webhooks) configuration +- Playbook templates +- Utility tools, such as importers, command line interfaces, and scripts + +## Submit your contribution for the web Marketplace + +Please fill out the information in [this form](https://forms.gle/i7aiX3uVMzHJVAUh8) to be reviewed by a member of the Mattermost team. + +Every contribution goes through the following checklist before being added to the web Marketplace at [mattermost.com/marketplace](https://mattermost.com/marketplace): + +1. There is a link to the contribution so we can test it out. +2. There is documentation to support people installing, configuring, and using the contribution. We also recommend including screenshots to give users a better understanding of the workflow and user experience. +3. There is a public issue or bug tracker for users to report bugs or issues they encounter. +4. You've included a link to an image for your contribution: + - Dimensions: 512 x 512 recommended + - File size: Maximum 5 MB + - File types: PNG, JPG, or SVG + +We will also reach out to you to learn more about the integration, your experience developing with Mattermost, and to coordinate postings for social media. + +## Security issues + +Any security issues found in contributions in the web Marketplace should be reported by email to [`responsibledisclosure@mattermost.com`](mailto:responsibledisclosure@mattermost.com), or sent directly to a member of the [Security team](https://handbook.mattermost.com/operations/security#where-to-find-us) on the [Community Server](https://community.mattermost.com/). + +## Takedown policy + +If an integration available through the Marketplace contains a medium or greater security issue or bug that blocks or prevents usage for users isn't fixed within 14 days of being acknowledged, that integration will be removed from the Marketplace, and may be resubmitted to the Marketplace once the issue is resolved. Mattermost reserves the right to take down contributions at any time if a fix for a security issue is not forthcoming, or the issue is critical enough to justify an immediate takedown. diff --git a/docs/develop/integrate/plugins/best-practices.md b/docs/develop/integrate/plugins/best-practices.md new file mode 100644 index 000000000000..f5c4842cd81e --- /dev/null +++ b/docs/develop/integrate/plugins/best-practices.md @@ -0,0 +1,161 @@ +--- +title: "Best practices" +sidebar_position: 100 +--- + +See here for [server-specific best practices for plugins](/developers/integrate/plugins/components/server/best-practices). Webapp-specific best practices are incoming. + +## How can a plugin enable its configuration through the System Console? + +Once a plugin is installed, Administrators have access to the plugin's configuration page in the __System Console > Plugins__ section. The configurable settings must first be defined in the plugin's manifest [setting schema](/developers/integrate/plugins/manifest-reference#settings_schema). The web app supports several basic pre-defined settings type, e.g. `bool` and `dropdown`, for which the corresponding UI components are provided in order to complete configuration in the System Console. + +These settings are stored within the server configuration under [`Plugins`] indexed by plugin ids. The plugin's server code can access their current configuration calling the [`getConfig`](/developers/integrate/reference/server/server-reference#API.GetConfig) API call and can also make changes as needed with [`saveConfig`](/developers/integrate/reference/server/server-reference#API.SaveConfig). + +## How can a plugin define its own setting type? + +A plugin could define its own type of setting with a corresponding custom user interface that will be displayed in the System Console following the process below. + +1. Define a `type: custom` setting in the plugins manifest `settings_schema` + + ```diff + "settings_schema": { + "settings": [{ + "key": "NormalSetting", + "type": "text", + + }, { + + "key": "CustomSetting", + + "type": "custom" + }] + } + ``` + +2. In the plugin's web app code, define a custom component to manage the plugin's custom setting and register it in the web app with [`registerAdminConsoleCustomSetting`](/developers/integrate/reference/webapp/webapp-reference#registerAdminConsoleCustomSetting). This component will be instantiated in the System Console with the following `props` passed in: + + - `id`: The setting `key` as defined in the plugin manifest within `settings_schema.settings`. + - `label`: The text for the component label based on the setting's `displayName` defined in the manifest. + - `helpText`: The help text based on the setting's `helpText` defined in the manifest. + - `value`: The setting's current json value in the config at the time the component is loaded. + - `disabled`: Boolean indicating if the setting is disabled by a parent component within the System Console. + - `config`: The server configuration loaded by the web app. + - `license`: The license information for the related Mattermost server. + - `setByEnv`: Boolean that indicates if the setting is based on a server environment variable. + - `onChange`: Function that receives the setting id and current json value of the setting when it has been changed within the custom component. + - `setSaveNeeded`: Function that will prompt the System Console to enable the Save button in the plugin settings screen. + - `registerSaveAction`: Registers the given function to be executed when the setting is saved. This is registered when the custom component is mounted. + - `unRegisterSaveAction`: On unmount of the custom component, unRegisterSaveAction will remove the registered function executed on save of the custom component. + +3. On initialization of the custom component, the current value of the custom setting is passed in the `props.value` in a json format as read from the config. This value can be processed as necessary to display in your custom UI and ready to be modified by the end user. In the example below, it processes the initial `props.value` and sets it in a local state for the component to use as needed: + + ```js + constructor(props) { + super(props); + + this.state = { + attributes: this.initAttributes(props.value), + } + } + ``` + +4. When a user makes a change in the UI, the `OnChange` handler sends back the current value of the setting as a json. Additionally, `setSaveNeeded` should be called to enable the `Save` button in order for the changes to be saved. + + ```js + handleChange = () => { + // ... + this.props.onChange(this.props.id, Array.from(this.state.attributes.values())); + this.props.setSaveNeeded() + }; + ``` + +5. Once the user saves the changes, any handler that was registered with `registerSaveAction` will be executed to perform any additional custom actions the plugin may require, such as calling an additional endpoint within the plugin. + +For examples of custom settings see: Demo Plugin [`CustomSetting`](https://github.com/mattermost/mattermost-plugin-demo/blob/master/webapp/src/components/admin_settings/custom_setting.jsx) and Custom Attributes Plugin [implementation](https://github.com/mattermost/mattermost-plugin-custom-attributes/pull/18). + +## How can I review the entire code base of a plugin? + +Sometimes, you have been working on a personal repository for a new plugin, most probably based on the [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template/) repo. As it was a personal project, you may have pushed all of your commits directly to `master`. And now that it's functional, you need a reviewer to take a look at the whole thing. + +For this, it is useful to create a PR with only the commits you added. Follow these steps to do so: + +1. First of all, you need to obtain the identifier of the oldest commit that should be reviewed. You can review your history with `git log --oneline`, where you need to look for the very first commit that you added. Imagine that the output is something like the following: + + ``` + f7d89b8 (HEAD -> master, origin/master) Lint code + fa99500 Fix bug + 0b3b5bd Add feature + 8f6aef3 My first commit to the plugin + ... + ... rest of commits from mattermost-plugin-starter-template + ... + ``` + +```text +In this case, the identifier that we need to copy is `8f6aef3`. +``` + +2. Create a new branch without the commits that you added. Using the SHA that you copied, create the branch `base` and push it: + + ```shell + git branch base 8f6aef3~1 + git push origin base + ``` + +```text +Note that `8f6aef3~1` means _the parent commit of `8f6aef3`_, effectively selecting all the commits in the branch except the ones that you added. +``` + +3. Create a branch with all the commits, included the ones that you added, and push it. This branch, `compare`, will be an exact copy of `master`: + + ```sh + git branch compare master + git push origin compare + ``` + +4. Now you have two new branches in the repository: `base` and `compare`. In Github, create a new PR in your repository, setting the _base_ branch to `base` and the _compare_ branch to `compare`. + +5. Request a code review on the resulting PR. + +For future changes, you can always repeat this process, making sure to identify the first commit you want to be reviewed. You can also consider the more common scenario of creating a feature branch (using something like `git checkout -b my.feature.branch`) and opening a PR whenever you want to merge the changes into `master`. It's up to you! + +## When to write a new API method or hook? + +Don't be afraid to extend the API or hooks to support brand new functionality. Consider accepting an options struct instead of a list of parameters to simplify extending the API in the future: + +```go +// GetUsers a list of users based on search options. +// +// Minimum server version: 5.10 +GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError) +``` + +Old servers won't do anything with new, unrecognized fields, but also won't break if they are present. + + +## How to expose performance metrics for a plugin? + +From Mattermost v9.4, a [`ServeMetrics`](/developers/integrate/reference/server/server-reference#API.ServeMetrics) hook can be used to expose performance metrics in the [open metrics format](https://openmetrics.io/) under the common HTTP listener controlled by the [`MetricsSettings.ListenAddress`](https://docs.mattermost.com/configure/environment-configuration-settings.html#listen-address-for-performance) config setting. + +Data returned by the hook's implementation through the given `http.ResponseWriter` object will be served through the `http://SITE_URL:8067/plugins/PLUGIN_ID/metrics` URL. + +Here's a sample implementation using the [Prometheus HTTP client +library](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus): + +```go +import ( + "net/http" + + "github.com/mattermost/mattermost/server/public/plugin" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +func (p *Plugin) initMetrics() { + p.registry = prometheus.NewRegistry() + // ... Registrations +} + +func (p *Plugin) ServeMetrics(_ *plugin.Context, w http.ResponseWriter, r *http.Request) { + promhttp.HandlerFor(p.registry, promhttp.HandlerOpts{}).ServeHTTP(w, r) +} +``` + diff --git a/docs/develop/integrate/plugins/community-plugin-marketplace.md b/docs/develop/integrate/plugins/community-plugin-marketplace.md new file mode 100644 index 000000000000..08ea3e02ff93 --- /dev/null +++ b/docs/develop/integrate/plugins/community-plugin-marketplace.md @@ -0,0 +1,10 @@ +--- +title: "Community plugins in the Marketplace" +sidebar_position: 110 +--- + +Once your plugin has reached a certain level of quality, you might consider submitting it to the web Marketplace. The [Mattermost web Marketplace](https://mattermost.com/marketplace/) supports discovery, installation, and updates of extensions of the Mattermost platform. + +If you have built a plugin, app, playbook, integration, or tool that helps other users get more from Mattermost, the web Marketplace is a great way to get feedback on your contribution and help make it more popular. + +Read more about the process on the [Marketplace submissions](/developers/integrate/marketplace-submissions) page. diff --git a/docs/develop/integrate/plugins/community_process.md b/docs/develop/integrate/plugins/community_process.md new file mode 100644 index 000000000000..8e254d817db2 --- /dev/null +++ b/docs/develop/integrate/plugins/community_process.md @@ -0,0 +1,81 @@ +--- +title: "Process to include plugin on community" +sidebar_position: 120 +--- + +Getting your plugin onto our Community server https://community.mattermost.com is a valuable source of feedback. Whether you're a [core committer](/developers/contribute/more-info/getting-started/core-committers) or anyone from the community, we want you to get feedback to improve your plugin. + +However we must ensure that our Community server remains stable for everyone. This document outlines the process of getting your plugin onto the Community server and some of these steps are required to get your plugin into the [Marketplace](/developers/integrate/plugins/community-plugin-marketplace). + +When you're ready to begin this process for your plugin, ask in the [Toolkit channel](https://community.mattermost.com/core/channels/developer-toolkit) on the Community server. The PM, or someone else from the Integrations team, will help you start the process. + +## Checklist + +### Deploy to ci-extensions + +- [Basic Code Review](#basic-code-review) passed +- [CI system setup](#ci-system-setup) to build master +- Has a [compatible licence](#compatible-licence). + +### Deploy to ci-extensions-release + +- Complete code review by two core committers. One focused on security. +- [QA pass](#qa-pass) +- [PM/UX review](#pmux-review) +- Release created and [CI system setup](#ci-system-setup) to build releases + +### Deploy to community.mattermost.com + +- QA pass on ci-extensions-release of the release to deploy. + +## Step definitions + +### Basic code review + +Basic code review of an experimental plugin involves a quick review by a [core committer](/developers/contribute/more-info/getting-started/core-committers) to verify that the plugin does what it says it does and to provide any guidance and feedback. To make it easier to provide feedback, a PR can be made that contains all the code of the plugin that isn't the boilerplate from mattermost-plugin-starter-template. + +- When you are ready for your plugin to start this process, post an introduction in the [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the Community server. Here is [an example](https://community.mattermost.com/core/pl/6dci1ssexjrh9rmdzt4pdpb9zy). + +### CI system setup + +Setting up the CI system for your plugin will allow continuous testing of your master branch and releases on our testing servers. Master branch testing is done on https://ci-extensions.azure.k8s.mattermost.com/ and release testing is done on https://ci-extensions-release.azure.k8s.mattermost.com/. + +In order to set this up, the plugin creator needs to provide a URL that hosts latest master build, which we can pull on a nightly basis. Once that exists you can make a request in the [Integrations and Apps](https://community.mattermost.com/core/channels/integrations) channel. + +### Compatible licence + +Recommended licences: + +- Apache Licence 2.0 +- MIT +- BSD 2-clause +- BSD 3-clause + +[More info](https://www.apache.org/legal/resolved.html#category-a) + +### Complete code review + +A more thorough code review is performed before allowing a plugin on `ci-extensions-release`. This review works the same as the basic code review, but the developers performing the review will be more thorough. If the developer that performed the first review is available, they should be one of the reviewers. Another of the reviewers should focus their review on any security implications of the plugin. + +### QA pass + +QA pass involves getting a member of our QA team to take a look and verify the functionality advertised by your plugin. + +Steps involved: + +- Ensure all setup documentation needed is clear and can be successfully followed. +- Dedicated instance or test account to access and test the third-party service, if applicable. +- Functional testing has been done to ensure the integration works as expected. +- For plugins owned by Mattermost, release testing is added to cover the main functionality of the plugin. + +### PM/UX review + +A PM/UX pass involves getting PM support in ironing out any user experience or UI issues with the plugin. + +Steps involved: + +- Create a one paragraph summary of the integration. +- Document the main use cases in bullet form. +- Review the primary use cases and run through them to ensure they are complete, clear, and functional. +- Ensure there is documentation to support the plugin. This may include having sufficient helper text in the plugin. +- Consider if communication to other teams or users is required as part of the rollout to our Community server. diff --git a/docs/develop/integrate/plugins/components/index.md b/docs/develop/integrate/plugins/components/index.md new file mode 100644 index 000000000000..f69c6f6eda6e --- /dev/null +++ b/docs/develop/integrate/plugins/components/index.md @@ -0,0 +1,10 @@ +--- +title: "Components" +sidebar_position: 40 +--- + +A Mattermost plugin consists of several components: + +- [Server](/server): subprocesses invoked by the Mattermost Server that communicate using RPC +- [Webapp](/webapp): extensions/modifications to the Mattermost web and desktop apps +- [Mobile](/mobile): mobile device support diff --git a/docs/develop/integrate/plugins/components/mobile/index.md b/docs/develop/integrate/plugins/components/mobile/index.md new file mode 100644 index 000000000000..5ead2a280d0b --- /dev/null +++ b/docs/develop/integrate/plugins/components/mobile/index.md @@ -0,0 +1,8 @@ +--- +title: "Mobile plugins" +sidebar_position: 30 +--- + +[Server plugins](/developers/integrate/plugins/components/server) may use [interactive dialogs](/developers/integrate/plugins/interactive-dialogs) and [interactive messages](/developers/integrate/plugins/interactive-messages) to build cross platform interactions that are compatible with mobile. + +It isn't possible to customize the mobile user experience in the same way the [webapp](/developers/integrate/plugins/components/webapp) can be extended. diff --git a/docs/develop/integrate/plugins/components/server/best-practices.md b/docs/develop/integrate/plugins/components/server/best-practices.md new file mode 100644 index 000000000000..b367879d91e8 --- /dev/null +++ b/docs/develop/integrate/plugins/components/server/best-practices.md @@ -0,0 +1,18 @@ +--- +title: "Best practices" +sidebar_position: 0 +--- + +## How should plugins serve publicly available static files? + +Add all static files under a file directory named `public` within the plugin directory, and include the files in the plugin bundle using the Makefile. + +## How do plugins make sure http requests are authentic? + +Plugins can implement the [`ServeHTTP`](/developers/integrate/reference/server/server-reference#Hooks.ServeHTTP) to listen to http requests. This can be used to receive post action requests when [Interactive Messages Buttons and Menus](https://docs.mattermost.com/developer/interactive-messages.html) are triggered by users. + +When plugins act as an HTTP server, they serve requests from Mattermost clients (which are authenticated in a Mattermost sense), but may also serve HTTP requests from external services like webhooks. These requests from external services might use the Authorization header to authorize themselves against the plugin. + +Since these requests are just HTTP requests, anyone can send them to the plugin. Hence, the plugin must make sure the requests are authentic. The Mattermost Server sets the HTTP header ``Mattermost-User-Id`` when the request is made by an authenticated client. If the plugin is expecting the request to come from an authenticated Mattermost user, and the ``Mattermost-User-Id`` is blank, it's the plugin's responsibility to reject the request. + +From Mattermost v9.4, external systems can use the ``Authorization`` header to authenticate with the plugin. HTTP requests to server-side plugins can use an ``Authorization`` header in the request for the plugin to use, and the header value will be present in the request received by the plugin, as long as the token provided in the header is not a user token issued by the Mattermost server. This is useful for connecting external systems that require authentication through an Authorization header with their own token. diff --git a/docs/develop/integrate/plugins/components/server/debugging.md b/docs/develop/integrate/plugins/components/server/debugging.md new file mode 100644 index 000000000000..b5c798eaf8e1 --- /dev/null +++ b/docs/develop/integrate/plugins/components/server/debugging.md @@ -0,0 +1,9 @@ +--- +title: "Debug Server plugins" +--- + +Plugins communicate with the main Mattermost Server by [RPC](https://github.com/hashicorp/go-plugin). In order to debug them with Delve, a few steps are necessary. +### macOS +1. After starting the main Mattermost application, run `ps aux | grep name.of.your.plugin`. This will print a list of running processes that match that name, as such: `username 78836 0.0 0.1 4397696 12492 s006 S 7:07AM 0:00.03 plugins/name.of.your.plugin/server/dist/plugin-darwin-amd64`. +2. Grab the `pid`, which is the second number after your username in the output above. Run `dlv attach pid`, where `pid` is that number. let the plugin continue executing soon after connecting; Otherwise, the server will detect it as stopped and attempt to restart it. +3. You're done. You should have access to your plugin's code through Delve and be able to set breakpoints, etc. diff --git a/docs/develop/integrate/plugins/components/server/ha.md b/docs/develop/integrate/plugins/components/server/ha.md new file mode 100644 index 000000000000..9ed2505620e0 --- /dev/null +++ b/docs/develop/integrate/plugins/components/server/ha.md @@ -0,0 +1,42 @@ +--- +title: "High availability" +sidebar_position: 60 +--- + +Mattermost Enterprise Edition servers with an E20 license have the ability to run in [High Availability (HA)](https://docs.mattermost.com/deployment/cluster.html) mode, meaning a cluster of Mattermost app servers running together as a single Mattermost deployment. + +It is important that all plugins consider HA environments when being built. + +Plugins are started as subprocesses of the main Mattermost process on each app server. This means a Mattermost deployment that has three app servers will have three separate copies of the same plugin running. Each running copy of the plugin will be isolated from one another on different servers. Therefore, to run properly in HA the plugin's server-side code must be stateless. + +To be stateless, the plugin must not retain any information or status in memory that may be needed across multiple events (e.g. HTTP requests or in other hooks). This data should instead be stored in a place that all running copies of the plugin have access to. For example, the [key-value store](/developers/integrate/reference/server/server-reference#API.KVSet) the plugin API provides. + +To better explain the problem with having a plugin store data in-memory, consider this case: + +Let's say we have two Mattermost app servers running together in HA and an installed plugin with a feature that alerts a user any time a trigger word is posted in a channel. + +1. The user uses the web app side of the plugin to set the word `hello` as the trigger word +2. An HTTP request is made to the server-side of the plugin to set `hello` +3. The plugin process running on app server 1 handles the request and stores `hello` in a variable + +In this scenario, the trigger word is now only set for the plugin process running on app server 1. The plugin process running on app server 2 is unaware that the trigger word is `hello`. This means when someone posts a message containing `hello` and the request is load balanced to app server 2, the plugin is not going to alert our user when it should. + +The proper way to deal with this case would be for the plugin to store the trigger word in a global store, such as the KV store. Then any time a user posts the plugin can pull the trigger word from the store and properly alert the user, regardless of which app server handles the request. + +## Run a scheduled job in high availability mode + +Using the [mattermost/public/pluginapi/cluster](https://github.com/mattermost/mattermost/blob/d2c3710265c293281c2b445d4f72f27871c2e127/server/public/pluginapi/cluster/job.go#L115-L116) package, we can schedule jobs to perform background activity at regular intervals, without having to explicitly coordinate with other instances of the same plugin. Here's an example from the [Demo Plugin](https://github.com/mattermost/mattermost-plugin-demo/blob/d647f1ed7fdc384f5bc163a6bba689ab4293704e/server/activate_hooks.go#L72): + +```go +job, cronErr := cluster.Schedule( + p.API, + "BackgroundJob", + cluster.MakeWaitForRoundedInterval(15*time.Minute), + p.BackgroundJobFunc, +) +if cronErr != nil { + return errors.Wrap(cronErr, "failed to schedule background job") +} + +p.backgroundJob = job +``` diff --git a/docs/develop/integrate/plugins/components/server/hello-world.md b/docs/develop/integrate/plugins/components/server/hello-world.md new file mode 100644 index 000000000000..576e880a1a66 --- /dev/null +++ b/docs/develop/integrate/plugins/components/server/hello-world.md @@ -0,0 +1,113 @@ +--- +title: "Plugin quick start" +sidebar_position: -10 +--- + +This tutorial will walk you through the basics of writing a Mattermost plugin with a server component. + +Note that the steps below are intentionally very manual to explain all of the pieces fitting together. In practice, we recommend referencing [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) for helpful build scripts. Also, the plugin API changed in Mattermost 5.2. Consult the [migration](/developers/integrate/plugins/migration) document to upgrade older plugins. + +## Prerequisites + +Mattermost plugins extend the server using a Go API. In the future, gRPC may be supported, allowing you to write plugins in any language. For now, you'll need a functioning Go environment, so follow [Go's Getting Started](https://golang.org/doc/install) guide if needed. + +You'll also need a Mattermost server to install and test the plugin. This server must have [Enable](https://docs.mattermost.com/administration/config-settings.html#enable-plugins) set to true in the [PluginSettings](https://docs.mattermost.com/administration/config-settings.html#plugins-beta) section of its config file. If you want to upload plugins via the System Console or API, you'll also need to set [EnableUploads](https://docs.mattermost.com/administration/config-settings.html#enable-plugin-uploads) to true in the same section. + +## Build the plugin + +The process that will communicate with the Mattermost server is built using a set of APIs provided by the source code for the Mattermost server. + +Download the source code for the Mattermost server: + +```bash +go get -u github.com/mattermost/mattermost/server/v8 +``` + +Define `$GOPATH`. By default, this is already `$HOME/go`, but it's helpful to make this explicit: +```shell +export GOPATH=$HOME/go +``` + +Now, create a directory to act as your workspace: + +```bash +mkdir -p $GOPATH/src/my-plugin +cd $GOPATH/src/my-plugin +``` + +Create a file named `plugin.go` with the following contents: + +\{/* TODO: unconverted Hugo shortcode \{\{<plugingoexamplecode name="_helloWorld">\}\} (sources/mattermost-developer-documentation/site/content/integrate/plugins/components/server/hello-world.md) */\} + +This plugin will register an HTTP handler that will respond with "Hello, world!" when requested. + +Build the executable that will be distributed with your plugin: + +```bash +go build -o plugin.exe plugin.go +``` + + + +Your executable is platform specific! If you're building the plugin for a server running on a different operating system, you'll need to use a slightly different command. For example, if you're developing the plugin from MacOS and deploying to a Linux server, you'll need to use this command: + + + +```bash +GOOS=linux GOARCH=amd64 go build -o plugin.exe plugin.go +``` + +Also note that the ".exe" extension is required if you'd like your plugin to run on Windows, but is otherwise optional. Consider referencing [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) for helpful build scripts. + +Now, we'll need to define the required manifest describing your plugin's entry point. Create a file named `plugin.json` with the following contents: + +```json +{ + "id": "com.mattermost.server-hello-world", + "name": "Hello World", + "server": { + "executable": "plugin.exe" + } +} +``` + +This manifest gives the server the location of your executable within your plugin bundle. Consult the [manifest reference](/developers/integrate/plugins/manifest-reference) for more details, including how to define a cross-platform bundle by defining multiple executables, and how to define a minimum required server version for your plugin. + +Note that you may also use `plugin.yaml` to define the manifest. + +Bundle the manifest and executable into a tar file: + +```bash +tar -czvf plugin.tar.gz plugin.exe plugin.json +``` + +You should now have a file named `plugin.tar.gz` in your workspace. Congratulations! This is your first server plugin! + +## Install the plugin + +Install the plugin in one of the following ways: + +1) Through System Console UI: + +```text +- Log in to Mattermost as a System Admin. +- Open the System Console at `/admin_console` +- Navigate to *Plugins > Plugin Management** and upload the `plugin.tar.gz` you generated above. +- Click **Enable** under the plugin after it has uploaded. +``` + +2) Or, manually: + + - Extract `plugin.tar.gz` to a folder with the same name as the plugin id you specified in ``plugin.json``, in this case `com.mattermost.server-hello-world/`. + - Add the plugin to the directory set by **PluginSettings > Directory** in your ``config.json`` file. If none is set, defaults to `./plugins` relative to your Mattermost installation directory. The resulting directory structure should look something like: + + ``` + mattermost/ + plugins/ + com.mattermost.server-hello-world/ + plugin.json + plugin.exe + ``` + - Restart the Mattermost server. + +Once you've installed the plugin in one of the ways above, browse to `https:///plugins/com.mattermost.server-hello-world`, and you'll be greeted by your plugin. diff --git a/docs/develop/integrate/plugins/components/server/index.md b/docs/develop/integrate/plugins/components/server/index.md new file mode 100644 index 000000000000..e4fa0dca585a --- /dev/null +++ b/docs/develop/integrate/plugins/components/server/index.md @@ -0,0 +1,48 @@ +--- +title: "Server plugins" +sidebar_position: 10 +--- + +Server plugins are subprocesses invoked by the server that communicate with Mattermost using remote procedure calls (RPC). + +Looking for a quick start? [See our "Hello, world!" tutorial](/developers/integrate/plugins/components/server/hello-world). + +Want the Server SDK reference doc? [Find it here](/developers/integrate/reference/server/server-reference). + +## Features + +#### RPC API + +Use the [RPC API](/developers/integrate/reference/server/server-reference#API) to execute create, read, update and delete (CRUD) operations on server data models. + +For example, your plugin can consume events from a third-party webhook and create corresponding posts in Mattermost, without having to host your code outside Mattermost. + +#### Hooks + +Register for [hooks](/developers/integrate/reference/server/server-reference#Hooks) and get alerted when certain events occur. + +For example, consume the [OnConfigurationChange](/developers/integrate/reference/server/server-reference#Hooks.OnConfigurationChange) hook to respond to server configuration changes, or the [MessageHasBeenPosted](/developers/integrate/reference/server/server-reference#Hooks.MessageHasBeenPosted) hook to respond to posts. + +#### REST API + +Implement the [ServeHTTP](/developers/integrate/) hook to extend the existing Mattermost REST API. + +Plugins with both a web app and server component can leverage this REST API to exchange data. Alternatively, expose your REST API to services and developers connecting from outside Mattermost. + +## How it works + +When starting a plugin, the server consults the [plugin's manifest](/developers/integrate/plugins/manifest-reference) to determine if a server component was included. If found, the server launches a new process using the executable included with the plugin. + +The server will trigger the [OnActivate](/developers/integrate/reference/server/server-reference#Hooks.OnActivate) hook if the plugin is successfully started, allowing you to perform startup events. If the plugin is disabled, the server will trigger the [OnDeactivate](/developers/integrate/reference/server/server-reference#Hooks.OnDeactivate) hook. While running, the server plugin can consume hook events, make API calls, launch threads or subprocesses of its own, interact with third-party services or do anything else a regular program can do. + +## High availability + +Considerations for plugins in a high availability configuration are documented here: [High Availability](/developers/integrate/plugins/components/server/ha) + +## Best practices + +Some best practices for working with the server component of a plugin are documented here: [Best Practices](/developers/integrate/plugins/components/server/best-practices) + +## Debug Server plugins + +Guidelines for debugging the server-side of plugins are documented here: [Debug Server plugins](/developers/integrate/plugins/components/server/debugging) diff --git a/docs/develop/integrate/plugins/components/webapp/actions.md b/docs/develop/integrate/plugins/components/webapp/actions.md new file mode 100644 index 000000000000..ea430d20ded2 --- /dev/null +++ b/docs/develop/integrate/plugins/components/webapp/actions.md @@ -0,0 +1,282 @@ +--- +title: "Redux actions" +sidebar_position: 11 +--- + +When building web app plugins, it's common to perform actions or access the state that web and mobile apps already support. The majority of these actions exist in [mattermost-redux](https://github.com/mattermost/mattermost-redux), which is our library of shared code between Mattermost JavaScript clients. The `mattermost-redux` library exports types and functions that are imported by the web application. These functions can be imported by plugins and used the same way. There are a few different kinds of functions exported by the library: + +* [actions](https://github.com/mattermost/mattermost-redux/tree/master/src/actions): Actions perform API requests and can change the state of Mattermost. +* [client](https://github.com/mattermost/mattermost-redux/tree/master/src/client): The client package can be used to instantiate a Client4 object to interact with the Mattermost API directly. This is useful in plugins as well as JavaScript server applications communicating with Mattermost. +* [constants](https://github.com/mattermost/mattermost-redux/tree/master/src/constants): An assortment of constants within Mattermost's data model. +* [selectors](https://github.com/mattermost/mattermost-redux/tree/master/src/selectors): Selectors return certain data from the Redux store, such as getPost which allows you get a post by id. +* [store](https://github.com/mattermost/mattermost-redux/tree/master/src/store): Functions related to the Redux store itself. +* [types](https://github.com/mattermost/mattermost-redux/tree/master/src/types): Various types of objects in Mattermost's data model. These are useful for plugins written in Typescript. +* [utils](https://github.com/mattermost/mattermost-redux/tree/master/src/utils): Various utility functions shared across the web application. + +## Prerequisites + +It's assumed you have already set up your plugin development environment for web app plugins to match [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template). If not, follow the README instructions of that repository first, or [see the Hello, World! guide](/developers/integrate/plugins/components/webapp/hello-world). + +## Basic example + +Here's an example of a web app plugin making use of [mattermost-redux's](https://github.com/mattermost/mattermost-redux) selectors: + +```ts +import {useSelector} from 'react-redux'; + +import {getPost} from 'mattermost-redux/selectors/entities/posts'; +import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; +import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels'; +import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; + +const MyComponent = ({postId}) => { + const post = useSelector((state) => getPost(state, postId)); + const currentUser = useSelector(getCurrentUser); + const currentChannel = useSelector(getCurrentChannel); + const currentTeam = useSelector(getCurrentTeam); + + // ... +}; +``` + +## Some common actions + +We've listed out some of the commonly-used actions that you can use in your web app plugin. You can find all the actions are available for your plugin to import [in the source code for mattermost-redux](https://github.com/mattermost/mattermost-redux/tree/master/src/actions). + +* ### [createChannel(channel: Channel, userId: string)](https://github.com/mattermost/mattermost-redux/blob/3d1028034d7677adfda58e91b9a5dcaf1bc0ff99/src/actions/channels.ts#L47) + +Dispatch this action to create a new channel. + + +* ### [getCustomEmoji(emojiId: string)](https://github.com/mattermost/mattermost-redux/blob/3d1028034d7677adfda58e91b9a5dcaf1bc0ff99/src/actions/emojis.ts#L32) + +Dispatch this action to fetch a specific emoji associated with the `emojiId` provided. + + +* ### [createPost(post: Post, files: any\[\] = \[\])](https://github.com/mattermost/mattermost-redux/blob/3d1028034d7677adfda58e91b9a5dcaf1bc0ff99/src/actions/posts.ts#L162) + +Dispatch this action to create a new post. + + +* ### [getMyTeams()](https://github.com/mattermost/mattermost-redux/blob/3d1028034d7677adfda58e91b9a5dcaf1bc0ff99/src/actions/teams.ts#L67) + +Dispatch this action to fetch all the team types associated with the current user. + + +* ### [createUser(user: UserProfile, token: string, inviteId: string, redirect: string)](https://github.com/mattermost/mattermost-redux/blob/3d1028034d7677adfda58e91b9a5dcaf1bc0ff99/src/actions/users.ts#L53) + +Dispatch this action to create a new user profile. + + +## Some common selectors + +Here are some examples of commonly-used selectors you can use in your web app plugin. You can find all the selectors that are available for your plugin to import [in the source code for mattermost-redux](https://github.com/mattermost/mattermost-redux/tree/master/src/selectors). + +* ### [getCurrentUserId(state)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/common.ts#L46) + +Retrieves the `userId` of the current user from the `Redux store`. + + +* ### [getCurrentUser(state: GlobalState): UserProfile](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/common.ts#L42) + +Retrieves the user profile of the current user from the `Redux store`. + + +* ### [getUsers(state: GlobalState): IDMappedObjects<UserProfile>](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/common.ts#L50) + +Retrieves all user profiles from the `Redux store`. + + +* ### [getChannel(state: GlobalState, id: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/channels.ts#L218) + +Retrieves a channel as it exists in the store without filling in any additional details such as the `display_name` for Direct Messages/Group Messages. + + +* ### [getCurrentChannelId(state: GlobalState)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/common.ts#L14) + +Retrieves the channel ID of the current channel from the `Redux store`. + + +* ### [getCurrentChannel: (state: GlobalState)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/channels.ts#L235) + +Retrieves the complete channel info of the current channel from the `Redux store`. + + +* ### [getPost(state: GlobalState, postId: $ID<Post>)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/posts.ts#L46) + +Retrieves the specific post associated with the supplied `postID` from the `Redux store`. + + +* ### [getCurrentTeamId(state: GlobalState)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/teams.ts#L20) + +Retrieves the `teamId` of the current team from the `Redux store`. + + +* ### [getCurrentTeam: (state: GlobalState)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/teams.ts#L57) + +Retrieves the team info of the current team from the `Redux store`. + + +* ### [getCustomEmojisByName: (state: GlobalState)](https://github.com/mattermost/mattermost-redux/blob/master/src/selectors/entities/emojis.ts#L37) + +Retrieves the the specific emoji associated with the supplied `customEmojiName` from the `Redux store`. + + +## Some common client functions + +We've listed out some of the commonly-used client functions you can use in your web app plugin. You can find all the client functions that are available for your plugin to import [in the source code for mattermost-redux](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts). + +* ### [getUser = (userId: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L846) + +Routes to the user profile of the specified `userId` from the `Mattermost Server`. + + +* ### [getUserByUsername = (username: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L853) + +Routes to the user profile of the specified `username` from the `Mattermost Server`. + + +* ### [getChannel = (channelId: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L1600) + +Routes to the channel of the specified `channelId` from the `Mattermost Server`. + + +* ### [getChannelByName = (teamId: string, channelName: string, includeDeleted = false)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L1609) + +Routes to the channel of the specified `channelName` from the `Mattermost Server`. + + +* ### [getTeam = (teamId: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L1192) + +Routes to the team of the specified `teamId` from the `Mattermost Server`. + + +* ### [getTeamByName = (teamName: string)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L1199) + +Routes to the team of the specified `teamName` from the `Mattermost Server`. + + +* ### [executeCommand = (command: string, commandArgs: CommandArgs)](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L2463) + +Executes the specified command with the arguments provided and fetches the response. + + +* ### [getOptions(options: Options) \{const newOptions: Options = \{...options\}](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L440) + +Get the client options to make requests to the server. Use this to create your own custom requests. + +## Custom reducers and actions + +Reducers in Redux are pure functions that describe how the data in the store changes after any given action. Reducers will always produce the same resulting state for a given state and action. You can register a custom reducer for your plugin against the Redux store with the `registerReducer` function. + +### [registerReducer(reducer)](/developers/integrate/reference/webapp/webapp-reference#registerReducer) + +Registers a reducer against the Redux store. It will be accessible in Redux state under `state['plugins-']`. It generally accepts a reducer and returns undefined. + +When building web app plugins, it is common to perform actions that web and mobile apps already support. The majority of these actions exist in [mattermost-redux](https://github.com/mattermost/mattermost-redux), our library of shared code between Mattermost JavaScript clients. + +Here we'll show how to use Redux actions with a plugin. To learn more about these actions, see the [contributor documentation](/developers/contribute/more-info/webapp/redux/actions). + +## Prerequisites + +This guide assumes you have already set up your plugin development environment for web app plugins to match [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template). If not, follow the README instructions of that repository first, or [see the Hello, World! guide](/developers/integrate/plugins/components/webapp/hello-world). + +## Import mattermost-redux + +First, you'll need to add `mattermost-redux` as a dependency of your web app plugin. + +```bash +cd /path/to/plugin/webapp +npm install mattermost-redux +``` + +That will add `mattermost-redux` as a dependency in your `package.json` file, allowing it to be imported into any of your plugin's JavaScript files. + +## Use an action + +Actions are used as part of components. To give components access to these actions, we pass them in as React props from the component's container `index.js` file. To demonstrate this, we'll create a new component. + +In the `webapp` directory, let's create a component folder called `action_example` and switch into it. + +```bash +mkdir -p src/components/action_example +cd src/components/action_example +``` + +In there, create two files: `index.js` and `action_example.jsx`. If you're not familiar with why we're creating these directories and files, [read the contributor documentation on using React with Redux](/developers/contribute/more-info/webapp/redux/react-redux). + +Open up `action_example.jsx` and add the following: + +```jsx +import React from 'react'; +import PropTypes from 'prop-types'; + +export default class ActionExample extends React.PureComponent { + static propTypes = { + user: PropTypes.object.isRequired, + patchUser: PropTypes.func.isRequired, // here we define the action as a prop + } + + updateFirstName = () => { + const patchedUser = { + id: this.props.user.id, + first_name: 'Jim', + }; + + this.props.patchUser(patchedUser); // here we use the action + } + + render() { + return ( +
+ {'First name: ' + this.props.user.first_name} + + Click me to update the first name! + +
+ ); + } +} +``` + +This component will display a user's first name and then, when the link is clicked, use an action to update that user's first name to "Jim". + +The action `patchUser` is from mattermost-redux. It takes in a subset of a user object and updates the user on the server, [using the `PUT /users/\{user_id\}/patch` endpoint](https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1patch%2Fput). + +We must now use our container to import this action and pass it our component. Open up the `index.js` file and add: + +```javascript +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; + +import {patchUser} from 'mattermost-redux/actions'; // importing the action + +import ActionExample from './action_example.jsx'; + +const mapStateToProps = (state) => { + const currentUserId = state.entities.users.currentUserId; + + return { + user: state.entities.users.profiles[currentUserId], + }; +}; + +const mapDispatchToProps = (dispatch) => bindActionCreators({ + patchUser, // passing the action as a prop +}, dispatch); + +export default connect(mapStateToProps, mapDispatchToProps)(ActionExample); +``` + +The container is doing two things. First, it's grabbing the current (logged in) user from the Redux state and passing it in as a prop. Anytime the Redux state updates, for example when we use the `patchUser` action, our component will get the updated copy of the current user. Second, the container is importing the `patchUser` action from mattermost-redux and passing it in as an action prop to our component. + +Now we can use `this.props.patchUser()` to update a user. The example component we made uses it to patch the current user's first name. + +To use our component in our plugin we would then use the registry in the initialization function of the plugin to register the component somewhere in the Mattermost UI. That is beyond the scope of this guide, but you can [read more about that here](/developers/integrate/reference/webapp/webapp-reference). + +## Available actions + +The actions that are available for your plugin to import can be [found in the source code for mattermost-redux](https://github.com/mattermost/mattermost-redux/tree/master/src/actions). diff --git a/docs/develop/integrate/plugins/components/webapp/best-practices.md b/docs/develop/integrate/plugins/components/webapp/best-practices.md new file mode 100644 index 000000000000..827a7848281a --- /dev/null +++ b/docs/develop/integrate/plugins/components/webapp/best-practices.md @@ -0,0 +1,95 @@ +--- +title: "Best practices" +sidebar_position: 0 +--- + +## Design best practices + +### Actions that apply to specific Channels +- Recommendation: Have your plugin register the actions to [the channel header](/developers/integrate/reference/webapp/webapp-reference#registerChannelHeaderButtonAction). This makes it quickly accessible for users and the actions apply on the channel they're viewing. +- Example: Zoom meeting posts to a channel + + ![Custom Channel Header Button](/img/extend/bp-channel-header.png) + +You can additionally [register a slash command](/developers/integrate/reference/server/server-reference#API.RegisterCommand) on the server-side to take channel-specific actions. +- Example: Jira project actions + + ![Slash Command](/img/extend/bp-slash-command.gif) + +### Actions that apply to specific messages +- Recommendation: Have your plugin register a [post dropdown menu component](/developers/integrate/reference/webapp/webapp-reference#registerPostDropdownMenuComponent) with some text, icon and an action function. This adds your action to the "More Actions" post menu dropdown for easy discovery. +- Examples: Create or attach to Jira issue from a message; copy a message to another channel; report an inappropriate message +- Sample code: [mattermost/mattermost-plugin-todo/webapp/src/index.js](https://github.com/mattermost/mattermost-plugin-todo/blob/0c4dbfb58a72f8392ea66e101996afd06fdb2913/webapp/src/index.js#L30-L37) + + ![Post Dropdown Menu](/img/extend/bp-post-dropdown-menu.png) + +### Actions related to files or images +- Recommendation: Have your plugin register a [file upload method](/developers/integrate/reference/webapp/webapp-reference#registerFileUploadMethod) with some text, icon and an action function. This adds your new action to the file upload menu. +- Examples: File sharing from OneDrive or GDrive; Draw plugin for sketches + + ![File Upload Action](/img/extend/bp-file-upload.png) + +### Actions that apply to specific teams +- Recommendation: Have your plugin register [left sidebar header component](/developers/integrate/reference/webapp/webapp-reference#registerLeftSidebarHeaderComponent) with some text, icon and an action function. This adds your action above your team's channels in the sidebar. +- Examples: Trello kanban board plugin, GitHub Plugin + + ![left sidebar header](/img/extend/bp-left-sidebar-header.png) + +### Quick links or status summaries of workflows +- Recommendation: Have your plugin register a [bottom team sidebar component](/developers/integrate/reference/webapp/webapp-reference#registerBottomTeamSidebarComponent). This adds icons to the lower left corner of the UI. +- Examples: GitHub sidebar links with summary of outstanding reviews or unread messages; ServiceNow incident status summary + + ![bottom team sidebar](/img/extend/bp-bottom-team-sidebar.png) + +### Global actions that can be taken anywhere in the server and not directly related to teams, channels or users +- Recommendation: Have your plugin register [main menu action](/developers/integrate/reference/webapp/webapp-reference#registerMainMenuAction) with some text, icon for mobile, and an action function. This adds your action to the Main Menu. You can additionally [register a slash command](/developers/integrate/reference/server/server-reference#API.RegisterCommand) on the server-side. +- Examples: Share feedback plugin in Main Menu; /jira slash commands for quick actions + + ![main menu action](/img/extend/bp-main-menu-action.png) + +### Actions that apply to specific users +- Recommendation: Have your plugin register a [popover user actions component](/developers/integrate/reference/webapp/webapp-reference#registerPopoverUserActionsComponent). This adds your action button to the user profile popover. +- Examples: Report User plugin; Display extra information about the user from an LDAP server + + ![popover user actions component](/img/extend/bp-user-popover.png) + +### Extra information on a user profile +- Recommendation: Have your plugin register a [popover user attribute component](/developers/integrate/reference/webapp/webapp-reference#registerPopoverUserAttributesComponent). This adds your custom attributes to the user profile popover. +- Examples: Custom User Attributes plugin + + ![popover user attribute component](/img/extend/bp-user-attributes.png) + +### Actions related to emoji and GIFs +- Recommendation: Have your plugin add a component to the emoji picker. This is not yet supported, but some [work had previously started](https://github.com/mattermost/mattermost/issues/10412#issuecomment-481776595) with the issue currently opened as Help Wanted. +- Examples: Bitmoji plugin; GIFs via Giphy or Gfycat + +## Set up the plugin to properly communicate with the Mattermost Server + +### Use the Mattermost Server's `SiteURL` in your web app plugin + +In order to make sure your plugin has full compatibility with your Mattermost server, you should use the server's configured SiteURL in each API call you send to the server from the webapp. Here's an [example](https://github.com/mattermost/mattermost-plugin-jira/blob/19a9c2442817132b4eee5c77e259b80a40188a6a/webapp/src/selectors/index.js#L13-L26) of how to compute the SiteURL: + +```js +export const getPluginServerRoute = (state) => { + const config = getConfig(state); + + let basePath = ''; + if (config && config.SiteURL) { + basePath = new URL(config.SiteURL).pathname; + + if (basePath && basePath[basePath.length - 1] === '/') { + basePath = basePath.substr(0, basePath.length - 1); + } + } + + return basePath + '/plugins/' + PluginId; +}; +``` + +### Include the server's CSRF token in your web app plugin's requests + +The Mattermost server can be configured to require a CSRF token to be present in HTTP requests sent from the webapp. In order to include the token in each request, you can use the `mattermost-redux` library's `Client4.getOptions` function to add the token to your `fetch` request. Here's an [example](https://github.com/mattermost/mattermost-plugin-jira/blob/19a9c2442817132b4eee5c77e259b80a40188a6a/webapp/src/client/index.js#L14) of how to include the CSRF token. + +```js +const response = await fetch(url, Client4.getOptions(options)); +``` diff --git a/docs/develop/integrate/plugins/components/webapp/hello-world.md b/docs/develop/integrate/plugins/components/webapp/hello-world.md new file mode 100644 index 000000000000..03e80bd85505 --- /dev/null +++ b/docs/develop/integrate/plugins/components/webapp/hello-world.md @@ -0,0 +1,178 @@ +--- +title: "Web app quick start" +sidebar_position: -10 +--- + +This tutorial will walk you through the basics of extending the Mattermost web app. + +Note that the steps below are intentionally very manual to explain all of the pieces fitting together. In practice, we recommend referencing [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) for helpful build scripts. Also, the plugin API changed in Mattermost 5.2. Consult the [migration](/developers/integrate/plugins/migration) document to upgrade older plugins. + +## Prerequisites + +Plugins, just like the Mattermost web app itself, are built using [ReactJS](https://react.dev/) with [Redux](https://redux.js.org/). Make sure to install [npm](https://www.npmjs.com/get-npm) to manage your JavaScript dependencies. + +You'll also need a Mattermost server to install and test the plugin. This server must have [Enable](https://docs.mattermost.com/administration/config-settings.html#enable-plugins) set to true in the [PluginSettings](https://docs.mattermost.com/administration/config-settings.html#plugins-beta) section of its config file. If you want to upload plugins via the System Console or API, you'll also need to set [EnableUploads](https://docs.mattermost.com/administration/config-settings.html#enable-plugin-uploads) to true in the same section. + +## Set up the workspace + +Create a directory to act as your plugin workspace. With that directory, create and switch to a `webapp` directory: + +```bash +mkdir webapp +cd webapp +``` + +Install the necessary NPM dependencies: + +```bash +npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli +npm install --save react +``` + +Configure Webpack by creating a `webpack.config.js` file: + +```js +var path = require('path'); + +module.exports = { + entry: [ + './src/index.jsx', + ], + resolve: { + modules: [ + 'src', + 'node_modules', + ], + extensions: ['*', '.js', '.jsx'], + }, + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-react', + [ + "@babel/preset-env", + { + "modules": "commonjs", + "targets": { + "node": "current" + } + } + ] + ], + }, + }, + }, + ], + }, + externals: { + react: 'React', + }, + output: { + path: path.join(__dirname, '/dist'), + publicPath: '/', + filename: 'main.js', + }, +}; +``` + +Observe that `react` is specified as an external library. This allows you to test your code locally (e.g. with [jest](https://jestjs.io/) and snapshots) but leverage the version of React shipped with Mattermost to avoid bloating your plugin. + +Now create the entry point file and output directory: +```bash +mkdir src dist +touch src/index.jsx +``` + +Then populate `src/index.jsx` with the following: +```jsx +import React from 'react'; + +// Courtesy of https://feathericons.com/ +const Icon = () => ; + +class HelloWorldPlugin { + initialize(registry, store) { + registry.registerChannelHeaderButtonAction( + // icon - JSX element to use as the button's icon + , + // action - a function called when the button is clicked, passed the channel and channel member as arguments + // null, + () => { + alert("Hello World!"); + }, + // dropdown_text - string or JSX element shown for the dropdown button description + "Hello World", + ); + } +} + +window.registerPlugin('com.mattermost.webapp-hello-world', new HelloWorldPlugin()); +``` + +Generate a minified bundle ready to install as a web app plugin: + +```bash +./node_modules/.bin/webpack --mode=production +``` + +Now, we'll need to define the required manifest describing your plugin's entry point. Create a file named `plugin.json` with the following contents: + +```json +{ + "id": "com.mattermost.webapp-hello-world", + "name": "Hello World", + "webapp": { + "bundle_path": "main.js" + } +} +``` + +This manifest gives the server the location of your components within your plugin bundle. Consult the [manifest reference](/developers/integrate/plugins/manifest-reference) for more details, including how to define a minimum required server version for your plugin. + +Note that you may also use `plugin.yaml` to define the manifest. + +Bundle the manifest and entry point into a tar file: + +```bash +mkdir -p com.mattermost.webapp-hello-world +cp -r dist/main.js com.mattermost.webapp-hello-world/ +cp plugin.json com.mattermost.webapp-hello-world/ +tar -czvf plugin.tar.gz com.mattermost.webapp-hello-world +``` + +You should now have a file named `plugin.tar.gz` in your workspace. Congratulations! This is your first web app plugin! + +## Install the plugin + +Install the plugin in one of the following ways: + +1) Through System Console UI: + +```text +- Log in to Mattermost as a System Admin. +- Open the System Console at `/admin_console` +- Navigate to **Plugins > Plugin Management** and upload the `plugin.tar.gz` you generated above. +- Click **Enable** under the plugin after it has uploaded. +``` + +2) Or, manually: + + - Extract `plugin.tar.gz` to a folder with the same name as the plugin id you specified in ``plugin.json``, in this case `com.mattermost.server-hello-world/`. + - Add the plugin to the directory set by **PluginSettings > Directory** in your ``config.json`` file. If none is set, defaults to `./plugins` relative to your Mattermost installation directory. The resulting directory structure should look something like: + + ``` + mattermost/ + plugins/ + com.mattermost.webapp-hello-world/ + plugin.json + main.js + ``` + - Restart the Mattermost server. + - Enable the plugin in **System Console > Plugins > Plugin Management**. + +Navigate to a regular Mattermost page and observe the new icon in the channel header. Click the icon and observe the alert dialog. diff --git a/docs/develop/integrate/plugins/components/webapp/index.md b/docs/develop/integrate/plugins/components/webapp/index.md new file mode 100644 index 000000000000..461e48eae624 --- /dev/null +++ b/docs/develop/integrate/plugins/components/webapp/index.md @@ -0,0 +1,50 @@ +--- +title: "Web app plugins" +sidebar_position: 20 +--- + +Web app plugins extend and modify the Mattermost web and desktop apps, without having to fork and rebase on every Mattermost release. + +Looking for a quick start? [See our "Hello, world!" tutorial](/developers/integrate/plugins/components/webapp/hello-world). + +Want the web app SDK reference doc? [Find it here](/developers/integrate/reference/webapp/webapp-reference). + +## Features + +#### Extend existing components + +Register your own React components to be added to the channel header, sidebars, user details popover, main menu and other supported components. Multiple plugins can add to the same component simultaneously. This API focuses on ease of use and maintaining compatibility with future Mattermost releases. + +For example, the [Mattermost Zoom Plugin](https://github.com/mattermost/mattermost-plugin-zoom) registers a button in the channel header to trigger a Zoom call and post a link to the call in the current channel. + +#### Add new root components + +Register your own React components alongside other root components like the sidebars and modals. This enables whole new interactions that aren't constrained by the set of existing components. This API is geared towards power and flexibility, but may require fine tuning with future Mattermost releases. + +#### Custom post type components + +Web app plugins can also render different post components based on the post's type. Any time the web app encounters a post with this post type, it replaces the default rendering of the post component with your own custom implementation. Only one plugin can own the rendering for a given custom post type at a time: the last plugin to register will own the rendering for that custom post type. + +For example, you can register a custom post type `custom_poll` using [registerPostTypeComponent](/developers/integrate/reference/webapp/webapp-reference#registerPostTypeComponent). Then, any time the web app sees that post type, it replaces the regular rendering of the post component with your own custom implementation. + +Use this in conjunction with setting the post type in webhooks or slash commands, through the REST API or with a server plugin, and you can deeply integrate or extend Mattermost posts to fit your needs. + +## How it works + +When a plugin is uploaded to a Mattermost server and activated, the server checks to see if there is a webapp portion included as part of the plugin by looking at the [plugin's manifest](/developers/integrate/plugins/manifest-reference). If one is found, the server copies the bundled JavaScript included with the plugin into the static directory for serving. A WebSocket event is then fired off to the connected clients signalling the activation of a new plugin. + +On web app launch, a request is made to the server to get a list of plugins that contain web app components. The web app then proceeds to download and execute the JavaScript bundles for each plugin. A similar process happens if an already launched web app receives a WebSocket event for a newly activated plugin. + +Once downloaded and executed, each plugin should have registered itself via the global [registerPlugin](/developers/integrate/reference/webapp/webapp-reference#registerPlugin). The web app then invokes the `initialize` function defined on the plugin class, passing a registry and store. The registry passed allows the plugin to register (and unregister) components, event callbacks and Redux reducers to track plugin state. The store passed is the same Redux store used by the web app, giving the plugin access to the full state of the web app. + +Components registered by the plugin via the registry are tracked in the Redux store and used by `Pluggable` components throughout the web app. `Pluggable` components with a `pluggableName` attribute can render multiple such components registered by plugins. + +Custom post types work similarly, but are registered slightly differently, use a separate reducer and have more of a custom implementation. + +## Redux actions + +Further information on the available Redux Actions is documented here: [Redux Actions](/developers/integrate/plugins/components/webapp/actions) + +## Best practices + +Some best practices for working with the webapp component of a plugin are documented here: [Best Practices](/developers/integrate/plugins/components/webapp/best-practices) diff --git a/docs/develop/integrate/plugins/developer-setup.md b/docs/develop/integrate/plugins/developer-setup.md new file mode 100644 index 000000000000..db2e4d973e26 --- /dev/null +++ b/docs/develop/integrate/plugins/developer-setup.md @@ -0,0 +1,79 @@ +--- +title: "Developer setup" +sidebar_position: 20 +--- + +Once you have your [server](/developers/contribute/developer-setup) and [webapp](/developers/contribute/developer-setup) set up, you can start developing on plugins. + + + +Plugin development doesn't require a development build of Mattermost. Development builds of Mattermost are only required if you want to develop for Mattermost internally. + + + +For developing on Mattermost-managed plugins, each plugin's setup instructions can be found in the plugin repository's README. Some plugins do not have external dependencies and require little to no setup, like the [Todo Plugin](https://github.com/mattermost/mattermost-plugin-todo) while others require an external service to be set up, like the [Jira Plugin](https://github.com/mattermost/mattermost-plugin-jira) and [GitHub Plugin](https://github.com/mattermost/mattermost-plugin-github). + +## Set up your environment to deploy plugins + +### Deploy with local mode + + + +Deploying with local mode will only work for plugins that have been updated with the functionality from the [Plugin Starter Template](https://github.com/mattermost/mattermost-plugin-starter-template). + + + +If your Mattermost server is running locally, you can enable [local mode](https://docs.mattermost.com/manage/mmctl-command-line-tool.html#local-mode) and [plugin uploads](https://docs.mattermost.com/configure/configuration-settings.html#enable-plugin-uploads) to streamline deploying your plugin. Edit your server configuration as follows: + +```json +{ + "ServiceSettings": { + // ... + "EnableLocalMode": true, + "LocalModeSocketLocation": "/var/tmp/mattermost_local.socket" + }, + "PluginSettings": { + // ... + "Enable": true, + "EnableUploads": true + } +} +``` + +and then deploy your plugin: + +```shell +make deploy +``` + +You may also customize the Unix socket path: + +```shell +export MM_LOCALSOCKETPATH=/var/tmp/alternate_local.socket +make deploy +``` + +### Deploy with authentication credentials + +Alternatively, you can authenticate with the server's API with credentials: + +```shell +export MM_SERVICESETTINGS_SITEURL=http://localhost:8065 +export MM_ADMIN_USERNAME=admin +export MM_ADMIN_PASSWORD=password +make deploy +``` + +or with a [personal access token](https://developers.mattermost.com/integrate/reference/personal-access-token/): + +```shell +export MM_SERVICESETTINGS_SITEURL=http://localhost:8065 +export MM_ADMIN_TOKEN=j44acwd8obn78cdcx7koid4jkr +make deploy +``` + + + +Different plugin projects may require specific versions of Node.js. The recommended version for the given project is always defined in a file in the root of the repository called `.nvmrc`. You can use the tool [Node Version Manager](https://nvm.sh) to install and switch between node versions in your terminal. If you have `nvm` installed, you can run `nvm install` anywhere in the plugin repository, and it will automatically find the `.nvmrc` file in the root, and install and use that version. If you already have that version installed, you can run `nvm use`, though `nvm install` can be easier since you don't need to check if you already have the specific Node version installed. + + diff --git a/docs/develop/integrate/plugins/developer-workflow.md b/docs/develop/integrate/plugins/developer-workflow.md new file mode 100644 index 000000000000..9a23bb82228f --- /dev/null +++ b/docs/develop/integrate/plugins/developer-workflow.md @@ -0,0 +1,163 @@ +--- +title: "Developer workflow" +sidebar_position: 30 +--- + +### Common `make` commands for working with plugins + +- `make test` - Runs the plugin's server tests and webapp tests +- `make check-style` - Runs linting checks on the plugin's server and webapp folders +- `make deploy` - Compiles the plugin using the `make dist` command, then automatically deploys the plugin to the Mattermost server. Enabling [Local Mode](/developers/integrate/plugins/developer-setup#deploying-with-local-mode) on your server is the easiest way to use this command. +- `make watch` - Uses webpack's watch feature to re-compile and deploy the webapp portion of your plugin on any change to the `webapp/src` folder. +- `make dist` - Compile the plugin into a g-zipped file, ready to upload to a Mattermost server. The file is saved in the plugin repo's `dist` folder. +- `make enable` - Enables the plugin on the Mattermost server +- `make disable` - Disables the plugin on the Mattermost server. +- `make reset` - Disables and re-enables the plugin on the Mattermost server. +- `make attach-headless` - Starts a `delve` process and attaches it to your running plugin. +- `make clean` - Force deletes the content of build-related files. Use when running into build issues. + +You can run the development build of the plugin by setting the environment variable `MM_DEBUG=1`, or prefixing the variable at the beginning of the `make` command. For example, `MM_DEBUG=1 make deploy` will deploy the development build of the plugin to your server, allowing you to have a more fluid debugging experience. To use the production build of the plugin instead, unset the `MM_DEBUG` environment variable before running the `make` commands. + +### Develop in the plugin's webapp folder + +In order for your IDE to know the root directory of the plugin's webapp code, it is advantageous to open the IDE in the webapp folder itself when working on the webapp portion of the plugin. This way, the IDE is aware of files such as `webpack.config.js` and `tsconfig.json`. + +### Expose the Mattermost server using `ngrok` + +When a plugin integrates with an external service, webhooks and/or authentication redirects are necessary, which requires your local server to be available on the web. In order for your Mattermost server to be available to process webhook requests, it needs to expose its port to an external address. A common way to do this is to use the command line tool [ngrok](https://ngrok.com). Follow these steps to set up `ngrok` with your server: + +- Download the ngrok tool from [here](https://ngrok.com/download). +- Put the executable somewhere within your shell's `PATH`. +- With your Mattermost server already running, use the command `ngrok http 8065` to make your Mattermost server available for webhook requests. +- Visit the `https` URL from the `ngrok` command's output, and log into Mattermost. +- Set your Mattermost server's [Site URL](http://localhost:8065/admin_console/environment/web_server) to the `https` address given from the `ngrok` command output. +- Monitor incoming webhook requests with ngrok's request inspector. Visit [http://localhost:4040](http://localhost:4040) once you have your tunnel open. You can analyze the contents of the HTTP request from the external service, and the response from your plugin. + +If you're using a free ngrok account, the URL given by the output of the `ngrok http` command will be different each time you run the command. As a result, you'll need to adjust the webhook URL on Mattermost's side and the external service's side (e.g. GitHub) each time you run the command. + +With this setup, many integrations require you to be logged into Mattermost using your ngrok URL. After logging into your ngrok URL pointed to your Mattermost server, in most cases you can continue using your `localhost` address in your browser for quicker network requests to your server. If you receive an error like `unauthorized` or `enable third-party cookies` when connecting to an external service, make sure you're logged into your ngrok URL in the same browser. + +##### Use `localhost.run` instead of `ngrok` + +If you would like to avoid using ngrok, there is another free option that you can run from your terminal, called [`localhost.run`](https://localhost.run). Use this command to expose your server: + +```sh +ssh -R 80:localhost:8065 ssh.localhost.run +``` + +An `http` URL pointing to your server should show in the terminal. The `https` version of this same URL should also work, which is what you will want to use for your webhook URLs. One disadvantage of using `localhost.run` is there is no request/response logging dashboard that is available with ngrok. + +### Debug server-side plugins using `delve` + +Using the `delve` debugger, we can step through code for a running plugin on our local Mattermost server. There are a few steps for setup to make this work properly. + +#### Configure Mattermost server for debugging plugins + +In order to allow the debugger to pause code execution, we need to disable Mattermost's "health check" for plugins and the Hashicorp `go-plugin` package's "keep alive" feature for its RPC connection. We'll configure the server with the following steps: + +- In the server's `config.json`, set `PluginSettings.EnableHealthCheck` to `false` +- Run the script below with `./patch_go_plugin.sh $GO_PLUGIN_PACKAGE_VERSION` where `GO_PLUGIN_PACKAGE_VERSION` is the version of `go-plugin` that your Mattermost server is using. This can be found in the monorepo at [server/go.mod](https://github.com/mattermost/mattermost/blob/4bdd8bb18e47d16f9680905972516526b6fd61d8/server/go.mod#L141) on your local server. +- Restart the server + +More details on this are explained below: + +##### Disable Mattermost plugin health check job + +To disable the Mattermost plugin health check job, go into your `config.json` and set `PluginSettings.EnableHealthCheck` to `false`. Note that this will make it so if your plugin panics/crashes for any reason during your development, the Mattermost server will not restart the plugin or notice that it crashed. It will remain with the status of "running" in the plugin management page, even though it has crashed. Because of this, you'll need to watch server logs for any information related to plugin panics during your debugging. + +##### Disable `go-plugin` RPC client "keep alive" + +We'll be editing external library source code directly, so we only want to do this in a development environment. + +By default, the `go-plugin` package runs plugins with a "keep alive" feature enabled, which essentially pings the plugin RPC connection every 30 seconds, and if the plugin doesn't respond, the RPC connection will be terminated. There is a way to disable this, though the `go-plugin` currently doesn't expose a way to configure this setting, so we need to edit the `go-plugin` package's source code to have the right configuration for our debugging use case. + +In the script below, we automatically modify the file located at `${GOPATH}/pkg/mod/github.com/hashicorp/go-plugin@${GO_PLUGIN_PACKAGE_VERSION}/rpc_client.go`, where `GO_PLUGIN_PACKAGE_VERSION` is the version of `go-plugin` that your Mattermost server is using. This can be found in your local copy of the monorepo at [server/go.mod](https://github.com/mattermost/mattermost/blob/4bdd8bb18e47d16f9680905972516526b6fd61d8/server/go.mod#L141). This script essentially replaces the line in [go-plugin/rpc_client.go](https://github.com/hashicorp/go-plugin/blob/586d14f3dcef1eb42bfb7da4c7af102ec6638668/rpc_client.go#L66) to have a custom configuration for the RPC client connection, that disables the "keep alive" feature. This makes it so the debugger can be paused for long amounts of time, and the Mattermost server will keep the connection with the plugin open. + +```sh +# patch_go_plugin.sh + +GO_PLUGIN_PACKAGE_VERSION=$1 + +GO_PLUGIN_RPC_CLIENT_PATH=${GOPATH}/pkg/mod/github.com/hashicorp/go-plugin@${GO_PLUGIN_PACKAGE_VERSION}/rpc_client.go + +echo "Patching $GO_PLUGIN_RPC_CLIENT_PATH for debugging Mattermost plugins" + +if ! grep -q 'mux, err := yamux.Client(conn, nil)' "$GO_PLUGIN_RPC_CLIENT_PATH"; then + echo "The file has already been patched or the target line was not found." + exit 0 +fi + +sudo sudo sed -i '' '/import (/a\ + "time" +' $GO_PLUGIN_RPC_CLIENT_PATH + +sudo sed -i '' '/mux, err := yamux.Client(conn, nil)/c\ + sessionConfig := yamux.DefaultConfig()\ + sessionConfig.EnableKeepAlive = false\ + sessionConfig.ConnectionWriteTimeout = time.Minute * 5\ + mux, err := yamux.Client(conn, sessionConfig) +' $GO_PLUGIN_RPC_CLIENT_PATH + +echo "Patched go-plugin's rpc_client.go for debugging Mattermost plugins" +``` + +Then run the script like so: + +```sh +chmod +x patch_go_plugin.sh +./patch_go_plugin.sh v1.6.0 # as of writing, this is the version of `go-plugin` being used by the server +``` + +#### Configure VSCode for debugging + +This section assumes you are using VSCode to debug your plugin. If you want to use a different IDE, the process will be mostly the same. If you want to debug in your terminal directly with `delve` instead of using an IDE, you can run `make attach` instead of `make attach-headless` below, which will launch a `delve` process as an interactive terminal. + +Include this configuration in your VSCode instance's [launch.json](https://learn.microsoft.com/en-us/microsoft-edge/visual-studio-code/microsoft-edge-devtools-extension/launch-json): + +```json +{ + "name": "Attach to Mattermost plugin", + "type": "go", + "request": "attach", + "mode": "remote", + "port": 2346, + "host": "127.0.0.1", + "apiVersion": 2 +} +``` + +#### Attach headless `delve` process to the running plugin + +Build the plugin and deploy to your local Mattermost server: + +```sh +make deploy +``` + +In a separate terminal, open a `delve` process for VSCode to connect to: + +```sh +make attach-headless +``` + +This starts a headless `delve` process for your IDE to connect to. The process listens on port `2346`, which is the port defined in our `launch.json` configuration. Somewhat related, the Mattermost server's `Makefile` has a command `debug-server-headless`, which starts a headless `delve` process for the Mattermost server, listening on port `2345`. So you can create a similar `launch.json` configuration in the server directory of the monorepo to connect to your server by using that port. + +#### Attach the debugger to the `delve` process + +Run the debugger in VSCode by navigating to the "Run and Debug" tab on the left side of the IDE, selecting your launch configuration, and clicking the green play button. This should bring up a debugging widget that looks like this: + +![image](https://github.com/mattermost/mattermost-developer-documentation/assets/6913320/9419ce8b-c803-40b7-82bb-9ccd64971676) + +![image](https://github.com/mattermost/mattermost-developer-documentation/assets/6913320/f28681c3-c256-41a1-b1f4-835f96628d6a) + +Your IDE's debugger is now running and ready to pause your plugin's execution at any breakpoints you set in the IDE. + +### Troubleshooting + +If you run into issues with debugging, first make sure you've stopped any active debugging sessions by clicking the red disconnect button in the VSCode debugging widget. + +You can then use the `make reset` command in the plugin repository to do the following: +- Disable and re-enable the plugin +- Terminate any running `delve` processes running for this plugin + +For more discussion on this, please join the Toolkit channel on our community server: https://community.mattermost.com/core/channels/developer-toolkit diff --git a/docs/develop/integrate/plugins/example-plugins.md b/docs/develop/integrate/plugins/example-plugins.md new file mode 100644 index 000000000000..13953c635d93 --- /dev/null +++ b/docs/develop/integrate/plugins/example-plugins.md @@ -0,0 +1,68 @@ +--- +title: "Example plugins" +sidebar_position: 90 +--- + +## Server "Hello, world!" + +To get started extending server-side functionality with plugins, take a look at our [server "Hello, world!" tutorial](/developers/integrate/plugins/components/server/hello-world). + +## Web app "Hello, world!" + +To get started extending browser-side functionality with plugins, take a look at our [web app "Hello, world!" tutorial](/developers/integrate/plugins/components/webapp/hello-world). + +## Demo plugin + +To see a demonstration of all server-side hooks and webapp components, take a look at our [demo plugin](https://github.com/mattermost/mattermost-plugin-demo). + +## Sample plugin + +To see a stripped down version of the demo plugin with just the build scripts and templates to get started, take a look at our [plugin starter template](https://github.com/mattermost/mattermost-plugin-starter-template). + +## Zoom + +The [Zoom plugin for Mattermost](https://github.com/mattermost/mattermost-plugin-zoom) adds UI elements that allow users to easily create and join Zoom meetings: + + + +Topics demonstrated: + +* Uses a custom HTTP handler to integrate with external systems. +* Defines a settings schema, allowing system administrators to configure the plugin via system console UI. +* Implements tests using the [plugin/plugintest](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin/plugintest) package. +* Creates rich posts using custom post types. +* Extends existing webapp components to add elements to the UI. + +## JIRA + +The [JIRA plugin for Mattermost](https://github.com/mattermost/mattermost-plugin-jira) creates a webhook that your JIRA server can use to post messages to Mattermost when issues are created: + + + +Topics demonstrated: + +* Uses a custom HTTP handler to integrate with external systems. +* Defines a settings schema, allowing system administrators to configure the plugin via system console UI. +* Implements tests using the [plugin/plugintest](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin/plugintest) package. +* Compiles and publishes releases for multiple platforms using Travis-CI. + +## Profanity filter + +The [profanity filter plugin for Mattermost](https://github.com/mattermost/mattermost-plugin-profanity-filter) automatically detects restricted words in posts and censors them prior to writing to the database. For more use cases, [see this forum post](https://forum.mattermost.com/t/coming-soon-apiv4-mattermost-post-intercept/4982). + +Topics demonstrated: + +* Interception and modification of posts prior to writing them into the database. +* Rejection of posts prior to writing them into the database. + +## Memes + +The [Memes plugin for Mattermost](https://github.com/mattermost/mattermost-plugin-memes) creates a slash command that can be used to create dank memes: + + + +Topics demonstrated: + +* Registers a custom slash command. +* Uses a custom HTTP handler to generate and serve content. +* Compiles and publishes releases for multiple platforms using Travis-CI. diff --git a/docs/develop/integrate/plugins/helpers.md b/docs/develop/integrate/plugins/helpers.md new file mode 100644 index 000000000000..78320a0bb5d7 --- /dev/null +++ b/docs/develop/integrate/plugins/helpers.md @@ -0,0 +1,6 @@ +--- +title: "Plugin helpers" +sidebar_position: 105 +--- + +In Mattermost v6.0, Plugin Helpers have been removed in favor of the [Mattermost plugin API](https://github.com/mattermost/mattermost-plugin-api). diff --git a/docs/develop/integrate/plugins/index.md b/docs/develop/integrate/plugins/index.md new file mode 100644 index 000000000000..08b226bc29fc --- /dev/null +++ b/docs/develop/integrate/plugins/index.md @@ -0,0 +1,34 @@ +--- +title: "Plugins" +sidebar_position: 40 +--- + +Mattermost supports plugins that offer powerful features for extending and deeply integrating with both the Server and Web/Desktop Apps. + +Share constructive feedback [on our forum post](https://forum.mattermost.com/t/plugin-system-upgrade-in-mattermost-5-2/5498) or join the [Toolkit channel](https://community.mattermost.com/core/channels/developer-toolkit) on our Mattermost community server. + +## Features + +### Customize user interfaces + +Write a Web App plugin to add to the channel header, sidebars, main menu, and more. Register your plugin against a post type to render custom posts or wire up a root component to build an entirely new experience. All this is possible without having to fork the source code and rebase on every Mattermost release. + +### Launch tightly-integrated services + +Launch and manage Server plugins as services from your Mattermost server over RPC. Handle events via real-time hooks and invoke Mattermost server methods directly using a dedicated plugin API. + +### Extend the Mattermost REST API + +Extend the Mattermost REST API with custom endpoints for use by Web App plugins or third-party services. Custom endpoints have access to all the features of the standard Mattermost REST API, including personal access tokens and OAuth 2.0. + + + +See the [Mattermost Server SDK Reference](/developers/integrate/reference/server/server-reference) and [Mattermost Client UI SDK Reference](/developers/integrate/reference/webapp/webapp-reference) documentation for details on available server API endpoints and client methods. + + + +### Simple development and installation + +It's simple to set up a plugin development environment with the [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template). Just select "Use this template" when cloning the repository. Please see the [developer setup](https://developers.mattermost.com/integrate/plugins/developer-setup) and [developer workflow](https://developers.mattermost.com/integrate/plugins/developer-workflow) pages for more information. + +Read the plugins [overview](/developers/integrate/plugins/overview) to learn more. diff --git a/docs/develop/integrate/plugins/interactive-dialogs/index.md b/docs/develop/integrate/plugins/interactive-dialogs/index.md new file mode 100644 index 000000000000..c5389dca814f --- /dev/null +++ b/docs/develop/integrate/plugins/interactive-dialogs/index.md @@ -0,0 +1,1093 @@ +--- +title: "Interactive dialogs" +sidebar_position: 70 +--- + +Integrations open dialogs by sending an `HTTP POST`, containing some data in the request body, to an endpoint on the Mattermost server. Integrations can use this endpoint to open dialogs when users [click message buttons or select an option from a menu](/developers/integrate/plugins/interactive-messages), or use a +[custom slash command](/developers/integrate/slash-commands). + +Moreover, [plugins](/developers/integrate/plugins/using-and-managing-plugins) can trigger a dialog based on user actions. For instance, if a plugin adds a button in the channel header, clicking that button may open a dialog. + +Here is an example of what a dialog looks like for creating a Jira issue within the Mattermost user interface: + +![image](interactive-dialog-example.png) + +## Open a dialog + +To open a dialog, your integration must first receive an HTTP request from the Mattermost server. This request will be triggered by a slash command or an interactive message. It will include a trigger ID. + +Once you have the trigger ID you can use it to open the interactive dialog by sending an `HTTP POST` request to `https:///api/v4/actions/dialogs/open`. See the below section for what to include in the body of that HTTP request. + +## Parameters + +Interactive dialogs support the following parameters: + +| Parameter | Type | Description | +|---------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `title` | String | Title of the dialog. Maximum 24 characters. | +| `introduction_text` | String | Markdown-formatted introduction text which is displayed above the dialog `elements`. | +| `elements` | Array | See below for more details on elements. If none are supplied the dialog box acts as a simple confirmation. | +| `url` | String | The URL to send the submitted dialog payload to. | +| `icon_url` | String | (Optional) The URL of the icon used for your dialog. If none specified, no icon is displayed. | +| `submit_label` | String | (Optional) Label of the button to complete the dialog. Default is `Submit`. | +| `notify_on_cancel` | Boolean | (Optional) When `true`, sends an event back to the integration whenever there's a user-induced dialog cancellation. No other data is sent back with the event. Default is `false`. | +| `state` | String | (Optional) String provided by the integration that will be echoed back with dialog submission. Default is the empty string. | +| `source_url` | String | (Optional) URL for field refresh requests. When a select element with `refresh: true` changes value, Mattermost sends a refresh request to this URL. Also used as the endpoint for multi-step form responses. | + +Sample JSON is given below. Form submissions are sent back to the URL defined by the integration. You must also include the trigger ID you received from the slash command or interactive message. + +```json +{ + "trigger_id": "", + "url": "", + "dialog": { + "callback_id": "", + "title": "", + "introduction_text": "<Text describing the dialog box content>", + "elements": ["<Array of UI elements to display in the dialog>"], + "submit_label": "<label of the button to complete the dialog>", + "notify_on_cancel": false, + "state": "<string provided by the integration that will be echoed back with dialog submission>", + "source_url": "<optional URL for field refresh and multi-step form handling>" + } +} +``` + +## Elements + +Each dialog supports elements for users to enter information. + +- `text`: Single-line plain text field. Use this for inputs such as names, email addresses, or phone numbers. +- `textarea`: Multi-line plain text field. Use this field when the answer is expected to be longer than 150 characters. +- `select`: Message menu. Use this for pre-selected choices. Can either be static menus or dynamic menus generated from users and Public channels of the system. For more information on message menus, see [the documentation](/developers/integrate/plugins/interactive-messages). +- `bool`: Checkbox option. Use this for binary selection. +- `radio`: Radio button option. Use this to quickly select an option from pre-selected choices. +- `date`: Date picker field. Use this for selecting dates without time information. +- `datetime`: Date and time picker field. Use this for selecting both date and time with timezone support. + +Each element is required by default, otherwise the client will return an error as shown below. Note that the error message will appear below the help text, if one is specified. To make an element optional, set the field `"optional": "true"`. + +![image](interactive-dialog-error.png) + +### Text elements + +Text elements are single-line plain text fields. Below is an example of a `text` element that asks for an email address. + +![image](interactive-dialog-text.png) + +```json +{ + "display_name": "Email", + "name": "email", + "type": "text", + "subtype": "email", + "placeholder": "placeholder@example.com" +} +``` + +There is an optional `"subtype": "email"` field in the above example, which specifies the keyboard layout used on mobile. For this example, the email keypad is shown to the user given the subtype is set to `email`. + +The full list of supported fields is included below: + +| Field | Type | Description | +|----------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `text` for a text element. | +| `subtype` | String | (Optional) One of `text`, `email`, `number`, `password` (as of v5.14), `tel`, or `url`. Default is `text`. Use this to set which keypad is presented to users on mobile when entering the field. | +| `min_length` | Integer | (Optional) Minimum input length allowed for an element. Default is 0. | +| `max_length` | Integer | (Optional) Maximum input length allowed for an element. Default is 150. If you expect the input to be greater 150 characters, consider using a `textarea` type element instead. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `help_text` | String | (Optional) Set help text for this form element. Maximum 150 characters. | +| `default` | String | (Optional) Set a default value for this form element. Maximum 150 characters. | +| `placeholder` | String | (Optional) A string displayed to help guide users in completing the element. Maximum 150 characters. | + +### Textarea elements + +Textarea elements are multi-line plain text fields. A sample JSON is provided below: + +```json +{ + "display_name": "Ticket Description", + "name": "ticket_description", + "type": "textarea", + "help_text": "Provide description for your ticket." +} +``` + +The maximum length for a `textarea` is 3,000 characters. + +The list of supported fields is the same as for the `textarea` type element. + + +| Field | Type | Description | +|----------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `texareat` for a textarea element. | +| `subtype` | String | (Optional) One of `text`, `email`, `number`, `password` (as of v5.14), `tel`, or `url`. Default is `text`. Use this to set which keypad is presented to users on mobile when entering the field. | +| `min_length` | Integer | (Optional) Minimum input length allowed for an element. Default is 0. | +| `max_length` | Integer | (Optional) Maximum input length allowed for an element. Default is 3000. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `help_text` | String | (Optional) Set help text for this form element. Maximum 150 characters. | +| `default` | String | (Optional) Set a default value for this form element. Maximum 3000 characters. | +| `placeholder` | String | (Optional) A string displayed to help guide users in completing the element. Maximum 3000 characters. | + +### Select elements + +Select elements are message menus that allow users to select one or multiple predefined options from a list. Below is an example of a `select` element that asks for one of three different options. + +![image](interactive-dialog-select.png) + +![image](interactive-dialog-select-menu.png) + +```json +{ + "display_name": "Option Selector", + "name": "options", + "type": "select", + "options": [ + { + "text": "Option1", + "value": "opt1" + }, + { + "text": "Option2", + "value": "opt2" + }, + { + "text": "Option3", + "value": "opt3" + } + ] +} +``` + +#### Multiselect support +##### Minimum Server Version: 11.0 + +Select elements can be configured to allow multiple selections by setting the `multiselect` parameter to `true`. When multiselect is enabled, users can choose multiple options from the list. + +```json +{ + "display_name": "Multiple Options", + "name": "multi_options", + "type": "select", + "multiselect": true, + "default": "opt1,opt3", + "options": [ + { + "text": "Option1", + "value": "opt1" + }, + { + "text": "Option2", + "value": "opt2" + }, + { + "text": "Option3", + "value": "opt3" + } + ] +} +``` + +For multiselect elements, default values can be specified as a comma-separated string (e.g., `"opt1,opt3"` to pre-select Option1 and Option3). + +#### Dynamic select support +##### Minimum Server Version: 11.0 + +Select elements can be configured to load options dynamically from an external API endpoint. This enables real-time filtering, searching, and loading of options based on user input. + +To use dynamic select, set `data_source: "dynamic"` and provide a `data_source_url` that points to your lookup endpoint: + +```json +{ + "display_name": "Dynamic Options", + "name": "dynamic_field", + "type": "select", + "data_source": "dynamic", + "data_source_url": "https://your-mattermost-server.com/plugins/your-plugin-id/api/lookup", + "placeholder": "Search for options..." +} +``` + +When users interact with a dynamic select field, Mattermost sends an HTTP POST request to the `/api/v4/actions/dialogs/lookup` endpoint, which proxies the request to your `data_source_url`. The payload uses the same `SubmitDialogRequest` structure: + +```json +{ + "type": "dialog_lookup", + "url": "<your data_source_url>", + "callback_id": "<callback ID>", + "state": "<state>", + "user_id": "<user ID>", + "channel_id": "<channel ID>", + "team_id": "<team ID>", + "submission": { + "query": "user_search_input", + "selected_field": "dynamic_field", + "other_field_name": "current_value" + } +} +``` + +The `submission` map contains `query` (the user's search input), `selected_field` (the field being searched), and current values of all other form fields. + +Your endpoint should respond with an array of options: + +```json +{ + "items": [ + { + "text": "Option 1", + "value": "option1" + }, + { + "text": "Option 2", + "value": "option2" + } + ] +} +``` + +**Security Requirements:** +- External URLs must use HTTPS +- Plugin paths (starting with `/plugins/`) are proxied locally and do not require HTTPS +- The lookup endpoint should validate user permissions + +**Dynamic select with multiselect:** + +```json +{ + "display_name": "Multiple Dynamic Options", + "name": "multi_dynamic_field", + "type": "select", + "multiselect": true, + "data_source": "dynamic", + "data_source_url": "https://your-mattermost-server.com/plugins/your-plugin-id/api/lookup", + "placeholder": "Search and select multiple options..." +} +``` + +The `select` element can also be generated dynamically from users and channels of the system. + +For users, use: + +```json +{ + "display_name": "Assignee", + "name": "assignee", + "type": "select", + "data_source": "users" +} +``` + +For multiple user selection: + +```json +{ + "display_name": "Multiple Assignees", + "name": "assignees", + "type": "select", + "multiselect": true, + "data_source": "users" +} +``` + +For Public channels, use: + +```json +{ + "display_name": "Post this message to", + "name": "channel", + "type": "select", + "data_source": "channels" +} +``` + +For multiple channel selection: + +```json +{ + "display_name": "Post to multiple channels", + "name": "channels", + "type": "select", + "multiselect": true, + "data_source": "channels" +} +``` + +The list of supported fields for the `select` type element is included below: + +| Field | Type | Description | +|--------------------|---------|------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `select` for a `select` element. | +| `multiselect` | Boolean | (Optional) Set to `true` to allow multiple selections from the list. Default is `false`. | +| `data_source` | String | (Optional) One of `users`, `channels`, or `dynamic`. If none specified, assumes a manual list of options is provided by the integration. | +| `data_source_url` | String | (Optional) URL for dynamic option loading when `data_source` is `dynamic`. Must be HTTPS or a `/plugins/` path. | +| `refresh` | Boolean | (Optional) When `true`, triggers a field refresh request to the dialog's `source_url` when this field's value changes. Use this for dependent dropdowns or conditional form fields. Default is `false`. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `options` | Array | (Optional) An array of options for the select element. Not applicable for `users`, `channels`, or `dynamic` data sources. | +| `help_text` | String | (Optional) Set help text for this form element. Maximum 150 characters. | +| `default` | String | (Optional) Set a default value for this form element. For multiselect, use comma-separated values. Maximum 3,000 characters. | +| `placeholder` | String | (Optional) A string displayed to help guide users in completing the element. Maximum 3,000 characters. | + + +### Checkbox element + +From Mattermost v5.16 you can use `checkbox` elements. It looks like a plain text field with a checkbox to be selected. Below is an example of a `checkbox` element that asks for meeting feedback. + +![image](interactive-dialog-bool.png) + +```json +{ + "display_name": "Can you please select below", + "placeholder": "The meeting was helpful.", + "name": "meeting_input", + "type": "bool" +} +``` + +The full list of supported fields is included below: + +| Field | Type | Description | +|----------------|---------|------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `bool` for a checkbox element. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `help_text` | String | (Optional) Set help text for this form element. Maximum 150 characters. | +| `default` | String | (Optional) Set a default value for this form element. `true` or `false`. | +| `placeholder` | String | (Optional) A string displayed to include a label besides the checkbox. Maximum 150 characters. | + +### Radio element + +From Mattermost v5.16 you can use `radio` elements. It looks like a plain text field with a radio button to be selected. Below is an example of a `radio` element that asks for a department. + +![image](interactive-dialog-radio.png) + +```json +{ + "display_name": "Which department do you work in?", + "name": "department", + "type": "radio", + "options": [ + { + "text": "Engineering", + "value": "engineering" + }, + { + "text": "Sales", + "value": "sales" + }, + { + "text": "Administration", + "value": "administration" + } + ], + "help_text": "Please indicate your department as of January 1.", + "default": "engineering" +} +``` + +The full list of supported fields are included below: + +| Field | Type | Description | +|----------------|--------|------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `radio` for a radio element. | +| `options` | Array | (Optional) An array of options for the radio element. | +| `help_text` | String | (Optional) Set help text for this form element. Maximum 150 characters. | +| `default` | String | (Optional) Set a default value for this form element. | + +### Date elements +##### Minimum Server Version: 11.1 + +Date elements provide native date picker functionality for selecting dates without time information. Below is an example of a `date` element for event scheduling. + +![image](interactive-dialog-date.png) + +```json +{ + "display_name": "Event Date", + "name": "event_date", + "type": "date", + "default": "2024-03-15", + "placeholder": "Select a date", + "help_text": "Choose the date for your event", + "optional": false, + "datetime_config": { + "min_date": "today", + "max_date": "+30d" + } +} +``` + +The full list of supported fields for `date` elements is included below: + +| Field | Type | Description | +|-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `date` for a date element. | +| `default` | String | (Optional) Default value in ISO date format (YYYY-MM-DD) or relative format (`today`, `tomorrow`, `+1d`, `+1w`, `+1M`, `+1y`). Full ISO datetime strings are accepted, but only the date part is parsed; timezone information is ignored. | +| `placeholder` | String | (Optional) Placeholder text shown in the input field. Maximum 150 characters. | +| `help_text` | String | (Optional) Help text displayed below the field. Maximum 150 characters. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `datetime_config` | Object | (Optional) Nested date configuration object. See [datetime_config object](#datetime_config-object) for supported properties. | +| `min_date` | String | (Deprecated — use `datetime_config.min_date`.) Earliest selectable date. Supports ISO date format (YYYY-MM-DD) or relative formats (`today`, `tomorrow`, `+1d`, `-7d`, etc.). Full ISO datetime strings are accepted, but only the date part is parsed; timezone information is ignored. | +| `max_date` | String | (Deprecated — use `datetime_config.max_date`.) Latest selectable date. Supports ISO date format (YYYY-MM-DD) or relative formats (`today`, `+30d`, `+1y`, etc.). Full ISO datetime strings are accepted, but only the date part is parsed; timezone information is ignored. | + +#### Date field usage examples + +**Basic date selection:** +```json +{ + "display_name": "Project Deadline", + "name": "deadline", + "type": "date", + "help_text": "When is this project due?", + "datetime_config": { + "min_date": "today" + }, + "optional": false +} +``` + +**Date range with relative defaults:** +```json +{ + "display_name": "Flexible Date", + "name": "any_date", + "type": "date", + "help_text": "Any date within the next year", + "datetime_config": { + "min_date": "today", + "max_date": "+1y" + }, + "default": "+1w", + "optional": true +} +``` + +### DateTime elements +##### Minimum Server Version: 11.1 + +DateTime elements provide combined date and time picker functionality with timezone support. Below is an example of a `datetime` element for meeting scheduling. + +![image](interactive-dialog-datetime.png) + +```json +{ + "display_name": "Meeting Time", + "name": "meeting_time", + "type": "datetime", + "default": "2024-03-15T14:30:00Z", + "placeholder": "Select date and time", + "help_text": "Choose when the meeting should start", + "optional": false, + "datetime_config": { + "min_date": "today", + "max_date": "+7d", + "time_interval": 30 + } +} +``` + +The full list of supported fields for `datetime` elements is included below: + +| Field | Type | Description | +|-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name of the field shown to the user in the dialog. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `datetime` for a datetime element. | +| `default` | String | (Optional) Default value in ISO datetime format (RFC3339) or relative format. For relative dates, time defaults to noon. When specifying a time, it must align with `datetime_config.time_interval` (be a multiple of the interval). | +| `placeholder` | String | (Optional) Placeholder text shown in the input field. Maximum 150 characters. | +| `help_text` | String | (Optional) Help text displayed below the field. Maximum 150 characters. | +| `optional` | Boolean | (Optional) Set to `true` if this form element is not required. Default is `false`. | +| `datetime_config` | Object | (Optional) Nested datetime configuration object. See [datetime_config object](#datetime_config-object) for supported properties. | +| `min_date` | String | (Deprecated — use `datetime_config.min_date`.) Earliest selectable date. Supports ISO format or relative formats (`today`, `tomorrow`, `+1d`, `-7d`, etc.). | +| `max_date` | String | (Deprecated — use `datetime_config.max_date`.) Latest selectable date. Supports ISO format or relative formats (`today`, `+30d`, `+1y`, etc.). | +| `time_interval` | Integer | (Deprecated — use `datetime_config.time_interval`.) Time selection interval in minutes. Must be between 1 and 1440, and must be a divisor of 1440 to create evenly spaced intervals throughout the day. Common values: 15, 30, 60, 90, 120. Default is 60. | + +#### DateTime field usage examples + +**Meeting scheduler with business hours:** +```json +{ + "display_name": "Meeting Time", + "name": "meeting_time", + "type": "datetime", + "help_text": "Select a time during business hours", + "datetime_config": { + "min_date": "+1d", + "max_date": "+14d", + "time_interval": 30 + }, + "optional": false +} +``` + +**Event with custom time intervals:** +```json +{ + "display_name": "Event Start Time", + "name": "event_start", + "type": "datetime", + "help_text": "When does your event begin?", + "datetime_config": { + "min_date": "today", + "max_date": "+90d", + "time_interval": 15 + }, + "default": "today" +} +``` + +**Fixed location timezone with manual entry:** +```json +{ + "display_name": "Conference Start", + "name": "conference_start", + "type": "datetime", + "help_text": "All attendees see this time in the conference timezone", + "datetime_config": { + "location_timezone": "America/Denver", + "manual_time_entry": true, + "time_interval": 30 + } +} +``` + +#### datetime_config object +##### Minimum Server Version: 11.6 + +The `datetime_config` object groups date/datetime configuration into a single nested structure. It is supported on both `date` and `datetime` elements. + +| Field | Type | Applies to | Since | Description | +|---------------------------|---------|--------------------|--------|-----------------------------------------------------------------------------------------------------------------------------| +| `min_date` | String | `date`, `datetime` | 11.8 | (Optional) Earliest selectable date. Supports ISO format or relative formats (`today`, `+1d`, etc.). | +| `max_date` | String | `date`, `datetime` | 11.8 | (Optional) Latest selectable date. Supports ISO format or relative formats (`+30d`, `+1y`, etc.). | +| `time_interval` | Integer | `datetime` | 11.6 | (Optional) Time selection interval in minutes. Must be between 1 and 1440, and must be a divisor of 1440. Default is 60. | +| `location_timezone` | String | `datetime` | 11.6 | (Optional) IANA timezone used to display and submit the time (e.g. `America/Denver`, `Asia/Tokyo`). When set, all users see the same wall-clock time regardless of their own timezone. Defaults to the viewing user's timezone. | +| `manual_time_entry` | Boolean | `datetime` | 11.8 | (Optional) When `true`, users can type the time directly in addition to using the dropdown. Default is `false`. | +| `allow_manual_time_entry` | Boolean | `datetime` | 11.6 (deprecated in 11.8) | (Deprecated — use `manual_time_entry`.) When both are set, either enabling turns the feature on. | + +**Backward compatibility (new in 11.8):** The top-level `min_date`, `max_date`, and `time_interval` fields on `date` and `datetime` elements are still accepted for existing integrations, but are deprecated in favor of `datetime_config`. When both are provided on the same element, values inside `datetime_config` take precedence over the legacy top-level values. + +#### Date and DateTime field specifications + +**Relative Date Formats:** +- `today`: Current date +- `tomorrow`: Next day +- `yesterday`: Previous day +- `+Nd`: N days from today (e.g., `+1d`, `+7d`) +- `+Nw`: N weeks from today (e.g., `+1w`, `+2w`) +- `+NM`: N months from today (e.g., `+1M`, `+6M`) +- `+Ny`: N years from today (e.g., `+1y`) +- `-Nd`: N days ago (e.g., `-1d`, `-7d`) + +**ISO Format Examples:** +- Date: `2024-03-15` (YYYY-MM-DD) +- DateTime: `2024-03-15T14:30:00Z` (RFC3339 format) +- DateTime with timezone: `2024-03-15T14:30:00-05:00` + +**Form Submission Format:** +- Date fields submit in ISO date format: `2024-03-15` +- DateTime fields submit in RFC3339 format with user's timezone: `2024-03-15T14:30:00-05:00` + +**Localization:** +- Date fields automatically format according to user's locale (e.g., "Mar 15, 2024" for en-US) +- DateTime fields respect user's 12/24 hour preference and locale-specific formatting +- Time picker displays times according to user's timezone + +**Validation:** +- Client validates date formats and range constraints +- Server validates relative date resolution and field configuration +- For datetime fields, `datetime_config.time_interval` must be a divisor of 1440 (24 hours in minutes) +- Default times must align with the effective `time_interval` (be a multiple of the interval) +- Invalid dates, times, or out-of-range selections show appropriate error messages + +**Time Interval Examples:** +- `"time_interval": 15` creates options: 00:00, 00:15, 00:30, 00:45, 01:00, etc. +- `"time_interval": 30` creates options: 00:00, 00:30, 01:00, 01:30, etc. +- `"time_interval": 60` creates options: 00:00, 01:00, 02:00, 03:00, etc. +- Invalid: `"time_interval": 7` (7 is not a divisor of 1440) + +## Dialog submission + +When a user submits a dialog, Mattermost will perform client-side input validation to make sure: + + - All required fields are filled. + - All formats are correct (e.g. email, telephone number, etc.). + +The submission payload sent to the integration is: + +```json +{ + "type": "dialog_submission", + "callback_id": "<callback ID provided by the integration>", + "state": "<state provided by the integration>", + "user_id": "<user ID of the user who submitted the dialog>", + "channel_id": "<channel ID the user was in when submitting the dialog>", + "team_id": "<team ID the user was on when submitting the dialog>", + "submission": { + "some_element_name": "<value of that element>", + "some_other_element": "<value of some other element>" + }, + "cancelled": false +} +``` + +Optionally, the dialog can send an event back to the integration if `notify_on_cancel` parameter is set to `true`. If this happens, `cancelled` will be set to `true` on the above payload, and `submission` will be empty. + +Moreover, Mattermost also allows the integration itself to perform input validation. This can be done by responding to the dialog submission request with a JSON body containing an `errors` field. The `errors` field can contain a JSON object, mapping input field names to string error messages you would like to display to the user. For example, if you have a field named `num_between_0_and_10`, you can enforce the user to enter a number between 0 and 10 by returning the following response body if the condition isn't satisfied: + +```json +{"errors": {"num_between_0_and_10": "Enter a number between 0 and 10."}} +``` + +The integration may also return a generic error message to the user that is not attached to a specific field. This can be done by responding to the dialog submission request with a JSON body containing an `error` field. The `error` field should contain a string with the error message to display to the user. For example, if a server-side error occurs, you can return a message explaining it: + +```json +{"error": "Failed to fetch additional data. Please try again."} +``` + +Support for generic error messages was added in Mattermost v5.18. + +Finally, once the request is submitted, we recommend that the integration responds with a system message or an ephemeral message confirming the submission. This should be a separate request back to Mattermost once the service has received and responded to a submission request from a dialog. This can be done either via [the REST API](https://api.mattermost.com/#tag/posts%2Fpaths%2F~1posts~1ephemeral%2Fpost), or via the [Plugin API](/developers/integrate/reference/server/server-reference#API.SendEphemeralPost) if you're developing a plugin. + +## Multi-step dialogs +##### Minimum Server Version: 11.1 + +Multi-step dialogs enable wizard-like form experiences where users progress through multiple steps to complete a complex workflow. Each step can have different fields, and form values are accumulated across steps. + +Multi-step behavior is achieved by having your submit handler return a new form instead of closing the dialog. No special dialog property is required. + +### Multi-step workflow + +1. **Initial dialog**: Open a normal dialog with the first step's elements. Use the `state` field to track which step you're on (e.g., `"step_1"`). +2. **Step submission**: When the user clicks Submit, your integration receives a standard `dialog_submission` request with `type: "dialog_submission"`. +3. **Return next step**: Instead of returning an empty response (which closes the dialog), return a response with `type: "form"` and a `form` object containing the next step's dialog definition. +4. **Value accumulation**: The client automatically accumulates submission values across steps. Each step's submission includes all values from previous steps plus the current step. +5. **Final submission**: On the last step, return an empty response (HTTP 200) or `{"type": "ok"}` to close the dialog. + +### Multi-step submission handling + +Each step submission uses the standard dialog submission format: + +```json +{ + "type": "dialog_submission", + "callback_id": "<callback ID>", + "state": "step_1", + "user_id": "<user ID>", + "channel_id": "<channel ID>", + "team_id": "<team ID>", + "submission": { + "step1_field": "value_from_step_1" + }, + "cancelled": false +} +``` + +To advance to the next step, your integration responds with a new form: + +```json +{ + "type": "form", + "form": { + "callback_id": "multistep_wizard", + "title": "Setup Wizard - Step 2 of 3", + "elements": [ + { + "display_name": "Step 2 Field", + "name": "step2_field", + "type": "text" + } + ], + "submit_label": "Next", + "state": "step_2" + } +} +``` + +On the final step, the submission includes accumulated values from all steps: + +```json +{ + "type": "dialog_submission", + "callback_id": "<callback ID>", + "state": "step_3", + "user_id": "<user ID>", + "channel_id": "<channel ID>", + "team_id": "<team ID>", + "submission": { + "step1_field": "value_from_step_1", + "step2_field": "value_from_step_2", + "step3_field": "value_from_step_3" + }, + "cancelled": false +} +``` + +Return an empty response (HTTP 200 with empty body) or `{"type": "ok"}` to close the dialog. + +### Multi-step example + +```json +{ + "trigger_id": "trigger_id_here", + "url": "https://your-integration.com/dialog", + "dialog": { + "callback_id": "multistep_wizard", + "title": "Setup Wizard - Step 1 of 3", + "introduction_text": "Welcome to the setup wizard", + "elements": [ + { + "display_name": "Project Name", + "name": "project_name", + "type": "text", + "placeholder": "Enter project name" + } + ], + "submit_label": "Next", + "state": "step_1" + } +} +``` + +## Dynamic field refresh +##### Minimum Server Version: 11.1 + +Interactive dialogs support dynamic field refresh functionality, allowing fields to be updated based on user input. This is useful for dependent dropdowns or conditional form fields. + +To enable field refresh, two things are required: +1. Set `refresh: true` on the **element** that should trigger refreshes when its value changes. +2. Set `source_url` on the **dialog** to specify where refresh requests are sent. + +When a user changes a select element that has `refresh: true`, Mattermost sends a request to the dialog's `source_url` via the `/api/v4/actions/dialogs/submit` endpoint. + +### Field refresh webhook + +The field refresh request uses the standard `SubmitDialogRequest` structure with `type` set to `"refresh"`: + +```json +{ + "type": "refresh", + "url": "<source_url>", + "callback_id": "<callback ID>", + "state": "<current state>", + "user_id": "<user ID>", + "channel_id": "<channel ID>", + "team_id": "<team ID>", + "submission": { + "category": "software", + "subcategory": "", + "selected_field": "category" + } +} +``` + +The `submission` map contains the current values of all form fields, plus a `selected_field` key indicating which field triggered the refresh. Cleared fields are sent as empty strings. + +Your integration should respond with a complete updated dialog wrapped in a `form` response: + +```json +{ + "type": "form", + "form": { + "callback_id": "dynamic_form", + "title": "Dynamic Form", + "source_url": "/plugins/your-plugin-id/refresh", + "elements": [ + { + "display_name": "Category", + "name": "category", + "type": "select", + "refresh": true, + "options": [ + {"text": "Software", "value": "software"}, + {"text": "Hardware", "value": "hardware"} + ] + }, + { + "display_name": "Subcategory", + "name": "subcategory", + "type": "select", + "options": [ + {"text": "Frontend", "value": "frontend"}, + {"text": "Backend", "value": "backend"} + ] + } + ], + "submit_label": "Submit", + "state": "step_1" + } +} +``` + +The response replaces the entire dialog with the new form definition. The client preserves the user's current field values where field names match. + +### Field refresh example + +```json +{ + "trigger_id": "trigger_id_here", + "url": "https://your-integration.com/dialog/submit", + "dialog": { + "callback_id": "dynamic_form", + "title": "Dynamic Form", + "source_url": "/plugins/your-plugin-id/refresh", + "elements": [ + { + "display_name": "Category", + "name": "category", + "type": "select", + "refresh": true, + "options": [ + {"text": "Software", "value": "software"}, + {"text": "Hardware", "value": "hardware"} + ] + }, + { + "display_name": "Subcategory", + "name": "subcategory", + "type": "select", + "options": [] + } + ], + "submit_label": "Submit", + "state": "step_1" + } +} +``` + + +<Note title="Note"> +If the dialog is closed by clicking **Cancel** or **X**, no data will be submitted. If a user clicks away from the dialog, the dialog won’t close. This is to prevent accidentally losing any answers they've made to an unsubmitted dialog. +</Note> + + +## Example + +Below is a full example of a JSON payload that creates an interactive dialog in Mattermost: + +```json +{ + "trigger_id":"nbt1dxzqwpn6by14sfs66ganhc", + "url":"http://localhost:5000/dialog_submit", + "dialog":{ + "callback_id":"somecallbackid", + "title":"Test Title", + "icon_url":"https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "elements":[ + { + "display_name":"Display Name", + "name":"realname", + "type":"text", + "subtype":"", + "default":"default text", + "placeholder":"placeholder", + "help_text":"This a regular input in an interactive dialog triggered by a test integration.", + "optional":false, + "min_length":0, + "max_length":0, + "data_source":"", + "options":null + }, + { + "display_name":"Email", + "name":"someemail", + "type":"text", + "subtype":"email", + "default":"", + "placeholder":"placeholder@bladekick.com", + "help_text":"This a regular email input in an interactive dialog triggered by a test integration.", + "optional":false, + "min_length":0, + "max_length":0, + "data_source":"", + "options":null + }, + { + "display_name":"Number", + "name":"somenumber", + "type":"text", + "subtype":"number", + "default":"", + "placeholder":"", + "help_text":"", + "optional":false, + "min_length":0, + "max_length":0, + "data_source":"", + "options":null + }, + { + "display_name":"Display Name Long Text Area", + "name":"realnametextarea", + "type":"textarea", + "subtype":"", + "default":"", + "placeholder":"placeholder", + "help_text":"", + "optional":true, + "min_length":5, + "max_length":100, + "data_source":"", + "options":null + }, + { + "display_name":"User Selector", + "name":"someuserselector", + "type":"select", + "subtype":"", + "default":"", + "placeholder":"Select a user...", + "help_text":"", + "optional":false, + "min_length":0, + "max_length":0, + "data_source":"users", + "options":null + }, + { + "display_name":"Channel Selector", + "name":"somechannelselector", + "type":"select", + "subtype":"", + "default":"", + "placeholder":"Select a channel...", + "help_text":"Choose a channel from the list.", + "optional":true, + "min_length":0, + "max_length":0, + "data_source":"channels", + "options":null + }, + { + "display_name":"Option Selector", + "name":"someoptionselector", + "type":"select", + "subtype":"", + "default":"", + "placeholder":"Select an option...", + "help_text":"", + "optional":false, + "min_length":0, + "max_length":0, + "data_source":"", + "options":[ + { + "text":"Option1", + "value":"opt1" + }, + { + "text":"Option2", + "value":"opt2" + }, + { + "text":"Option3", + "value":"opt3" + } + ] + }, + { + "display_name":"Multiple Option Selector", + "name":"somemultioptionselector", + "type":"select", + "multiselect":true, + "default":"opt1,opt3", + "placeholder":"Select multiple options...", + "help_text":"You can select multiple options from this list.", + "optional":true, + "data_source":"", + "options":[ + { + "text":"Option1", + "value":"opt1" + }, + { + "text":"Option2", + "value":"opt2" + }, + { + "text":"Option3", + "value":"opt3" + }, + { + "text":"Option4", + "value":"opt4" + } + ] + }, + { + "display_name":"Dynamic Lookup", + "name":"somedynamicfield", + "type":"select", + "data_source":"dynamic", + "data_source_url":"https://your-mattermost-server.com/plugins/your-plugin-id/api/lookup", + "placeholder":"Search for dynamic options...", + "help_text":"Type to search for options from external API", + "optional":true + }, + { + "display_name":"Event Date", + "name":"eventdate", + "type":"date", + "default":"today", + "placeholder":"Select event date", + "help_text":"Choose when your event takes place", + "datetime_config":{ + "min_date":"today", + "max_date":"+30d" + }, + "optional":false + }, + { + "display_name":"Meeting Time", + "name":"meetingtime", + "type":"datetime", + "default":"", + "placeholder":"Select meeting date and time", + "help_text":"Schedule your meeting with date and time", + "datetime_config":{ + "min_date":"today", + "max_date":"+14d", + "time_interval":30 + }, + "optional":true + } + ], + "submit_label":"Submit", + "notify_on_cancel":true, + "state":"somestate" + } +} +``` + +![image](interactive-dialog-complete-example.png) + +## Share your integration + +If you've built an integration for Mattermost, please consider [sharing your work](/developers/integrate/getting-started) in our [app directory](https://mattermost.com/marketplace/). + +The [app directory](https://mattermost.com/marketplace/) lists open source integrations developed by the Mattermost community and are available for download, customization and deployment to your private cloud or self-hosted infrastructure. + +## Slack compatibility + +Like Slack, dialogs are triggered by an interactive message menu or button, or by a custom slash command. Additionally, Mattermost can trigger dialogs via plugins. + +The schema for these objects is the same as Slack's, except for the following differences: + + - `url` field must be specified for Mattermost dialogs, which specifies where the request is sent to. In Slack, this is handled by specifying the URL within the Slack app that uses the dialog. + - `icon_url` is an optional field to set the icon for Mattermost dialogs. In Slack, the dialogs use the icon set for the app that uses the dialog. + - `label` in Slack dialogs is `display_name` in Mattermost dialogs for a more consistent naming convention with other integration types. + - `hint` in Slack dialogs is `help_text` in Mattermost dialogs for a more consistent naming convention with other integration types. + - `value` in Slack dialogs is `default` in Mattermost dialogs for a more consistent naming convention with other integration types. + +Moreover, the JSON payload for `select` type elements matches [interactive message menus](/developers/integrate/plugins/interactive-messages). diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-bool.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-bool.png new file mode 100644 index 000000000000..7f4d4b1f0c0c Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-bool.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-complete-example.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-complete-example.png new file mode 100644 index 000000000000..a0b7cf461d48 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-complete-example.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-error.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-error.png new file mode 100644 index 000000000000..fe73f33cbd50 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-error.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-example.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-example.png new file mode 100644 index 000000000000..71929860ee42 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-example.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-radio.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-radio.png new file mode 100644 index 000000000000..a519907ff7f8 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-radio.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select-menu.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select-menu.png new file mode 100644 index 000000000000..d3976235e801 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select-menu.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select.png new file mode 100644 index 000000000000..384bb2d8c3c7 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-select.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-text.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-text.png new file mode 100644 index 000000000000..f3c272a8111b Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-dialog-text.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive-messages.png b/docs/develop/integrate/plugins/interactive-dialogs/interactive-messages.png new file mode 100644 index 000000000000..db8e3b954678 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive-messages.png differ diff --git a/docs/develop/integrate/plugins/interactive-dialogs/interactive_message.gif b/docs/develop/integrate/plugins/interactive-dialogs/interactive_message.gif new file mode 100644 index 000000000000..946352bb38d9 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-dialogs/interactive_message.gif differ diff --git a/docs/develop/integrate/plugins/interactive-messages/action-button-error.png b/docs/develop/integrate/plugins/interactive-messages/action-button-error.png new file mode 100644 index 000000000000..684ff41f939e Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/action-button-error.png differ diff --git a/docs/develop/integrate/plugins/interactive-messages/index.md b/docs/develop/integrate/plugins/interactive-messages/index.md new file mode 100644 index 000000000000..fddd692dfd20 --- /dev/null +++ b/docs/develop/integrate/plugins/interactive-messages/index.md @@ -0,0 +1,473 @@ +--- +title: "Interactive messages" +sidebar_position: 80 +--- + +![image](interactive-messages.png) + +For information on interactive dialogs, [see here](/developers/integrate/plugins/interactive-dialogs). + +Use interactive messages to simplify complex workflows by allowing users to take quick actions directly through your integration post. For example, they enable your integration to: + +- Mark a task complete in your project management tracker. +- Conduct a customer survey or a poll. +- Initiate a command to merge a branch into a release. + +To try it out, you can use this [Matterpoll plugin](https://github.com/matterpoll/matterpoll) to add polling to Mattermost channels via a `/poll` slash command. + +![image](poll.png) + +## Message buttons + +Add message buttons as `actions` in your integration [message attachments](https://docs.mattermost.com/developer/message-attachments.html). + +The following payload gives an example that uses message buttons. + +```json +{ + "attachments": [ + { + "pretext": "This is the attachment pretext.", + "text": "This is the attachment text.", + "actions": [ + { + "id": "message", + "name": "Ephemeral Message", + "tooltip": "Send a message only visible to you", + "integration": { + "url": "http://127.0.0.1:7357", + "context": { + "action": "do_something_ephemeral" + } + } + }, { + "id": "update", + "name": "Update", + "tooltip": "Update this message", + "integration": { + "url": "http://127.0.0.1:7357", + "context": { + "action": "do_something_update" + } + } + } + ] + } + ] +} +``` + +In the HTTP response for this request, the integration can choose to update the original post, and/or respond with an ephemeral message: + +```json +{ + "update": { + "message": "Updated!", + "props": {} + }, + "ephemeral_text": "You updated the post!" +} +``` + +To return a custom error message to the user, your integration can respond with an error object: + +```json +{ + "error": { + "message": "Unable to complete action. Please check your permissions." + } +} +``` + +The error message will be displayed to the user below the message attachment. If no custom error message is provided, a default "Action failed to execute" message is shown. This feature is available in Mattermost v10.5 and later. + +![image](interactive_message.gif) + +Button actions support a style parameter to change the color of the button. The possible values for style are: `good`, `warning`, `danger`, `default`, `primary`, and `success`. It's also possible to pass a theme variable or a hex color, but we discourage this approach because it won't be resilient against theme changes. + +![image](interactive_button_style.png) + +The actions used in the previous example include the following: + +```json +[ + { + "id": "vote0", + "type": "button", + "name": "Yes", + "style": "default" + }, + { + "id": "vote1", + "type": "button", + "name": "No", + "style": "primary" + }, + { + "id": "addOption", + "type": "button", + "name": "Add Option", + "style": "warning" + }, + { + "id": "deletePoll", + "type": "button", + "name": "Delete Poll", + "style": "success" + }, + { + "id": "endPoll", + "type": "button", + "name": "End Poll", + "style": "danger" + } +] +``` + +### Tooltips on buttons + +You can add tooltips to provide helpful information when users hover over action buttons: + +```json +{ + "attachments": [ + { + "pretext": "Review this pull request", + "text": "Pull request #1234: Add new feature", + "actions": [ + { + "id": "approve", + "type": "button", + "name": "Approve", + "tooltip": "Click to approve this pull request", + "style": "primary", + "integration": { + "url": "http://127.0.0.1:7357", + "context": { + "action": "approve", + "pr_id": 1234 + } + } + }, + { + "id": "reject", + "type": "button", + "name": "Reject", + "tooltip": "Click to reject this pull request", + "style": "danger", + "integration": { + "url": "http://127.0.0.1:7357", + "context": { + "action": "reject", + "pr_id": 1234 + } + } + } + ] + } + ] +} +``` + +## Message menus + +Similar to buttons, add message menus as `actions` in your integration [message attachments](/developers/integrate/reference/message-attachments). + +![image](message-menus.png) + +The following payload gives an example that uses message menus (where id in the actions array may only consist of letters and numbers, no other characters are allowed): + +```json +{ + "attachments": [ + { + "pretext": "This is the attachment pretext.", + "text": "This is the attachment text.", + "actions": [ + { + "id": "actionoptions", + "name": "Select an option...", + "integration": { + "url": "http://127.0.0.1:7357/actionoptions", + "context": { + "action": "do_something" + } + }, + "type": "select", + "options": [ + { + "text": "Option1", + "value": "opt1" + }, + { + "text": "Option2", + "value": "opt2" + }, + { + "text": "Option3", + "value": "opt3" + } + ] + } + ] + } + ] +} +``` + +The integration can respond with an update to the original post, or with an ephemeral message: + +```json +{ + "update": { + "message": "Updated!", + "props": {} + }, + "ephemeral_text": "You updated the post!" +} +``` + +### Message menus for channels + +You can provide a list of channels for message menus for users to select from. Users can only select from public channels in their teams. + +Specify `channels` as your action's `data_source` as follows: + +```json +{ + "attachments": [ + { + "pretext": "This is the attachment pretext.", + "text": "This is the attachment text.", + "actions": [ + { + "id": "actionoptions", + "name": "Select an option...", + "integration": { + "url": "http://127.0.0.1:7357/actionoptions", + "context": { + "action": "do_something" + } + }, + "type": "select", + "data_source": "channels" + } + ] + } + ] +} +``` + +### Message menus for users + +Similar to channels, you can also provide a list of users for message menus. The user can choose the user who is part of the Mattermost system. + +Specify `users` as your action's `data_source` as follows: + +```json +{ + "attachments": [ + { + "id": "actionoptions", + "pretext": "This is the attachment pretext.", + "text": "This is the attachment text.", + "actions": [ + { + "name": "Select an option...", + "integration": { + "url": "http://127.0.0.1:7357/actionoptions", + "context": { + "action": "do_something" + } + }, + "type": "select", + "data_source": "users" + } + ] + } + ] +} +``` + +### Parameters + +Below is a brief description of each parameter to help you customize the interactive message button and menu in Mattermost. For more information on message attachments, [see our documentation](https://docs.mattermost.com/developer/message-attachments.html). + +**ID**<br/> +A per post unique identifier. + +**Name**<br/> +Give your action a descriptive name. + +**Tooltip** (optional)<br/> +Display helpful text when users hover over the button. Available in Mattermost v10.5 and later. + +**URL**<br/> +The actions are backed by an integration that handles HTTP POST requests when users select the message button. The URL parameter determines where this action is sent. The request contains an `application/json` JSON string. As of 5.14, relative URLs are accepted, simplifying the workflow when a plugin handles the action. + +**Context**<br/> +The requests sent to the specified URL contain the user ID, post ID, channel ID, team ID, and any context that was provided in the action definition. If the post was of type `Message Menus`, then context also contains the `selected_option` field with the user-selected option value. The post ID can be used to, for example, delete or edit the post after selecting a message button. + +A simple example of a request is given below: + +```json +{ + "user_id": "rd49ehbqyjytddasoownkuqrxe", + "post_id": "gqrnh3675jfxzftnjyjfe4udeh", + "channel_id": "j6j53p28k6urx15fpcgsr20psq", + "team_id": "5xxzt146eax4tul69409opqjlf", + "context": { + "action": "do_something" + } +} +``` + +In most cases, your integration will do one or both of these things: + + 1. **Identifying which action was triggered**. For example, a GitHub integration might store something like this in the context: + + ```json + { + "user_id": "rd49ehbqyjytddasoownkuqrxe", + "post_id": "gqrnh3675jfxzftnjyjfe4udeh", + "channel_id": "j6j53p28k6urx15fpcgsr20psq", + "team_id": "5xxzt146eax4tul69409opqjlf", + "context": { + "repo": "mattermost/mattermost", + "pr": 1234, + "action": "merge" + } + } + ``` + + In the example above, when the message button is selected, your integration sends a request to the specified URL with the intention to merge the pull request identified by the context. + + 2. **Authenticating the server**. An important property of the context parameter is that it's kept confidential. If your integration is not behind a firewall, you could add a token to your context without users ever being able to see it: + + ```json + { + "user_id": "rd49ehbqyjytddasoownkuqrxe", + "post_id": "gqrnh3675jfxzftnjyjfe4udeh", + "channel_id": "j6j53p28k6urx15fpcgsr20psq", + "team_id": "5xxzt146eax4tul69409opqjlf", + "context": { + "repo": "mattermost/mattermost", + "pr": 1234, + "action": "merge", + "token": "somerandomlygeneratedsecret" + } + } + ``` + + Then, when your integration receives the request, it can verify that the token matches one that you previously generated and know that the request is legitimately coming from the Mattermost server and is not forged. + + Depending on the application, integrations can also perform authentication statelessly with cryptographic signatures such as: + + ```json + { + "user_id": "rd49ehbqyjytddasoownkuqrxe", + "post_id": "gqrnh3675jfxzftnjyjfe4udeh", + "channel_id": "j6j53p28k6urx15fpcgsr20psq", + "team_id": "5xxzt146eax4tul69409opqjlf", + "context": { + "repo": "mattermost/mattermost", + "pr": 1234, + "action": "merge", + "signature": "mycryptographicsignature" + } + } + ``` + + It's also possible for integrations to do both of these things with a single token and use something like this as context: + + ```json + { + "user_id": "rd49ehbqyjytddasoownkuqrxe", + "post_id": "gqrnh3675jfxzftnjyjfe4udeh", + "channel_id": "j6j53p28k6urx15fpcgsr20psq", + "team_id": "5xxzt146eax4tul69409opqjlf", + "context": { + "action_id": "someunguessableactionid" + } + } + ``` + + Then, when the integration receives the request, it can act based on the action ID. + +## Error handling + +When an action button integration fails, Mattermost automatically displays an error message to the user below the message attachment. This provides immediate feedback when button actions don't work as expected. + +![image](action-button-error.png) + +**Key behaviors:** +- Integrations can return custom error messages using the error response format (see above) +- If no custom message is provided, a default "Action failed to execute" message is shown +- Previous errors are automatically cleared when a new action is triggered +- Error display works for both button and menu actions + +This feature is available in Mattermost v10.5 and later. + +**Automatic error display scenarios:** + +When your integration returns an error response with a custom message, that message is displayed to the user. For system-level errors where no custom message can be returned, a default error message is shown: + +- Network connection fails when contacting the integration URL +- Integration URL is invalid or unreachable +- Integration returns a non-200 HTTP status code +- Integration returns invalid JSON + +For troubleshooting integration errors from the server side, see the FAQ section "Why does an interactive button or menu return a 400 error?" below. + +## Tips and best practices + +1. The external application may be written in any programming language. It needs to provide a URL which receives the request sent by your Mattermost server and responds within the required JSON format. +2. To get started, you can use this [sample plugin](https://github.com/matterpoll/matterpoll) to add polling to Mattermost channels via a `/poll` slash command. + +## Share your integration + +If you've built an integration for Mattermost, please consider sharing your work in our [app directory](https://integrations.mattermost.com). + +The [app directory](https://integrations.mattermost.com) lists open source integrations developed by the Mattermost community and are available for download, customization, and deployment to your private cloud or self-hosted infrastructure. + +## Slack compatibility + +Like Slack, actions are specified in an **Actions** list within the message attachment. Moreover, your integrations can react with ephemeral messages or message updates similar to Slack. + +However, the schema for these objects is slightly different given Slack requires a Slack App and action URL to be pre-configured beforehand. Mattermost instead allows an integration to create an interactive message without pre-configuration. + +If your `ephemeral_text` gets incorrectly handled by the Slack-compatibility logic, send `"skip_slack_parsing":true` along your `ephemeral_text` to bypass it. + +```json +{ + "update": { + "message": "Updated!" + }, + "ephemeral_text": "You updated the post!", + "skip_slack_parsing": true +} +``` + +## Frequently asked questions + +### Are message buttons and menus supported in ephemeral messages? + +Yes, message buttons and menus are supported in ephemeral messages in Mattermost 5.10 and later. This applies to integrations using plugins, the RESTful API and webhooks, across the browser and Desktop App. + +As an advanced feature, you can also use plugins to update the contents of an ephemeral message with message buttons or menus with the [UpdateEphemeralMessage plugin API](/developers/integrate/reference/server/server-reference#API.UpdateEphemeralPost). + +### Why does an interactive button or menu return a 400 error? + +It is likely for one of three reasons: + +1. Mattermost wasn't able to connect to the integration. If the integration is on your internal infrastructure, it'll need to be whitelisted (see [AllowedUntrustedInternalConnections config.json setting](https://docs.mattermost.com/configure/configuration-settings.html#allow-untrusted-internal-connections-to)). The log will include the text `err=address forbidden` in the error message. +2. The integration didn't return HTTP status 200. The log will include the text `status=XXX` in the error message. +3. The integration didn't return a valid JSON response. The log will include the text `err=some json error message` in the error message. + +### How do I manage properties of an interactive message? + +Use `update.Props` in the following ways to manage properties (`Props`) of an interactive message after a user performs an action via an interactive button or menu: + + - `update.Props == nil` - Do not update `Props` field. + - `update.Props == {}` - Clear all properties, except the username and icon of the original message, as well as whether the message was pinned to channel or contained emoji reactions. + - `update.Props == some_props` - Post will be updated to `some_props`. Username and icon of the original message, and whether the message was pinned to channel or contained emoji reactions will not be updated. diff --git a/docs/develop/integrate/plugins/interactive-messages/interactive-messages.png b/docs/develop/integrate/plugins/interactive-messages/interactive-messages.png new file mode 100644 index 000000000000..db8e3b954678 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/interactive-messages.png differ diff --git a/docs/develop/integrate/plugins/interactive-messages/interactive_button_style.png b/docs/develop/integrate/plugins/interactive-messages/interactive_button_style.png new file mode 100644 index 000000000000..21cbd47493d7 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/interactive_button_style.png differ diff --git a/docs/develop/integrate/plugins/interactive-messages/interactive_message.gif b/docs/develop/integrate/plugins/interactive-messages/interactive_message.gif new file mode 100644 index 000000000000..946352bb38d9 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/interactive_message.gif differ diff --git a/docs/develop/integrate/plugins/interactive-messages/message-menus.png b/docs/develop/integrate/plugins/interactive-messages/message-menus.png new file mode 100644 index 000000000000..fdea56a860c7 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/message-menus.png differ diff --git a/docs/develop/integrate/plugins/interactive-messages/poll.gif b/docs/develop/integrate/plugins/interactive-messages/poll.gif new file mode 100644 index 000000000000..c226567d90c2 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/poll.gif differ diff --git a/docs/develop/integrate/plugins/interactive-messages/poll.png b/docs/develop/integrate/plugins/interactive-messages/poll.png new file mode 100644 index 000000000000..80784e6f9253 Binary files /dev/null and b/docs/develop/integrate/plugins/interactive-messages/poll.png differ diff --git a/docs/develop/integrate/plugins/manifest-reference.md b/docs/develop/integrate/plugins/manifest-reference.md new file mode 100644 index 000000000000..64a2ccf45eec --- /dev/null +++ b/docs/develop/integrate/plugins/manifest-reference.md @@ -0,0 +1,12 @@ +--- +title: "Manifest reference" +sidebar_position: 130 +--- + + +<Note title="Generated content (migrating)"> + +This section was rendered by the Hugo `pluginmanifestdocs` shortcode from the upstream plugin reference. Migration follow-up — see PLAN.md §11.2. + +</Note> + diff --git a/docs/develop/integrate/plugins/migration.md b/docs/develop/integrate/plugins/migration.md new file mode 100644 index 000000000000..ae1a19d713c4 --- /dev/null +++ b/docs/develop/integrate/plugins/migration.md @@ -0,0 +1,262 @@ +--- +title: "Migrate plugins" +sidebar_position: 60 +--- + +The plugin package exposed by Mattermost 5.6 and later drops support for automatically unmarshalling a plugin's configuration onto the struct embedding `MattermostPlugin`. As server plugins are inherently concurrent (hooks being called asynchronously) and the plugin configuration can change at any time, access to the configuration must be synchronized. + +Plugins compiled against 5.5 and earlier will continue to work without modification, automatically unmarshalling a plugin's configuration but with the existing risk of a corrupted read or write. Once the plugin is recompiled against Mattermost 5.6, it will be necessary to manually unmarshal your plugin's configuration. Client-only plugins and server plugins without public fields require no modifications. + +Note that you do not need to wait until Mattermost 5.6 to make these changes, as the hardened approach explained below will work with Mattermost 5.5 and earlier. Any implementation of `OnConfigurationChange` you define overrides the one automatically unmarshalling. + +### Server changes + +#### Unmarshalling configuration + +Previously, any public fields defined on the struct embedding `MattermostPlugin` would be automatically unmarshalled from the plugin's configuration: + +```go +type Plugin struct { + plugin.MattermostPlugin + + Greeting string +} + +func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello %s!", p.Greeting) +} +``` + +Writing to `Greeting` while the plugin may be concurrently reading from same could result in a corrupted read or write. The [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) and [mattermost-plugin-demo](https://github.com/mattermost/mattermost-plugin-demo) have both been updated with more complete examples, but the general idea is to manually handle the `OnConfigurationChange` hook and synchronize access to these variables. One such way is with a [sync.RWMutex](https://golang.org/pkg/sync/#RWMutex): + +```go +type Plugin struct { + plugin.MattermostPlugin + + greetingLock sync.Mutex + greeting string +} + +func (p *Plugin) OnConfigurationChange() error { + type configuration struct { + Greeting string + } + + // Load the public configuration fields from the Mattermost server configuration. + if err := p.API.LoadPluginConfiguration(configuration); err != nil { + return errors.Wrap(err, "failed to load plugin configuration") + } + + p.configurationLock.Lock() + defer p.configurationLock.Unlock() + p.greeting = configuration.Greeting + + return nil +} + +func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + p.configurationLock.RLock() + defer p.configurationLock.RUnlock() + + fmt.Fprintf(w, "Hello %s!", p.greeting) +} +``` + +Unfortunately, this adds a fair bit of extra complexity. You may wish to base your updated implementation off of [mattermost-plugin-starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) or [mattermost-plugin-demo](https://github.com/mattermost/mattermost-plugin-demo) to simplify your code. + +## Migrate plugins from Mattermost 5.1 and earlier + +Mattermost 5.2 introduces breaking changes to the plugins beta. This page documents the changes necessary to migrate your existing plugins to be compatible with Mattermost 5.2 and later. + +See [mattermost-plugin-zoom](https://github.com/mattermost/mattermost-plugin-zoom/compare/98eca6653e1a62c6b758e39b24d6ea075905c210...master) for an example migration involving both a server and web app component. + +### Server changes + +Although the underlying changes are significant, the required migration for server plugins is minimal. + +#### Entry point + +The plugin entry point was previously: + +```go +import "github.com/mattermost/server/public/plugin/rpcplugin" + +func main() { + rpcplugin.Main(&HelloWorldPlugin{}) +} +``` + +Change the imported package and invoke `ClientMain` instead: + +```go +import "github.com/mattermost/mattermost/server/public/plugin" + +func main() { + plugin.ClientMain(&HelloWorldPlugin{}) +} +``` + +#### Hook parameters + +Most hook callbacks now contain a leading `plugin.Context` parameter. Consult the [Hooks](/developers/integrate/reference/server/server-reference#Hooks) documentation for more details, but for example, the `ServeHTTP` hook was previously: + +```go +func (p *MyPlugin) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // ... +} +``` + +Change it to: + +```go +func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + // ... +} +``` + +#### API changes + +Most of the previous API calls remain available and unchanged, with the notable exception of removing the `KeyValueStore()`. Use [KVSet](/developers/integrate/reference/server/server-reference#API.KVSet), [KVGet](/developers/integrate/reference/server/server-reference#API.KVGet) and [KVDelete](/developers/integrate/reference/server/server-reference#API.KVDelete) instead test: + +```go +func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + key := r.URL.Query().Get("key") + switch r.Method { + case http.MethodGet: + value, _ := p.API.KVGet(key) + fmt.Fprintf(w, string(value)) + case http.MethodPut: + value := r.URL.Query().Get("value") + p.API.KVSet(key, []byte(value)) + case http.MethodDelete: + p.API.KVDelete(key) + } +} +``` + +Any standard error from your plugin will now be captured in the server logs, including output from the standard [log](https://golang.org/pkg/log/) package, but there are also explicit API methods for emitting structured logs: + +```go +func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + p.API.LogDebug("received http request", "user_agent", r.UserAgent()) + if r.Referer() == "" { + p.API.LogError("missing referer") + } +} +``` + +This would generate something like the following in your server logs: +```json +{"level":"debug","ts":1531494669.83655,"caller":"app/plugin_api.go:254","msg":"received http request","plugin_id":"my-plugin","user_agent":"HTTPie/0.9.9"} +{"level":"error","ts":1531494669.8368616,"caller":"app/plugin_api.go:260","msg":"missing referer","plugin_id":"my-plugin"} +``` + +### Web app changes + +The changes to web app plugins are more significant than server plugins. + +#### Entry point + +The plugin entry point was previously registered by directly manipulating a global variable: + +```js +window.plugins['my-plugin'] = new MyPlugin(); +``` + +Instead, use the globally exported `registerPlugin` method: + +```js +window.registerPlugin('my-plugin', new MyPlugin()); +``` + +#### Externalize dependencies + +The plugins beta suggested relying on the global export of common libraries from the web app: + +```js +const React = window.react; +``` + +While this remains supported, it is more natural to leverage Webpack [Externals](https://webpack.js.org/configuration/externals/). Configure this in your `.webpack.config.js`: + +```js +module.exports = { + // ... + externals: { + react: 'react', + }, + // ... +}; +``` + +and then import your modules naturally: + +```js +import React from 'react'; +``` + +Note however that the exported variables have changed to the following: + +| Prior to Mattermost 5.2 | Mattermost 5.2 | +|---------------------------|-----------------------| +| window.react | window.React | +| window['react-dom'] | window.ReactDom | +| window.redux | window.Redux | +| window['react-redux'] | window.ReactRedux | +| window['react-bootstrap'] | window.ReactBootstrap | +| window['post-utils'] | window.PostUtils | +| _N/A_ | window.PropTypes | + +#### Initialization + +The `initialize` callback used to receive a `registerComponents` callback to configure components, post types and main menu overrides: + +```js +import ChannelHeaderButton from './components/channel_header_button'; +import MobileChannelHeaderButton from './components/mobile_channel_header_button'; +import PostTypeZoom from './components/post_type_zoom'; +import {configureZoom} from './actions/zoom'; + +class MyPlugin { + initialize(registerComponents) { + registerComponents( + {ChannelHeaderButton, MobileChannelHeaderButton}, + {custom_zoom: PostTypeZoom}, + { + id: 'zoom-configuration', + text: 'Zoom Configuration', + action: configureZoom, + }, + ); + } +} +``` + +The `initialize` callback now receives an instance of the plugin [registry](/developers/integrate/reference/webapp/webapp-reference#registry). In some cases, the registry's API now requires a more discrete breakdown of the registered component to allow the web app to handle various rendering scenarios: + +```js +import ChannelHeaderButtonIcon from './components/channel_header_button/icon'; +import MobileChannelHeaderButton from './components/mobile_channel_header_button'; +import PostTypeZoom from './components/post_type_zoom'; +import {startZoomMeeting, configureZoom} from './actions/zoom'; + +class MyPlugin { + initialize(registry) { + registry.registerChannelHeaderButtonAction( + ChannelHeaderButtonIcon, + startZoomMeeting, + 'Start Zoom Meeting', + ); + + registry.registerPostTypeComponent('custom_zoom', PostTypeZoom); + + registry.registerMainMenuAction( + 'Zoom Configuration', + configureZoom, + MobileChannelHeaderButton, + ); + } +} +``` + +Restructuring your plugin to use the new registry API will likely prove to be the hardest part of migrating. diff --git a/docs/develop/integrate/plugins/overview.md b/docs/develop/integrate/plugins/overview.md new file mode 100644 index 000000000000..18b2a28e9a4c --- /dev/null +++ b/docs/develop/integrate/plugins/overview.md @@ -0,0 +1,36 @@ +--- +title: "Overview" +sidebar_position: 10 +--- + +Plugins are defined by a manifest file and contain at least a server or web app component, or both. + +The [Plugin Starter Template](https://github.com/mattermost/mattermost-plugin-starter-template) is a starting point and illustrates the different components of a Mattermost plugin. + +A more detailed example is the [Demo Plugin](https://github.com/mattermost/mattermost-plugin-demo), which showcases many of the features of plugins. + +If you'd like to better understand how plugins work, [see the contributor documentation on plugins](/developers/contribute/more-info/server/plugins). + +### Manifest +The plugin manifest provides required metadata about the plugin, such as name and ID. It is defined in JSON or YAML. This is `plugin.json` in both the [sample](https://github.com/mattermost/mattermost-plugin-starter-template/blob/master/plugin.json) and [demo](https://github.com/mattermost/mattermost-plugin-demo/blob/master/plugin.json) plugins. + +See the [manifest reference](/developers/integrate/plugins/manifest-reference) for more information. + +### Server +The server component of a plugin is written in Go and runs as a subprocess of the Mattermost server process. The Go code extends the [MattermostPlugin](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin#MattermostPlugin) struct that contains an [API](/developers/integrate/reference/server/server-reference#API) and allows for the implementation of [Hook](/developers/integrate/reference/server/server-reference#Hooks) methods that enable the plugin to interact with the Mattermost server. + +The sample plugin implements this simply in [plugin.go](https://github.com/mattermost/mattermost-plugin-starter-template/blob/master/server/plugin.go) and the demo plugin splits the API and hook usage throughout [multiple files](https://github.com/mattermost/mattermost-plugin-demo/tree/master/server). + +Read more about the server-side of plugins [here](/developers/integrate/plugins/components/server). + +### Web/desktop app +The web app component of a plugin is written in JavaScript with [React](https://react.dev/) and [Redux](https://redux.js.org/). The plugin's bundled JavaScript is included on the page and runs alongside the web app code as a [PluginClass](/developers/integrate/reference/webapp/webapp-reference#pluginclass) that has initialize and uninitialize methods available for implementation. The initialize function is passed through the [registry](/developers/integrate/reference/webapp/webapp-reference#registry) which allows the plugin to register React components, actions and hooks to modify and interact with the Mattermost web app. + +The sample plugin has a [shell of an implemented PluginClass](https://github.com/mattermost/mattermost-plugin-starter-template/blob/master/webapp/src/index.tsx), while the demo plugin [contains a more complete example](https://github.com/mattermost/mattermost-plugin-demo/blob/master/webapp/src/plugin.jsx). + +The desktop app is a shim of the web app, meaning any plugin that works in the web app will also work in the desktop app. + +Read more about the web app component of plugins [here](/developers/integrate/plugins/components/webapp). + +### Mobile app +Currently there is no mobile app component of plugins but it is planned for the near term. diff --git a/docs/develop/integrate/plugins/source-available-license.md b/docs/develop/integrate/plugins/source-available-license.md new file mode 100644 index 000000000000..00ffbe6a801b --- /dev/null +++ b/docs/develop/integrate/plugins/source-available-license.md @@ -0,0 +1,34 @@ +--- +title: "Source available license" +sidebar_position: 140 +--- + +Some plugins authored by Mattermost are licensed under the [Mattermost Source Available License](https://docs.mattermost.com/overview/faq.html#mattermost-source-available-license). This document outlines how to apply the license in various situations. + +## How do I apply the license to an enterprise-only plugin? + +An Enterprise-only plugin is a plugin that requires a valid Mattermost Enterprise E20 license. It is not designed to be used with Team Edition or any other Enterprise license. + +1. Add the [LICENSE](LICENSE) file to the root of your plugin repository. +2. Add the following section to your README.md directly below the opening paragraph: + + ```md + ## License + + This repository is licensed under the [Mattermost Source Available License](LICENSE) and requires a valid Enterprise E20 license. See [Mattermost Source Available License](https://docs.mattermost.com/overview/faq.html#mattermost-source-available-license) to learn more. + ``` + +## How do I apply the license to a mixed-license plugin? + +A mixed-license plugin includes components that require a valid Mattermost Enterprise E20 license. Not all features are available when used with Team Edition or any other enterprise license. + +1. Organize the Enterprise-only, server-side parts of your plugin in a dedicated folder, typically `server/enterprise`. +2. Add the [LICENSE](LICENSE) file to the `server/enterprise` folder. +3. Symlink that license in the root of your repository as `LICENSE.enterprise`. +4. Add the following section to your README.md directly below the opening paragraph: + + ```md + ## License + + This repository is licensed under the Apache 2.0 License, except for the [server/enterprise](server/enterprise) directory which is licensed under the [Mattermost Source Available License](LICENSE.enterprise). See [Mattermost Source Available License](https://docs.mattermost.com/overview/faq.html#mattermost-source-available-license) to learn more. + ``` diff --git a/docs/develop/integrate/plugins/source-available-license/LICENSE b/docs/develop/integrate/plugins/source-available-license/LICENSE new file mode 100644 index 000000000000..c698c02052e6 --- /dev/null +++ b/docs/develop/integrate/plugins/source-available-license/LICENSE @@ -0,0 +1,39 @@ +The Mattermost Source Available License license (the “Source Available License”) +Copyright (c) 2015-present Mattermost + +With regard to the Mattermost Software: + +This software and associated documentation files (the "Software") may only be +used in production, if you (and any entity that you represent) have agreed to, +and are in compliance with, the Mattermost Terms of Service, available at +https://mattermost.com/enterprise-edition-terms/ (the “EE Terms”), or other +agreement governing the use of the Software, as agreed by you and Mattermost, +and otherwise have a valid Mattermost Enterprise E20 subscription for the +correct number of user seats. Subject to the foregoing sentence, you are free +to modify this Software and publish patches to the Software. You agree that +Mattermost and/or its licensors (as applicable) retain all right, title and +interest in and to all such modifications and/or patches, and all such +modifications and/or patches may only be used, copied, modified, displayed, +distributed, or otherwise exploited with a valid Mattermost Enterprise E20 +Edition subscription for the correct number of user seats. Notwithstanding +the foregoing, you may copy and modify the Software for development and testing +purposes, without requiring a subscription. You agree that Mattermost and/or +its licensors (as applicable) retain all right, title and interest in and to +all such modifications. You are not granted any other rights beyond what is +expressly stated herein. Subject to the foregoing, it is forbidden to copy, +merge, publish, distribute, sublicense, and/or sell the Software. + +The full text of this EE License shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +For all third party components incorporated into the Mattermost Software, those +components are licensed under the original license provided by the owner of the +applicable component. diff --git a/docs/develop/integrate/plugins/using-and-managing-plugins.md b/docs/develop/integrate/plugins/using-and-managing-plugins.md new file mode 100644 index 000000000000..33d12f6ec21b --- /dev/null +++ b/docs/develop/integrate/plugins/using-and-managing-plugins.md @@ -0,0 +1,290 @@ +--- +title: "Use and manage plugins" +sidebar_position: 50 +--- + +See our [demo plugin](https://github.com/mattermost/mattermost-plugin-demo) that illustrates the potential for a Mattermost plugin. To start writing your own plugin, consult our [starter template](https://github.com/mattermost/mattermost-plugin-starter-template). + +Consider using a plugin in the following scenarios: + + - When you want to customize the Mattermost user interface. + - When you want to extend Mattermost functionality to meet a specific, complex requirement. + - When you want to build integrations that are managed by your Mattermost server. + +Plugins are fully supported in both Team Edition and Enterprise Edition. + +## Marketplace + +The Marketplace is a collection of plugins that can greatly increase the value and capabilities of your Mattermost deployment. End users can see increased productivity through quick access to systems such as Jira, Zoom, Webex, and GitHub. Mattermost System Admins can discover new plugins and quickly deploy them to their servers, including High Availability clusters. + +The Marketplace is available from v5.16 and is accessed via **Product menu > Marketplace**. More listings will be added as we add new features and plugins that our customers request. + +### Plugin labels + +Plugins in the Marketplace are labeled to make it easier for administrators to choose plugins that fit their company's security and risk policies if they do not allow for community plugins to be used. + +**Community plugins** + +Plugins identified as "Community" are produced by the open-source community or partners and the features/roadmap are not controlled directly by Mattermost. Prior to being listed on the Marketplace, they are reviewed by the Mattermost development team and code-signed to ensure the code Mattermost reviewed, is delivered. Mattermost does not directly support these plugins in production environments. + +**Beta plugins** + +Plugins may be labeled as "Beta" if they're released to the Marketplace early for customer previews. We do not recommend running beta plugins on production servers. + +**Experimental** + +Plugins labeled as "Experimental" are still being tested. These should not be run on production servers. + +**Partner** + +Plugins identified as "Partner" are created and maintained by a Mattermost partner. + +### Install a plugin + +When a new plugin becomes available on the Marketplace, it's listed with an option to **Install**. Select **Install** to download and install the latest plugin binary from its respective GitHub repository. If there's a cluster present, the plugin will be distributed to each server automatically. + +### Configure and enable a plugin + +Once a plugin is installed (or pre-installed if shipped with Mattermost binary release): + +1. Select **Configure > Settings**. +2. Enter the plugin settings as required. +3. Set **Enable Plugin** setting to **True**. If this flag is not enabled, the plugin will not become active. +4. Test out the plugin as needed. + +### Upgrade plugins + +Upgrade a plugin on demand when a new version becomes available. New versions of plugins that you have already installed will display a link to easily install the upgraded plugins. Some plugin versions may have breaking changes; please check the release notes if you're performing a major version change. + +### Upgrade plugins (prior to v5.18) + +In v5.16 and v5.17 the Marketplace only supports the installation of new plugins. To upgrade a plugin, you need to manually update it by downloading the binary file from the GitHub repository and then upload it in **System Console > Plugin Management**. + +## Marketplace server + +There are two settings in **System Console > Plugin Management**: + +![](https://user-images.githubusercontent.com/915956/66892854-94660d80-efa1-11e9-805c-a85223d43a07.png) + +- **Enable Marketplace:** Turns the Marketplace user interface on or off for System Admins (end users cannot see the Marketplace). +- **Marketplace URL:** The location of the Marketplace server to query for new plugins. Mattermost hosts a Marketplace for the community and this is the default value for this field. You can also set up your own Marketplace server. + +When you first access the Marketplace, your Mattermost server will attempt to contact the Mattermost Marketplace server and return a list of available plugins that are appropriate based on the server version that is currently running. Only your server version and search query is passed over to the Mattermost Marketplace; we retain an anonymized record for product analytics whenever a new plugin is installed, unless you have opted out of [Telemetry](https://docs.mattermost.com/manage/telemetry.html). + +The [Marketplace server code](https://github.com/mattermost/mattermost-marketplace) is available as an open source project and can be used to set up your own private Marketplace if desired. + +### Mattermost Marketplace + +The [Mattermost Marketplace](https://github.com/mattermost/mattermost-marketplace) is a service run by Mattermost that contains listings of plugins that we have reviewed and, in many cases, built. In the future, we plan to include community-developed plugins that will be labeled separately to Mattermost-developed plugins. as well as settings that would restrict which types of plugins you can install. Comments in our forum are welcome as we develop this feature further. + +## Mattermost integration directory + +There are many ways to integrate Mattermost aside from plugins, and we have created a directory of integration "recipes", some of which are scripts, plugins, or instructions on how to connect Mattermost with your Enterprise systems. Many are sourced from our community of customers. You can browse the directory at [https://integrations.mattermost.com](https://integrations.mattermost.com). + +## About plugins + +Plugins may have one or both of the following parts: + + - **Web App plugins:** Customize the Mattermost user interface by adding buttons to the channel header, overriding the `RHS`, or even rendering a custom post type within the center channel. All this is possible without having to fork the source code and rebase on every Mattermost release. For a sample plugin, see [our Zoom plugin](https://github.com/mattermost/mattermost-plugin-zoom). + - **Server plugins:** Run a Go process alongside the server, filtering messages, or integrating with third-party systems such as Jira, GitLab, or Jenkins. For a sample plugin, see [our Jira plugin](https://github.com/mattermost/mattermost-plugin-jira). + +## Security + +Plugins are intentionally powerful and not artificially sandboxed in any way and effectively become part of the Mattermost server. Server plugins can execute arbitrary code alongside your server and webapp plugins can deploy arbitrary code in client browsers. + +While this power enables deep customization and integration, it can be abused in the wrong hands. Plugins have full access to your server configuration and thus also to your Mattermost database. Plugins can read any message in any channel, or perform any action on behalf of any user in the Web App. + +You should only install custom plugins from sources you trust to avoid compromising the security of your installation. + +## Plugin signing + +The Marketplace allows System Admins to download and install plugins from a central repository. Plugins installed via the Marketplace must be signed by a public key certificate trusted by the local Mattermost server. + +While the server ships with a default certificate used to verify plugins from the default Mattermost Marketplace, the server can be configured to trust different certificates and point at a different plugin marketplace. This document outlines the steps for generating a public key certificate and signing plugins for use with a custom plugin marketplace. It assumes access to the [GNU Privacy Guard (GPG)](https://gnupg.org) tool. + +### Configuration + +Configuring plugin signatures allows finer control over the verification process: + +`PluginSettings.RequirePluginSignature = true` + +This is used to enforce plugin signature verification. With flag on, only Marketplace plugins will be installed and verified. With flag off, customers will be able to install plugins manually without signature verification. + +Note that the Marketplace plugins will still be verified even if the flag is off. + +### Key generation + +Public and private key pairs are needed to sign and verify plugins. The private key is used for signing and should be kept in a secure location. The public key is used for verification and can be distributed freely. To generate a key pair, run the following command: + +``` + gpg --full-generate-key + + Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) + Your selection? 1 + + RSA keys may be between 1024 and 4096 bits long. + What keysize do you want? (2048) 3072 + + Requested keysize is 3072 bits + + Please specify how long the key should be valid. + 0 = key does not expire + <n> = key expires in n days + <n>w = key expires in n weeks + <n>m = key expires in n months + <n>y = key expires in n years + Key is valid for? (0) 0 + + Key expires at ... + + Is this correct? (y/N) y + + GnuPG needs to construct a user ID to identify your key. + Real name: Mattermost Inc + + Email address: info@mattermost.com + Comment: + + You selected this USER-ID: + "Mattermost Inc <info@mattermost.com>" + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O +``` + +Key size should be at least 3072 bits. + +### Export the private key + +Find the ID of your private key first. The ID is a hexadecimal number. + +`gpg --list-secret-keys` + +This is your private key and should be kept secret. Your hexadecimal key ID will, of course, be different. + +`gpg --export-secret-keys F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F > ./my-priv-key` + +### Export the public key + +Find the ID of your public key first. The ID is a hexadecimal number. + +`gpg --list-keys` + +`gpg --export F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F > ./my-pub-key` + +### Importing the key + +If you already have a public and private key pair, you can import them to the GPG. + +`gpg --import ./my-priv-gpg-key` +`gpg --import ./my-pub-gpg-key` + +## Sign the plugin + +For plugin signing, you have to know the hexadecimal ID of the private key. Let's assume you want to sign `com.mattermost.demo-plugin-0.1.0.tar.gz` file, run: + +`gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign com.mattermost.demo-plugin-0.1.0.tar.gz` + +This command will generate `com.mattermost.demo-plugin-0.1.0.tar.gz.sig`, which is the signature of your plugin. + +## Plugin verification + +Mattermost server will verify plugin signatures downloaded from the Marketplace. To add custom public keys, run the following command on the Mattermost server: + +`mattermost plugin add key my-pub-key` + +Multiple public keys can be added to the Mattermost server: + +`mattermost plugin add key my-pk-file1 my-pk-file2` + +To list the names of all public keys installed on your Mattermost server, use: + +`mattermost plugin keys` + +To delete public key(s) from your Mattermost server, use: + +`mattermost plugin delete key my-pk-file1 my-pk-file2` + +### Implementation + +See the [implementation document](https://docs.google.com/document/d/1qABE7VEx4k_ZAeh6Ydn4pGbu6BQfZt65x68i2s65MOQ) for more information. + +## Set up guide + +To manage plugins, go to **System Console > Plugins > Plugin Management**. From here, you can: + + - Enable or disable pre-packaged plugins. + - Install and manage custom plugins. + +### Pre-packaged plugins + +Mattermost ships with a number of pre-packaged plugins written and maintained by Mattermost. Instead of building these features directly into the product, you can selectively enable the functionality your installation requires. Install pre-packaged plugins from the Marketplace, even if your system cannot directly connect to the internet. + +Prior to v5.20, pre-packaged plugins were installed by default and could not be uninstalled without manually modifying the `prepackaged_plugins` directory. Any pre-packaged plugins installed prior to v5.20 and left enabled on upgrade will remain installed, but can now be uninstalled. + +### Custom plugins + +Installing a custom plugin introduces some risks. As a result, plugin uploads are disabled by default and cannot be enabled via the System Console or REST API. + +To enable plugin uploads, manually set `PluginSettings > EnableUploads` to `true` in your `config.json` file and restart your server. + +If you have installed Mattermost Omnibus, to enable plugin uploads, manually set `enable_plugin_uploads:` true in the `mmomni.yml` file and restart your server. + +You can disable plugin uploads at any time without affecting previously uploaded plugins. + +With plugin uploads enabled, navigate to **System Console > Plugins > Management** and upload a plugin bundle. Plugin bundles are `*.tar.gz` files containing the server executables and web app resources for the plugin. You can also specify a URL to install a plugin bundle from a remote source. + + +<Note title="Note"> +1. When `RequirePluginSignature` is `true`, plugin uploads cannot be enabled, and may only be installed via the Marketplace (which verifies Plugin Code Signatures). +2. `EnableRemoteMarketplaceURL` also remains disabled as long as `EnableUploads` is disabled. +</Note> + + +Custom plugins may also be installed via the [command line interface](https://docs.mattermost.com/administration/command-line-tools.html#mattermost-plugin). + +While no longer recommended, plugins may also be installed manually by unpacking the plugin bundle inside the `plugins` directory of a Mattermost installation. + +### Plugin uploads in high availability mode + +Prior to Mattermost 5.14, Mattermost servers configured for [High Availability mode](https://docs.mattermost.com/deployment/cluster.html) required plugins to be installed manually. As of Mattermost 5.14, plugins uploaded via the System Console or the CLI are persisted to the configured file store and automatically installed on all servers that join the cluster. + +Manually installed plugins remain supported, but must be individually installed on each server in the cluster. + +## Frequently asked questions + +### Where can I share feedback on plugins? + +Join our community server discussion in the [Toolkit channel](https://community.mattermost.com/core/channels/developer-toolkit). + +## Troubleshooting + +Please see common questions below. For further assistance, review the [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot) for previously reported errors, or [join the Mattermost user community for troubleshooting help](https://mattermost.com/pl/default-ask-mattermost-community). + +### Plugin uploads fail even though uploads are enabled + +If plugin uploads fail and you see `permission denied` errors in **System Console > Logs** such as: + +`[2017/11/13 20:42:18 UTC] [EROR] failed to start up plugins: mkdir /home/ubuntu/mattermost/client/plugins: permission denied` + +It's likely that the Mattermost server doesn't have the necessary permissions for uploading plugins. Ensure the Mattermost server has write access to the `mattermost/client` directory. + +It may also be that the working directory for the service running Mattermost is not correct. On Ubuntu you might see: + +`[2018/01/03 08:34:47 EST] [EROR] failed to start up plugins: mkdir ./client/plugins: no such file or directory` + +This can be fixed on Ubuntu 16.04 and RHEL by opening the service configuration file and setting `WorkingDirectory` to the path to Mattermost (generally it's `/opt/mattermost`). + +A similar problem can occur on Windows: + +`[EROR] failed to start up plugins: mkdir ./client/plugins: The system cannot find the path specified.` + +To fix this, set the `AppDirectory` of your service using `nssm set mattermost AppDirectory c:\mattermost`. + +### `x509: certificate signed by unknown authority` + +If you're seeing `x509: certificate signed by unknown authority` in your server logs, it usually means that the CA for a self-signed certificate for a server your plugin is trying to access has not been added to your local trust store of the machine the Mattermost server is running on. + +You can add one in Linux [following instructions in this StackExchange article](https://unix.stackexchange.com/questions/90450/adding-a-self-signed-certificate-to-the-trusted-list), or set up a load balancer like NGINX per [production install guide](https://docs.mattermost.com/config-ssl-http2-nginx.html) to resolve the issue. diff --git a/docs/develop/integrate/reference/bot-accounts/index.md b/docs/develop/integrate/reference/bot-accounts/index.md new file mode 100644 index 000000000000..d12d34114e25 --- /dev/null +++ b/docs/develop/integrate/reference/bot-accounts/index.md @@ -0,0 +1,187 @@ +--- +title: "Bot accounts" +sidebar_position: 30 +--- + +Bot accounts access the Mattermost [RESTful API](https://api.mattermost.com) on behalf of a bot through the use of the [personal access tokens feature](/developers/integrate/reference/personal-access-token). Bot accounts are just like user accounts, except they: + + - Can't be logged into. + - Can't be used to create other bot accounts. + - Can't be used to upload files to a channel, unless they are also added to the channel as a channel member. + - Don't count as a registered user and therefore don't count towards the total number of users for an Enterprise Edition license. + +Additional benefits include: + + - System Admins can enable bot accounts to post to any channel in the system, including private teams, Private channels, or Direct Messages. + - Integrations created by a user and tied to a bot account no longer break if the user leaves the company. + - Once created, bot accounts behave just like regular user accounts and can be added to teams and channels similar to users. + - Bot accounts are a safer way to integrate with Mattermost through the RESTful API and Plugin API because there is no need to manage shared logins with these accounts. + - A `BOT` tag is used throughout Mattermost where bot accounts are referenced, including messages and user lists. + +Note that currently: + + - Only System Admins or plugins can create or manage bot accounts. + - In Mattermost Enterprise Edition, service accounts without an email address pulled from LDAP or SAML systems are not yet supported. + +If you would like to see improvements to bot accounts, [let us know in the Feature Proposal Forum](https://mattermost.uservoice.com). + +## Configuration settings + +By default, plugins can create and manage bot accounts. To enable bot account creation through the user interface or the RESTful API: + +1. Go to **System Console > Integrations > Bot Accounts**. +2. Set **Enable Bot Account Creation** to **true**. + +Once set, System Admin can create bot accounts for integrations using the **Integrations > Bot Accounts** link in the description provided. + +## Bot account creation + +Below are different ways to create bot accounts. After the bot account is created, make sure to: + +1. Copy the generated bot access token for your integration. +2. To add the bot account to teams and channels you want it to interact in, select the team drop-down menu, then select **Invite People**. Next, select **Invite Member** and enter the bot account in the **Add or Invite People** field. Then select **Invite Members**. You should now be able to add the bot account to channels like any other user. + +### User interface (UI) + +1. Go to the Product menu and select **Integrations > Bot Accounts**. +2. Select **Add Bot Account**. +3. Set the **Username** of the bot. The username must begin with a letter, and contain between 3 and 22 lowercase characters made up of numbers, letters, and symbols including ".", "-", or "\_". +4. (Optional) Upload an image for the **Bot Icon**. This will be used as the profile image of the bot throughout Mattermost. +5. (Optional) Set a **Display Name** and **Description**. +6. (Optional) Choose what role the bot should have. Defaults to **Member**. If you assign **System Admin**, the bot will have read and write access for any Public channels, Private channels, and Direct Messages. +7. (Optional) Select additional permissions for the account. Enable the bot to post to all Mattermost channels, or post to all Mattermost Public channels. +8. Select **Create Bot Account**. +9. Copy the token displayed on the **Setup Successful** page before you select **Done** as you won't have access to the token again once you close the screen. + +### RESTful API + +Use the RESTful API `POST /bots` to create a bot. You must have permissions to create bots. + +See our [API documentation](https://api.mattermost.com/#tag/bots) to learn more about creating and managing bots through the API. + +To authorize your bot via RESTful API use `curl -i -H 'authorization: Bearer <Access Token>' http://localhost:8065/api/v4/users/me`. **Access Token** is not the `Token ID` and won't be visible again once created. + +### Command line interface (CLI) + +You can use the following CLI command to convert an existing user account to a bot: + +```shell +user convert user@example.com --bot +``` + +In addition to email, you can identify the user by its username or user ID. + +Bot accounts which were converted from user accounts will have their authentication data cleared if they were email/password accounts. Those synchronized from LDAP/SAML will not have their authentication data cleared so that LDAP/SAML synchronization performs correctly. + +### Plugins + +Plugins can create bot accounts through an `EnsureBot` helper function. For an example, see [the Demo Plugin](https://github.com/mattermost/mattermost-plugin-demo/blob/master/server/configuration.go#L210-L217). + +Bots created by a plugin use the plugin's ID as the creator, unless otherwise specified by the plugin. + +## Technical notes + +### Data model + +Each bot account has a row in the **Users** table and the **Bots** table. The entries are tied together by `User.Id = Bot.UserId`. + +The Bots table schema is described as follows: + +| Field | Description | Type | Required | +|-------------|---------------------------------|--------|----------| +| UserId | User ID of the bot user | string | Y | +| Username | Username of the bot account | string | Y | +| DisplayName | Display name of the bot account | string | N | +| Description | Description of the bot account | string | N | +| OwnerId | User ID of the owner of the bot | string | Y | +| CreateAt | Unix timestamp of creation time | int64 | Y | +| UpdateAt | Unix timestamp of update time | int64 | Y | +| DeleteAt | Unix timestamp of deletion time | int64 | Y | + +## Frequently asked questions + +### Should I migrate all my integrations to use bot accounts? + +For your integrations using RESTful API and plugins, yes. To do so, you can either convert an existing account to a bot, or create a new bot account using the steps outlined above. + +Once you create a bot account, use the generated token to access the RESTful API on behalf of a bot and interact in the Mattermost server. + +For your webhook and slash command integrations, you cannot migrate them to use bot accounts, as they require a user account at this time. However, an option is to migrate the webhooks or slash commands to a plugin, which in turn can use bot accounts. + +### What happens if a plugin is using a bot account that already exists as a user account? + +For a concrete example, suppose you enable the [Mattermost GitHub plugin](https://github.com/mattermost/mattermost-plugin-github), which uses a `github` bot account, while an existing `github` user account was created for webhook integrations. + +Once the plugin is enabled, the plugin posts as the `github` account but without a `BOT` tag. An error message is logged to the server logs recommending the System Admin to convert the `github` user to a bot account by running `mattermost user convert <username> --bot` in the CLI. + +If the user is an existing user account you want to preserve, change its username and restart the Mattermost server, after which the plugin will create a bot account with the name `github`. + +### How do I convert an existing account to a bot account? + +Use the following CLI command to convert an existing user account to a bot: + +`user convert user@example.com --bot` + +In addition to email, you may identify the user by its username or user ID. + +Bot accounts which were converted from user accounts will have their authentication data cleared if they were email/password accounts. Those synchronized from LDAP/SAML will not have their authentication data cleared so that LDAP/SAML synchronization performs correctly. + +### How can I quickly test if my bot account is working? + +Add the bot to a team and channel you belong to, then use the following curl command to post with the bot: + +`curl -i -X POST -H 'Content-Type: application/json' -d '{"channel_id":"<channel-id>", "message":"This is a message from a bot", "props":{"attachments": [{"pretext": "Look some text","text": "This is text"}]}}' -H 'Authorization: Bearer <bot-access-token>' <mattermost-url>/api/v4/posts` + +Replace the following parameters: + +- `<channel-id>` with the channel you added the bot to +- `<bot-access-token>` with the bot access token generated when you created the bot account +- `<mattermost-url>` with your Mattermost domain, e.g. ``https://example.mattermost.com`` + +### Do bot access tokens expire? + +No, but you can automate your integration to cycle its token through the REST API: +1. Use [GetUserAccessTokensForUser](https://api.mattermost.com/#operation/GetUserAccessTokensForUser) to list the existing tokens for the `bot` user. +2. Use [CreateUserAccessToken](https://api.mattermost.com/#operation/CreateUserAccessToken) to generate a new token. +3. Update the services that leverage the token with the new `token` value from step 1. +4. Use [RevokeUserAccessToken](https://api.mattermost.com/#operation/RevokeUserAccessToken) to revoke the old token based on the `token_id`. + +For more information about access tokens, see [the personal access tokens documentation](/developers/integrate/reference/personal-access-token). + +### Do bot accounts make it easier to impersonate someone else such as the CEO or an HR coordinator? + +Possibly yes. Currently a System Admin can disable overriding the profile picture and the username from integrations to help prevent impersonation, but this is not the case for bot accounts. + +Mitigations: + +- `BOT` tag is used everywhere in the UI where bot accounts are referenced, including messages and user lists. +- For Direct Message channels, the channel header distinguishes the bot from a regular user account with a `BOT` tag. + +### What happens when a user who owns bot accounts is disabled? + +By default, bot accounts managed by the deactivated user are disabled for enhanced security. Those with permissions to manage bot accounts can re-enable them via the **Product menu > Integrations > Bot Accounts**. + +We strongly recommend creating new tokens for the bot, to ensure the user who was deactivated no longer has access to read or write data in the system via the bot access token. + +If you prefer to have bot accounts remain enabled after user deactivation, set `DisableBotsWhenOwnerIsDeactivated` to `false` in your `config.json` file. + +### Can bot accounts edit messages through the RESTful API? + +Yes. By default, bot accounts can update their own posts. + +If you find yourself unable to edit posts as a bot, check the following: + +1. Instead of using a slash command to respond directly, use an an API call for the initial interaction with a user to enable message edits. +2. If your system is using [advanced permissions](https://docs.mattermost.com/onboard/advanced-permissions.html), then post edits could be disabled for users. + +If neither of the above help resolve your issue, you also have the option to choose what role the bot account has. If System Admin is chosen, then the bot can update any posts in the system. Note that giving the System Admin role to a bot account enables the bot with other System Admin privileges so this should be done with care. + +### If AD/LDAP or SAML synchronization is enabled, do bot accounts need to have an associated email address in AD/LDAP or SAML? + +When AD/LDAP or SAML synchronization is enabled, you can create bot accounts using the steps outlined above. These bot accounts won't require an email address. + +If you need to sync service accounts from AD/LDAP or SAML to Mattermost and use them as bot accounts, [please reach out to us](https://mattermost.com/contact-us) to discuss in detail. You may not need to sync service accounts and use them as bot accounts to meet your use case. + +### How are bot accounts identified in compliance exports? + +As of v5.14, a field named `UserType` is added to Compliance Exports, including Global Relay, Actiance, and CSV. The field identifies whether a message was posted by a `user` or by a `bot` account. diff --git a/docs/develop/integrate/reference/index.md b/docs/develop/integrate/reference/index.md new file mode 100644 index 000000000000..b0e7e3c2848c --- /dev/null +++ b/docs/develop/integrate/reference/index.md @@ -0,0 +1,6 @@ +--- +title: "Quick reference" +sidebar_position: 90 +--- + +This reference section contains information on integrating plugins with Mattermost, including Server SDK, Web App SDK, and REST API references. diff --git a/docs/develop/integrate/reference/message-attachments/attachments-author.png b/docs/develop/integrate/reference/message-attachments/attachments-author.png new file mode 100644 index 000000000000..740080b6854c Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-author.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-color.png b/docs/develop/integrate/reference/message-attachments/attachments-color.png new file mode 100644 index 000000000000..5dea1019ab59 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-color.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-example.png b/docs/develop/integrate/reference/message-attachments/attachments-example.png new file mode 100644 index 000000000000..cc140111c9c7 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-example.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-fields.png b/docs/develop/integrate/reference/message-attachments/attachments-fields.png new file mode 100644 index 000000000000..beeb401fb50d Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-fields.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-footer.png b/docs/develop/integrate/reference/message-attachments/attachments-footer.png new file mode 100644 index 000000000000..47ff7bc4cf98 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-footer.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-image.png b/docs/develop/integrate/reference/message-attachments/attachments-image.png new file mode 100644 index 000000000000..d81c1ea691f1 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-image.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-pretext.png b/docs/develop/integrate/reference/message-attachments/attachments-pretext.png new file mode 100644 index 000000000000..968f42bdc02a Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-pretext.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-text.png b/docs/develop/integrate/reference/message-attachments/attachments-text.png new file mode 100644 index 000000000000..40b85d561c86 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-text.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-thumb.png b/docs/develop/integrate/reference/message-attachments/attachments-thumb.png new file mode 100644 index 000000000000..64bc8aea46a9 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-thumb.png differ diff --git a/docs/develop/integrate/reference/message-attachments/attachments-titles.png b/docs/develop/integrate/reference/message-attachments/attachments-titles.png new file mode 100644 index 000000000000..1c16521dfc04 Binary files /dev/null and b/docs/develop/integrate/reference/message-attachments/attachments-titles.png differ diff --git a/docs/develop/integrate/reference/message-attachments/index.md b/docs/develop/integrate/reference/message-attachments/index.md new file mode 100644 index 000000000000..912daa9ac484 --- /dev/null +++ b/docs/develop/integrate/reference/message-attachments/index.md @@ -0,0 +1,174 @@ +--- +title: "Message attachments" +sidebar_position: 40 +--- + +For additional formatting options, and for compatibility with Slack non-markdown integrations, an `attachments` array can be sent by integrations and rendered by Mattermost. + +You can also add interactive message buttons as part of attachments. They help make your integrations richer by completing common tasks inside Mattermost conversations, increasing user engagement and productivity. For more information, see [documentation](/developers/integrate/plugins/interactive-messages). + +## Attachment options + +When sending an attachment, you can use any of the following to format how you want the posted message to look. + +`fallback`: A required plain-text summary of the attachment. This is used in notifications, and in clients that don’t support formatted text (e.g. IRC). + +`color`: A hex color code that will be used as the left border color for the attachment. If not specified, it will default to match the channel sidebar header background color. + +![image](attachments-color.png) + +`pretext`: An optional line of text that will be shown above the attachment. Supports @mentions. + +![image](attachments-pretext.png) + +`text`: The text to be included in the attachment. It can be formatted using [Markdown](https://docs.mattermost.com/help/messaging/formatting-text.html). For long texts, the message is collapsed and a “Show More” link is added to expand the message. Supports @mentions. + +![image](attachments-text.png) + +### Author details + +`author_name`: An optional name used to identify the author. It will be included in a small section at the top of the attachment. + +`author_link`: An optional URL used to hyperlink the `author_name`. If no `author_name` is specified, this field does nothing. + +`author_icon`: An optional URL used to display a 16x16 pixel icon beside the `author_name`. + +![image](attachments-author.png) + +### Titles + +`title`: An optional title displayed below the author information in the attachment. + +`title_link`: An optional URL used to hyperlink the `title`. If no `title` is specified, this field does nothing. + +![image](attachments-titles.png) + +### Fields + +Fields can be included as an optional array within `attachments`, and are used to display information in a table format inside the attachment. + +`title`: A title shown in the table above the `value`. As of v5.14 a title will render emojis properly. + +`value`: The text value of the field. It can be formatted using [Markdown](https://docs.mattermost.com/help/messaging/formatting-text.html). Supports @mentions. + +`short`: Optionally set to true or false (boolean) to indicate whether the `value` is short enough to be displayed beside other values. + +![image](attachments-fields.png) + +### Images + +`image_url`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed inside a message attachment. + +Large images are resized to a maximum width of 400px or a maximum height of 300px, while still maintaining the original aspect ratio. + +![image](attachments-image.png) + +`thumb_url`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed as a 75x75 pixel thumbnail on the right side of an attachment. We recommend using an image that is already 75x75 pixels, but larger images will be scaled down with the aspect ratio maintained. + +![image](attachments-thumb.png) + +## Example message attachment + +Here is an example message attachment: + +```json +{ + "attachments": [ + { + "fallback": "test", + "color": "#FF8000", + "pretext": "This is optional pretext that shows above the attachment.", + "text": "This is the text of the attachment. It should appear just above an image of the Mattermost logo. The left border of the attachment should be colored orange, and below the image it should include additional fields that are formatted in columns. At the top of the attachment, there should be an author name followed by a bolded title. Both the author name and the title should be hyperlinks.", + "author_name": "Mattermost", + "author_icon": "https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png", + "author_link": "https://mattermost.org/", + "title": "Example Attachment", + "title_link": "https://developers.mattermost.com/integrate/reference/message-attachments/", + "fields": [ + { + "short":false, + "title":"Long Field", + "value":"Testing with a very long piece of text that will take up the whole width of the table. And then some more text to make it extra long." + }, + { + "short":true, + "title":"Column One", + "value":"Testing" + }, + { + "short":true, + "title":"Column Two", + "value":"Testing" + }, + { + "short":false, + "title":"Another Field", + "value":"Testing" + } + ], + "image_url": "https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png" + } + ] +} +``` + +And here is how it renders in Mattermost: + +![image](attachments-example.png) + +### Footer + +`footer`: An optional line of text that will be displayed at the bottom of the attachment. Footers with more than 300 characters will be truncated with an ellipsis (``…``). + +`footer_icon`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed as a 16x16 pixel thumbnail before the footer text. + +![image](attachments-footer.png) + +## Known issues + +1. The footer timestamp field (`ts`) is not yet supported. +2. Message Attachment contents do not show up in search. + +## Frequently asked questions + +### Can I send a message attachment via the API? + +Yes, you can use the [create post RESTful API](https://api.mattermost.com/#operation/CreatePost). + +You need to add an `attachments` key to the post’s `props` JSON field. The value is an array of message attachments you want attached to the post. See below for an example curl command. + +`curl -i -X POST -H 'Content-Type: application/json' -d '{"channel_id":"qmd5oqtwoibz8cuzxzg5ekshgr", "message":"Test message #testing", "props":{"attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}}' https://{your-mattermost-site}/api/v4/posts` + +Below is an example HTTP request: + +```http request +POST /api/v4/posts HTTP/1.1 +Host: {your-mattermost-site} +User-Agent: curl/7.63.0 +Accept: */* +Content-Type: application/json +Content-Length: 192 + +{"channel_id":"qmd5oqtwoibz8cuzxzg5ekshgr", "message":"Test message #testing", "props":{"attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}} +``` + +### Can I post a message attachment using a webhook? + +Yes, you can also use an [incoming webhook](/developers/integrate/webhooks/incoming) to post a message attachment. + +You need to add an `attachments` key to the post's JSON. The value is an array of message attachments you want attached to the post. See below for an example curl command. + +`curl -i -X POST -H 'Content-Type: application/json' -d '{"text":"Test message #testing", "attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}' https://{your-mattermost-site}/hooks/{your-webhook-id}` + +Below is an example HTTP request: + +```http request +POST /hooks/{your-webhook-id} HTTP/1.1 +Host: {your-mattermost-site} +User-Agent: curl/7.63.0 +Accept: */* +Content-Type: application/json +Content-Length: 192 + +{"text":"Test message #testing", "attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]} +``` diff --git a/docs/develop/integrate/reference/message-priority/index.md b/docs/develop/integrate/reference/message-priority/index.md new file mode 100644 index 000000000000..44739c19ad97 --- /dev/null +++ b/docs/develop/integrate/reference/message-priority/index.md @@ -0,0 +1,50 @@ +--- +title: "Message priority" +sidebar_position: 50 +--- + +Messages can be sent with a priority level to help users identify the importance of the message. For more information about message priority, see [formatting text](https://docs.mattermost.com/collaborate/message-priority.html). + +## Priority options + +When sending a message, you can use any of the following to format how you want the posted message to look. + +`priority`: A required plain-text summary of the message. This is used in notifications, and in clients that don’t support formatted text (e.g. IRC). + +`requested_ack`: If set to `true`, the message will be marked as requiring an acknowledgment from the users by displaying a checkmark icon next to the message. Keep in mind that this requires the message priority to be set to _Important_ or _Urgent_. + +`persistent_notifications`: Only for _Urgent_ messages. If set to `true` recipients will receive a persistent notification every five minutes until they acknowledge the message. + +## Example of post priority + +```json +{ + "priority": { + "priority": "urgent", + } +} +``` + +And this is how it renders on Mattermost: + +![Urgent message priority](./message-priority-urgent.jpg) + +## Example of post priority with requested acknowledgment + +```json +{ + "priority": { + "priority": "important", + "requested_ack": true + } +} +``` + +And this is how it renders on Mattermost: + +![Important message priority](./message-priority-requested-ack.jpg) + +## Related documentation + +- [Message priority](https://docs.mattermost.com/collaborate/message-priority.html) +- [CreatePost API](https://api.mattermost.com/#operation/CreatePost) diff --git a/docs/develop/integrate/reference/message-priority/message-priority-requested-ack.jpg b/docs/develop/integrate/reference/message-priority/message-priority-requested-ack.jpg new file mode 100644 index 000000000000..10691faa4a76 Binary files /dev/null and b/docs/develop/integrate/reference/message-priority/message-priority-requested-ack.jpg differ diff --git a/docs/develop/integrate/reference/message-priority/message-priority-urgent.jpg b/docs/develop/integrate/reference/message-priority/message-priority-urgent.jpg new file mode 100644 index 000000000000..ed08e8693020 Binary files /dev/null and b/docs/develop/integrate/reference/message-priority/message-priority-urgent.jpg differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_create.png b/docs/develop/integrate/reference/personal-access-token/access_token_create.png new file mode 100644 index 000000000000..a3110d4cf9b4 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_create.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_console.png b/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_console.png new file mode 100644 index 000000000000..0b797377c725 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_console.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_profile.png b/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_profile.png new file mode 100644 index 000000000000..cf48e8ee1f06 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_delete_from_profile.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_enable.png b/docs/develop/integrate/reference/personal-access-token/access_token_enable.png new file mode 100644 index 000000000000..e676c55c753c Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_enable.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_manage_roles.png b/docs/develop/integrate/reference/personal-access-token/access_token_manage_roles.png new file mode 100644 index 000000000000..acfe8e52a3e6 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_manage_roles.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_save.png b/docs/develop/integrate/reference/personal-access-token/access_token_save.png new file mode 100644 index 000000000000..2b3d897c7da1 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_save.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_token_settings.png b/docs/develop/integrate/reference/personal-access-token/access_token_settings.png new file mode 100644 index 000000000000..dc4448f924ac Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_token_settings.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/access_tokens_additional_roles.png b/docs/develop/integrate/reference/personal-access-token/access_tokens_additional_roles.png new file mode 100644 index 000000000000..ad321b448673 Binary files /dev/null and b/docs/develop/integrate/reference/personal-access-token/access_tokens_additional_roles.png differ diff --git a/docs/develop/integrate/reference/personal-access-token/index.md b/docs/develop/integrate/reference/personal-access-token/index.md new file mode 100644 index 000000000000..0185533daff6 --- /dev/null +++ b/docs/develop/integrate/reference/personal-access-token/index.md @@ -0,0 +1,88 @@ +--- +title: "Personal access tokens" +sidebar_position: 20 +--- +Personal access tokens function similar to session tokens and can be used by integrations to [authenticate against the REST API.](https://api.mattermost.com/#tag/authentication) It is the most commonly used type of token for integrations. + +## Create a personal access token + +1. Enable personal access tokens in **System Console > Integrations > Integration Management**. + + ![Enable Access Token Settings under Integration Management using the System Console.](access_token_enable.png) + +2. Identify the account you want to create a personal access token with. You may optionally create a new user account for your integration, such as for a bot account. By default, only System Admins have permissions to create a personal access token. +3. To create an access token with a non-admin account, you must first give it the appropriate permissions. Go to **System Console > User Management > Users**, search for the user account, then select **Manage Roles** from the dropdown. + + ![Apply appropriate Access Token permission through Manage Roles section under User Management using the System Console.](access_token_manage_roles.png) + +4. Select **Allow this account to generate personal access tokens.** + + ![Provide additional Roles to the user using the User Management section in the System Console](access_tokens_additional_roles.png) + +```text +You may optionally allow the account to post to any channel in your Mattermost server, including direct messages by choosing the **post:all** role. **post:channels** role allows the account to post to any public channel in the Mattermost server. + +Then select **Save**. +``` + +5. Sign in to the user account to create a personal access token. +6. Go to **Profile > Security > Personal Access Tokens**, then select **Create Token**. + + ![Create a Access Token in the Security tab under the Profile Menu.](access_token_create.png) + +7. Enter a description for the token, so you remember what it's used for. Then select **Save**. + + ![Save the Access Token with a description.](access_token_save.png) + + +<Note title="Note"> +If you create a personal access token for a System Admin account, be extra careful who you share it with. The token enables a user to have full access to the account, including System Admin privileges. It's recommended to create a personal access token for non-admin accounts. +</Note> + + +8. Copy the access token now for your integration and store it in a secure location. You won't be able to see it again! +9. You're all set! You can now use the personal access token for integrations to interact with your Mattermost server and [authenticate against the REST API](https://api.mattermost.com/#tag/authentication). + + ![Find details about the Access Token on the Personal Access Token section in the Security tab of your Profile.](access_token_settings.png) + +## Revoke a personal access token + +A personal access token can be revoked by deleting the token from either the user's profile settings or from the System Console. Once deleted, all sessions using the token are deleted, and any attempts to use the token to interact with the Mattermost server are blocked. + +Tokens can also be temporarily deactivated from the user's profile. Once deactivated, all sessions using the token are deleted, and any attempts to use the token to interact with the Mattermost server are blocked. However, the token can be reactivated at any time. + +### User's profile + +1. Sign in to the user account, select the user avatar, then select **Profile > Security > Personal Access Tokens**. +2. Identify the access token you want to revoke, then select **Delete** and confirm the deletion. + + ![Delete a Access Token through the Security tab under the Profile section.](access_token_delete_from_profile.png) + +### System Console + +1. Go to **System Console > User Management > Users**, search for the user account which the token belongs to, then select **Manage Tokens** from the dropdown. +2. Identify the access token you want to revoke, then select **Delete** and confirm the deletion. + + ![Delete a Access Token using the Manage Tokens section under User Management in the System Console.](access_token_delete_from_console.png) + +## Frequently asked questions (FAQ) + +### How do personal access tokens differ from regular session tokens? + +- Personal access tokens do not expire. As a result, you can more easily integrate with Mattermost, bypassing the [session length limits set in the System Console](https://docs.mattermost.com/configure/environment-configuration-settings.html#session-lengths). +- Personal access tokens can be used to authenticate against the API more easily, including with AD/LDAP and SAML accounts. +- You can optionally assign additional roles for the account creating personal access tokens. This lets the account post to any channel in Mattermost, including direct messages. + +Besides the above differences, personal access tokens are exactly the same as regular session tokens. They are cryptic random IDs and are not different from a user's regular session token created after logging in to Mattermost. + +### Can I set personal access tokens to expire? + +Not in Mattermost, but you can automate your integration to cycle its token [through the REST API](https://api.mattermost.com/#operation/CreateUserAccessToken). + +### How do I identify a badly behaving personal access token? + +The best option is to go to **System Console > Logs** and finding error messages relating to a particular token ID. Once identified, you can search which user account the token ID belongs to in **System Console > Users** and revoke it through the **Manage Tokens** dropdown option. + +### Do personal access tokens continue to work if the user is deactivated? + +No. The session used by the personal access token is revoked immediately after a user is deactivated, and a new session won't be created. The tokens are preserved and continue to function if the user account is re-activated. This is useful when a bot account is temporarily deactivated for troubleshooting, for instance. diff --git a/docs/develop/integrate/reference/rest-api/index.md b/docs/develop/integrate/reference/rest-api/index.md new file mode 100644 index 000000000000..3aed66557e03 --- /dev/null +++ b/docs/develop/integrate/reference/rest-api/index.md @@ -0,0 +1,6 @@ +--- +title: "REST API reference" +sidebar_position: 19 +--- + +The Mattermost REST API is documented here: [Mattermost REST API](https://api.mattermost.com) diff --git a/docs/develop/integrate/reference/server/server-reference.md b/docs/develop/integrate/reference/server/server-reference.md new file mode 100644 index 000000000000..ecd97ef2c7d8 --- /dev/null +++ b/docs/develop/integrate/reference/server/server-reference.md @@ -0,0 +1,18 @@ +--- +title: "Server plugin SDK reference" +sidebar_position: 10 +--- + +This is the documentation for the Go <code>github.com/mattermost/mattermost/server/public/plugin</code> package. It can also be found on [GoDoc](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin). + +Visit the [Plugins](/developers/integrate/plugins) section to learn more about [developing Mattermost plugins](/developers/integrate/plugins/developer-setup) and our recommended [developer workflow](/developers/integrate/plugins/developer-workflow) for Mattermost plugins. + +*** + + +<Note title="Generated content (migrating)"> + +This section was rendered by the Hugo `plugingodocs` shortcode from the upstream plugin reference. Migration follow-up — see PLAN.md §11.2. + +</Note> + diff --git a/docs/develop/integrate/reference/webapp/webapp-reference.md b/docs/develop/integrate/reference/webapp/webapp-reference.md new file mode 100644 index 000000000000..430cbaa2c408 --- /dev/null +++ b/docs/develop/integrate/reference/webapp/webapp-reference.md @@ -0,0 +1,215 @@ +--- +title: "Web app plugin SDK reference" +sidebar_position: 10 +--- + +Visit the [Plugins](/developers/integrate/plugins) section to learn more about [developing Mattermost plugins](/developers/integrate/plugins/developer-setup) and our recommended [developer workflow](/developers/integrate/plugins/developer-workflow) for Mattermost plugins. + +## Table of contents + +- [PluginClass](#pluginclass) + * [Example](#example) +- [Registry](#registry) +- [Theme](#theme) +- [Exported Libraries and Functions](#exported-libraries-and-functions) + + [post-utils](#post-utils) + - [`formatText(text, options)`](#formattexttext-options) + - [`messageHtmlToComponent(html, isRHS, options)`](#messagehtmltocomponenthtml-isrhs-options) + - [Usage Example](#usage-example) + +## PluginClass + +The PluginClass interface defines two methods used by the Mattermost Web App to `initialize` and `uninitialize` your plugin: + +```javascript +class PluginClass { + /** + * initialize is called by the webapp when the plugin is first loaded. + * Receives the following: + * - registry - an instance of the registry tied to your plugin id + * - store - the Redux store of the web app. + */ + initialize(registry, store) + + /** + * uninitialize is called by the webapp if your plugin is uninstalled + */ + uninitialize() +} +``` + +<a id="registerPlugin"></a> + +Your plugin should implement this class and register it using the global `registerPlugin` method defined on the window by the webapp: + +```javascript +window.registerPlugin('myplugin', new PluginClass()); +``` + +Use the provided [registry](#registry) to register components, post type overrides and callbacks. Use the store to access the global state of the web app, but note that you should use the registry to register any custom reducers your plugin might require. + +### Example + +The entry point `index.js` of your application might contain: + +```javascript +import UserPopularity from './components/profile_popover/user_popularity'; +import SomePost from './components/some_post'; +import MenuIcon from './components/menu_icon'; +import {openExampleModal} from './actions'; + +class PluginClass { + initialize(registry, store) { + registry.registerPopoverUserAttributesComponent( + UserPopularity, + ); + registry.registerPostTypeComponent( + 'custom_somepost', + SomePost, + ); + registry.registerMainMenuAction( + 'Plugin Menu Item', + () => store.dispatch(openExampleModal()), + mobile_icon: MenuIcon, + ); + } + + uninitialize() { + // No clean up required. + } +} + +window.registerPlugin('myplugin', new PluginClass()); +``` + +This will add a custom `UserPopularity` component to the profile popover, render a custom `SomePost` component for any post with the type `custom_somepost`, and insert a custom main menu item. + +## Registry + +An instance of the plugin registry is passed to each plugin via the `initialize` callback. + + +<Note title="Generated content (migrating)"> + +This section was rendered by the Hugo `pluginjsdocs` shortcode from the upstream plugin reference. Migration follow-up — see PLAN.md §11.2. + +</Note> + + +### Theme + +In Mattermost, users are able to set custom themes that change the color scheme of the UI. It's important that plugins have access to a user's theme so that they can set their styling to match and not look out of place. + +Every pluggable component in the web app will have the theme object as a prop. + +The colors are exposed via CSS variables as well. + +The theme object has the following properties: + +| Property | CSS Variable | Description | +|-------------------------|------------------------------|-------------------------------------------------------------------------------------| +| sidebarBg | --sidebar-bg | Background color of the left-hand sidebar | +| sidebarText | --sidebar-text | Color of text in the left-hand sidebar | +| sidebarUnreadText | --sidebar-unread-text | Color of text for unread channels in the left-hand sidebar | +| sidebarTextHoverBg | --sidebar-text-hover-bg | Background color of channels when hovered in the left-hand sidebar | +| sidebarTextActiveBorder | --sidebar-text-active-border | Color of the selected indicator channel indicator in the left-hand siebar | +| sidebarTextActiveColor | --sidebar-text-active-color | Color of the text for the selected channel in the left-hand sidebar | +| sidebarHeaderBg | --sidebar-header-bg | Background color of the left-hand sidebar header | +| sidebarHeaderTextColor | --sidebar-header-text-color | Color of text in the left-hand sidebar header | +| onlineIndicator | --online-indicator | Color of the online status indicator | +| awayIndicator | --away-indicator | Color of the away status indicator | +| dndIndicator | --dnd-indicator | Color of the do not disturb status indicator | +| mentionBg | --mention-bg | Background color for mention jewels in the left-hand sidebar | +| mentionColor | --mention-color | Color of text for mention jewels in the left-hand sidebar | +| centerChannelBg | --center-channel-bg | Background color of channels, right-hand sidebar and modals/popovers | +| centerChannelColor | --center-channel-color | Color of text in channels, right-hand sidebar and modals/popovers | +| newMessageSeparator | --new-message-separator | Color of the new message separator in channels | +| linkColor | --link-color | Color of text for links | +| buttonBg | --button-bg | Background color of buttons | +| buttonColor | --button-color | Color of text for buttons | +| errorTextColor | --error-text | Color of text for errors | +| mentionHighlightBg | --mention-highlight-bg | Background color of mention highlights in posts | +| mentionHighlightLink | --mention-highlight-link | Color of text for mention links in posts | +| codeTheme | NA | Code block theme, either 'github', 'monokai', 'solarized-dark' or 'solarized-light' | + +## Exported libraries and functions + +The web app exposes a number of [exported libraries and functions](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/plugins/export.js) on the `window` object for plugins to use. To avoid bloating your plugin, we recommend depending on these using [Webpack externals](https://webpack.js.org/configuration/externals/) or importing them manually from the window. Below is a list of the exposed libraries and functions: + +| Library | Exported Name | Description | +|-----------------|-----------------------|--------------------------------------------------------------------| +| react | window.React | [ReactJS](https://react.dev/) | +| react-dom | window.ReactDOM | [ReactDOM](https://react.dev/docs/react-dom.html) | +| redux | window.Redux | [Redux](https://redux.js.org/) | +| react-redux | window.ReactRedux | [React bindings for Redux](https://github.com/reactjs/react-redux) | +| react-bootstrap | window.ReactBootstrap | [Bootstrap for React](https://react-bootstrap.github.io/) | +| prop-types | window.PropTypes | [PropTypes](https://www.npmjs.com/package/prop-types) | +| post-utils | window.PostUtils | Mattermost post utility functions (see below) | + + +<Note title="Note"> +Some sets of functions like "Functions exposed on window for plugin to use" and "Components exposed on window for internal plugin use only" are not listed here. You can refer to [export.js](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/plugins/export.js) file which contains all the exports. +</Note> + + + +#### post-utils + +Contains the following post utility functions: + +##### `formatText(text, options)` +Performs formatting of text including Markdown, highlighting mentions and search terms and converting URLs, hashtags, @mentions and ~channels to links by taking a string and returning a string of formatted HTML. + +* `text` - String of text to format, e.g. a post's message. +* `options` - (Optional) An object containing the following formatting options +* `searchTerm` - If specified, this word is highlighted in the resulting HTML. Defaults to nothing. +* `mentionHighlight` - Specifies whether or not to highlight mentions of the current user. Defaults to true. +* `mentionKeys` - A list of mention keys for the current user to highlight. +* `singleline` - Specifies whether or not to remove newlines. Defaults to false. +* `emoticons` - Enables emoticon parsing with a data-emoticon attribute. Defaults to true. +* `markdown` - Enables markdown parsing. Defaults to true. +* `siteURL` - The origin of this Mattermost instance. If provided, links to channels and posts will be replaced with internal links that can be handled by a special click handler. +* `atMentions` - Whether or not to render "@" mentions into spans with a data-mention attribute. Defaults to false. +* `channelNamesMap` - An object mapping channel display names to channels. If `channelNamesMap` and `team` are provided, ~channel mentions will be replaced with links to the relevant channel. +* `team` - The current team object. +* `proxyImages` - If specified, images are proxied. Defaults to false. + +##### `messageHtmlToComponent(html, isRHS, options)` +Converts HTML to React components. + +* `html` - String of HTML to convert to React components. +* `isRHS` - Boolean indicating if the resulting components are to be displayed in the right-hand sidebar. Has some minor effects on how UI events are triggered for components in the RHS. +* `options` - (Optional) An object containing options +* `mentions` - If set, mentions are replaced with the AtMention component. Defaults to true. +* `emoji` - If set, emoji text is replaced with the PostEmoji component. Defaults to true. +* `images` - If set, markdown images are replaced with the PostMarkdown component. Defaults to true. +* `latex` - If set, latex is replaced with the LatexBlock component. Defaults to true. + +##### Usage example + +A short usage example of a `PostType` component using the post utility functions to format text. + +```jsx +import React from 'react'; // accessed through webpack externals +import PropTypes from 'prop-types'; + +const PostUtils = window.PostUtils; // must be accessed through `window` + +export default class PostTypeFormatted extends React.PureComponent { + + // ... + + render() { + const post = this.props.post; + + const formattedText = PostUtils.formatText(post.message); // format the text + + return ( + <div> + {'Formatted text: '} + {PostUtils.messageHtmlToComponent(formattedText)} // convert the html to components + </div> + ); + } +} +``` diff --git a/docs/develop/integrate/slash-commands/built-in/index.md b/docs/develop/integrate/slash-commands/built-in/index.md new file mode 100644 index 000000000000..17f6a3a09198 --- /dev/null +++ b/docs/develop/integrate/slash-commands/built-in/index.md @@ -0,0 +1,7 @@ +--- +title: "Built-in commands" +sidebar_position: 10 +--- +Each Mattermost installation comes with some built-in slash commands that are ready to use. See the [Mattermost product documentation](https://docs.mattermost.com/channels/interact-with-channels.html) for details on available slash commands available in the [latest Mattermost release](https://mattermost.com/download) + +To create a custom slash command, see the [Custom slash commands](/developers/integrate/slash-commands/custom) developer documentation. diff --git a/docs/develop/integrate/slash-commands/custom/index.md b/docs/develop/integrate/slash-commands/custom/index.md new file mode 100644 index 000000000000..f8144bfbf511 --- /dev/null +++ b/docs/develop/integrate/slash-commands/custom/index.md @@ -0,0 +1,135 @@ +--- +title: "Custom commands" +sidebar_position: 20 +--- +Suppose you want to write an external application that is able to check the weather for certain cities. By creating a custom slash command and setting up the application to handle the HTTP `POST` or `GET` from the command, you can let your users check the weather in their city for the week using your command, say `/weather toronto week`. + +You can follow these general guidelines to set up a custom Mattermost slash command for your application. + +1. Open **Product menu > Integrations > Slash Commands**. If you don't have the **Integrations** option in your Main Menu, slash commands may not be enabled on your Mattermost Server or may be disabled for non-admins. Enable them from **System Console > Integrations > Integration Management** or ask your Mattermost System Admin to do so. + +2. Select **Add Slash Command**; the **Add** dialog will appear. Use the following guidelines to configure the slash command: + + - Set the **Title** and **Description** for the command. + - Set the **Command Trigger Word**. The trigger word must be unique and cannot begin with a slash or contain any spaces. It also cannot be one of the [built-in commands](/developers/integrate/slash-commands/built-in). + - Set the **Request URL** and **Request Method**. The request URL is the endpoint that Mattermost hits to reach your application, and the request method is either `POST` or `GET` and specifies the type of request sent to the request URL. + - (_Optional_) Set the **Response Username** and **Response Icon** the command will post messages as in Mattermost. If not set, the command will use your username and profile picture. + - (_Optional_) Select the **Autocomplete** option to include the slash command in the command autocomplete list, displayed when typing ``/`` in an empty input box. Use it to make your command easier to discover by your teammates. You can also provide a hint listing the arguments of your command and a short description displayed in the autocomplete list. + + +<Note title="Note"> +[Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) must be set to `true` in `config.json` to override usernames. Enable them from **System Console > Integrations > Integration Management**, or ask your System Admin to do so. If not enabled, the username is set to `webhook`. + + Similarly, [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) must be set to `true` in `config.json` to override profile picture icons. Enable them from **System Console > Integrations > Integration Management**, or ask your System Admin to do so. If not enabled, the icon of the creator of the webhook URL is used to post messages. +</Note> + + +3. Select **Save**. On the next page, copy the **Token** value. This will be used in a later step. + + ![image](slash_commands_token.png) + +4. Next, write your external application. Include a function which receives HTTP `POST` or HTTP `GET` requests from Mattermost. The request will look something like this: + + ```http request + POST /weather HTTP/1.1 + Host: weather-service:4000 + Accept: application/json + Accept-Encoding: gzip + Authorization: Token qzgakf1nx3yt9dr4n8585ihbxy + Content-Length: 567 + Content-Type: application/x-www-form-urlencoded + User-Agent: Mattermost-Bot/1.1 + + channel_id=fukxanjgjbnp7ng383at53k1sy& + channel_name=town-square& + command=%2Fweather& + response_url=http%3A%2F%2Flocalhost%3A8066%2Fhooks%2Fcommands%2Fi11f6nnfgfyk8eg56x9omc6dpa& + team_domain=team-awesome& + team_id=wx4zz8t4ttgmtxqiwfohijayzc& + text=toronto+week& + token=qzgakf1nx3yt9dr4n8585ihbxy& + trigger_id=ZWZ5ZjRndzR4YmJxOHJlZWh4MXpkaHozbnI6ZXJqNnFjazNyZmd0dWpzODZ3NXI2cmNremg6MTY2MjA0MTY5Njg5NjpNRVFDSUQ5cTZ3MkRHU1RaNjhyaDh1TGl1STlSVHh2R1czSXZ5aGVRYjhkWThuZnlBaUI2YnlPR2ZpWlczR1FmVkdIODlreEp4MmlVT0UxMm9LMjlkZ1d0RC8xbjZRPT0%3D& + user_id=erj6qck3rfgtujs86w5r6rckzh& + user_name=alan + ``` + + If your integration sends back a JSON response, make sure it returns the `application/json` content-type. + +5. The HTTP `POST` or `GET` request will contain an `Authorization` header with a bearer token. The bearer token should match the **Token** value from step 3 for a request to be considered valid. + +6. To have your application post a message back to `town-square`, it can respond to the HTTP `POST` or `GET` request with a JSON payload. + + Mattermost supports several [parameters](#response-parameters) in the response to fine-tune the user's experience. For instance, you can override the username and profile picture the messages post as, or specify a custom post type when sending a webhook message for use by [plugins](/developers/integrate/plugins). Messages with advanced formatting can be created by including an [attachment array](/developers/integrate/reference/message-attachments) and [interactive message buttons](/developers/integrate/plugins/interactive-messages) in the response payload. + + Our external weather application could respond with a JSON payload like so: + + ``` + {"response_type": "in_channel", "text": " + --- + #### Weather in Toronto, Ontario for the Week of February 16th, 2016 + + | Day | Description | High | Low | + |:--------------------|:---------------------------------|:-------|:-------| + | Monday, Feb. 15 | Cloudy with a chance of flurries | 3 °C | -12 °C | + | Tuesday, Feb. 16 | Sunny | 4 °C | -8 °C | + | Wednesday, Feb. 17 | Partly cloudly | 4 °C | -14 °C | + | Thursday, Feb. 18 | Cloudy with a chance of rain | 2 °C | -13 °C | + | Friday, Feb. 19 | Overcast | 5 °C | -7 °C | + | Saturday, Feb. 20 | Sunny with cloudy patches | 7 °C | -4 °C | + | Sunday, Feb. 21 | Partly cloudy | 6 °C | -9 °C | + --- + "} + ``` + + The JSON response would render in Mattermost as: + + ![image](weatherBot.png) + + +## Response parameters + +Slash command responses support more than just the `text` field. Here is a full list of supported parameters. + +| Parameter | Description | Required | +|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------| +| `text` | [Markdown-formatted](https://docs.mattermost.com/messaging/formatting-text.html) message to display in the post. | If `attachments` is not set, yes | +| `attachments` | [Message attachments](/developers/integrate/reference/message-attachments) used for richer formatting options. | If `text` is not set, yes | +| `response_type` | Set to blank or `ephemeral` to reply with a message that only the user can see. <br/> Set to `in_channel` to create a regular message.<br/> Defaults to `ephemeral`. | No | +| `username` | Overrides the username the message posts as.<br/> Defaults to the username set during webhook creation or the webhook creator's username if the former was not set.<br/> Must be enabled [in the configuration](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames). | No | +| `channel_id` | Overrides the channel to which the message gets posted.<br/> Defaults to the channel in which the command was issued. | No | +| `icon_url ` | Overrides the profile picture the message posts with.<br/> Defaults to the URL set during webhook creation or the webhook creator's profile picture if the former was not set.<br/> Must be enabled [in the configuration](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons). | No | +| `goto_location` | A URL to redirect the user to. Supports many protocols, including `http://`, `https://`, `ftp://`, `ssh://` and `mailto://`. | No | +| `type` | Sets the post `type`, mainly for use by plugins.<br/> If not blank, must begin with `custom_`. Passing `attachments` will ignore this field and set the type to `slack_attachment`. | No | +| `extra_responses` | An array of responses used to send more than one post in your response. Each item in this array takes the shape of its own command response, so it can include any of the other parameters listed here, except `goto_location` and `extra_responses` itself. Available from Mattermost v5.6. | No | +| `skip_slack_parsing` | If set to `true` Mattermost will skip the [Slack compatibility](/developers/integrate/slash-commands/slack) handling. Useful if the post contains text or code which is incorrectly handled by the Slack compatibility logic. Available from Mattermost v5.20. | No | +| `props` | Sets the post `props`, a JSON property bag for storing extra or meta data on the post. Mainly used by other integrations accessing posts through the [REST API](https://api.mattermost.com).<br/>The following keys are reserved: `from_webhook`, `override_username`, `override_icon_url` and `attachments`. | No | + +An response payload using several parameters could look like this: + +```json +{ + "response_type": "in_channel", + "text": "\n#### Test results for July 27th, 2017\n@channel here are the requested test results.\n\n| Component | Tests Run | Tests Failed |\n| ---------- | ----------- | ---------------------------------------------- |\n| Server | 948 | :white_check_mark: 0 |\n| Web Client | 123 | :warning: 2 [(see details)](https://linktologs) |\n| iOS Client | 78 | :warning: 3 [(see details)](https://linktologs) |\n\t\t ", + "username": "test-automation", + "icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "props": { + "test_data": { + "ios": 78, + "server": 948, + "web": 123 + } + }, +} +``` + +## Delayed and multiple responses + +You can use the `response_url` parameter to supply multiple responses or a delayed response to a slash command. Response URLs can be used to send five additional messages within a 30-minute time period from the original command invocation. + +Delayed responses are useful when the action takes more than three seconds to perform. For instance: +- Retrieval of data from external third-party services, where the response time may take longer than three seconds. +- Report generation, batch processing or other long-running processes that take longer than three seconds to respond. + +Any requests that are made to the response URL should either be a plain text or JSON-encoded body. The JSON-encoded message supports both [Markdown formatting](https://docs.mattermost.com/messaging/formatting-text.html) and [message attachments](/developers/integrate/reference/message-attachments). + +For information on the Slack compatibility of slash commands, see the [Slack compatibility](/developers/integrate/slash-commands/slack) page. diff --git a/docs/develop/integrate/slash-commands/custom/slash_commands_token.png b/docs/develop/integrate/slash-commands/custom/slash_commands_token.png new file mode 100644 index 000000000000..5eddd9b4a4bc Binary files /dev/null and b/docs/develop/integrate/slash-commands/custom/slash_commands_token.png differ diff --git a/docs/develop/integrate/slash-commands/custom/weatherBot.png b/docs/develop/integrate/slash-commands/custom/weatherBot.png new file mode 100644 index 000000000000..80b621716439 Binary files /dev/null and b/docs/develop/integrate/slash-commands/custom/weatherBot.png differ diff --git a/docs/develop/integrate/slash-commands/index.md b/docs/develop/integrate/slash-commands/index.md new file mode 100644 index 000000000000..87963c80d21d --- /dev/null +++ b/docs/develop/integrate/slash-commands/index.md @@ -0,0 +1,115 @@ +--- +title: "Slash commands" +sidebar_position: 30 +--- + +Slash commands are messages that begin with `/` and trigger an HTTP request to a web service that can in turn post one or more messages in response. + +Slash commands have an additional feature, **autocomplete**, that displays a list of possible commands based on what has been typed in the message box. Typing `/` in an empty message box will display a list of all slash commands. As the slash command is typed in the message box, autocomplete will also display possible arguments and flags for the command. + +Unlike [outgoing webhooks](/developers/integrate/webhooks/outgoing), slash commands work in private channels and direct messages in addition to public channels, and can be configured to auto-complete when typing. +Mattermost includes a number of [built-in slash commands](https://docs.mattermost.com/channels/interact-with-channels.html). You can also create [custom slash commands](/custom). + +## Tips and best practices + +1. Slash commands are designed to easily allow you to post messages. For other actions such as channel creation, you must also use the [Mattermost APIs](https://api.mattermost.com). +2. Posts size is limited to 16383 characters for servers running [Mattermost Server v5.0 or later](https://docs.mattermost.com/administration/important-upgrade-notes.html). Use the `extra_responses` field to reply to a triggered slash command with more than one post. +3. You can restrict who can create slash commands in [System Console > Integrations > Integration Management](https://docs.mattermost.com/configure/configuration-settings.html#enable-custom-slash-commands). +4. Mattermost [outgoing webhooks](/developers/integrate/webhooks/outgoing) are Slack-compatible. You can copy-and-paste code used for a Slack outgoing webhook to create Mattermost integrations. Mattermost [automatically translates Slack's proprietary JSON payload format](/slack#translate-slacks-data-format-to-mattermost). +5. The external application may be written in any programming language. It needs to provide a URL which receives the request sent by your Mattermost Server and responds with in the required JSON format. + +## FAQ + +### How do I debug slash commands? + +To debug slash commands in **System Console > Logs**, set **System Console > Logging > Enable Webhook Debugging** to **true** and set **System Console > Logging > Console Log Level** to **DEBUG**. + +### How do I send multiple responses from a slash command? + +You can send multiple responses with an `extra_responses` parameter as follows. + +```http +HTTP/1.1 200 OK +Content-Type: application/json +Content-Length: 696 + +{ + "response_type": "in_channel", + "text": "\n#### Test results for July 27th, 2017\n@channel here are the requested test results.\n\n| Component | Tests Run | Tests Failed |\n| ---------- | ----------- | ---------------------------------------------- |\n| Server | 948 | :white_check_mark: 0 |\n| Web Client | 123 | :warning: 2 [(see details)](http://linktologs) |\n| iOS Client | 78 | :warning: 3 [(see details)](http://linktologs) |\n\t\t ", + "username": "test-automation", + "icon_url": "https://www.mattermost.org/wp-content/uploads/2016/04/icon.png", + "props": { + "test_data": { + "ios": 78, + "server": 948, + "web": 123 + } + }, + "extra_responses": [ + { + "text": "message 2", + "username": "test-automation" + }, + { + "text": "message 3", + "username": "test-automation" + } + ] +} +``` + +### What if my slash command takes time to build a response? + +Reply immediately with an `ephemeral` message to confirm response of the command, and then use the `response_url` to send up to five additional messages within a 30-minute time period from the original command invocation. + +### Why does my slash command fail to connect to `localhost`? + +By default, Mattermost prohibits outgoing connections that resolve to certain common IP ranges, including the loopback (`127.0.0.0/8`) and various private-use subnets. + +During development, you may override this behaviour by setting `ServiceSettings.AllowedUntrustedInternalConnections` to `"127.0.0.0/8"` in your `config.json` or via **System Console > Advanced > Developer**. See the [configuration settings documentation](https://docs.mattermost.com/configure/environment-configuration-settings.html#allow-untrusted-internal-connections) for more details. + +### Should I configure my slash command to use `POST` or `GET`? + +Best practice suggests using `GET` only if a request is considered idempotent. This means that the request can be repeated safely and can be expected to return the same response for a given input. Some servers hosting your slash command may also impose a limit to the amount of data passed through the query string of a `GET` request. + +Ultimately, however, the choice is yours. If in doubt, configure your slash command to use a `POST` request. + + +<Note title="Mattermost releases prior to 5.0.0"> +Note that slash commands configured to use a <code>GET</code> request were broken prior to Mattermost release 5.0.0. The payload was incorrectly encoded in the body of the <code>GET</code> request instead of in the query string. While it was still technically possible to extract the payload, this was non-standard and broke some development stacks. +</Note> + + +### Why does my slash command always fail with `returned an empty response`? + +If you are emitting the `Content-Type: application/json` header, your body must be valid JSON. Any JSON decoding failure will result in this error message. + +Also, you must provide a `response_type`. Mattermost does not assume a default if this field is missing. + +### Why does my slash command print the JSON data instead of formatting it? + +Ensure you are emitting the `Content-Type: application/json` header, otherwise your body will be treated as plain text and posted as such. + +### Are slash commands Slack-compatible? + +See the [Slack compatibility](/slack) page. + +### How do I use Bot Accounts to reply to slash commands? + +#### If you are developing an integration +- Set up a [Personal Access Token](/developers/integrate/reference/personal-access-token) for the Bot Account you want to reply with. +- Use the [REST API](https://api.mattermost.com/#tag/posts/operation/CreatePost) to create a post with the Access Token. + +#### If you are developing a plugin + +Use [`CreatePost`](/developers/integrate/reference/server/server-reference#API.CreatePost) plugin API. Make sure to set the `UserId` of the post to the `UserId` of the Bot Account. If you want to create an ephemeral post, use [`SendEphemeralPost`](/developers/integrate/reference/server/server-reference#API.SendEphemeralPost) plugin API instead. + +## Troubleshoot slash commands + +Join the [Mattermost user community](https://mattermost.com/pl/default-ask-mattermost-community) for help troubleshooting your slash command. + +## Share your integration + +If you've built an integration for Mattermost, please consider [sharing your work](/developers/integrate/getting-started) in our [Marketplace](https://mattermost.com/marketplace/). + +The [Marketplace](https://mattermost.com/marketplace/) lists open source integrations developed by the Mattermost community and are available for download, customization, and deployment to your private cloud or self-hosted infrastructure. diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/add_outgoing_oauth_connection_form.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/add_outgoing_oauth_connection_form.png new file mode 100644 index 000000000000..f01d8210592f Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/add_outgoing_oauth_connection_form.png differ diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/backstage_sidebar.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/backstage_sidebar.png new file mode 100644 index 000000000000..441d036d9925 Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/backstage_sidebar.png differ diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/edit_outgoing_oauth_connection_form.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/edit_outgoing_oauth_connection_form.png new file mode 100644 index 000000000000..5cb3a6fd410b Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/edit_outgoing_oauth_connection_form.png differ diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/index.md b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/index.md new file mode 100644 index 000000000000..426d69ad78b3 --- /dev/null +++ b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/index.md @@ -0,0 +1,45 @@ +--- +title: "Outgoing OAuth connections" +sidebar_position: 30 +--- + +From Mattermost v9.6, you can integrate Mattermost with custom integrations hosted within your internal OAuth infrastructure. More specifically, [slash commands](https://developers.mattermost.com/integrate/slash-commands/custom) now support communicating to external systems using the [Client Credentials](https://oauth.net/2/grant-types/client-credentials) OAuth 2.0 grant type. In a future iteration of this feature, we plan to support [outgoing webhooks](https://developers.mattermost.com/integrate/webhooks/outgoing), [interactive dialogs](https://developers.mattermost.com/integrate/plugins/interactive-dialogs), and [interactive messages](https://developers.mattermost.com/integrate/plugins/interactive-messages). + +To configure Mattermost to communicate with your OAuth system, you first need to create an Outgoing OAuth Connection in Mattermost. This involves providing the following values in the connection configuration form: + +- `Client Id` & `Client Secret` +- `Token URL` - The URL that Mattermost will contact to retrieve a new token for each request to your integration. +- `Audience URLs` - The URLs that your custom integration hosts to process requests, e.g. slash command submission requests. + +Once this is set up, whenever Mattermost sends a request to your custom integration, Mattermost will first fetch an access token from the `Token URL`, and include the access token in the request to your integration. A new token will be requested for every request sent to your integration. + +### Configure the Outgoing OAuth Connection + +To configure a new outgoing OAuth connection, navigate to your Mattermost server's integrations backstage console, as shown below, then go to the **Outgoing OAuth 2.0 Connections** tab, and select **Add Outgoing OAuth Connection**. If you don't have the **Integrations** option, integrations may not be enabled on your Mattermost Server, or integrations may be disabled for non-admins. Enable integrations by going to **System Console > Integrations > Integration Management** or ask your Mattermost system admin to do so. + +![image](product_switcher.png) + +![image](backstage_sidebar.png) + +Now we can configure our OAuth connection. With the values configured in the example below, Mattermost will perform the following operations when a user interacts with your integration, e.g. when the user submits a slash command associated with your integration. + +- Mattermost will request an access token from `Token URL`, by providing the `Client Id` and `Client Secret` via a URL-encoded form submission. +- Mattermost will send a request to your slash command submission handler, with the access token in the request's `Authorization` HTTP header, in the format of `Bearer (token)`. + +In the future, any further requests to your integration (such as interactive dialog submissions) will perform the above steps as well. + +Notice that the `Audience URL` configured below ends in a wildcard `*`. This means that an access token will be retrieved for any integration request that matches that URL, i.e. any URL that has the prefix of the string leading up to the `*` character. If you would like to restrict the OAuth connection to exact URLs, simply omit the `*`, and supply the exact URLs you would like to configure for your integration. You can come back to this form to update these values at any time. Note that the `Client Secret` will not be shown again when you return to this form. + +You can validate that the connection is set up properly by selecting the **Validate Connection** button. This will cause Mattermost to request a token from the `Token URL` using the provided credentials. If a token is retrieved successfully, a **Validated Connection** message will be shown in the UI. If the token retrieval was unsuccessful for any reason, an error will be shown in the UI. Note that validating the connection here is optional, though a warning will be shown upon submitting the form if the connection was not validated before submission. + +![image](add_outgoing_oauth_connection_form.png) + +![image](edit_outgoing_oauth_connection_form.png) + +### Configure a Slash Command to use the Outgoing OAuth Connection + +In order to configure your custom Slash Command to use the OAuth connection, we just need to provide a request URL that matches the `Audience URL` provided in the OAuth connection form. If you have at least one OAuth connection configured on your Mattermost instance, you will see a message in the slash command configuration form stating whether or not your slash command will use a configured OAuth connection. + +![image](slash_command_form_not_connected.png) + +![image](slash_command_form_connection.png) diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/product_switcher.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/product_switcher.png new file mode 100644 index 000000000000..0c7620f54ef9 Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/product_switcher.png differ diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_connection.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_connection.png new file mode 100644 index 000000000000..5d47d68dcba4 Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_connection.png differ diff --git a/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_not_connected.png b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_not_connected.png new file mode 100644 index 000000000000..1027550cde5f Binary files /dev/null and b/docs/develop/integrate/slash-commands/outgoing-oauth-connections/slash_command_form_not_connected.png differ diff --git a/docs/develop/integrate/slash-commands/slack/index.md b/docs/develop/integrate/slash-commands/slack/index.md new file mode 100644 index 000000000000..bd3115affa93 --- /dev/null +++ b/docs/develop/integrate/slash-commands/slack/index.md @@ -0,0 +1,27 @@ +--- +title: "Slack compatibility" +sidebar_position: 40 +--- +Mattermost makes it easy to migrate integrations written for Slack to Mattermost. + +## Translate Slack's data format to Mattermost + +Mattermost automatically translates the data coming from Slack: + +1. JSON responses written for Slack, that contain the following, are translated to Mattermost markdown and rendered equivalently to Slack: + + - `<>` to denote a URL link, such as `{"text": "<https://mattermost.com/>"}`. + - `|` within a `<>` to define linked text, such as `{"text": "Click <https://mattermost.com/|here> for a link."}`. + - `<userid>` to trigger a mention to a user, such as `{"text": "<5fb5f7iw8tfrfcwssd1xmx3j7y> this is a notification."}`. + - `<!channel>`, `<!here>`, or `<!all>` to trigger a mention to a channel, such as `{"text": "<!channel> this is a notification."}`. + +2. Both the HTTP `POST` and `GET` request bodies sent to a web service are formatted the same as Slack's. This means your Slack integration's receiving function does not need change to be compatible with Mattermost. + +## Known Slack compatibility issues + +- Using `icon_emoji` to override the username is not supported. +- Referencing channels using `<#CHANNEL_ID>` does not link to the channel. +- `<!everyone>` and `<!group>` are not supported. +- Parameters `mrkdwn`, `parse`, and `link_names` are not supported (Mattermost always converts markdown and automatically links @mentions). +- Bold formatting supplied as `*bold*` is not supported (must be done as `**bold**`). +- Slack assumes default values for some fields if they are not specified by the integration, while Mattermost does not. diff --git a/docs/develop/integrate/webhooks/incoming/incoming_webhooks_create_simple.png b/docs/develop/integrate/webhooks/incoming/incoming_webhooks_create_simple.png new file mode 100644 index 000000000000..ecd5b8f99b3d Binary files /dev/null and b/docs/develop/integrate/webhooks/incoming/incoming_webhooks_create_simple.png differ diff --git a/docs/develop/integrate/webhooks/incoming/incoming_webhooks_full_example.png b/docs/develop/integrate/webhooks/incoming/incoming_webhooks_full_example.png new file mode 100644 index 000000000000..57db76170769 Binary files /dev/null and b/docs/develop/integrate/webhooks/incoming/incoming_webhooks_full_example.png differ diff --git a/docs/develop/integrate/webhooks/incoming/index.md b/docs/develop/integrate/webhooks/incoming/index.md new file mode 100644 index 000000000000..eefaec511182 --- /dev/null +++ b/docs/develop/integrate/webhooks/incoming/index.md @@ -0,0 +1,200 @@ +--- +title: "Incoming webhooks" +sidebar_position: 10 +--- +## Create an incoming webhook + +Let's learn how to create a simple incoming webhook that posts the following message to Mattermost. + +![An incoming webhook that posts `Hello, this is some text. This is some more text.](incoming_webhooks_create_simple.png) + +1. In Mattermost, go to **Product menu > Integrations > Incoming Webhook**. + - If you don't have the **Integrations** option, incoming webhooks may not be enabled on your Mattermost server or may be disabled for non-admins. They can be enabled by a System Admin from **System Console > Integrations > Integration Management**. Once incoming webhooks are enabled, continue with the steps below. +2. Select **Add Incoming Webhook** and add a name and description for the webhook. The description can be up to 500 characters. +3. Select the channel to receive webhook payloads, then select **Add** to create the webhook. + +You will end up with a webhook endpoint that looks like so: + +``` +https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx +``` + +__Treat this endpoint as a secret.__ Anyone who has it will be able to post messages to your Mattermost instance. + +## Use an incoming webhook + +To use the endpoint, have your application make the following request: + +```http request +POST /hooks/xxx-generatedkey-xxx HTTP/1.1 +Host: your-mattermost-server.com +Content-Type: application/json +Content-Length: 63 + +{ + "text": "Hello, this is some text\nThis is more text. :tada:" +} +``` + +For example, here is the same request using `cURL`: + +```bash +curl -i -X POST -H 'Content-Type: application/json' -d '{"text": "Hello, this is some text\nThis is more text. :tada:"}' https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx +``` + +For compatibility with Slack incoming webhooks, if no `Content-Type` header is set then the request body must be prefixed with `payload=`, like so: + +``` +payload={"text": "Hello, this is some text\nThis is more text. :tada:"} +``` + +A successful request will get the following response: + +``` +HTTP/1.1 200 OK +Content-Type: text/plain +X-Request-Id: hoan6o9ws7rp5xj7wu9rmysrte +X-Version-Id: 4.7.1.dev.12799cd77e172e8a2eba0f9091ec1471.false +Date: Sun, 04 Mar 2018 17:19:09 GMT +Content-Length: 2 + +ok +``` + +All webhook posts will display a `BOT` indicator next to the username in Mattermost clients to help prevent against [phishing attacks](https://en.wikipedia.org/wiki/Phishing). + + +### Parameters + +Incoming webhooks support more than just the `text` field. Here is a full list of supported parameters. + +| Parameter | Description | Required | +|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------| +| `text` | [Markdown-formatted](https://docs.mattermost.com/messaging/formatting-text.html) message to display in the post.<br/>To trigger notifications, use `@<username>`, `@channel`, and `@here` like you would in other Mattermost messages. | If `attachments` is not set, yes | +| `channel` | Overrides the channel the message posts in. Use the channel's name and not the display name, e.g. use `town-square`, not `Town Square`.<br/>Use an "@" followed by a username to send to a Direct Message.<br/>Defaults to the channel set during webhook creation.<br/>The webhook can post to any Public channel and Private channel the webhook creator is in.<br/>Posts to Direct Messages will appear in the Direct Message between the targeted user and the webhook creator. | No | +| `username` | Overrides the username the message posts as.<br/>Defaults to the username set during webhook creation; if no username was set during creation, `webhook` is used.<br/>The [Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) configuration setting must be enabled for the username override to take effect. | No | +| `icon_url` | Overrides the profile picture the message posts with.<br/>Defaults to the URL set during webhook creation; if no icon was set during creation, the standard webhook icon (<CompassIcon name="webhook" />) is displayed.<br/>The [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) configuration setting must be enabled for the icon override to take effect. | No | +| `icon_emoji` | Overrides the profile picture and `icon_url` parameter.<br/>Defaults to none and is not set during webhook creation.<br/>The expected value is an emoji name as typed in a message, either with or without colons (`:`).<br/>The [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) configuration setting must be enabled for the override to take effect.. | No | +| `attachments` | [Message attachments](/developers/integrate/reference/message-attachments) used for richer formatting options. | If `text` is not set, yes | +| `type` | Sets the post `type`, mainly for use by plugins.<br/>If not blank, must begin with `custom_` unless set to `burn_on_read`. | No | +| `props` | Sets the post `props`, a JSON property bag for storing extra or meta data on the post.<br/>Mainly used by other integrations accessing posts through the REST API.<br/>The following keys are reserved: `from_webhook`, `override_username`, `override_icon_url`, `override_icon_emoji`, `webhook_display_name`, `card`, and `attachments`.<br/>Props `card` allows for extra information (Markdown-formatted text) to be sent to Mattermost that will only be displayed in the RHS panel after a user selects the **info** icon displayed alongside the post.<br/>The **info** icon cannot be customized and is only rendered visible to the user if there is `card` data passed into the message.<br/>This property is available from Mattermost v5.14.<br/>There is currently no Mobile support for `card` functionality. | No | +| `priority` | Set the priority of the message. See [Message Priority](/integrate/reference/message-priority/) | No | + +An example request using more parameters would look like this: + +```http request +POST /hooks/xxx-generatedkey-xxx HTTP/1.1 +Host: your-mattermost-server.com +Content-Type: application/json +Content-Length: 630 + +{ + "channel": "town-square", + "username": "test-automation", + "icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "text": "#### Test results for July 27th, 2017\n@channel please review failed tests.\n\n| Component | Tests Run | Tests Failed |\n|:-----------|:-----------:|:-----------------------------------------------|\n| Server | 948 | :white_check_mark: 0 |\n| Web Client | 123 | :warning: 2 [(see details)](https://linktologs) |\n| iOS Client | 78 | :warning: 3 [(see details)](https://linktologs) |" +} +``` + +This content will be displayed in the Town Square channel: + +![`test-automation` bot showing test results](incoming_webhooks_full_example.png) + +An example request displaying additional data in the right-hand side panel, by passing Markdown text into the `card` field of the `props` object would look like this: + +```http request +POST /hooks/xxx-generatedkey-xxx HTTP/1.1 +Host: your-mattermost-server.com +Content-Type: application/json + +{ + "channel": "town-square", + "username": "Winning-bot", + "text": "#### We won a new deal!", + "props": { + "card": "Salesforce Opportunity Information:\n\n [Opportunity Name](https://salesforce.com/OPPORTUNITY_ID)\n\n-Salesperson: **Bob McKnight** \n\n Amount: **$300,020.00**" + } +} +``` + +When there is a `props` object with a `card` property attached to the webhook payload, the posted message displays a small info icon next to the timestamp. Clicking this icon expands the right-hand side panel to display the Markdown included in the `card` property: + +![Clicking the info icon opens a right-hand side panel to display Markdown of the `card` property](https://user-images.githubusercontent.com/915956/64055959-ec0cfe80-cb44-11e9-8ee3-b64d47c86032.png) + +### Slack compatibility + +Mattermost makes it easy to migrate integrations written for Slack to Mattermost. Using the Slack ``icon_emoji`` parameter overrides the profile icon and the `icon_url` parameter and is supported from Mattermost v5.14. + +#### Translate Slack's data format to Mattermost + +Mattermost automatically translates the data coming from Slack: + +1. JSON payloads written for Slack, that contain the following, are translated to Mattermost markdown and rendered equivalently to Slack: + + - `<>` to denote a URL link, such as `{"text": "<https://mattermost.com/>"}` + - `|` within a `<>` to define linked text, such as `{"text": "Click <https://mattermost.com/|here> for a link."}` + - `<userid>` to trigger a mention to a user, such as `{"text": "<5fb5f7iw8tfrfcwssd1xmx3j7y> this is a notification."}` + - `<!channel>`, `<!here>`, or `<!all>` to trigger a mention to a channel, such as `{"text": "<!channel> this is a notification."}` + +2. You can override the channel name with a *@username*, such as `payload={"text": "Hi", channel: "@jim"}` to send a direct message like in Slack. +3. You can prepend a channel name with *#* and the message will still be sent to the correct channel like in Slack. + +#### Mattermost webhooks in GitLab using Slack UI + +GitLab is the leading open-source alternative to GitHub and offers built-in integrations with Slack. You can use the Slack interface in GitLab to add Mattermost webhooks directly without changing code: + +1. In GitLab, go to **Settings > Services** and select **Slack**. +2. Paste the incoming webhook URL provided by Mattermost from **Main Menu > Integrations > Incoming Webhooks**. +3. Optionally set the **Username** you'd like displayed when the notification is made. Leave the **Channel** field blank. +4. Select **Save**, then test the settings to confirm messages are sent successfully to Mattermost. + +#### Known Slack compatibility issues + +1. Referencing channels using `<#CHANNEL_ID>` does not link to the channel. +2. `<!everyone>` and `<!group>` are not supported. +3. Parameters "mrkdwn", "parse", and "link_names" are not supported. Mattermost converts Markdown by default and automatically links @mentions. +4. Bold formatting as `*bold*` is not supported (must be done as `**bold**`). +5. Webhooks cannot direct message the user who created the webhook. + +### Tips and best practices + + +1. If the `text` is longer than the allowable character limit per post, the message is split into multiple consecutive posts, each within the character limit. From Mattermost Server v5.0, [posts up to 16383 characters are supported](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +2. Your webhook integration may be written in any programming language as long as it supports sending an HTTP POST request. +3. Both `application/x-www-form-urlencoded` and `multipart/form-data` are supported `Content-Type` headers. If no `Content-Type` is provided, `application/json` is assumed. +4. To send a message to a direct message channel, add an "@" symbol followed by the username to the channel parameter. You can add your own username to send the webhook posts to a direct message channel with yourself. + + ``` + payload={"channel": "@username", "text": "Hello, this is some text\nThis is more text. :tada:"} + ``` + + This will send a message from the account that has set up the incoming webhook to the username after the "@" symbol. For example, if you create a webhook with the user `alice` and send a direct message to `bob` using a webhook, it will show up as a direct message from `alice` to `bob` regardless of other settings such as username. + + To send a message to a different direct message channel between two other users, you can specify the channel with the user IDs for the users separated with two underscore (_) symbols. To find the user ID you can use [mmctl user search](https://docs.mattermost.com/manage/mmctl-command-line-tool.html#mmctl-user-search). + + + ``` + payload={"channel": "6w41z1q367dujfaxr1nrykr5oc__94dzjnkd8igafdraw66syi1cde", "text": "Hello, this is some text\nThis is more text. :tada:"} + ``` + +### Troubleshoot incoming webhooks + +To debug incoming webhooks in **System Console > Logs**, set **System Console > Logging > Enable Webhook Debugging** to **true**, and set **System Console > Logging > Console Log Level** to **DEBUG**. + +Some common error messages include: + +1. `Couldn't find the channel`: Indicates that the channel doesn't exist or is invalid. Please modify the ``channel`` parameter before sending another request. +2. `Couldn't find the user`: Indicates that the user doesn't exist or is invalid. Please modify the ``user`` parameter before sending another request. +3. `Unable to parse incoming data`: Indicates that the request received is malformed. Try reviewing that the JSON payload is in a correct format and doesn't have typos such as extra `"`. +4. `curl: (3) [globbing] unmatched close brace/bracket in column N`: Typically an error when using cURL on Windows, when: + + - You have space around JSON separator colons, `payload={"Hello" : "test"}` or + - You are using single quotes to wrap the `-d` data, `-d 'payload={"Hello":"test"}'` + +If your integration prints the JSON payload data instead of rendering the generated message, make sure your integration is returning the `application/json` content-type. + +#### Why aren't my message attachments rendering? +Make sure `attachments` is a **top-level field** in your webhook JSON payload, not nested inside `props`. While the REST API uses `props.attachments`, incoming webhooks expect `attachments` at the top level. + +For further assistance, review the [Troubleshooting forum](https://forum.mattermost.org/t/how-to-use-the-troubleshooting-forum/150) for previously reported errors, or [join the Mattermost user community](https://mattermost.com/pl/default-ask-mattermost-community/) for troubleshooting help. + diff --git a/docs/develop/integrate/webhooks/index.md b/docs/develop/integrate/webhooks/index.md new file mode 100644 index 000000000000..fc04d7264f88 --- /dev/null +++ b/docs/develop/integrate/webhooks/index.md @@ -0,0 +1,29 @@ +--- +title: "Webhooks" +sidebar_position: 20 +--- + +Mattermost supports webhooks to easily integrate external applications into the server. + +### Incoming webhooks + +Use incoming webhooks to post messages to Mattermost public channels, private channels, and direct messages. Messages are sent via an HTTP POST request to a Mattermost URL generated for each application and contain a specifically formatted JSON payload in the request body. + +[Create an incoming webhook](/developers/integrate/webhooks/incoming) + +### Outgoing webhooks + +Outgoing webhooks will send an HTTP POST request to a web service and process a response back to Mattermost when a message matches one or both of the following conditions: + +- It's posted in a specified channel. +- The first word matches or starts with one of the defined trigger words, such as `gif`. + +Outgoing webhooks are supported in public channels only. If you need a trigger that works in a private channel or a direct message, consider using a [slash command](/developers/integrate/slash-commands) instead. + + +<Note title="Note"> +To prevent malicious users from trying to perform [phishing attacks](https://en.wikipedia.org/wiki/Phishing) a **BOT** indicator appears next to posts coming from webhooks regardless of what username is specified. +</Note> + + +[Create an outgoing webhook](/developers/integrate/webhooks/outgoing) diff --git a/docs/develop/integrate/webhooks/outgoing/index.md b/docs/develop/integrate/webhooks/outgoing/index.md new file mode 100644 index 000000000000..d718bd52a7e1 --- /dev/null +++ b/docs/develop/integrate/webhooks/outgoing/index.md @@ -0,0 +1,128 @@ +--- +title: "Outgoing webhooks" +sidebar_position: 20 +--- + +## Create an outgoing webhook + +Suppose you want to write an external application, which executes software tests after someone posts a message starting with the word `#build` in the `town-square` channel. + +You can follow these general guidelines to set up a Mattermost outgoing webhook for your application. + +1. First, go to **Product menu > Integrations > Outgoing Webhook**. If you don't have the **Integrations** option available, outgoing webhooks may not be enabled on your Mattermost server or may be disabled for non-admins. Enable them from **System Console > Integrations > Integration Management** or ask your System Admin to do so. +2. Select **Add Outgoing Webhook** and add name and description for the webhook. The description can be up to 500 characters. +3. Choose the content type by which the request will be sent. + - If `application/x-www-form-urlencoded` is chosen, the server will encode the parameters in a URL format in the request body. + - If `application/json` is chosen, the server will format the request body as JSON. +4. Select the public channel to receive webhook responses, or specify one or more trigger words that send an HTTP POST request to your application. You may configure either the channel or the trigger words for the outgoing webhook, or both. If both are specified, then the message must match both values. + + In our example, we would set the channel to `town-square` and specify `#build` as the trigger word. + + +<Note title="Note"> +If you leave the channel field blank, the webhook will respond to trigger words in all public channels of your team. Similarly, if you don't specify trigger words, then the webhook will respond to all messages in the selected public channel. +</Note> + + +5. If you specified one or more trigger words on the previous step, choose when to trigger the outgoing webhook. + + - If the first word of a message matches one of the trigger words exactly, or + - If the first word of a message starts with one of the trigger words. + +6. Finally, set one or more callback URLs that HTTP POST requests will be sent to, then select **Save**. If the URL is private, add it as a [trusted internal connection](https://docs.mattermost.com/configure/environment-configuration-settings.html#dev-allowuntrustedinternalconnections). + +7. On the next page, copy the **Token** value. This will be used in a later step. + + ![Dialog box showing `Setup Successful` message and `Token` in the description message](/integrate/faq/images/outgoing_webhooks_token.png) + +## Use an outgoing webhook + +1. Include a function in your application which receives HTTP POST requests from Mattermost. The POST request should look something like this: + + ```http request + POST /my-endpoint HTTP/1.1 + Content-Length: 244 + User-Agent: Go 1.1 package http + Host: localhost:5000 + Accept: application/json + Content-Type: application/x-www-form-urlencoded + + channel_id=hawos4dqtby53pd64o4a4cmeoo& + channel_name=town-square& + team_domain=someteam& + team_id=kwoknj9nwpypzgzy78wkw516qe& + post_id=axdygg1957njfe5pu38saikdho& + text=some+text+here& + timestamp=1445532266& + token=zmigewsanbbsdf59xnmduzypjc& + trigger_word=some& + user_id=rnina9994bde8mua79zqcg5hmo& + user_name=somename + ``` + + If your integration sends back a JSON response, make sure it returns the `application/json` content-type. + +2. Add a configurable *MATTERMOST_TOKEN* variable to your application and set it to the **Token** value from step 7. This value will be used by your application to confirm the HTTP POST request came from Mattermost. +3. To have your application post a message back to `town-square`, it can respond to the HTTP POST request with a JSON response such as: + + ```json + {"text": " + | Component | Tests Run | Tests Failed | + |:-----------|:----------|:-----------------------------------------------| + | Server | 948 | :white_check_mark: 0 | + | Web Client | 123 | :warning: [2 (see details)](http://linktologs) | + | iOS Client | 78 | :warning: [3 (see details)](http://linktologs) | + "} + ``` + +```text +which would render in Mattermost as: + +![Test results for Server, Web Client and iOS client](/integrate/faq/images/webhooksTable.png) +``` + +You're all set! + +## Parameters + +Outgoing webhooks support more than just the `text` field. Here is a full list of supported parameters. + + +| Parameter | Description | Required | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------| +| `text` | [Markdown-formatted](https://docs.mattermost.com/messaging/formatting-text.html) message to display in the post.<br/>To trigger notifications, use `@<username>`, `@channel`, and `@here` like you would in other Mattermost messages. | If `attachments` is not set, yes | +| `response_type` | Set to `comment` to reply to the message that triggered it.<br/>Set to blank or `post` to create a regular message.<br/>Defaults to `post`. | No | +| `username` | Overrides the username the message posts as.<br/>Defaults to the username set during webhook creation; if no username was set during creation, `webhook` is used.<br/>The [Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) configuration setting must be enabled for the username override to take effect. | No | +| `icon_url` | Overrides the profile picture the message posts with.<br/>Defaults to the URL set during webhook creation; if no icon was set during creation, the standard webhook icon (<CompassIcon name="webhook" />) is displayed.<br/>The [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) configuration setting must be enabled for the icon override to take effect. | No | +| `attachments` | [Message attachments](/developers/integrate/reference/message-attachments) used for richer formatting options. | If `text` is not set, yes | +| `type` | Sets the post `type`, mainly for use by plugins.<br/>If not blank, must begin with "`custom_`".<br/>Specifying a value for the `attachments` property will cause this field to be ignored, and the `type` value set to `slack_attachment`. | No | +| `props` | Sets the post `props`, a JSON property bag for storing extra or meta data on the post.<br/>Mainly used by other integrations accessing posts through the REST API.<br/>The following keys are reserved: `from_webhook`, `override_username`, `override_icon_url`, `webhook_display_name`, and `attachments`. | No | +| `priority` | Set the priority of the message. See [Message Priority](/integrate/reference/message-priority/) | No | + +An example response using more parameters would look like this: + +```http +HTTP/1.1 200 OK +Content-Type: application/json +Content-Length: 755 + +{ + "response_type": "comment", + "username": "test-automation", + "icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "text": "\n#### Test results for July 27th, 2017\n@channel here are the requested test results.\n\n| Component | Tests Run | Tests Failed |\n| ---------- | ----------- | ---------------------------------------------- |\n| Server | 948 | :white_check_mark: 0 |\n| Web Client | 123 | :warning: 2 [(see details)](http://linktologs) |\n| iOS Client | 78 | :warning: 3 [(see details)](http://linktologs) |\n\t\t ", + "props": { + "test_data": { + "server": 948, + "web": 123, + "ios": 78 + } + } +} +``` + +The response would produce a message like the following: + +![`test-automation` bot showing test results](outgoing_webhooks_full_example.png) + +Messages with advanced formatting can be created by including an [attachment array](/developers/integrate/reference/message-attachments) and [interactive message buttons](/developers/integrate/plugins/interactive-messages) in the JSON payload. diff --git a/docs/develop/integrate/webhooks/outgoing/outgoing_webhooks_full_example.png b/docs/develop/integrate/webhooks/outgoing/outgoing_webhooks_full_example.png new file mode 100644 index 000000000000..57db76170769 Binary files /dev/null and b/docs/develop/integrate/webhooks/outgoing/outgoing_webhooks_full_example.png differ diff --git a/docs/develop/integrate/zapier-integration/index.md b/docs/develop/integrate/zapier-integration/index.md new file mode 100644 index 000000000000..0bbd529faaba --- /dev/null +++ b/docs/develop/integrate/zapier-integration/index.md @@ -0,0 +1,145 @@ +--- +title: "Integrate with Zapier" +sidebar_position: 100 +--- + +You can create "zaps" that contain a trigger and an action for a task that you want to perform repeatedly. Zapier regularly checks your trigger for new data and automatically performs the action for you. + +Using Zapier you can integrate over 700 apps into Mattermost, including [Email](https://zapier.com/apps/email-parser/integrations), [GitHub](https://zapier.com/apps/github/integrations), [Jira](https://zapier.com/apps/jira/integrations), [Wufoo](https://zapier.com/apps/wufoo/integrations), [Salesforce](https://zapier.com/apps/salesforce/integrations), [Gmail](https://zapier.com/apps/gmail/integrations), and [many more](https://zapier.com/apps). + +## Zapier setup guide + +Zapier is authorized using OAuth2.0. The setup guide requires that a System Admin register the Zapier app on their Mattermost server and can then optionally allow any users with a Zapier account to create integrations. + +### Enable Zapier + +The first time you set up Zapier on your Mattermost instance you'll be required to enable an OAuth 2.0 application which can be used by everyone on your server. Your System Admin must execute these steps. + +To learn more about OAuth 2.0 applications, including what permissions they have access to, see the [OAuth 2.0 documentation](/developers/integrate/apps/authentication/oauth2). + +#### Enable OAuth 2.0 + +1. Open **Product menu > System Console**. +2. Under **Integrations > Integration Management**: + - Set [Enable OAuth 2.0 Service Provider](https://docs.mattermost.com/configure/configuration-settings.html#enable-oauth-2-0-service-provider) to **True**. + - If you’d like to allow Zapier integrations to post with customizable usernames and profile pictures, then set [Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) and [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) to **True**. + +#### Register Zapier as an OAuth 2.0 application + +1. Go to **Product menu > Integrations**. +2. Select **OAuth 2.0 Applications > Add OAuth 2.0 Application** and enter the following fields: + - **Is Trusted:** No + - **Display Name:** `Zapier` + - **Description:** `Application for Zapier integrations` + - **Homepage:** `https://zapier.com/` + - **Icon URL:** `https://cdn.zapier.com/zapier/images/logos/zapier-logomark.png` + - **Callback URLs:** `https://zapier.com/dashboard/auth/oauth/return/MattermostDevAPI/` +3. Select **Save** to create the application. + +You'll be provided with a **Client ID** and **Client Secret**. Save these values, or share them with your team to connect Zapier in the steps below. + +![image](zapier-oauth.png) + +### Create a Zap + +1. [Sign up](https://zapier.com/sign-up) for a free Zapier account or [log in](https://zapier.com/app/login) if you already have one. +2. On your [Zapier dashboard](https://zapier.com/app/dashboard) select **Make a Zap!**. +3. **Trigger App**: Events in this app will trigger new messages in Mattermost. + - **Select a Trigger App:** This will trigger new messages in Mattermost. If the app you’re looking to connect isn’t supported on Zapier, consider firing in-app events to a Gmail account and then connecting Gmail to Mattermost using Zapier. + - **Select the Trigger Event:** New messages in Mattermost will fire depending on these selected events in conjunction with any filters you apply. + - **Connect the Trigger Account:** Connect the account from which you’d like to trigger events and **Test** it to ensure Zapier can connect successfully. +4. **Filtering:** (Optional) Exclude certain events from triggering new messages. Learn more about using [Zapier custom filtering](https://help.zapier.com/hc/en-us/articles/8496276332557). + - Add a filter by selecting the small **+** icon before the **Action** step. + - Zapier supports **AND** and **OR** filters. Use the dropdown selectors to choose what events will allow the trigger to send a Mattermost message. +5. **Mattermost Action:** Connect your Mattermost Account and then specify posting details. + - **Select the Action App:** Search for “Mattermost”. + - **Select the Action Event:** Select **Post a Message**. The Mattermost team plans to expand the actions available here. + - **Connect the Action Account:** Select **Connect a New Account** and enter the following fields: + - **Mattermost URL:** This is the URL you use to access your Mattermost site. Don't include a slash at the end of the URL and don't append a team to the end of the server URL. For example, `https://community.mattermost.com/core` is the entire URL to the Contributors team on our community server. The **Mattermost URL** entered here would be `https://community.mattermost.com`. + - **Client ID/Secret:** If Zapier has been enabled as an OAuth application as per the steps above, then these values can be found by navigating to one of your Mattermost teams, then **Product menu > Integrations > OAuth 2.0 Applications**. Select **Show Secret** next to the Zapier app, then obtain the Client ID and Client Secret. + - **Log in to Mattermost:** After completing the above fields you will be prompted to log in to your Mattermost account if you're not logged in already. If you’re having trouble connecting then please read our troubleshooting guide. + - You'll then be prompted to allow Zapier to access your Mattermost account. Select **Allow**. + - **Message Post Details:** Specify the formatting of the messages and the team/channel where messages will be posted. + - **Team:** Choose the team where new messages will post. The dropdown should contain all teams you have access to on Mattermost. + - **Channel:** Choose the channel where new messages will post. The dropdown contains all channels that you belong to. Zapier cannot post into Direct Message channels. + - **Message Text:** Enter the message text that will post to Mattermost. This text can be formatted using [Markdown](https://docs.mattermost.com/messaging/formatting-text.html#formatting-text) and include the dynamic fields offered by your selected trigger app. Read our message formatting tips below. + + ![image](zapier-dynamic-fields.png) + +6. **Username:** This is the username that Zapier will post as. Zapier integrations will always appear with a `BOT` tag next to the username. In order for bots to override the username of the authorized user, your System Admin must set [Enable integrations to override usernames](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-usernames) to **True**. +7. **Icon URL:** This is the profile picture of the bot that Zapier will post as. In order for bots to override the profile picture of the authorized user, your System Admin must set [Enable integrations to override profile picture icons](https://docs.mattermost.com/configure/configuration-settings.html#enable-integrations-to-override-profile-picture-icons) to **True**. +8. **Test the Zap:** You may want to test your zap formatting in a Private Channel before posting in a channel that is visible to your entire team. + +## Message formatting tips + +Here are some useful tips we recommend to get the most out of Zapier integration: + +- **Markdown:** Mattermost supports the use of [Markdown](https://docs.mattermost.com/end-user-guide/collaborate/format-messages.html#use-markdown) in Zapier integrations. For example, use [heading markdown](https://docs.mattermost.com/messaging/formatting-text.html#headings) for Jira issue titles. +- **Custom Icons:** Use different icons for different services and Zapier integrations. +- **Hashtags:** Use hashtags to make your Zapier posts searchable. Use different hashtags for different services and Zapier integrations. For example, use the dynamic fields available in Zapier to include ticket a Jira ticket number in hashtags. This makes all conversation on a specific ticket instantly searchable by selecting the hashtag. +- **Quick Links:** Link back to the service that fired the zap through the use of Markdown [embedded links](https://docs.mattermost.com/messaging/formatting-text.html#links). For example, in our zaps we embed a link back to the service within the timestamp so it’s easy to take action on any zap. + +### Examples + +The Mattermost team has over 50 zaps integrated on our [Community Contributors tem](https://community.mattermost.com/core) used for internal communication and interacting with contributors. The [Community Heartbeat channel](https://community.mattermost.com/core/channels/community-heartbeat) integrates all our community services in one accessible location. These zaps are formatted in two ways depending on the service: + +**GitHub Issues and Comments, UserVoice Suggestions and Comments, GitLab MM Issues, GitLab Omnibus MM Issues** + +```md +#### [Title of issue] + +#[searchable-hashtag] in [external service](link to service) by [author](link to author profile) on [time-stamp](link to specific issue or comment) + +[Body of issue or comment] +``` + +![image](zapier-ch1.png) + +**Forum Posts, Jira Comments, Hacker News Mentions, Tweets** + +```md +> [forum post, media mention, or tweet] + +#[searchable-hashtag] in [external service](link to service) by [author](link to author profile) on [time-stamp](link to specific forum post, media mention or tweet) +``` + +![image](zapier-ch2.png) + +## Troubleshooting guide + +Possible solutions to common issues encountered during setup. + +### Cannot connect a Mattermost account + +1. `"Token named access_token was not found in oauth response!"` + a. Possible Solution: Try removing any trailing `/`'s on the end of your **Mattermost URL**. + - Correct: `https://community.mattermost.com` + - Incorrect: `https://community.mattermost.com/` + + ![image](zapier-error1.png) + +2. `"[Server URL] returned (404)"` + a. Possible Solution: The **Mattermost URL** cannot have a team appended to the end of the server URL. + - Correct: `https://community.mattermost.com` + - Incorrect: `https://community.mattermost.com/core` + + ![image](zapier-error2.png) + +3. `"[Server URL] returned (500) Internal Server Error"` + a. Possible Solution: The **Client Secret** might be incorrect. Verify this value by selecting **Integrations > OAuth 2.0 Applications** from the Product menu, or check with your System Admin. + + ![image](zapier-error4.png) + +4. `"Error Invalid client id"` + a. Possible Solution: The **Client ID** and/or **Client Secret** might have trailing spaces in them when copied and pasted into the form. Verify there are no trailing spaces in the **Client ID** and **Client Secret** fields then try again. + + ![image](zapier-trailing-space-error.png) + +5. `"Mattermost needs your help: We couldn't find the requested app"` + a. Possible Solution: The **Client ID** might be incorrect. Verify this value by selecting **Integrations > OAuth 2.0 Applications** from the Product menu, or check with your System Admin. + + ![image](zapier-error3.png) + +### Deauthorize the Zapier app + +If you'd like to deauthorize Zapier so it can no longer post through your connected account, select your avatar, then select **Profile > Security > OAuth 2.0 Applications**, then select **Deauthorize** on the Zapier app. diff --git a/docs/develop/integrate/zapier-integration/zapier-ch1.png b/docs/develop/integrate/zapier-integration/zapier-ch1.png new file mode 100644 index 000000000000..5f4e65024c40 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-ch1.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-ch2.png b/docs/develop/integrate/zapier-integration/zapier-ch2.png new file mode 100644 index 000000000000..01852194e200 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-ch2.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-dynamic-fields.png b/docs/develop/integrate/zapier-integration/zapier-dynamic-fields.png new file mode 100644 index 000000000000..fb9629b5261e Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-dynamic-fields.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-error1.png b/docs/develop/integrate/zapier-integration/zapier-error1.png new file mode 100644 index 000000000000..b185f8118d5b Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-error1.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-error2.png b/docs/develop/integrate/zapier-integration/zapier-error2.png new file mode 100644 index 000000000000..9b08b388a908 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-error2.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-error3.png b/docs/develop/integrate/zapier-integration/zapier-error3.png new file mode 100644 index 000000000000..42c9af8e5609 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-error3.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-error4.png b/docs/develop/integrate/zapier-integration/zapier-error4.png new file mode 100644 index 000000000000..4be90b6a9379 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-error4.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-oauth.png b/docs/develop/integrate/zapier-integration/zapier-oauth.png new file mode 100644 index 000000000000..2514060a1022 Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-oauth.png differ diff --git a/docs/develop/integrate/zapier-integration/zapier-trailing-space-error.png b/docs/develop/integrate/zapier-integration/zapier-trailing-space-error.png new file mode 100644 index 000000000000..693aeee5c56b Binary files /dev/null and b/docs/develop/integrate/zapier-integration/zapier-trailing-space-error.png differ diff --git a/docs/develop/internal/contributor.png b/docs/develop/internal/contributor.png new file mode 100644 index 000000000000..dd6203644349 Binary files /dev/null and b/docs/develop/internal/contributor.png differ diff --git a/docs/develop/internal/desktop-release-process.md b/docs/develop/internal/desktop-release-process.md new file mode 100644 index 000000000000..bd2ace4f65a1 --- /dev/null +++ b/docs/develop/internal/desktop-release-process.md @@ -0,0 +1,124 @@ +--- +title: "Desktop Release Process" +sidebar_position: 101 +--- + +***NOTE**: For the purposes of this document, the letter `X` will refer to the major version number, `Y` will refer to the minor version number, and `Z` will refer to the patch (dot) version number.* + +## Before you begin + +Before starting a new release, you want to make sure you do a few things: +- Check to make sure that there are no further Bug or Story tickets waiting to be merged. You can check JIRA to see if there are any tickets with the Fix version: `vX.Y Desktop App`. If there are, you'll want to wait until those have been merged. +- For major/minor releases, check to make sure that an Electron upgrade has been done shortly before the release. It's important to keep up with the latest security changes in Electron and Chrome. + +- If you work off of a fork of the `mattermost/desktop` repository, make sure your local master branch is up to date: + ``` + git checkout master && git fetch --all && git merge upstream/master` + ``` +- You might need to install `jq`, a parsing tool for JSON files: + ``` + // macOS + brew install jq + + // Linux (Ubuntu/Debian) + sudo apt-get install jq + + // Windows + choco install jq + ``` + +## Start a new release + +1. For a new major or minor release, check out the `master` branch and create a new release branch from it + ``` + git checkout master + git checkout -b release-X.Y + ``` + For a patch release, or if the branch already exists, just check out the existing release branch matching the version you're patching. + ``` + git checkout release-X.Y + ``` + +2. Run the release script to create the first release candidate. + Major/Minor release: + ``` + ./scripts/release.sh rc + ``` + Patch release: + ``` + ./scripts/release.sh patch + ``` + +3. When the script is finished, if it worked successfully, you should see an output like this: + ``` + [INFO ] Generating X.Y.Z release candidate 1 + [INFO ] Locally created an rc. In order to build you'll have to: + [INFO ] $ git push --follow-tags upstream release-X.Y:release-X.Y + ``` + If so, you can run the provided command. + +```text +If **not**, you may need to: +- Make sure there are no local uncommitted changes +- Make sure there are no tags matching the new version you're trying to create +``` + +4. **For major/minor releases only**: Once you have pushed the new release branch and tags, switch back to the `master` branch, and edit the `package.json` and `package-lock.json` files to reflect the next minor version. For example, if the version you're releasing is `5.0.0`, change the version number to `5.1.0`. When done, create a PR to bump `master` to the next release. + +5. Wait for the release candidate to finish building. You can monitor the progress [here](https://github.com/mattermost/desktop/actions/workflows/release.yaml). When it's finished, there will be a post in the `Release: Desktop Apps` channel with the new version number and a changelog. + +6. When the release process is finished, go to the `mattermost/desktop` GitHub repository and select **Releases**. +7. There should be a draft release of your new release candidate. Click the Pencil icon to edit. +8. Make sure it's checked off as a pre-release, then select **Publish Release**. + +## Generate additional release candidates + +If there are any bugs reported by QA, once they are fixed we will need to generate an additional release candidate to verify that any issues have been fixed. + +To generate additional release candidates, you'll simply run the following commands to kick it off: +``` +git checkout release-X.Y +./scripts/release.sh rc +git push --follow-tags upstream release-X.Y:release-X.Y +``` + +You can then follow steps **5-8** above to make sure the release is published. + +## Mac App Store + +Once the final release candidate has been approved by QA, you will need approval from the Mac App Store. To do so, we create a special release for them: +``` +git checkout release-X.Y +./scripts/release.sh pre-final +git push --follow-tags upstream release-X.Y:release-X.Y +``` + +### Submit to App Review + +In this case, you won't get any notifications from Mattermost or GitHub, as we are submitting directly to Apple at this point. From here, we will need to submit the app for review: + +1. Go to our app on [App Store Connect](https://appstoreconnect.apple.com/apps/1614666244/appstore) and log in with your credentials. + - If you do not have access to App Store Connect, you'll have to ask your team lead. +2. If there is not an unreleased version, select the **+** button in the top-left next to "macOS App", and fill out the version number (should just be `X.Y.Z`) +3. Copy the changelog for this version into the **"What's New in This Version"** section. +4. In the Build section, select **Add Build**. Find the build corresponding to the version that was just built. + - You should be able to recognize it by timestamp, but if not, grab the build from TestFlight and verify that the version number is correct. +5. Make sure under Version Release that "Manually release this version" is selected. +6. Once that's all done, you can select the **Add for Review** button and follow the prompts to submit a review. + +The review process is relatively quick in most cases, usually taking up to about 24 hours to complete. + +If the app is **approved** by App Review, you will get an email from App Store Connect saying "Your submission was accepted". From there, you can go back and release the app once the final release has been cut. + +If the app is **rejected** by App Review, you will get an email from App Store Connect saying "We noticed an issue with your submission". At that point, you'll need to log back into App Store Connect and review their comments. Make the necessary changes and you can follow the same process as above to re-submit for review until the app has been approved. + +## Cut the final release + +Once the app has been approved by all parties, we can cut the final release: +``` +git checkout release-X.Y +./scripts/release.sh final +git push --follow-tags upstream release-X.Y:release-X.Y +``` + +You can then follow steps **5-8** from the "Start a new release" section above to make sure the release is published, but make sure that the checkbox for 'Set as pre-release` is unchecked. diff --git a/docs/develop/internal/gitlab-omnibus.md b/docs/develop/internal/gitlab-omnibus.md new file mode 100644 index 000000000000..9cdd8c87ff9f --- /dev/null +++ b/docs/develop/internal/gitlab-omnibus.md @@ -0,0 +1,238 @@ +--- +title: "GitLab Omnibus" +sidebar_position: 130 +--- + +GitLab's Omnibus package bundles Mattermost Team Edition (TE) as an optional feature that can be enabled during installation. While GitLab maintains most of this integration, we send them new versions of Mattermost and occasionally assist with support on issues that relate to Mattermost. + +For every monthly GitLab release, we submit a merge request (MR) to [GitLab's repository](https://gitlab.com/gitlab-org/omnibus-gitlab/) to update the embedded version of Mattermost. GitLab releases in the middle of the month, so we'll generally submit the newest version of Mattermost to them at the start of the month to give time for the review process to happen. + +### Setting up GitLab Omnibus for development + +We maintain [our own fork of GitLab Omnibus](https://gitlab.com/mattermost/omnibus-gitlab) for use when submitting merge requests upstream. This should be cloned and kept up to date to ensure that we're testing and submitting against the latest code. + +These are the steps for checking out GitLab Omnibus and installing its dependencies: + +1. Clone our fork. + + ```bash + git clone https://gitlab.com/mattermost/omnibus-gitlab.git + ``` + +2. Add the upstream repository as a git remote. + + ```bash + git remote add upstream https://gitlab.com/gitlab-org/omnibus-gitlab.git + ``` + +3. Install Docker. GitLab packages all dependencies for building GitLab Omnibus in a Docker image which will be pulled later. + +### Submitting a new version of Mattermost + +These are the steps to update GitLab Omnibus with a new version of Mattermost: + +1. Ensure our fork's master branch is up to date with upstream. + + ```bash + git checkout master + git fetch upstream + git pull upstream master + git push + ``` + +2. Create a branch for the new version of Mattermost. + + ```bash + git checkout -b mattermost-X.Y + ``` + +3. Update the version of Mattermost downloaded at build time by modifying `config/software/mattermost.rb`. The `default_version` and `md5` fields need to be set to the match the latest release of Mattermost TE. + +4. Add an entry to the table in `doc/gitlab-mattermost/README.md` that maps GitLab versions to the corresponding Mattermost version. This step is not necessary for dot releases of Mattermost. + +5. Commit the changes made to `config/software/mattermost.rb` and `doc/gitlab-mattermost/README.md`. The commit message is used to generate a changelog entry, so it must include a second line containing the type of change made. For regular releases, it should be the following: + + ``` + Update Mattermost to X.Y + + Changelog: other + ``` + +For security backports, the type should be changed to "security". + +You can now test the build and submit an MR upstream. For an example of how the branch should look after that, see [here](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5068). + +### Building GitLab Omnibus + +As mentioned above, GitLab Omnibus is built in a Docker container containing all of the needed dependencies. To test it, the generated `.deb` package needs to be copied off of the Docker container and installed locally on the test server. Details on how to do that follow. + +These steps differ slightly from the more detailed ones available from GitLab ([link](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/doc/build/build_package.md)) since they were changed to keep the Git repository outside of Docker container, but they still work as of March 4, 2021. + +1. Get the current `BUILDER_IMAGE_REVISION` value from `.gitlab-ci.yml`. + +2. Run the builder in a Docker container. You may have to run these with `sudo` depending on permissions. This assumes you're using Ubuntu 18.04, but there are other Docker images available for different OSes. + + ```bash + docker pull registry.gitlab.com/gitlab-org/gitlab-omnibus-builder/ubuntu_18.04:${BUILDER_IMAGE_REVISION} + docker run -it registry.gitlab.com/gitlab-org/gitlab-omnibus-builder/ubuntu_18.04:${BUILDER_IMAGE_REVISION} bash + ``` + +3. Inside the container, clone the repo and change to the folder. Note that we're cloning our fork here. + + ```bash + git clone https://gitlab.com/mattermost/omnibus-gitlab.git ~/omnibus-gitlab + cd ~/omnibus-gitlab + ``` + +4. Change to the correct branch. + + ```bash + git checkout mattermost-X.Y + ``` + +5. Specify where to grab GitLab dependencies and assets from. + + ```bash + export ALTERNATIVE_SOURCES=true + export ASSET_REGISTRY=registry.gitlab.com + export COMPILE_ASSETS=true + ``` + +6. Install Ruby dependencies. + + ```bash + bundle install + bundle binstubs --all + ``` + +7. Build everything. This can take a couple of hours, so go grab lunch. + + ```bash + bin/omnibus build gitlab + ``` + +8. From the host machine, copy the compiled package out of the Docker container. + + ```bash + docker cp <container>:/root/omnibus-gitlab/pkg/<package>.deb . + ``` + +Note that Docker likes to eat up space on the disk without cleaning up after itself, so you'll want to remove old Docker containers with `docker rm` after building and copying the package to the host machine. + +### Installing and configuring GitLab Omnibus + +To install GitLab Omnibus with Mattermost, you'll need to configure your DNS with two domain names for the test server: one for GitLab and one for Mattermost. The following steps will use `gitlab.dev.mm` and `mattermost.dev.mm` as those domains. + +The package generated above can be installed with `sudo dpkg -i <package>.deb`. + +After first installing GitLab Omnibus, the external URLs for GitLab need to be configured, and Mattermost needs to be enabled in the GitLab config. To do that: + +1. Open `/etc/gitlab/gitlab.rb` using vi or your preferred text editor. + + ```bash + sudo vi /etc/gitlab/gitlab.rb + ``` + +2. Set the `external_url` to set GitLab's external URL. + + ```ruby + external_url "http://gitlab.dev.mm" + ``` + +3. Find and uncomment the line which sets `mattermost_external_url` and set it to Mattermost's external URL. + + ```ruby + mattermost_external_url "http://mattermost.dev.mm" + ``` + +4. Find and uncomment the line which sets `mattermost['enable']` and set it to `true`. + + ```ruby + mattermost['enable'] = true + ``` + +5. Leave your editor and use `gitlab-ctl` to reconfigure and restart its services. + + ```bash + sudo gitlab-ctl reconfigure + ``` + +After a few minutes, Mattermost and GitLab should be accessible from their respective URLs and GitLab sign-in should be automatically configured in Mattermost. The default admin login on GitLab has the username `root` and the password `5iveL!fe`. + +A few more commands for working with GitLab can be found [in our support documentation](https://docs.mattermost.com/process/support.html#other-debugging-information). + +### Testing Mattermost in GitLab Omnibus + +To test a new version of Mattermost running in GitLab, you'll have to test the three main ways they interact: logging in, creating a Mattermost team for a GitLab group, and adding notifications/slash commands to Mattermost. Using the same URLs as above, the steps for testing are: + +1. Test signing into Mattermost, once when not logged into GitLab and then again after having already logged in. + + 1. Visit `http://mattermost.dev.mm` in a browser. + + 2. Select **Sign in with GitLab**. You should be directed to the GitLab login screen. + + 3. Log in as any user. You should be sent back to Mattermost and logged in. + + 4. Log out and back in through the same process. You should skip the GitLab login screen since you were still logged into GitLab. + +2. Test creating a team in Mattermost for a new GitLab group. + + 1. Open `http://gitlab.dev.mm` in another window. + + 2. Select the plus icon in the header bar and select **New group**. + + 3. Enter a name for the group and check **Create a Mattermost team for this group**. + + 4. Go back to Mattermost. You should have been added to a new team matching the name of the group. + +3. Test adding the GitLab slash command. + + 1. Go to GitLab. + + 2. Select the plus icon in the header bar and select **New project**. + + 3. Select **Create blank project**. Enter a name and choose **Create project**. + + 4. From the sidebar on the left, go to **Settings > Integrations**. + + 5. Scroll down and select **Mattermost slash commands**. + + 6. Select **Add to Mattermost**. + + 7. Select the team you created above from the drop-down, then choose **Install**. + + 8. Go back to Mattermost and use `/<project>`. + + 9. When prompted, select **Connect your GitLab Account**, then choose **Authorize**. + + 10. You should now be able to use the slash command to do things like creating and viewing issues. + +4. Test adding GitLab notifications. + + 1. In Mattermost, go to **Integrations > Incoming Webhooks** and add an incoming webhook. + + 2. Copy the URL of the webhook and return to Mattermost. + + 3. Go to GitLab. From the sidebar on the left, go to **Settings > Integrations**. + + 4. Scroll down and select **Mattermost notifications**. + + 5. Paste the previously copied webhook URL into the **Webhook** field, then select **Save changes**. + + 6. Create an issue either from the GitLab UI or by using the previously configured slash command. A notification should be posted by the webhook in the channel you created. + +### Useful Files and Commands + +When working on GitLab Omnibus, the following files might be useful: + +- `config/software/mattermost.rb` - The script for downloading Mattermost during GitLab Omnibus's build and extracting the required files for it. +- `doc/gitlab-mattermost/README.md` - GitLab's documentation for using the embedded version of Mattermost. +- `files/gitlab-cookbooks/mattermost/libraries/mattermost_helper.rb` - The list of environment variables that GitLab Omnibus passes to Mattermost. +- `files/gitlab-cookbooks/mattermost/recipes/enable.rb` - The script to set up the required files and folders for Mattermost after installation. + +After installing GitLab Omnibus, the following files and folders might be useful: +- `/etc/gitlab/gitlab.rb` - The configuration files for GitLab Omnibus itself. `gitlab reconfigure [<service>]` must be called to apply any changes made. +- `/var/opt/gitlab/mattermost/config.json` - The location of Mattermost's `config.json`. +- `/var/log/gitlab/mattermost/logs/current` - The logs for Mattermost. +- `/var/opt/gitlab/mattermost/data` - The data directory for Mattermost. +- `/opt/gitlab/embedded/service/mattermost` - The static files used by Mattermost (web app code, i18n strings, email templates, etc). diff --git a/docs/develop/internal/index.md b/docs/develop/internal/index.md new file mode 100644 index 000000000000..63639ea452aa --- /dev/null +++ b/docs/develop/internal/index.md @@ -0,0 +1,5 @@ +--- +title: "Internal" +--- + +This is a place for documentation used internally by Mattermost employees. If you're not a Mattermost employee, you probably won't find anything useful here. diff --git a/docs/develop/internal/infrastructure/aws.md b/docs/develop/internal/infrastructure/aws.md new file mode 100644 index 000000000000..10c4ca407d7d --- /dev/null +++ b/docs/develop/internal/infrastructure/aws.md @@ -0,0 +1,60 @@ +--- +title: "AWS" +sidebar_position: 40 +--- + +Most of our infrastructure is hosted in AWS. + +## Accessing AWS + +You can sign into the web console for the master AWS account at this URL: + +https://mattermost.signin.aws.amazon.com/console + +After signing into the master account, you can access other accounts within the organization through role switching. This can be done from the dropdown on the right side of the console's menu bar, or you can use this link to switch to the developer account: + +https://signin.aws.amazon.com/switchrole?account=mattermost-dev&roleName=DeveloperRole&displayName=mattermost-dev + +This will require you to have signed in using MFA (When you first enable MFA, you'll have to sign out and back in again.). + +Once you switch to another account for the first time, you can quickly switch back and forth through the menu bar dropdown. + +## Enabling MFA (Multi-Factor Authentication) + +All developers that access AWS are required to enable MFA on their account(s). To enable MFA, follow these instructions: + +1. Download Authy, Google Authenticator, or any other MFA app for your smartphone of choice +2. Sign in to the AWS console with your username/password +3. From the 'Services' dropdown in the top-left corner of the AWS Console, choose 'IAM' from the 'Security, Identity, and Compliance' section +4. Click on 'Users' in the left-most column of the page +5. Find your username in the list of users in the centre of the page and click on it +6. Click on the 'Security Credentials' tab on the 'Summary' page that appears +7. Click on the pencil icon beside the 'Assigned MFA device' label in the 'Sign-in credentials' section +8. Follow the on-screen instructions to activate MFA on your device +9. Sign out of the AWS Console and sign back in + +## Accessing the Machines on AWS + +Most of the machines at the time of writing use an SSH key. If the description for the machine says it uses a key such as "mm-admin", "mm-ci", or "mm-dev", you'll need to get that key from someone else. + +If the machine does not have an SSH key associated with it, you'll need to generate an SSH key and have it signed by [Vault](../vault/). + +## Creating Machines on AWS + +Unless the machine is for your personal use only, use [Vault](../vault/) to control access to it: Create it *without* a key, then give it the following user data. + +```yaml +#cloud-config +bootcmd: + - cloud-init-per once ssh-users-ca echo "TrustedUserCAKeys /etc/ssh/trusted_ca_keys.pub" >> /etc/ssh/sshd_config +write_files: + - path: /etc/ssh/trusted_ca_keys.pub + content: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHDwQhQ3eRiW4CV5RKAJb0n9P/07aHrku5hAVc+M59ejZHPVD/4sEfSaKvIXNTcY5TsrudzEhY3nVBsJDcJjb5qC5ayy+JNGFNnF05JoZ4E3tggJm5HQv3Znm/N6s65ZMA0HsZojCvEf+K8P0AKdJWiZbZGF095+N3WL9bUQIxBmCIBVPAOQSTCo8QKeorFfxhw/XcmH3s/KDV52/hEt6RWTxaDup03r7y8fbVo81F4QJ2ItmHgL3vGSpJk/nkLB2RWxT6zp4JIEo7PZ6S2Gm/2jaW+B5DftUd0gI8GKo9+vhtWjEEbOdu/mz92/GHLHW+s3TnftLeXVs7a8UYwdh/qJ4P64U3wlA//igo7ToXONsZ4TwmcKg6FD9JAq+LKTC0+prx/Gulx5esiPS+bgnkM/CMuoWMtucLoXaNz9ELBmeb6QSj1a7T/4LFzBiefT977OIhglORnEsKvY0HXvzX66a73Lm3bC9mUXxi1HSJNTDdLOmnVK+ipVjViy2/C9KJmKL3ePwBQSJ9d9IK76W4SGXTGT4mTVBSSF6j+/2a4tXq9c3NCuEWyXgPJRP1t6Iib42oAosxPoZ4zeBZM05BHbveD2b0G/bmeaZRgsEaZ3Qjnr50a6Wke7Vr9q3QGjn3+8QEdUdrnCTN8dlloLYhwY9pgh1JEYDaCdPHSP1ppw== +``` + +## Best Practices + +* Do not configure services to use access keys that are associated with a human IAM user. Create separate IAM users for each service and write strict access policies for them. +* Do not create multiple IAM users for yourself. There are extremely few legitimate reasons for a human to need a second IAM user. +* Do not use access tokens if you can use IAM roles instead. For example, services running on an EC2 instance should almost never use tokens. +* We can create new AWS accounts within seconds. Don't be afraid to ask for a clean one. New production services can be placed in their own account for increased security and isolation. If you need to dirty up an account with experiments or testing, you can also do so in a dedicated account. diff --git a/docs/develop/internal/infrastructure/build.md b/docs/develop/internal/infrastructure/build.md new file mode 100644 index 000000000000..3280afe4279b --- /dev/null +++ b/docs/develop/internal/infrastructure/build.md @@ -0,0 +1,32 @@ +--- +title: "Build" +sidebar_position: 50 +--- + +## Jenkins + +### [build.mattermost.com](https://build.mattermost.com/) + +Most of our automated builds currently take place on Jenkins at [build.mattermost.com](https://build.mattermost.com/). + +#### Updating Go + +Builds on this Jenkins installation use a globally installed Golang distribution. To update it, you'll need to access the master instance and all of its slaves. Make sure the machine isn't in use, then run the following (replacing "1.22" with the desired Go version): + +```bash +wget https://storage.googleapis.com/golang/go1.22.linux-amd64.tar.gz +sudo su +rm -r /usr/local/go/ +tar -C /usr/local -xzf go1.22.linux-amd64.tar.gz +export PATH=$PATH:/usr/local/go/bin +env GOOS=windows GOARCH=amd64 go install std +env GOOS=darwin GOARCH=amd64 go install std +``` + +### [newbuild.mattermost.com](https://newbuild.mattermost.com/) + +The Jenkins installation at [newbuild.mattermost.com](https://newbuild.mattermost.com/) is currently used only by the webapp build, but is intended to be the home of new builds that use more modern practices such as containerization and configuration as code via [Jenkins pipelines](https://jenkins.io/doc/book/pipeline/). + +## Travis CI + +Some light-weight, open source projects use [Travis CI](https://travis-ci.org/). diff --git a/docs/develop/internal/infrastructure/grafana.md b/docs/develop/internal/infrastructure/grafana.md new file mode 100644 index 000000000000..ebfb70551dbf --- /dev/null +++ b/docs/develop/internal/infrastructure/grafana.md @@ -0,0 +1,22 @@ +--- +title: "Community Grafana" +sidebar_position: 20 +--- + +## Community Grafana + +The Grafana application is used to visualise the performance metrics of the community installations. The application runs in the Mattermost Cloud infrastructure in the same cluster that community installations are hosted. + +Grafana URL: https://grafana.mattermost.com + +## How to create and use the variable that enables selection between installations + +To get the different versions of installations in a simple variable, a variable of type query needs to be created with a query value of **label_values(v1alpha1_mattermost_com_installation)**. Then in each of the Grafana panels that selection between installations is required, the following filter should be applied in the query **\{v1alpha1_mattermost_com_installation=~"$mattermost"\}** where *mattermost* is the name of the variable created. An example of a query can be seen below: + +``` +sum(irate(mattermost_post_total{v1alpha1_mattermost_com_installation=~"$mattermost"}[5m])) +``` + +Due to the fact that the community servers are running in the cloud infrastructure and because the **community-daily** installation is managed by the cloud provisioner it needs to have a unique name, which in this case is **mm-swbn**. Therefore, users in the dropdown list of their community server variable will see the options **community**, **community-release** and **mm-swbn**, which is the community-daily. + +For any questions please contact the [cloud team](https://community-daily.mattermost.com/core/channels/cloud) diff --git a/docs/develop/internal/infrastructure/guidelines.md b/docs/develop/internal/infrastructure/guidelines.md new file mode 100644 index 000000000000..b2ae6d50331b --- /dev/null +++ b/docs/develop/internal/infrastructure/guidelines.md @@ -0,0 +1,28 @@ +--- +title: "Guidelines for New Infrastructure" +sidebar_position: 100 +--- + +## All new infrastructure should meet these requirements. + +### Authentication should be centralized. + +OneLogin, LDAP, IAM Groups, GitHub, or even Mattermost should define the level of access granted to a person. We want to minimize the number of steps required to onboard or offboard new team members and don't want to have to grant or revoke access service-by-service. + +For example, new machines in AWS should be created without a keypair and use Vault+OneLogin to control SSH access. + +### Credentials should be revocable. + +It should be possible to remove a person's access to resources without disrupting operations or others' access. + +For example, each service that requires an AWS access token should use its own instead of sharing a token with other services or employees. + +### Follow the principle of least privilege. + +If a service doesn't require access to a given resource, it shouldn't have access to that resource. + +### Configuration and provisioning should be reproducible. + +Usually this means everything you do should be reviewed and committed as code to a repo. The only thing you should have to do manually to deploy is `aws cloudformation deploy`, `serverless deploy`, `kubectl apply`, etc. + +If there's a good reason you can't define everything as code, create thorough step-by-step documentation of everything you do. diff --git a/docs/develop/internal/infrastructure/index.md b/docs/develop/internal/infrastructure/index.md new file mode 100644 index 000000000000..029718e15159 --- /dev/null +++ b/docs/develop/internal/infrastructure/index.md @@ -0,0 +1,6 @@ +--- +title: "Infrastructure" +sidebar_position: 10 +--- + +Select a topic to the left. diff --git a/docs/develop/internal/infrastructure/kubernetes/index.md b/docs/develop/internal/infrastructure/kubernetes/index.md new file mode 100644 index 000000000000..e75590786ca7 --- /dev/null +++ b/docs/develop/internal/infrastructure/kubernetes/index.md @@ -0,0 +1,6 @@ +--- +title: "Kubernetes" +sidebar_position: 10 +--- + +Select a topic to the left. diff --git a/docs/develop/internal/infrastructure/kubernetes/kubernetes-troubleshooting.md b/docs/develop/internal/infrastructure/kubernetes/kubernetes-troubleshooting.md new file mode 100644 index 000000000000..accf70198fc1 --- /dev/null +++ b/docs/develop/internal/infrastructure/kubernetes/kubernetes-troubleshooting.md @@ -0,0 +1,67 @@ +--- +title: "Kubernetes Maintenance" +sidebar_position: 10 +--- + +This page helps developers access and perform any type of maintenance in the Production Mattermost Kubernetes Cluster, which is running on AWS using EKS. + +## Set up a local environment to access Kubernetes (K8s) + +1. Make sure you have `kubectl` version 1.10 or later installed. If not, follow [these instructions](https://kubernetes.io/docs/tasks/tools/install-kubectl/). + +2. Use your OneLogin account to retrieve AWS Keys for the main Mattermost AWS account following [these instructions](../../onelogin-aws/) to install onelogin-aws command line application. + +Steps: + +- run `onelogin-aws-login` in the command line, it will ask your username, password and the two-factor auth. +- select `arn:aws:iam::521493210219:role/OneLoginPowerUsers` +- export the environment variable `AWS_PROFILE` which will be something like `521493210219/OneLoginPowerUsers/YOUR_EMAIL` + +3. Install `aws-iam-authenticator` following [these instructions](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#eks-prereqs) section `To install aws-iam-authenticator for Amazon EKS`. + +4. Get the kubeconfig + +Cluster Name: `mattermost-prod-k8s` + +```Bash +$ aws eks update-kubeconfig --name mattermost-prod-k8s --region us-east-1 +``` + +5. Confirm the set up is correct by checking if the puds are running in the K8s cluster: + +```Bash +$ kubectl get po -n community +NAME READY STATUS RESTARTS AGE +mattermost-community-0 1/1 Running 0 5h +mattermost-community-1 1/1 Running 0 23h +mattermost-community-jobserver-65985bfc47-88qq9 1/1 Running 0 5h + +$ kubectl get po -n community-daily +NAME READY STATUS RESTARTS AGE +mattermost-community-daily-0 1/1 Running 0 3h +mattermost-community-daily-1 1/1 Running 0 3h +mattermost-community-daily-jobserver-78f7cbf756-wls4f 1/1 Running 0 2h +``` + +If one or more pods show a status other than `Running`, use `kubectl describe` and `kubectl logs` to troubleshoot: + +```Bash +$ kubectl describe pods ${POD_NAME} -n ${NAMESPACE} +``` + +```Bash +$ kubectl logs pods ${POD_NAME} -n ${NAMESPACE} +``` + +## Namespaces + +We are using two namespaces to deploy Mattermost + +```text +- `community` namespace holds the Mattermost deployment which uses the Release Branch or a stable release. The ingress is points to `https://community.mattermost.com/` and `https://pre-release.mattermost.com/` +- `community-daily` namespace holds the Mattermost deployment which uses the `master` branch. The ingress points to `https://community-daily.mattermost.com/` +``` + +## Troubleshooting + +This section will be populated nas we run into issues and find solutions to them. diff --git a/docs/develop/internal/infrastructure/onelogin-aws.md b/docs/develop/internal/infrastructure/onelogin-aws.md new file mode 100644 index 000000000000..dc10845f0f32 --- /dev/null +++ b/docs/develop/internal/infrastructure/onelogin-aws.md @@ -0,0 +1,6 @@ +--- +title: "OneLogin and AWS" +sidebar_position: 45 +--- + +Please refer to https://docs.google.com/document/d/1S4i1XFGn7a1VXbtFV28GtbAe56m7fOHDZDgRmm5FBkg/edit#heading=h.ortqmqq1zjyx for the latest instructions to generate AWS credentials for development environments. diff --git a/docs/develop/internal/infrastructure/plugins.md b/docs/develop/internal/infrastructure/plugins.md new file mode 100644 index 000000000000..61febc40785a --- /dev/null +++ b/docs/develop/internal/infrastructure/plugins.md @@ -0,0 +1,17 @@ +--- +title: "Adding a Plugin to Community" +sidebar_position: 40 +--- + +To add a plugin to https://community.mattermost.com, you need to do the following: + +1. Add the configuration for your plugin and enable it by modifying PluginSettings and PluginState here: https://github.com/mattermost/platform-private/blob/master/kubernetes/community-kubernetes/configmap-config.yaml + - community-daily is using the configuration in the Database, so to configure the plugin you need first deploy the plugin and then access the system console and configure the plugin and enable it. +2. Add a line for your plugin here so it gets downloaded https://github.com/mattermost/platform-private/blob/master/kubernetes/community-kubernetes/configmap-plugins.yaml + - Copy those changes to https://github.com/mattermost/platform-private/blob/master/kubernetes/community-daily-kubernetes/configmap-plugins.yaml for community-daily +3. Upload your plugin to the `mattermost-public-plugins-kubernetes` S3 bucket on our main AWS account +4. Run https://build.mattermost.com/job/build-pushes/job/comunity_update/ to update community.mattermost.com (you can check the ONLY_CONFIG option) +5. Run https://build-push.internal.mattermost.com/job/kubernetes-servers/job/comunity-update/ to update community-daily.mattermost.com + + +See an example commit here: https://github.com/mattermost/platform-private/commit/ee33cfcf14c195143d6c5ca008218f7fd710820b diff --git a/docs/develop/internal/infrastructure/vpn-cloud.md b/docs/develop/internal/infrastructure/vpn-cloud.md new file mode 100644 index 000000000000..0de06c167a91 --- /dev/null +++ b/docs/develop/internal/infrastructure/vpn-cloud.md @@ -0,0 +1,158 @@ +--- +title: "VPN(CLOUD)" +sidebar_position: 20 +--- + +Table of contents +- [Setup VPN access on Pritunl](#setup-vpn-access-on-pritunl) + - [Viscosity client](#viscosity-client) + - [Pritunl client](#pritunl-client) +- [Gnome VPN Client](#gnome-vpn-client) +- [Older Setup of VPN access on OpenVPN](#older-setup-of-vpn-access-on-openvpn) + +## Setup VPN access on Pritunl + +### Viscosity client +1. Install a VPN client that supports DNS settings such as Visocity. + +```bash +brew cask install viscosity +``` + +2. Go to the [VPN server](https://pritunl.core.cloud.mattermost.com) and select **Sign in with OneLogin**. +Then connect with your OneLogin username and password and when prompt put the OTP (One Time Password). +Select `Show More` and hit `Download Profile` +<span style={{display: 'block', textAlign: 'center', width: '40%'}}>![Pritunl User Profiles](/img/vpn_cloud_4.png)</span> + + +3. Open the Viscosity application or your preferred VPN client and go to settings/preferences. + +4. Click + to import the profile you downloaded from the VPN server on the step 1 + <span style={{display: 'block', textAlign: 'center', width: '50%'}}>![Viscosity Profile Add](/img/vpn_cloud_2.png)</span> + +5. After your profile is imported, select to edit the entry, + +- On the General tab update the Address of the Remote Server to be: `pritunl.core.cloud.mattermost.com` as shown below: + <span style={{display: 'block', textAlign: 'center', width: '50%'}}>![General settings Viscosity](/img/vpn_cloud_5.jpg)</span> + +- Go to Networking tab and update the DNS settings. + * Select for the Mode to be `Full DNS`. + * As `Servers` put: `pritunl.core.cloud.mattermost.com` which is VPN's server IP. + * In `Domains` put: `cloud.mattermost.com`, this will split traffic for those domains + <span style={{display: 'block', textAlign: 'center', width: '50%'}}>![Network settings Viscosity](/img/vpn_cloud_6.jpg)</span> + +6. Add, if it is not there, in your `/etc/resolv.conf`: + `nameserver 10.247.0.2` + +```text +For MacOS, first check what CIDR was in the resolv.conf with `cat /etc/resolv.conf` and then you will need to run +`sudo networksetup -setdnsservers Wi-Fi 10.247.0.2 8.8.8.8 X.X.X.X` with your extra CIDRs that they were already in +your resolv.conf. Also check if you are connected with Wi-Fi, or to find your available devices by running +`networksetup -listallnetworkservices` and to replace it in the above command. +``` + +7. After following these steps you should be able to connect to VPN and then to resolve private DNS entries. + + +### Pritunl client +1. Go to the [VPN server](https://pritunl.core.cloud.mattermost.com) and select **Sign in with OneLogin** +Then connect with your OneLogin username and password and when prompt put the OTP (One Time Password). + +2. Select `Download Client` which will redirect you to download the Pritunl Client. + + Select your OS, download and install the appropriate client. +<span style={{display: 'block', textAlign: 'center', width: '40%'}}>![Pritunl Download Client](/img/vpn_cloud_7.jpg)</span> + +1. Go back to browser and copy the `Profile URI link` +<span style={{display: 'block', textAlign: 'center', width: '40%'}}>![Pritunl Download Client](/img/vpn_cloud_8.jpg)</span> + +4. Open the Pritunl client and paste the `Profile URI link` from previous step + into `Import Profile URI` + <span style={{display: 'block', textAlign: 'center', width: '40%'}}>![Pritunl import URI](/img/vpn_cloud_9.jpg)</span> + + +5. Click the burger button on the newly imported profile and select `Edit Config` + <span style={{display: 'block', textAlign: 'center', width: '40%'}}>![Pritunl Config](/img/vpn_cloud_10.jpg)</span> + +6. On the config change the line that says: + + `remote X.XXX.XXX.XX 1194 udp` to be: + +```text +`remote pritunl.core.cloud.mattermost.com 1194 udp` +``` + + +<Note title="NOTE"> +Do NOT change the port, it will be either 1194, 1195 or something else + <span style={{display: 'block', textAlign: 'center', width: '50%'}}>![Pritunl Config remote](/img/vpn_cloud_11.jpg)</span> +</Note> + + +7. Add, if it is not there, in your `/etc/resolv.conf`: + `nameserver 10.247.0.2` + +```text +For MacOS, first check what CIDR was in the resolv.conf with `cat /etc/resolv.conf` and then you will need to run +`sudo networksetup -setdnsservers Wi-Fi 10.247.0.2 8.8.8.8 X.X.X.X` with your extra CIDRs that they were already in +your resolv.conf. Also check if you are connected with Wi-Fi, or to find your available devices by running +`networksetup -listallnetworkservices` and to replace it in the above command. +``` + +8. After following these steps you should be able to connect to VPN and resolve private DNS entries. + +## Gnome VPN Client +1. Go to the [VPN server](https://pritunl.core.cloud.mattermost.com) and select **Sign in with OneLogin**. + +2. Connect with your OneLogin username and password and when prompted input the OTP (One Time Password). + +3. Click `Download Profiles` and save the `.tar` file to your filesystem. + +4. Extract the `.tar` file (`tar xf yourusername.tar`) and note the location of the `.ovpn` file. + +5. Open the Gnome Settings manager and navigate to **Network > VPN**. Click the `+` to create a new VPN connection. + +6. Choose **Import from file...**. + +7. Select the `.ovpn` file downloaded earlier through the file picker. + +8. Open the **IPv4** tab and select **Use this connection only for resources on its network**. + +9. Open the **IPv6** tab and select **Use this connection only for resources on its network**. + +10. If desired, rename the VPN to something friendlier in **Identity > Name**. + +11. Choose **Add** to save the configuration. + +12. From now on, enable the VPN through the taskbar picker in the upper right corner of Gnome. + +## Older Setup of VPN access on OpenVPN + + +1. Login to the [VPN server](https://vpn.cloud.mattermost.com) using your mattermost email and OneLogin password. Please select `connect` instead of `login` on the drop down menu. + * If login fails, ask Cloud team to check if your username is in the correct group + +2. Please refresh the page if it says: *Please click here to continue to download OpenVPN Connect. +You will be automatically connected after the installation has finished.* + +3. Download the user-locked profile. + <span style={{display: 'block', textAlign: 'center'}}>![VPN HomePage](/img/vpn_cloud_1.png)</span> + +4. Install a VPN client that supports DNS settings such as Visocity. + +```bash +brew cask install viscosity +``` + +5. Open the Viscosity application or your preferred VPN client and go to settings/preferences. + +6. Click + to import the profile you downloaded from the VPN server on the step 1 + <span style={{display: 'block', textAlign: 'center'}}>![Viscosity Profile Add](/img/vpn_cloud_2.png)</span> + +7. After your profile is imported, select to edit the entry, go to Networking tab and update the DNS settings. + * Select for the Mode to be `Split DNS`. + * As a Server IP put: `10.247.4.47` which is VPN's server IP. + * In Domains put: `cloud.mattermost.com`, this will split traffic for those domains + <span style={{display: 'block', textAlign: 'center'}}>![Viscosity VPN CIDR](/img/vpn_cloud_3_new.png)</span> + +8. After following these steps you should be able to connect to VPN and then to resolve private DNS entries. diff --git a/docs/develop/internal/member.png b/docs/develop/internal/member.png new file mode 100644 index 000000000000..7af1ad62565e Binary files /dev/null and b/docs/develop/internal/member.png differ diff --git a/docs/develop/internal/mobile-build-process/bump-build-number.md b/docs/develop/internal/mobile-build-process/bump-build-number.md new file mode 100644 index 000000000000..018bd28fad41 --- /dev/null +++ b/docs/develop/internal/mobile-build-process/bump-build-number.md @@ -0,0 +1,40 @@ +--- +title: "Bump Build Number" +sidebar_position: 2 +--- + +This must be done in your local copy of the [mattermost-mobile](https://github.com/mattermost/mattermost-mobile) + +1. Source the environment variables + ``` + export LC_ALL="en_US.UTF-8" + + ############ MATTERMOST BUILD ############ + export COMMIT_CHANGES_TO_GIT=true + export BRANCH_TO_BUILD=master + export GIT_LOCAL_BRANCH=build-number + export RESET_GIT_BRANCH=false + + export INCREMENT_BUILD_NUMBER=true + export INCREMENT_BUILD_NUMBER_MESSAGE="Bump app build number to" + ``` + + +<Note title="Env vars"> +Alternatively you can copy the environment variables to the `mattermost-mobile/fastlane/.env` file. +</Note> + + + +<Note title="Specify build number"> +Sometimes you need to specify the build number instead of just increasing it by one.<br />In that case add the environment variable `BUILD_NUMBER` and set the build number. +</Note> + + +2. Increase the build number of the app. + - ``$ cd fastlane`` in the mattermost-mobile directory. + - run ``$ fastlane set_app_build_number``. + +3. Submit a PR on the mobile repo with the branch `build-number`. + +4. Merge the PR into master and cherry-pick to the release branch. diff --git a/docs/develop/internal/mobile-build-process/bump-version-number.md b/docs/develop/internal/mobile-build-process/bump-version-number.md new file mode 100644 index 000000000000..6e276c9982b3 --- /dev/null +++ b/docs/develop/internal/mobile-build-process/bump-version-number.md @@ -0,0 +1,41 @@ +--- +title: "Bump Version Number" +sidebar_position: 1 +--- + +This must be done in your local copy of the [mattermost-mobile](https://github.com/mattermost/mattermost-mobile) + +1. Source the environment variables + ``` + export LC_ALL="en_US.UTF-8" + + ############ MATTERMOST BUILD ############ + export COMMIT_CHANGES_TO_GIT=true + export BRANCH_TO_BUILD=master + export GIT_LOCAL_BRANCH=version-number + export RESET_GIT_BRANCH=false + + + export INCREMENT_VERSION_NUMBER_MESSAGE="Bump app version number to" + export VERSION_NUMBER= + ``` + + +<Note title="Env vars"> +Alternatively you can copy the environment variables to the `mattermost-mobile/fastlane/.env` file. +</Note> + + + +<Note title="Specify version number"> +Set the variable `VERSION_NUMBER` to X.X.X (eg: 1.17.0). +</Note> + + +2. Increase the version number of the app. + - ``$ cd fastlane`` in the mattermost-mobile directory. + - run ``$ fastlane set_app_version``. + +3. Submit a PR on the mobile repo with the branch `version-number`. + +4. Merge the PR into master and cherry-pick to the release branch. diff --git a/docs/develop/internal/mobile-build-process/index.md b/docs/develop/internal/mobile-build-process/index.md new file mode 100644 index 000000000000..57ede906d702 --- /dev/null +++ b/docs/develop/internal/mobile-build-process/index.md @@ -0,0 +1,63 @@ +--- +title: "Mobile Build Process" +sidebar_position: 31 +--- + +## 1. Prerequisites + +In order to run all the Fastlane scripts, you will need an Apple machine. The steps can be run manually, but the scripts make things much more easy. + +You must have ruby 2.7. You can use [`rbenv`](https://github.com/rbenv/rbenv) to manage your ruby version. + +The Fastlane scripts rely heavily on environment variables. In order to manage them, we recommend defining them in a `.env` file in the fastlane folder (`PROJECT_DIR/fastlane/.env`). + +The first time you run this, you will need to install fastlane. On the fastlane folder (`PROJECT_DIR/fastlane/`) run `bundle install`. + +## 2. Build and version bump +To bump the build number, we recommend using the following set of environment variables: +``` +export INCREMENT_BUILD_NUMBER=true +export BUILD_NUMBER=X +export COMMIT_CHANGES_TO_GIT=true +export BRANCH_TO_BUILD=main +export GIT_LOCAL_BRANCH=bump-build +``` +Where X is the build number. The build number **MUST** always be greater than the last build number used. Uploading two builds with the same build number to the stores will fail. + +For version bumps, also add the following environment variable: +``` +VERSION_NUMBER=X.Y.Z +``` +Where X.Y.Z is the version number. + +With the setup done, you can run the following commands, depending on what you want to bump: +- `bundle exec fastlane set_app_build_number` to bump only the build number. +- `bundle exec fastlane set_app_version` to bump only the version number. +- `bundle exec fastlane set_app_version_build` to bump both the build and version number. + +The command should create the branch, and commit the changes. Once that is done, push the branch and create a PR. + +## 3. Create a build and publish +When the version bump PR is merged, you can create the build. The build is created on the CI system and automatically sent to the stores. The Release Team takes care of publishing them in the beta or release track. + +In order to trigger the CI, you must create a new branch based on the commit you want to compile (usually the head of the main branch or the head of the release branch). The branch name has to follow one of the following patterns: + +- `build-X` where x is the build number for beta apps. +- `build-release-x` where x is the build number for official releases. + +When you create the branch, you will see that the CI system will build the apps. When the process finishes, the apps get posted in the ["Release: Mobile Apps"](https://community.mattermost.com/core/channels/release-mobile-apps) channel. + +If the build fails for one platform only, you shouldn't run the build for both platforms again because it will have a duplicate build number which will fail on upload. To release for one platform at a time, use the following branch names: +- `build-android-beta-X` where X is the build number for Android beta apps. +- `build-android-release-X` where X is the build number for official Android releases. +- `build-ios-beta-X` where X is the build number for iOS beta apps. +- `build-ios-release-X` where X is the build number for iOS official releases. + +## 4. Common problems and workarounds +Fastlane forces me to update it, and now the version won't bump because the branch is not clean. + +You can set the `COMMIT_CHANGES_TO_GIT` environment variable to `false`. That will remove the clean check, but you will need to commit the changes yourself. + +# 5. Environment variables +- [Android](https://developers.mattermost.com/contribute/more-info/mobile/build-your-own/android/#5-configure-environment-variables) +- [iOS](https://developers.mattermost.com/contribute/more-info/mobile/build-your-own/ios/#4-configure-environment-variables) diff --git a/docs/develop/internal/mobile-build-process/troubleshooting.md b/docs/develop/internal/mobile-build-process/troubleshooting.md new file mode 100644 index 000000000000..35daaeabdbfd --- /dev/null +++ b/docs/develop/internal/mobile-build-process/troubleshooting.md @@ -0,0 +1,28 @@ +--- +title: "Troubleshooting" +sidebar_position: 3 +--- + +##### Error message +Unable to resolve module `mattermost-redux/client` from `/Users/****/workspace/mm/mobile-build-app-pr/share_extension/android/index.js`: Module `mattermost-redux/client` does not exist in the Haste module map. + +##### Solution +Make sure the **mattermost-redux** package is build correctly. + +The `make build` set of commands uses `npm ci`, sometimes the `npm ci` command will not run +the *prepare* script used by `mattermost-redux` thus the library will not built causing the +mobile build to fail. + + - ssh to the build machine (MacStadium) + - ``cd ~/workspace/mm/mattermost-mobile-prod-release/mattermost-mobile`` + - ``rm -rf node_modules`` + - ``npm cache clean --force`` + - ``npm i`` + - Finally make sure ``ls node_modules/mattermost-redux/`` shows that mattermost-redux was built. + + +<Note title="Credentials"> +The IP of the build machine user/pwd can be found in the [build-machine-credentials.md](https://github.com/mattermost/mattermost-mobile-private/blob/master/build-machine-credentials.md) file that belongs to the +mattermost-mobile-private repo. +</Note> + diff --git a/docs/develop/internal/offboarding.md b/docs/develop/internal/offboarding.md new file mode 100644 index 000000000000..ec62081bd4c4 --- /dev/null +++ b/docs/develop/internal/offboarding.md @@ -0,0 +1,67 @@ +--- +title: "Offboarding" +sidebar_position: 30 +--- + +When an employee leaves the company, any credentials they had should be revoked. The more things they had access to, the harder this is, so when onboarding, it's important to give them only the necessary privileges. It's also important to avoid shared secrets that cannot be revoked from one person. + +The following is a list of things to do. It should be kept as complete and up-to-date as possible, but treated as non-comprehensive when offboarding someone. + +* **Delete AWS IAM users** – Ideally, each employee only has one in the master account and uses role delegation to access other accounts. But all accounts should be checked just in case. + +* **Rotate AWS access keys** – If the employee created IAM users and access keys for programmatic use in CI or other systems, they should be rotated. + +* **Delete AWS accounts** – If the employee had their own AWS account created within the organization, it should be deleted. The default role of "OrganizationAccountAccessRole" should be present in the account and can be used to delete it. + +* **Delete the user's LDAP account** + +* **Remove OneLogin user from the organization** + +* **Remove the user from the GitHub organization and repos** – Ideally, you would just need to remove the user from the organization, but they may have also been explicitly added as contributors to some repositories. As a quick check, a GitHub admin can use the following GraphQL to get an overview of Mattermost's repositories and collaborators (Mind the pagination, you may need multiple queries.): + + ```graphql + { + organization(login: "mattermost") { + members(first: 100) { + nodes { + login + } + } + repositories(first: 100) { + nodes { + name + collaborators(first: 100) { + edges { + node { + login + } + permission + } + pageInfo { + hasNextPage + } + } + } + pageInfo { + hasNextPage + } + } + } + } + ``` + +* **Rotate GitHub access tokens** – Such as Mattermod's. + +* **Revoke any secrets that may have been committed to Git repos** – Review [platform-private](https://github.com/mattermost/platform-private) for example. Once revoked, do not commit new secrets to Git. If you feel like you absolutely have to commit them, at least encrypt them with something like [AWS KMS](https://aws.amazon.com/kms/). + +* **Revoke SSH keys** – If the user had access to our "mm-ci", "mm-admin", etc. keys, they should be revoked. It would be a great time to replace keys with [certificate-based access via Vault](/internal/infrastructure/vault/) so developers can just SSH in with OneLogin. Or better yet, install the AWS SSM agent and use [Run Command](https://docs.aws.amazon.com/systems-manager/latest/userguide/execute-remote-commands.html) where possible instead of SSH. + +* **Revoke Azure access** + +* **Rotate Kubernetes key** + +* **Remove the user from private Mattermost teams and channels** + +* **Regenerate invite links for Mattermost teams** + +* **Delete WordPress account for https://mattermost.com/** \ No newline at end of file diff --git a/docs/develop/internal/onboarding/index.md b/docs/develop/internal/onboarding/index.md new file mode 100644 index 000000000000..6f8b745bfa08 --- /dev/null +++ b/docs/develop/internal/onboarding/index.md @@ -0,0 +1,6 @@ +--- +title: "Onboarding" +sidebar_position: 30 +--- + +Select a topic to the left. diff --git a/docs/develop/internal/onboarding/manager-guide.md b/docs/develop/internal/onboarding/manager-guide.md new file mode 100644 index 000000000000..250ac5a8083f --- /dev/null +++ b/docs/develop/internal/onboarding/manager-guide.md @@ -0,0 +1,42 @@ +--- +title: "Manager Guide" +sidebar_position: 30 +--- + +### Mentor For The Day +- Schedule a 1-1 each day between new staff and team members (including QA and PM) and other devs who would be relevant to meet with for the first two weeks + - These meetings should be about 30 minutes and do not need to be focused on work topics. They should spend some time getting to know each other + - The first 1-1 should be between you and the new staff member +- In addition to the above 1-1s, you should meet personally with the new staff member for 5-10 minutes every day for the first week or so to make sure everything is going well + +### Channels and Teams +- Make sure new staff is added to the private team `Private Core` and all relevant channels +- See [here](/internal/onboarding/new-staff-guide/#channels-and-teams) for basic list of channels + +### Meetings and Accounts +- Add new staff member to all appropriate meetings + +### OneLogin Account Set-up +- Login to OneLogin and go to https://mattermost.onelogin.com/admin +- Click Users -> All Users > New User +- Fill out first/last name, username, manager (use firstname.lastname as username) +- Save user, then go to Applications tab +- Add them to Developer, VPN, Vault, and Jenkins groups and save +- For the new user, go to More Actions and click Send Invitation (without this they won't get their invite) +- If the user is marked as unlicensed, ask Carlos or Corey to increase OneLogin seat count + +### GitHub Group Set-up +- The membership to the Mattermost Github organization is handle by Onelogin / Lamdba function that adds the user in the correct Github Team. +- For that work we need to add the user's GitHub handle in the user's OneLogin account. Please message @dschalla or @cpanato to add the data in OneLogin. + +### Core Committer Mug +- Message @hanna.park and ask her to send the new hire their core committer mug + +### Release Dates Google Calendar +- Message @amy.blais and ask her to add the new hire to the Mattermost Release Dates google calendar (if not added already) + +### R&D Google Calendar +- [This](https://calendar.google.com/calendar/embed?src=mattermost.com_u77qllr0v45a3vss7rqcutt7d4%40group.calendar.google.com&ctz=America%2FLos_Angeles) is a shared calendar for R&D related meetings and events. All events on this calendar are open to anyone who wants to join, and are shared here as a way for people both inside and outside R&D to be able to participate in discussions that they're interested in, and also keep track of the work that's happening in R&D. + +### Jira Access +- Message @daniel.sischy and ask him to add the new hire to ``jira-developers`` and ``internal`` groups in Jira (if not added already) diff --git a/docs/develop/internal/onboarding/new-staff-guide.md b/docs/develop/internal/onboarding/new-staff-guide.md new file mode 100644 index 000000000000..8c8c3379d7e6 --- /dev/null +++ b/docs/develop/internal/onboarding/new-staff-guide.md @@ -0,0 +1,102 @@ +--- +title: "New Staff Guide" +sidebar_position: 10 +--- + +### Helpful links + +- https://docs.mattermost.com/developer/developer-flow.html +- [Jira bug ticket process](https://docs.mattermost.com/process/new-bug-tickets.html) +- [Feature flag process](https://developers.mattermost.com/contribute/server/feature-flags/) +- [RN build process](https://developers.mattermost.com/internal/mobile-build-process/) if you are joining the Mobile team +- [Release processes](https://handbook.mattermost.com/operations/research-and-development/product/release-process/release-overview) docs +- Security: Read through the security channel/issues spreadsheet and look at past exploits +- Developer Reading List: Located in the header of the public [Developer channel](https://community.mattermost.com/core/channels/developers) + +### Mentor For The Day + +- Meet with a dev team member every day for about 30 mins. Dev member will rotate daily to expose the new hire to everyone. The process will run for approximately two weeks. The goal is to get to know each other, feel free to talk about non-work related stuff +- Schedule to be sent by manager in channel + +### Meet with a few PMs + +- List to be sent by manager in channel + +### Channels and Teams + +- You should be added to the private team `Staff` and join the following channels: + - Alerts + - Announcements + - Customer Success + - Customer Support + - Confidential Bugs + - Private Off-Topic (optional) + - R&D Meeting + - Social: * (optional) + - Stand-up + - Welcome +- Private channels to join in `Contributors` + - Security + - Confidential Bugs + - Developers: Private + - MVP Discussion +- Public channels to join in `Contributors` + - Developers + - Developers Meeting + - Bugs + - Contributors + - Release Announcements + - Toolkit (optional) + - Redux (optional) + - Installers and Images (optional) + - Native Mobile Apps (optional) + - Desktop App (optional) + - Developers: Performance (optional) + - Peer-to-peer Help (optional) + +### Meetings and Accounts + +- You manager should notify `people-ops` and have you added to all appropriate meetings + - `people-ops` will also set up your `@mattermost.com` email +- DevOps to setup various accounts as needed + - Add to email groups + - dev-ops + - build + - LDAP account + - OneLogin account + - VPN account + - Add to GitHub contributors + - Add IAM user to master AWS account + - Add to Azure + +### Daily Mentor Meeting: Potential Discussion Topics + +- GitHub workflow +- Jira workflow +- Sprint planning +- Mattermod +- Internal Jenkins build server +- External Jenkins build server +- API docs +- Web app structure +- Server structure +- React Native apps +- Desktop app +- Enterprise repo +- Platform-private repo +- Release process +- Org chart and roles +- Operation gaming +- Product analytics + +## GitHub Mattermost Organization Membership + +If you've previously contributed to a repository within the `mattermost` organization, you'll show up with a `Contributor` tag: + +![contributor](/internal/contributor.png) + +Once you're added to the `mattermost` organization on GitHub, you'll show up with the `Member` tag: + +![member](/internal/member.png) + +By default, however, this tag only appears to other members within the organization. Anyone outside will continue to see only the `Contributor` tag. If you want your membership in the `mattermost` organization to be public, follow the steps on https://help.github.com/articles/publicizing-or-hiding-organization-membership/ to find your username on https://github.com/orgs/mattermost/people and change your `Organization visibility` to `Public`. diff --git a/docs/develop/internal/plugin-release-process.md b/docs/develop/internal/plugin-release-process.md new file mode 100644 index 000000000000..8d1a8dbd1273 --- /dev/null +++ b/docs/develop/internal/plugin-release-process.md @@ -0,0 +1,8 @@ +--- +title: "Plugin Release Process" +sidebar_position: 101 +--- + +Redirecting to handbook.mattermost.com + +<meta http-equiv="refresh" content="0; url=https://handbook.mattermost.com/operations/research-and-development/engineering/plugin-release-process" /> \ No newline at end of file diff --git a/docs/develop/internal/qa/index.md b/docs/develop/internal/qa/index.md new file mode 100644 index 000000000000..f0e8e2b36f5b --- /dev/null +++ b/docs/develop/internal/qa/index.md @@ -0,0 +1,6 @@ +--- +title: "QA" +sidebar_position: 20 +--- + +Select a topic to the left. diff --git a/docs/develop/internal/rd-teams.md b/docs/develop/internal/rd-teams.md new file mode 100644 index 000000000000..cd89a553b6aa --- /dev/null +++ b/docs/develop/internal/rd-teams.md @@ -0,0 +1,8 @@ +--- +title: "R&D Teams" +sidebar_position: 110 +--- + +Redirecting to handbook.mattermost.com + +<meta http-equiv="refresh" content="0; url=https://handbook.mattermost.com/operations/research-and-development" /> \ No newline at end of file diff --git a/docs/develop/internal/sustained-engineering.md b/docs/develop/internal/sustained-engineering.md new file mode 100644 index 000000000000..281464e30879 --- /dev/null +++ b/docs/develop/internal/sustained-engineering.md @@ -0,0 +1,6 @@ +--- +title: "Sustained Engineering Team" +sidebar_position: 120 +--- + +This content [has moved to the handbook](https://handbook.mattermost.com/operations/research-and-development/engineering/team). \ No newline at end of file diff --git a/docs/develop/internal/tips-and-best-practices.md b/docs/develop/internal/tips-and-best-practices.md new file mode 100644 index 000000000000..b3f9091cd02e --- /dev/null +++ b/docs/develop/internal/tips-and-best-practices.md @@ -0,0 +1,20 @@ +--- +title: "Tips and Best Practices" +sidebar_position: 102 +--- + +## Engaging with Community + +Mattermost takes pride in working with the community and we encourage each Mattermost developer to find one or more community members to work with. Here is a basic three-step process for engaging with the community: + +1. **Welcoming** - Be welcoming and warm to new members. Go out of your way to say hello, offer them help and overall make them feel like part of the Mattermost tribe. +2. **Shepherding** - Find pull requests members are struggling with. Offer to help get their issues resolved. Go as far as helping them write code, such as making small improvements or adding unit tests. Not every person is familiar with every part of the system. When in doubt start with the oldest pull request. +3. **Guidance** - Once someone has been shepherded, then offer to guide them. Make suggestions on what the community would like to see next. For instance, you could say `Hey that was a cool <feature/improvement> you submitted, but we have a lot of people asking about feature <XYZ>, would you like to try? I can help you if needed.` Another option is to suggest them to work on a Mattermost campaign. Overall, make them feel like part of the Mattermost tribe. + +Video calls are also encouraged, something many find richly satisfying. Sample questions to start the video calls with include + +1. Where in the world do you live? (great conversation starter) +2. How did you get involved with Mattermost? +3. Anything we can do to improve the contributor process? + +For an excellent video on how to build effective open source campaigns, [see here](https://www.youtube.com/watch?v=rTiLgSF5KHQ). diff --git a/docs/develop/internal/writing-a-blog-post.md b/docs/develop/internal/writing-a-blog-post.md new file mode 100644 index 000000000000..dbf22aa31f1d --- /dev/null +++ b/docs/develop/internal/writing-a-blog-post.md @@ -0,0 +1,83 @@ +--- +title: "Writing a Blog Post" +sidebar_position: 105 +--- + +Been to a conference recently? Worked on something cool? Got something else Mattermost-related you want to post about? Writing a blog post is a great way to share your experience with the community. + +Blog posts can cover a wide range of topics, such as: + +- Addressing a customer-facing problem +- Describing an experience with Mattermost/your Mattermost implementation +- Sharing information about cool tech +- Sharing feedback on an interesting talk or conference +- Part of a Hackathon project +- A Help Wanted ticket +- A knowledge-share and call for feedback/community engagement +- A discussion of a specific problem or improvement that you worked on +- A breakdown of a new process or technology you’re using + + +Once you've got the topic in mind - what it's about, what you want to achieve with the post, and what the next steps are - it’s sometimes helpful to start writing the conclusion and expand to your jumping off point to introduce your topic/idea/discovery draws. + +Make a note of your intended audience, so you can decide whether to use very technical terms/jargon, or spend time unpacking terminology. + + +Structuring Your Blog Post +-------------------------- + +These are some ideas of the parts of a blog post. They’re not mandatory and not all blog posts will include every aspect. What works for some posts won’t work for others. + +- **Introduction/Overview:** An opening paragraph detailing the goal of the post and the technologies/processes that were used. For example: “Monitoring is an essential part of our organization. When we started, we were using “x” which gave us insight into “y”. With our growth as a company, we need more insights into areas that “x” can’t handle, so we decided to switch to “a” and “b””. +- **Problem/Solution/Situation:** Detail the problem or scenario that sparked the blog post. For example, “Our monitoring tools weren’t giving us the insight we needed, and were costing a lot of money. We decided to try solve this by using multiple tools that could be used or on standby as needed. This saves money.” +- **Environment:** Plugins, software, specific configurations/services used. +- **Steps:** The process followed to get from conception to implementation, for example, how the monitoring was configured initially, and the new configuration. Include code samples and/or screenshots. How long it took to build a database/history. What steps were taken to create a good alert system. +- **Samples:** Code samples are often useful, as are screenshots/animated GIFs if a complex process is being demonstrated. +- **Benefits:** The benefits of the exercise or process of the blog post - man-hours saved, budget target achieved, lower overheads, etc. +- **Conclusion:** Whether the exercise or process has long-term potential, whether it’s still in place, or whether it was a failure. + +Some popular blogs that are worth reading include: +- https://blog.golang.org/ +- https://dave.cheney.net/ +- https://technology.riotgames.com/ +- https://www.freecodecamp.org/news/ +- https://alistapart.com/ + +The [/site/content/blog/](https://github.com/mattermost/mattermost-developer-documentation/tree/master/site/content/blog) folder also has some good examples. + +Writing Your Blog Post +---------------------- + +The steps below outline the process involved in creating the blog post file from a cloned repo, and then submitting the PR. + +1. Clone https://github.com/mattermost/mattermost-developer-documentation. +2. Create a new .md file in the [/site/content/blog/](https://github.com/mattermost/mattermost-developer-documentation/tree/master/site/content/blog) folder. + - Use `YYYY-MM-DD-<your-blog-post-title>.md` as the filename. + +3. Paste this template into your file + + ``` + --- + title: <user readable title of your blog post, e.g. My Blog Post> + description: "<brief description of the post less than 160 characters in length>" + heading: "<the heading that appears at the top of the page content>" + slug: <URL name of your blog post, e.g. my-blog-post> + date: YYYY-MM-DDT12:00:00-04:00 + author: <FirstName LastName> + github: <your GitHub username> + community: <your community.mattermost.com username> + --- + + <intro to blog post> + + #### <some heading> + <some content> + + #### <another heading> + <some more content> + ``` + +4. Write your blog post. +5. (Optional) If you wrote the blog post with someone else, you can also add a second author by adding `author_2`, `github_2` and `community_2` to the [front matter](https://gohugo.io/content-management/front-matter). +6. Submit a pull request to https://github.com/mattermost/mattermost-developer-documentation and assign two dev reviews and an editor review from @amyblais or @justinegeffen. +7. Once merged it should show up on [developers.mattermost.com/blog](https://developers.mattermost.com/blog) within 10-15 minutes. When it shows up, post about it in the Developers channel on community.mattermost.com. diff --git a/docs/main/administration-guide/administration-guide-index.mdx b/docs/main/administration-guide/administration-guide-index.mdx new file mode 100644 index 000000000000..4523d8c35654 --- /dev/null +++ b/docs/main/administration-guide/administration-guide-index.mdx @@ -0,0 +1,16 @@ +--- +title: "Administration Guide" +--- +Welcome to the Mattermost Administration Guide. This guide is organized into sections based on administrative tasks and scenarios to help you effectively manage and optimize your Mattermost workspace. + +Whether you’re configuring server settings, managing users, monitoring performance, or ensuring compliance, this guide provides all the information you need. Use the navigation below to access detailed instructions and best practices for each topic. + +- [Self-hosted billing](/administration-guide/manage/admin/self-hosted-billing) - Billing and payment options for Mattermost self-hosted deployments. +- [Cloud workspace management](/administration-guide/cloud-workspace-management) - Learn how to manage cloud workspaces in Mattermost. +- [Server maintenance](/administration-guide/manage/admin/server-maintenance) - Learn about Mattermost server maintenance and best practices. +- [Server configuration](/administration-guide/manage/admin/server-configuration) - Learn about server configuration and settings. +- [User provisioning](/administration-guide/manage/admin/user-provisioning) - Learn about user provisioning and management. +- [User management](/administration-guide/manage/admin/user-management) - Learn about user management and best practices. +- [Monitoring and performance](/administration-guide/manage/admin/monitoring-and-performance) - Learn about monitoring and performance optimization. +- [Compliance](/administration-guide/compliance-with-mattermost) - Learn about compliance and security best practices. +- [Migration](/administration-guide/manage/admin/migration) - Learn about migrating to Mattermost. diff --git a/docs/main/administration-guide/cloud-workspace-management.mdx b/docs/main/administration-guide/cloud-workspace-management.mdx new file mode 100644 index 000000000000..71a0b5ee66dd --- /dev/null +++ b/docs/main/administration-guide/cloud-workspace-management.mdx @@ -0,0 +1,17 @@ +--- +title: "Cloud workspace management" +--- +This section of the guide is for system admins of Mattermost Cloud deployments. + +<Tip> + +If you're the system admin for a Mattermost self-hosted workspace, see the [Self-hosted administration](/administration-guide/manage/admin/server-maintenance) documentation. + +</Tip> + +- [Workspace migration](/administration-guide/manage/cloud-data-export) - Migrate your workspace using the mmctl tool. +- [Cloud data residency](/administration-guide/manage/cloud-data-residency) - Find information about your data in the Cloud. +- [Cloud IP Filtering](/administration-guide/manage/cloud-ip-filtering) - Restrict access to your Mattermost Cloud workspace to a specific IP address range. +- [Cloud Bring Your Own Key (BYOK)](/administration-guide/manage/cloud-byok) - Learn how to manage data encryption processes within a Mattermost Cloud Enterprise Dedicated deployment. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/compliance-with-mattermost.mdx b/docs/main/administration-guide/compliance-with-mattermost.mdx new file mode 100644 index 000000000000..348cc87e2f71 --- /dev/null +++ b/docs/main/administration-guide/compliance-with-mattermost.mdx @@ -0,0 +1,12 @@ +--- +title: "Compliance with Mattermost" +--- +Mattermost is purpose-built to help enterprises keep sensitive data safe and compliant in the strictest, most complex environments. Mattermost Enterprise Edition includes features designed to make compliance with all relevant regulations and internal policies easy to achieve and maintain. + +- [Compliance exports](/administration-guide/comply/compliance-export) - Export compliance reports to third-party systems to archive history. +- [Compliance monitoring](/administration-guide/comply/compliance-monitoring) - Enable oversight and prevent unauthorized queries with compliance exports. +- [Electronic discovery](/administration-guide/comply/electronic-discovery) - Extract data from Mattermost for eDiscovery. +- [Data retention](/administration-guide/comply/data-retention-policy) - Control how long data is stored in Mattermost with global and custom retention policies to meet data retention compliance requirements. +- [Export channel data](/administration-guide/comply/export-mattermost-channel-data) - Migrate data between systems and back data up for operational continuity. +- [Legal Hold](/administration-guide/comply/legal-hold) - Preserve relevant Mattermost information when litigation is anticipated. +- [JSON audit log schema](/administration-guide/comply/embedded-json-audit-log-schema) - Learn how to configure Mattermost audit logging using a JSON object. diff --git a/docs/main/administration-guide/comply/compliance-export.mdx b/docs/main/administration-guide/comply/compliance-export.mdx new file mode 100644 index 000000000000..e9d84bf30bb4 --- /dev/null +++ b/docs/main/administration-guide/comply/compliance-export.mdx @@ -0,0 +1,225 @@ +--- +title: "Compliance export" +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost Enterprise customers can archive history or transfer message data to third-party systems for auditing and compliance purposes with compliance exports. Supported integrations include [Smarsh (Actiance) Vantage](#actiance-xml), [Global Relay](#global-relay-eml), and [Proofpoint](#proofpoint). + +From Mattermost v10.5, compliance exports include performance improvements for large daily data sets with changes affecting output formats, system performance, and logic. Compliance exports provide compliance teams complete information to reconstruct the state of a channel, and to determine who had visibility on an initial message, or when the message was edited or deleted. Compliance teams can track a message by its MessageId as it is edited or deleted, and across batches and exports periods. + +## Overview + +Compliance exports are produced from the System Console, and contain all messages including: + +- Messages sent in direct message channels +- File uploads +- Posts from plugins +- Posts from bots/webhooks + +Exports include information on channel member history at the time the message was posted. + +## Set up guide + +Use the following guides to configure exports for [CSV](#csv), [Smarsh / Actiance XML](#actiance-xml), [Global Relay EML](#global-relay-eml), or [Proofpoint](#proofpoint). + +<Note> + +- For self-hosted deployments, compliance exports are written to the `exports` subdirectory of the configured filestore in the chosen format. This will either be in the [Local Storage directory](/administration-guide/configure/environment-configuration-settings#file-storage) or the Mattermost S3 bucket if S3 storage is configured. +- Alternatively, you can specify an alternate filestore target and generate an S3 presigned URL for compliance exports. See the [dedicated export filestore target](/administration-guide/configure/environment-configuration-settings#enable-dedicated-export-filestore-target) configuration settings documentation for details. +- Compliance exports don't contain posts sent before the feature was enabled. For self-hosted deployments, you can export past history via the `export` [command line tool](/../manage/command-line-tools). + +</Note> + +### CSV + +1. Go to **System Console \> Compliance \> Compliance Export**. +2. Set **Enable Compliance Exports** to **true**. +3. Set the **Compliance Export time**. This is the start time of the daily scheduled compliance export job and must be a 24-hour time stamp in the form `HH:MM`. Choose a time when fewer people are using your system. +4. Set the export file format to **CSV**. +5. Select **Save**. + +<div class="tab" parse-titles=""> + +From Mattermost v10.5 + +You can review export job status in the System Console. + +When the daily compliance export job is finished, a parent directory is created named based on when the export was started and the `startTimestamp` and `endTimestamp` of the export, e.g, `administration-guide/comply/compliance-export-2024-08-13-05h08m-1723105062492-1723109100075`. That parent directory contains 1 zip file for each batch, named based on the batch number and the start and end timestamps of the messages in that batch, e.g, `batch001-1723105062492-1723106622163.zip`. Each zip file contains the same information available in previous Mattermost server releases. + +Working from the same example above, the directory would look like this: + +``` bash +administration-guide/comply/compliance-export-2024-08-13-05h08m-1723105062492-1723109100075 +├── batch001-1723105062492-1723106622163.zip +├── batch002-1723106622163-1723108196005.zip +└── batch003-1723108196005-1723109100075.zip +``` + +And each batch would look like this: + +``` bash +batch001-1723105062492-1723106622163.zip +├── files +├── metadata.json +└── actiance_export.xml +``` + +## Updated CSV export fields + +**Post Creation Time** is always the `CreateAt` for messages and attachments, or `JoinTime` and `LeaveTime` for participant join and leave events, respectively. + +- **Update Time** indicates that the message has been updated, and this is the `updateAt` time. +- **Updated Type** helps differentiate what kind of update it was as one of the following: + - **EditedNewMsg** indicates that the message has been edited, and this is the new message (post-edit) content. + - **EditedOriginalMsg** indicates that the message has been edited, and this the original message (pre-edit) content. This message will have another field `EditedNewMsgId`, which is the Id of the message which holds the post-edited message contents. + - **UpdatedNoMsgChange** indicates that message's content hasn't changed, but the post was updated for some reason, such as reaction, replied-to, a reply was edited, or a reply was deleted. + - **Deleted** indicates that this message was deleted. + - **FileDeleted** indicates that this message is recording that a file was deleted. + +</div> + +<div class="tab"> + +Prior to Mattermost v10.5 + +The daily compliance export job creates a `.zip` file with a unique job identifier of all messages posted in the last 24 hours. You can unzip the file to easily transform the default `.csv` format into a desired format for your third-party archive system. + +For a sample CSV output, [download a CSV export file here](https://github.com/mattermost/docs/blob/master/source/samples/csv_export.zip). + +</div> + +### Actiance XML + +Actiance XML is the supported format for the 'Smarsh Vantage product \[https://central.smarsh.com/s/product/vantage\](https://central.smarsh.com/s/product/vantage\)\`\_. + +1. Go to **System Console \> Compliance \> Compliance Export**. +2. Set **Enable Compliance Exports** to **true**. +3. Set the **Compliance Export time**. This is the start time of the daily scheduled compliance export job and must be a 24-hour time stamp in the form HH:MM. Choose a time when fewer people are using your system. +4. Set the export file format to **Actiance XML**. +5. Select **Save**. + +<Note> + +In Actiance XML exports, channel type is prepended to the channel names. + +</Note> + +<div class="tab" parse-titles=""> + +From Mattermost v10.5 + +You can review export job status in the System Console. Once you've selected Actiance XML as your file format, you can set up an integration with Actiance Vantage archive system. + +When the daily compliance export job is finished, a parent directory is created named based on when the export was started and the `startTimestamp` and `endTimestamp` of the export, e.g, `administration-guide/comply/compliance-export-2024-08-13-05h08m-1723105062492-1723109100075`. That parent directory contains 1 zip file for each batch, named based on the batch number and the start and end timestamps of the messages in that batch, e.g, `batch001-1723105062492-1723106622163.zip`. Each zip file contains the same information available in previous Mattermost server releases. + +Working from the same example above, the directory would look like this: + +``` bash +administration-guide/comply/compliance-export-2024-08-13-05h08m-1723105062492-1723109100075 +├── batch001-1723105062492-1723106622163.zip +├── batch002-1723106622163-1723108196005.zip +└── batch003-1723108196005-1723109100075.zip +``` + +And each batch would look like this: + +``` bash +batch001-1723105062492-1723106622163.zip +├── 20240808 +└── actiance_export.xml +``` + +## Updated Actiance XML export fields + +If an XML field is empty, it won't be exported. This is a change from previous Mattermost releases, where empty XML nodes were exported. + +- `MessageId` is the unique `messageId`. +- `DateTimeUTC` is always the post's `CreateAt` time. +- `UpdatedDateTimeUTC` indicates that the message has been updated, and this is the `updateAt` time. +- `UpdatedType` helps differentiate what kind of update it was, including: + - `EditedNewMsg` indicates that this message has been edited, and this is the new message (post-edit) content. + - `EditedOriginalMsg` indicates that this message has been edited, and this the original message (pre-edit) content. This message will have another field `EditedNewMsgId`, which is the Id of the message which holds the post-edited message contents. + - `UpdatedNoMsgChange` indicates that this message's content hasn't changed, but the post was updated for some reason, such as a reaction, replied-to, a reply was edited, or a reply was deleted. + - `Deleted` indicates that the message was deleted. + - `FileDeleted` indicates that the message is recording that a file was deleted. + +</div> + +<div class="tab"> + +Prior to Mattermost v10.5 + +The daily compliance export job creates a `.zip` file with a unique job identifier of all messages posted in the last 24 hours. Once you've selected Actiance XML as your file format, you can set up an integration with Actiance Vantage archive system. For a sample Actiance output, [download an Actiance XML export file here](https://github.com/mattermost/docs/blob/master/source/samples/actiance_export.xml). + +</div> + +### Global Relay EML + +For more information on Global Relay archive system, visit [their website](https://www.globalrelay.com/). + +1. Go to **System Console \> Compliance \> Compliance Export**. +2. Set **Enable Compliance Export** to **true**. +3. Set the **Compliance Export time**. This is the start time of the daily scheduled compliance export job and must be a 24-hour time stamp in the form HH:MM. Choose a time when fewer people are using your system. +4. Set the **Export Format** to **GlobalRelay EML**. +5. Select **A9/Type 9**, **A10/Type 10**, or **Custom** for the **Global Relay Customer Account**. This is the type of Global Relay customer account your organization has. + - For **A9/Type 9** and **A10/Type 10** types, set the **Global Relay SMTP username**, **Global Relay SMTP password**, and **Global Relay SMTP email address**, provided by Global Relay. + - For a **Custom** type, set the **Global Relay SMTP username**, **Global Relay SMTP password**, **Global Relay SMTP email address**, **SMTP Server Name**, and the **SMTP Server Port**, provided by Global Relay. **Custom** type can be used to integrate with Proofpoint. +6. Select **Save**. + +<Note> + +Messages larger than 250 MB will have their attachments removed because they are too large to send to Global Relay. An error is added to the server logs with id `global_relay_attachments_removed`. It includes the post ID the attachments were removed from, as well as the attachment IDs. A [ticket is queued to better handle large messages](https://mattermost.atlassian.net/browse/MM-10038). + +</Note> + +Once you've selected Global Relay EML as your file format, you can set up an integration with Global Relay archive system. For more information, see [Global Relay Archive](https://www.globalrelay.com/products/archive-data-compliance/). + +### Proofpoint + +1. Go to **System Console \> Compliance \> Compliance Export**. +2. Set **Enable Compliance Export** to **true**. +3. Set the **Compliance Export time**. This is the start time of the daily scheduled compliance export job and must be a 24-hour time stamp in the form HH:MM. Choose a time when fewer people are using your system. +4. Set the **Export Format** to **GlobalRelay EML**. +5. Select **Custom** for the **Global Relay Customer Account** to integrate with Proofpoint. +6. Set the **SMTP username**, **SMTP password**, **SMTP email address**, **SMTP Server Name**, and the **SMTP Server Port**, provided by Proofpoint. +7. Select **Save**. + +See the [Global Relay](#global-relay-eml) section for details on updated Global Relay export fields. Now you can set up an integration with the Proofpoint archive system. For more information, visit the [Proofpoint Archive webiste](https://www.proofpoint.com/us/products/archiving-and-compliance/archive). + +## Frequently Asked Questions (FAQ) + +### Are Playbooks and Boards data included in compliance exports? + +No. Compliance exports only include channel messages, direct messages, file uploads, and posts from plugins/bots/webhooks. Data from Mattermost Playbooks (including run activities, status updates, and retrospectives) and Mattermost Boards (including cards, comments, and board activities) are not included in the compliance export functionality. Organizations requiring compliance archiving of Playbooks and Boards data should consider separate data retention strategies for these features. + +### How do I export past history? + +Run the `export` [command line tool](/../manage/command-line-tools). You can specify an `exportFrom` option to export data from a specified timestamp. All posts that were made after this timestamp will be exported. + +### How do I download compliance export jobs using mmctl? + +From Mattermost Server v10.11, system administrators can download compliance export jobs using the [mmctl compliance_export download](/administration-guide/manage/mmctl-command-line-tool#mmctl-compliance-export-download) command. This provides a command-line interface for retrieving completed compliance export jobs by job ID. + +### What happens if I export data manually? + +If the compliance export job is run automatically, manually via the System Console, or manually via the CLI (without the `--exportFrom` option), it exports all posts that were made since the last post that the previous execution of the job exported. If this is the first time that the job has ever run, all posts that were made since the feature was enabled will be exported. + +If the `--exportFrom` option is specified with the CLI command, all posts that have been made since the supplied timestamp will be exported. + +When run manually via the System Console, `.csv` and Actiance XML files are written to the `exports` subdirectory of the configured [Local Storage Directory](/administration-guide/configure/environment-configuration-settings#local-storage-directory). Files will be written to a folder with names based on an epoch time range. Global Relay EML export format files will be mailed to the configured email address when run manually. + +### Is there a maximum row limit for CSV files? + +No. There's no limit to the number of rows within Compliance Monitoring CSV files. + +### How do I know if a compliance export job fails? + +Mattermost provides the status of each compliance export job in **System Console \> Compliance \> Compliance Export**. Here, you can see if the job succeeded or failed, including the number of messages and files exported. + +In addition, any failures are returned in the server logs for self-hosted deployments. The error log begins with the string `Failed job` and includes a `job_id key/value` pair. Compliance export job failures are identified with worker name `MessageExportWorker`. You can optionally create a script that programmatically queries for such failures and notifies the appropriate system. + +<Note> + +This compliance export feature replaces legacy Compliance Reporting Oversight functionality. We recommend Enterprise customers migrate to the new system. For a sample CSV output of the new compliance export system, [download a CSV export file here](https://github.com/mattermost/docs/blob/master/source/samples/csv_export.zip). + +</Note> diff --git a/docs/main/administration-guide/comply/compliance-monitoring.mdx b/docs/main/administration-guide/comply/compliance-monitoring.mdx new file mode 100644 index 000000000000..96dbeef7adac --- /dev/null +++ b/docs/main/administration-guide/comply/compliance-monitoring.mdx @@ -0,0 +1,244 @@ +--- +title: "Compliance monitoring" +draft: true +--- +<PlanAvailability slug="ent-plus" /> + +This feature enables compliance exports to be produced from the System Console, with all query and download actions logged in an audit history to enable oversight and prevent unauthorized queries. + +Compliance exports can be filtered to date range, user account, and keyword list. Requests from queries can be downloaded from the user interface in `.csv` format, with a `.json` metafile documenting the query, as well as placed in a directory set by the system admin. + +Daily compliance reports may also be generated, supporting integration with compliance solutions like [Global Relay](#global-relay-support). + +By default, all Mattermost deployments retain all messages, including edits and deletes, along with all files uploaded. + +## Enable compliance reporting + +To enable the option to generate daily compliance reports: + +1. Go to **System Console \> Compliance \> Compliance Monitoring** and set the **Enable Compliance Reporting** value to **true**. +2. (Optional) In **Compliance Report Directory** specify the directory in which to place completed compliance reports. Defaults to `./data/` if left blank. +3. Select **Save**. + +## Turn on daily compliance reports + +After enabling compliance reporting: + +1. Go to **System Console \> Compliance \> Compliance Monitoring** and set the **Enable Daily Report** value to **true**. +2. Select **Save**. + +Your system will now export all new messages posted within a 24-hour period as a `.csv` file to the location specified in **Compliance Report Directory**. This feature can be used in conjunction with centralized compliance reporting systems that move. + +## Run compliance reports + +Compliance reports are exports of all messages in Mattermost that match the report criteria. To run a report: + +1. Go to **System Console \> Compliance \> Compliance Monitoring**. + +2. Fill in the following: + + > - **Job Name:** Name the compliance report you are about to run (e.g. "HR Audit 455"). + > - **From:** Start date for search in YYYY-MM-DD format (e.g. "2016-03-11"). + > - **To:** End date of search in YYYY-MM-DD format (e.g. "2016-05-11"). + > - **Emails:** Comma-separated list of email addresses of users whose posted messages you want to search (e.g. `bill@example.com, bob@example.com`). + > - **Keywords:** Indicate the words that would be contained in a message for it to be included in the compliance report results. + +3. Select **Run Compliance Report**. + +The report will be queued in the display below the fields described above. The properties of each compliance report run is explained as follows: + +- **Timestamp:** Time at which the report was requested. +- **Status:** `running` indicates the report is being run; `finished` indicates the report is complete and ready for download. +- **Records:** Shows the number of search results. +- **Type:** `adhoc` indicates the report was requested by completing query fields; `daily` indicates the report is a daily export. +- **Description:** Job Name indicated in request. +- **Requested by:** Email of person requesting the report. +- **Params:** Parameters of the compliance report request. + +Each compliance report includes a **Download** link which downloads a compressed file named `adhoc-[UNIQUE_ID].zip`. Inside the file is `meta.json`, which includes the parameters of the search executed and `posts.csv` which includes the contents of messages found by the request. + +### Compliance query definition stored in `meta.json` + +The `meta.json` file contains the following information about the compliance query: + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '17%'}} /> +<col style={{width: '52%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<thead> +<tr> +<th>Field</th> +<th>Description</th> +<th>Example</th> +</tr> +</thead> +<tbody> +<tr> +<td>id</td> +<td>Unique identifier for compliance query</td> +<td>ja8z8egap7nq9kqetz3rt98khe</td> +</tr> +<tr> +<td>create_at</td> +<td>Timestamp at which compliance query was executed</td> +<td>1463637842478</td> +</tr> +<tr> +<td>user_id</td> +<td>Mattermost User ID for person creating query</td> +<td>3bq1shta93yztg3i6aiu1tzi5h</td> +</tr> +<tr> +<td>status</td> +<td>Status of query: <em>finished</em> or <em>failed</em></td> +<td>"finished"</td> +</tr> +<tr> +<td>count</td> +<td>Count of messages found matching keyword</td> +<td>36</td> +</tr> +<tr> +<td>desc</td> +<td>User entered description of compliance query</td> +<td>Example Compliance Report</td> +</tr> +<tr> +<td>type</td> +<td>Type of compliance query: <em>adhoc</em> or <em>daily</em></td> +<td>"adhoc"</td> +</tr> +<tr> +<td>start_at</td> +<td>Timestamp at which query began to run</td> +<td>1451606400000</td> +</tr> +<tr> +<td>end_at</td> +<td>Timestamp at which query ended</td> +<td>1463529600000</td> +</tr> +<tr> +<td>keywords</td> +<td>Comma-separated, case insensitive keywords to match in query</td> +<td>"drinking"</td> +</tr> +<tr> +<td>emails</td> +<td>Comma-separated emails of users to search. Blank returns all</td> +<td><code>frank.yu@ha.ca, mary.li@hi.co</code></td> +</tr> +</tbody> +</table> + +### Compliance query results stored in `posts.csv` file + +`posts.csv` contains the following information about the compliance query results, one search result per row: + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '18%'}} /> +<col style={{width: '53%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<thead> +<tr> +<th>Field</th> +<th>Description</th> +<th>Example</th> +</tr> +</thead> +<tbody> +<tr> +<td>TeamName</td> +<td>URL name of team</td> +<td>contosi</td> +</tr> +<tr> +<td>TeamDisplayName</td> +<td>Display name of team</td> +<td>Contosi Corporation</td> +</tr> +<tr> +<td>ChannelDisplayName</td> +<td>Display name of channel where keyword was found</td> +<td>Community Heartbeat</td> +</tr> +<tr> +<td>ChannelName</td> +<td>URL name of channel</td> +<td>community-heartbeat</td> +</tr> +<tr> +<td>UserUsername</td> +<td>Username of user posting the message containing keyword</td> +<td>frank.yu</td> +</tr> +<tr> +<td>UserEmail</td> +<td>Email of user posting the message containing keyword</td> +<td>"frank.yu@contosi.com"</td> +</tr> +<tr> +<td>UserNickname</td> +<td>Nickname of user posting the message containing keyword</td> +<td>fan du</td> +</tr> +<tr> +<td>UserType</td> +<td>Type of user posting the message ("user" or "bot")</td> +<td>user</td> +</tr> +<tr> +<td>PostId</td> +<td>Unique ID of message post containing keyword</td> +<td>xt9anyx6x3fx9y84aehgakdpze</td> +</tr> +<tr> +<td>PostCreateAt</td> +<td>Timestamp at which post was created</td> +<td>2016-03-02T16:01:59Z</td> +</tr> +<tr> +<td>PostDeletedAt</td> +<td>Timestamp at which post was deleted (if applicable)</td> +<td>2016-03-02T16:01:59Z</td> +</tr> +<tr> +<td>PostUpdatedAt</td> +<td>Timestamp at which post was last edited (if applicable)</td> +<td>2016-03-02T16:01:59Z</td> +</tr> +<tr> +<td>PostParentId</td> +<td>Unique ID of parent post if post is a comment</td> +<td>xt9anyx6x3fx9y84aehgakdpze</td> +</tr> +<tr> +<td>PostOriginalId</td> +<td>Unique ID of post if deleted or edited</td> +<td>xt9anyx6x3fx9y84aehgakdpze</td> +</tr> +<tr> +<td>PostMessage</td> +<td>Message containing keyword</td> +<td>Drinking from the fire hose</td> +</tr> +<tr> +<td>PostFilenames</td> +<td>Comma separated list of filesnames attached to post</td> +<td>["/f../ho.png","/f../hi.png"]</td> +</tr> +</tbody> +</table> + +## Global Relay support + +Mattermost daily compliance reports are compatible with Global Relay compliance solutions through the conversion of Mattermost `.CSV` exports into Global Relay `EML` files. + +- This conversion can be done by in-house developers who have previously written scripts to convert other communication systems into Global Relay format based on your organization's specific needs. +- You can also contact your Global Relay account manager about a services project to establish this conversion. + +We recommend using the new [Compliance Export feature](/compliance-export) for Global Relay exports. diff --git a/docs/main/administration-guide/comply/custom-terms-of-service.mdx b/docs/main/administration-guide/comply/custom-terms-of-service.mdx new file mode 100644 index 000000000000..81430c8159ff --- /dev/null +++ b/docs/main/administration-guide/comply/custom-terms-of-service.mdx @@ -0,0 +1,47 @@ +--- +title: "Custom terms of service" +--- +<PlanAvailability slug="ent-plus" /> + +Increase clarity on legal Mattermost expectations for internal employees and guests with the ability to set custom Terms of Service (“ToS”) agreements and re-acceptable periods. + +## Configuring terms of service + +To enable custom terms of service: + +1. Go to **System Console \> Compliance \> Custom Terms of Service**. +2. Set **Enable Custom Terms of Service** to **true**. +3. Set **Custom Terms of Service Text** which contains your terms. Markdown formatting is supported, including lists, headings, and bolding. +4. Set **Re-Acceptance Period** to configure the number of days before Terms of Service acceptance expires, and when the terms must be re-accepted. Set to 0 if you don't want your terms to expire. +5. Select **Save**. + +Once saved, all users must accept the terms of service by clicking **I Agree** next time they log in, or on the next page refresh. If they do not accept, they will be logged out. + +<Note> + +If you make an update to your Terms of Service, make sure to update your terms of service link at **System Console \> Site Configuration \> Customization \> Terms of Service link**. This link is presented to all users when they log in, and it's easily accessible to end users after accepting the terms. + +</Note> + +## Frequently asked questions + +### What happens if I update my terms of service text? + +There will be no impact to your end users. Users will simply be required to accept the new terms on next login or page refresh. + +### What happens if a user doesn't accept the terms of service? + +Users won't be able to log in if they don't accept the Terms of Service. + +### How do I know if my users accepted the terms of service? + +Each time a user agrees to the terms of service, the agreement is recorded in the database: + +- A new field `AcceptedServiceTermsId` in the **Users** table indicates the most recent terms of service the user has accepted. +- Each time a user accepts the terms, the action is recorded in the **Audits** table, containing the username, timestamp of acceptance, and other relevant information. + +### Why isn't this feature in Team Edition for GDPR compliance? + +Terms of service is presented to users on login and account creation, and available to users at all times in the link available by going to **System Console \> Site Configuration \> Customization**. + +This feature is intended to meet compliance requirements for large Enterprise companies. diff --git a/docs/main/administration-guide/comply/data-retention-policy.mdx b/docs/main/administration-guide/comply/data-retention-policy.mdx new file mode 100644 index 000000000000..6e4c06bc659d --- /dev/null +++ b/docs/main/administration-guide/comply/data-retention-policy.mdx @@ -0,0 +1,120 @@ +--- +title: "Data retention policy" +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost stores all message history providing an unlimited search history to system admins and end users. + +Mattermost Enterprise customers can set a global retention policy as well as custom retention policies to manage how long messages and file uploads are kept in Mattermost channels and direct messages in order to meet data retention compliance requirements. + +<Warning> + +- By default, Mattermost uses a “soft delete” system where messages and files deleted based on user actions are removed from the user interface, but persist in the Mattermost database. +- Once a message or a file is permanently deleted, the action is irreversible. We recommend using caution when setting up global or custom data retention policies to avoid data loss. + +</Warning> + +## Configure a global data retention policy + +To set a global data retention policy: + +1. Go to **System Console \> Compliance \> Data Retention Policies**. +2. Select **Edit** from the menu located to the right of the **Global retention policy** table. +3. Specify a global retention policy for channel messages and direct messages by selecting a **Channel & direct message retention** option from the dropdown, then set how long to keep those messages in hours, days, or years. When a time is set, messages and file attachments older than the duration you set will be deleted. The minimum retention period is one hour. +4. Select a **File retention** option from the dropdown. Set the number of hours, days, or years to keep files. When a time is set, uploaded files which are older than the duration you set will be deleted from your file storage system (either from your local disk or your Amazon S3 service as specified in **System Console \> Environment \> File Storage**). The minimum retention period is one hour. The global file policy deletes all files regardless of whether they're in a direct message, private, or public channel. +5. From Mattermost v10.10, you can optionally preserve pinned posts when data retention policies delete messages by enabling [Preserve pinned posts](/administration-guide/configure/compliance-configuration-settings#preserve-pinned-posts). Once enabled, pinned posts won't be deleted even if they exceed the configured retention period. +6. Under the **Policy log** section, select **Edit** to specify the start time of the daily scheduled data retention job. Choose a time when fewer people are using your system. + +Select **Save**. Messages and files older than the duration you set will be deleted at the specified server time, as applicable. + +## Configure a custom data retention policy + +To set a custom data retention policy: + +1. Go to **System Console \> Compliance \> Data Retention Policies**. +2. Select **Add policy** to the right of the **Custom retention policies** table. +3. Specify a name for your policy. +4. Specify a custom retention policy for channel and direct messages by selecting a **Channel & direct message retention** option from the dropdown, then set how long to keep uploaded files in days or years. When a time is set, messages and file attachments older than the duration you set will be deleted. The minimum retention period is one day. +5. Assign teams and channels to this policy by selecting **Add teams** and searching for a specific team, or by selecting **Add channels** and searching for a specific channel. If only teams are specified, all channels for selected teams will be included in the a policy. +6. Under the **Policy log** section, select **Edit** to specify the start time of the daily scheduled data retention job. Choose a time when fewer people are using your system. If a time is already set for a global retention policy, then the same time applies to custom data retention policies. + +Save the settings. Messages and files older than the duration you set will be deleted at the specified server time, as applicable. + +## Run a deletion job manually + +You can also run the deletion job manually at any time by selecting **Run Deletion Job Now** in **System Console \> Compliance \> Data Retention Policy**. + +<Note> + +If using data retention with [ElasticSearch](/administration-guide/scale/elasticsearch-setup), ensure the [ElasticSearch aggregate search indexes](/administration-guide/configure/environment-configuration-settings#aggregate-search-indexes) setting is set to a value that is greater than your data retention policy in days. + +</Note> + +## Frequently Asked Questions (FAQs) + +### What happens when a message is deleted? + +The message is removed from the Mattermost user interface and deleted from the `Posts` table. The message is no longer searchable and cannot be retrieved in saved posts lists. + +Replies that did not exceed the message duration are still displayed in the user interface. However, further replies are no longer possible. + +If there was a file attached to the message, it will be removed from the user interface only. + +### Why can I still see messages that were supposedly deleted? + +The web and desktop app cache posts. Posts deleted by a data retention job will be visible to end users until they clear their cache and refresh. + +### What happens when a file is deleted by the file retention policy? + +The file attachment is removed from the Mattermost user interface, deleted from the `FileInfo` table, and from your local disk or Amazon S3 service as specified in **System Console \> Environment \> File Storage**. + +### Why do I see `Pending` in the deletion job table with no details? + +This usually means another data retention job is in progress. You can verify this in the deletion job table in **System Console \> Compliance \> Data Retention Policy**. + +### How is data retention handled in the mobile apps? + +When messages or files are deleted, they are no longer searchable in the Mattermost mobile apps. + +In v1.5 and later of the iOS and Android apps, messages and files are deleted from local storage in the following cases, if they exceed the retention policy duration: + +1. When the user opens the app. +2. When the user puts the app into the background. + +In v1.4 and earlier of the mobile apps, messages and files are not cleared from local storage when the data retention policy is enabled. + +### How do I know if a data retention job fails? + +Mattermost provides the status of each data retention job in **System Console** \> **Compliance** \> **Data Retention Policy**. Here, you can see if the job succeeded or failed, including the details of the error. + +Additionally, any failures are returned in the server logs. The error log begins with the string `Failed job` and includes a job_id key/value pair. Data retention job failures are identified with worker name `EnterpriseDataRetention`. You can optionally create a script that programmatically queries for such failures and notifies the appropriate system. + +### What happens when the data retention period is changed? + +Data retention runs once a day at the time specified in the `config.json` file. Changing the retention period does not automatically schedule any additional run of the data retention job - it only updates how long data is kept in Mattermost. + +### Does the system administrator get any notification when the data retention period is changed? + +No, the new config is updated, but the system admin does not receive any feedback on what the effects will be (e.g. reporting of how many messages are to be deleted). + +### Does the data retention job affect the audits table? + +Prior to v5.20, data retention would delete all user activity corresponding to the data retention time configuration. From v5.20, the audit table will retain the user activity corresponding to the data retention time configuration. + +### Does the data retention job include archived channels? + +Posts and attachments in archived channels are affected by the data retention job. If a post exceeds the age configured for the data retention job it will be deleted from the database. + +### How long does it take to run a deletion query and does it affect server performance? + +Data retention runs the actual deletion query in batches, deleting data in blocks of 1000 records per query. This is so the database won’t be locked up for extended periods of time with long-running queries. Keeping to this limit keeps the query down to a few milliseconds' execution time on the database itself. + +Each batch of data is deleted based on indexes - making the queries quick to execute on small batches. This helps the server remain fully responsive while the process is running. + +### How do I know whether the data retention job is running/scheduled? + +The job scheduler runs the data retention job based on the time specified in the configuration settings. At this time a `DEBUG`-level log line is printed: `Scheduling data retention job`. + +When a job server picks up that scheduled job for execution, a `DEBUG`-level log line is generated: `Worker EnterpriseDataRetention: Received a new candidate job`. + +When the job is complete, an `INFO`-level log line is generated: `Worker EnterpriseDataRetention: Job is complete`. diff --git a/docs/main/administration-guide/comply/electronic-discovery.mdx b/docs/main/administration-guide/comply/electronic-discovery.mdx new file mode 100644 index 000000000000..3184e8a2df1e --- /dev/null +++ b/docs/main/administration-guide/comply/electronic-discovery.mdx @@ -0,0 +1,113 @@ +--- +title: "Electronic discovery" +--- +<PlanAvailability slug="ent-plus" /> + +Electronic discovery (also known as eDiscovery) refers to a process where electronic data is searched with the intent to use it as evidence in a legal case. + +This page describes how to extract data from Mattermost for eDiscovery. There are three primary methods that can be used to accomplish the goal of extracting user post data from Mattermost: + +- [Mattermost Compliance Exports](/administration-guide/comply/compliance-export) +- [Mattermost RESTful API](/administration-guide/comply/electronic-discovery#mattermost-restful-api) +- [Mattermost database using standard SQL queries](/administration-guide/comply/electronic-discovery#mattermost-database) + +Each of the options is discussed in detail below. + +<Note> + +Litigation hold (also known as legal hold) is an extension of eDiscovery where in addition to searching for records, no electronically stored information nor paper documents may be discarded if they may be deemed relevant for a present or future legal case. + +</Note> + +## Mattermost compliance exports + +Mattermost Enterprise has compliance report export capabilities. + +Mattermost can export compliance related data, including the content of messages and who might have seen those messages, in three formats: Actiance XML, Global Relay EML, and generic CSV. Reports can be configured to run on a delay basis and stored in a shared location. + +For more information about the exports feature and how to set up reporting, see [our documentation](/administration-guide/comply/compliance-export). + +## Mattermost RESTful API + +The Mattermost API can be used to export a user's posts in CSV compliance format that is part of Mattermost Enterprise. The following section outlines how to use the API to create and retrieve a report for a specific user via the API. Please note that full documentation for the Mattermost API can be found at [https://api.mattermost.com](https://api.mattermost.com). + +To use the API, you must first authenticate [as described here](https://api.mattermost.com/#tag/authentication). The account you are authenticating with must have `manage_system` permissions. If you are using curl, you can authenticate using the following command: + +``` sh +curl -i -d '{"login_id": "username", "password": "password"}' https://yourmattermosturl/api/v4/users/login +``` + +Mattermost will return a response that looks like this: + +``` text +HTTP/2 200 +server: nginx/1.10.3 (Ubuntu) +date: Thu, 12 Jul 2018 14:43:45 GMT +content-type: application/json +content-length: 679 +set-cookie: MMAUTHTOKEN=yi94pwci6ibjfc9phbikhqutbe; Path=/; Expires=Sat, 11 Aug 2018 14:43:45 GMT; Max-Age=2592000; HttpOnly; Secure +set-cookie: MMUSERID=qfjzamfg47bu9gsyyfbqjk4s6a; Path=/; Expires=Sat, 11 Aug 2018 14:43:45 GMT; Max-Age=2592000; Secure +token: yi94pwci6ibjfc9phbikhqutbe +x-request-id: 5y45pxyfxpb8updtge1zts39he +x-version-id: 5.0.0.5.0.1.18c0fbd759664a85fe95132bb7fc04cf.true +``` + +Include the `token` value sent in the response as part of the Authorization header on your future API requests with the Bearer method, e.g.: + +``` sh +curl -i -H 'Authorization: Bearer yi94pwci6ibjfc9phbikhqutbe http://yourmattermosturl/api/v4/users/me' +``` + +Once you're authenticated into Mattermost, you can use the [Compliance API to create a new compliance report](https://api.mattermost.com/#tag/compliance%2Fpaths%2F~1compliance~1reports%2Fpost). The curl based example below demonstrates how to send a request that bases the authentication token and asks Mattermost to create a report that spans posts from Dec 31, 2017 - 8:15 PM to Dec 31, 2018 - 8:15 PM for a user with the email address [craig@mattermost.com](mailto:craig@mattermost.com): + +<Note> + +The data in the JSON payload must be formatted as Unix Epoch. A tool like [https://www.epochconverter.com/](https://www.epochconverter.com/) can be useful when converting to and from the required format. + +</Note> + +``` sh +curl --header "Content-Type: application/json" \ +--request POST \ +-H 'Authorization: Bearer yi94pwci6ibjfc9phbikhqutbe' \ +--data '{"id":"","create_at":0,"user_id":"craig","status":"","count":0,"desc":" ","type":"","start_at":1514769359000,"end_at": 1546305359000,"keywords":"","emails":"craig@mattermost.com"}' \ +https://yourmattermosturl/api/v4/compliance/reports +``` + +If the post is successful, Mattermost will return a message that looks like the following, indicating that the server is running the compliance export process: + +``` json +{"id":"du6kektczifqxexeroywpz3nbc"," create_at":1531444617901, "user_id":"qfjzamfg47bu9gsyyfbqjk4s6a", "status":"running", "count":0, "desc":" ", "type":"adhoc", "start_at":1514769359000, "end_at":1546305359000, "keywords":"", "emails":"craig@mattermost.com"} +``` + +When the export process is complete (the execution time is based on the number of records to return and the current server load), you will need to send another HTTP Post request to Mattermost to retrieve and download a zip file containing the report that looks like the following curl request: + +``` sh +curl --request GET \ +-H 'Authorization: Bearer p9o1qx457fbc9gdrn39z9ah59o' \ +--data '{"status_code":0,"id":"du6kektczifqxexeroywpz3nbc","message":"","requestion_id":""}' \ +--output report-zip.zip \ +https://yourmattermosturl/api/v4/compliance/reports/du6kektczifqxexeroywpz3nbc/download +``` + +When sending the request, you need to get the report ID from the response returned by Mattermost when the report was created. You also need to supply a name to save that file as. In the example above, the file will be saved as `report-zip.zip`. + +## Mattermost database + +Selecting messages from the Mattermost database using standard SQL is quite easy. If you know the username, the following query can be used to select all messages for the specified user: + +``` sql +SELECT * FROM mattermost.Posts WHERE UserId = (SELECT Id FROM mattermost.Users WHERE Username = 'username'); +``` + +If you want to limit the results of the query based on the date and time that the messages were posted, you can modify the above query to: + +``` sql +SELECT * FROM mattermost.Posts WHERE UserId = (SELECT Id FROM mattermost.Users WHERE Username = 'username' AND CreateAt > 1530405832000 AND CreateAt < 1532997832000); +``` + +<Note> + +The Mattermost database stores date and time stamps in the [Unix Epoch](https://en.wikipedia.org/wiki/Unix_time) format. A tool like the [Epoch Converter](https://www.epochconverter.com/) can be useful in converting to and from the required format. + +</Note> diff --git a/docs/main/administration-guide/comply/embedded-json-audit-log-schema.mdx b/docs/main/administration-guide/comply/embedded-json-audit-log-schema.mdx new file mode 100644 index 000000000000..e7837568ea39 --- /dev/null +++ b/docs/main/administration-guide/comply/embedded-json-audit-log-schema.mdx @@ -0,0 +1,2001 @@ +--- +title: "Audit Log JSON Schema" +draft: true +--- +<PlanAvailability slug="entry-ent" /> + +The audit log JSON schema functions as a standardized blueprint or schematic that consistently defines how a single event should appear when being written to the audit log, including: field names, data types, objects, and structure. + +An outline of the JSON audit logging schema is provided below. See the [JSON data model](#json-data-model) for additional details. + +``` json +{ + "timestamp": "", // Event time + "status": "", // Success or failure of the audited event or activity + "event_name": "", // Logged event name + "error": { // Error if status = fail + "status_code": 0, + "description": "" + }, + "actor": { // The user performing the action + "user_id": "" // Unique identifier of the event user + "session_id": "" // Unique session identifier of the event user + "client": "" // User agent of the client/platform in use by the event user + "ip_address": "" // IPv4/IPv6 IP address of the event user + }, + "event": { // Event-specific data + "parameters": {} // Map containing parameters of the audited event or activity + "prior_state": {} // Pre-event state of the object + "resulting_state": {} // Post-event state of the object + "object_type": "" // Object targeted by the event or activity + }, + "meta": { + "api_path": "", // API endpoint interacted with for event or activity + "cluster_id": "" // Unique identifier of the cluster in use by the event user + "non_channel_member_access": false // true if user accessed channel content without being a member (v11.5.0+) + } +} +``` + +## Audit log record examples + +### Update user preferences + +``` json +{ + "timestamp": "2022-08-17 20:37:52.846 +01:00", + "event_name": "updatePreferences", + "status": "success", + "actor": { + "user_id": "aw8ehkwaziytzry1qqxi9tsqwh", + "session_id": "kth3jyadc3b1p84kbz6y3o75na", + "client": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15", + "ip_address": "192.168.0.169" + }, + "event": { + "parameters": {}, + "prior_state": {}, + "resulting_state": {}, + "object_type": "" + }, + "meta": { + "api_path": "/api/v4/users/aw8ehkwaziytzry1qqxi9tsqwh/preferences", + "cluster_id": "8dxdbfx6fpdwtki1z6n8whtkho" + }, + "error": {} +} +``` + +### Create post + +``` json +{ + "timestamp": "2025-04-30 16:17:44.207 Z", + "event_name": "createPost", + "status": "success", + "actor": { + "user_id": "i764hi6h5bbz8p1955ed4ahj6y", + "session_id": "t7894ft76igtpb788nkkej1yoy", + "client": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "ip_address": "172.19.0.8" + }, + "event": { + "parameters": { + "post": { + "channel_id": "pfis7ycuy78o7m3zebajmxqeuo", + "user_id": "i764hi6h5bbz8p1955ed4ahj6y", + "message": "Sample post content" + } + }, + "prior_state": {}, + "resulting_state": { + "channel_id": "pfis7ycuy78o7m3zebajmxqeuo", + "create_at": 1746029864145, + "id": "xpw97hf6kfncirzhqisb5sym7e", + "user_id": "i764hi6h5bbz8p1955ed4ahj6y" + }, + "object_type": "post" + }, + "meta": { + "api_path": "/api/v4/posts", + "cluster_id": "i5twhjm3ainatcifiy3oksshae" + }, + "error": {} +} +``` + +### System configuration change + +``` json +{ + "timestamp": "2025-04-30 16:18:30.803 Z", + "event_name": "patchConfig", + "status": "success", + "actor": { + "user_id": "i764hi6h5bbz8p1955ed4ahj6y", + "session_id": "t7894ft76igtpb788nkkej1yoy", + "client": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "ip_address": "172.19.0.8" + }, + "event": { + "parameters": {}, + "prior_state": { + "config_diffs": [ + { + "actual_val": false, + "base_val": true, + "path": "MetricsSettings.EnableClientMetrics" + } + ] + }, + "resulting_state": {}, + "object_type": "config" + }, + "meta": { + "api_path": "/api/v4/config/patch", + "cluster_id": "i5twhjm3ainatcifiy3oksshae" + }, + "error": {} +} +``` + +## Audit event types + +The following tables list the comprehensive audit event types (`event_name` values) that are captured in Mattermost audit logs: + +### User Management Events + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '31%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>attachDeviceId</code></td> +<td>Attaching device IDs to user sessions</td> +</tr> +<tr> +<td><code>createUser</code></td> +<td>Creating new user accounts</td> +</tr> +<tr> +<td><code>createUserAccessToken</code></td> +<td>Creating user access tokens</td> +</tr> +<tr> +<td><code>deleteUser</code></td> +<td>Deleting user accounts</td> +</tr> +<tr> +<td><code>demoteUserToGuest</code></td> +<td>Demoting users to guest status</td> +</tr> +<tr> +<td><code>disableUserAccessToken</code></td> +<td>Disabling user access tokens</td> +</tr> +<tr> +<td><code>enableUserAccessToken</code></td> +<td>Enabling user access tokens</td> +</tr> +<tr> +<td><code>followThreadByUser</code></td> +<td>Following message threads by user</td> +</tr> +<tr> +<td><code>getUserAudits</code></td> +<td>Retrieving user audit logs</td> +</tr> +<tr> +<td><code>login</code></td> +<td>User login events</td> +</tr> +<tr> +<td><code>logout</code></td> +<td>User logout events</td> +</tr> +<tr> +<td><code>migrateAuthToLdap</code></td> +<td>Migrating user authentication to LDAP</td> +</tr> +<tr> +<td><code>migrateAuthToSaml</code></td> +<td>Migrating user authentication to SAML</td> +</tr> +<tr> +<td><code>patchUser</code></td> +<td>Updating user properties</td> +</tr> +<tr> +<td><code>promoteGuestToUser</code></td> +<td>Promoting guest users to regular users</td> +</tr> +<tr> +<td><code>resetPassword</code></td> +<td>Resetting user passwords</td> +</tr> +<tr> +<td><code>resetPasswordFailedAttempts</code></td> +<td>Resetting password failed attempt counters</td> +</tr> +<tr> +<td><code>revokeUserAccessToken</code></td> +<td>Revoking user access tokens</td> +</tr> +<tr> +<td><code>sendPasswordReset</code></td> +<td>Sending password reset emails</td> +</tr> +<tr> +<td><code>sendVerificationEmail</code></td> +<td>Sending email verification messages</td> +</tr> +<tr> +<td><code>setDefaultProfileImage</code></td> +<td>Setting default profile images</td> +</tr> +<tr> +<td><code>setProfileImage</code></td> +<td>Setting custom profile images</td> +</tr> +<tr> +<td><code>setUnreadThreadByPostId</code></td> +<td>Setting unread thread status by post ID</td> +</tr> +<tr> +<td><code>switchAccountType</code></td> +<td>Switching account types</td> +</tr> +<tr> +<td><code>unfollowThreadByUser</code></td> +<td>Unfollowing message threads by user</td> +</tr> +<tr> +<td><code>updatePassword</code></td> +<td>Updating user passwords</td> +</tr> +<tr> +<td><code>updateReadStateAllThreadsByUser</code></td> +<td>Updating read state for all threads by user</td> +</tr> +<tr> +<td><code>updateReadStateThreadByUser</code></td> +<td>Updating read state for specific threads by user</td> +</tr> +<tr> +<td><code>updateUser</code></td> +<td>Updating user account information</td> +</tr> +<tr> +<td><code>updateUserActive</code></td> +<td>Updating user active/inactive status</td> +</tr> +<tr> +<td><code>updateUserAuth</code></td> +<td>Updating user authentication settings</td> +</tr> +<tr> +<td><code>updateUserMfa</code></td> +<td>Updating user multi-factor authentication</td> +</tr> +<tr> +<td><code>updateUserRoles</code></td> +<td>Updating user roles and permissions</td> +</tr> +<tr> +<td><code>verifyUserEmail</code></td> +<td>Verifying user email addresses</td> +</tr> +<tr> +<td><code>verifyUserEmailWithoutToken</code></td> +<td>Verifying user email without token</td> +</tr> +</tbody> +</table> + +### Channel Management Events + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '30%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addChannelMember</code></td> +<td>Adding members to channels</td> +</tr> +<tr> +<td><code>convertGroupMessageToChannel</code></td> +<td>Converting group messages to channels</td> +</tr> +<tr> +<td><code>createChannel</code></td> +<td>Creating new channels</td> +</tr> +<tr> +<td><code>createChannelBookmark</code></td> +<td>Creating channel bookmarks</td> +</tr> +<tr> +<td><code>createDirectChannel</code></td> +<td>Creating direct message channels</td> +</tr> +<tr> +<td><code>createGroupChannel</code></td> +<td>Creating group message channels</td> +</tr> +<tr> +<td><code>deleteChannel</code></td> +<td>Deleting channels</td> +</tr> +<tr> +<td><code>deleteChannelBookmark</code></td> +<td>Deleting channel bookmarks</td> +</tr> +<tr> +<td><code>moveChannel</code></td> +<td>Moving channels between teams</td> +</tr> +<tr> +<td><code>patchChannel</code></td> +<td>Updating channel properties</td> +</tr> +<tr> +<td><code>patchChannelModerations</code></td> +<td>Updating channel moderation settings</td> +</tr> +<tr> +<td><code>removeChannelMember</code></td> +<td>Removing members from channels</td> +</tr> +<tr> +<td><code>restoreChannel</code></td> +<td>Restoring deleted channels</td> +</tr> +<tr> +<td><code>updateChannel</code></td> +<td>Updating channel information</td> +</tr> +<tr> +<td><code>updateChannelBookmark</code></td> +<td>Updating channel bookmarks</td> +</tr> +<tr> +<td><code>updateChannelBookmarkSortOrder</code></td> +<td>Updating channel bookmark sort order</td> +</tr> +<tr> +<td><code>updateChannelMemberNotifyProps</code></td> +<td>Updating channel member notification properties</td> +</tr> +<tr> +<td><code>updateChannelMemberRoles</code></td> +<td>Updating channel member roles</td> +</tr> +<tr> +<td><code>updateChannelMemberSchemeRoles</code></td> +<td>Updating channel member scheme roles</td> +</tr> +<tr> +<td><code>updateChannelPrivacy</code></td> +<td>Updating channel privacy settings</td> +</tr> +<tr> +<td><code>updateChannelScheme</code></td> +<td>Updating channel permission schemes</td> +</tr> +</tbody> +</table> + +### Team Management Events + +<table style={{width: '85%'}}> +<colgroup> +<col style={{width: '28%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addTeamMember</code></td> +<td>Adding members to teams</td> +</tr> +<tr> +<td><code>addTeamMembers</code></td> +<td>Adding multiple members to teams</td> +</tr> +<tr> +<td><code>addUserToTeamFromInvite</code></td> +<td>Adding users to teams from invitations</td> +</tr> +<tr> +<td><code>createTeam</code></td> +<td>Creating new teams</td> +</tr> +<tr> +<td><code>deleteTeam</code></td> +<td>Deleting teams</td> +</tr> +<tr> +<td><code>importTeam</code></td> +<td>Importing team data</td> +</tr> +<tr> +<td><code>invalidateAllEmailInvites</code></td> +<td>Invalidating all email invitations</td> +</tr> +<tr> +<td><code>inviteGuestsToChannels</code></td> +<td>Inviting guests to channels</td> +</tr> +<tr> +<td><code>inviteUsersToTeam</code></td> +<td>Inviting users to teams</td> +</tr> +<tr> +<td><code>patchTeam</code></td> +<td>Updating team properties</td> +</tr> +<tr> +<td><code>regenerateTeamInviteId</code></td> +<td>Regenerating team invitation IDs</td> +</tr> +<tr> +<td><code>removeTeamIcon</code></td> +<td>Removing team icons</td> +</tr> +<tr> +<td><code>removeTeamMember</code></td> +<td>Removing members from teams</td> +</tr> +<tr> +<td><code>restoreTeam</code></td> +<td>Restoring deleted teams</td> +</tr> +<tr> +<td><code>setTeamIcon</code></td> +<td>Setting team icons</td> +</tr> +<tr> +<td><code>updateTeam</code></td> +<td>Updating team information</td> +</tr> +<tr> +<td><code>updateTeamMemberRoles</code></td> +<td>Updating team member roles</td> +</tr> +<tr> +<td><code>updateTeamMemberSchemeRoles</code></td> +<td>Updating team member scheme roles</td> +</tr> +<tr> +<td><code>updateTeamPrivacy</code></td> +<td>Updating team privacy settings</td> +</tr> +<tr> +<td><code>updateTeamScheme</code></td> +<td>Updating team permission schemes</td> +</tr> +</tbody> +</table> + +### Posts & Content Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createPost</code></td> +<td>Creating new posts</td> +</tr> +<tr> +<td><code>createSchedulePost</code></td> +<td>Creating scheduled posts</td> +</tr> +<tr> +<td><code>deletePost</code></td> +<td>Deleting posts</td> +</tr> +<tr> +<td><code>deleteScheduledPost</code></td> +<td>Deleting scheduled posts</td> +</tr> +<tr> +<td><code>moveThread</code></td> +<td>Moving message threads</td> +</tr> +<tr> +<td><code>patchPost</code></td> +<td>Updating post properties</td> +</tr> +<tr> +<td><code>restorePostVersion</code></td> +<td>Restoring previous post versions</td> +</tr> +<tr> +<td><code>saveIsPinnedPost</code></td> +<td>Saving pinned post status</td> +</tr> +<tr> +<td><code>searchPosts</code></td> +<td>Searching through posts</td> +</tr> +<tr> +<td><code>updatePost</code></td> +<td>Updating post content</td> +</tr> +<tr> +<td><code>updateScheduledPost</code></td> +<td>Updating scheduled posts</td> +</tr> +</tbody> +</table> + +<Note> + +From Mattermost v11.5.0, audit log entries for posts and content access events include a `non_channel_member_access` field in the `meta` object. When a user accesses posts or content in a channel they are not a member of, this field is set to `true`. Admins can use this indicator to identify and review unauthorized or unexpected content access in their audit logs. + +</Note> + +### Authentication and Security Events + +<table style={{width: '86%'}}> +<colgroup> +<col style={{width: '29%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addLdapPrivateCertificate</code></td> +<td>Adding LDAP private certificates</td> +</tr> +<tr> +<td><code>addLdapPublicCertificate</code></td> +<td>Adding LDAP public certificates</td> +</tr> +<tr> +<td><code>addSamlIdpCertificate</code></td> +<td>Adding SAML IDP certificates</td> +</tr> +<tr> +<td><code>addSamlPrivateCertificate</code></td> +<td>Adding SAML private certificates</td> +</tr> +<tr> +<td><code>addSamlPublicCertificate</code></td> +<td>Adding SAML public certificates</td> +</tr> +<tr> +<td><code>completeSaml</code></td> +<td>Completing SAML authentication</td> +</tr> +<tr> +<td><code>extendSessionExpiry</code></td> +<td>Extending session expiry times</td> +</tr> +<tr> +<td><code>idMigrateLdap</code></td> +<td>Migrating IDs to LDAP</td> +</tr> +<tr> +<td><code>linkLdapGroup</code></td> +<td>Linking LDAP groups</td> +</tr> +<tr> +<td><code>removeLdapPrivateCertificate</code></td> +<td>Removing LDAP private certificates</td> +</tr> +<tr> +<td><code>removeLdapPublicCertificate</code></td> +<td>Removing LDAP public certificates</td> +</tr> +<tr> +<td><code>removeSamlIdpCertificate</code></td> +<td>Removing SAML IDP certificates</td> +</tr> +<tr> +<td><code>removeSamlPrivateCertificate</code></td> +<td>Removing SAML private certificates</td> +</tr> +<tr> +<td><code>removeSamlPublicCertificate</code></td> +<td>Removing SAML public certificates</td> +</tr> +<tr> +<td><code>revokeAllSessionsAllUsers</code></td> +<td>Revoking all sessions for all users</td> +</tr> +<tr> +<td><code>revokeAllSessionsForUser</code></td> +<td>Revoking all sessions for specific user</td> +</tr> +<tr> +<td><code>revokeSession</code></td> +<td>Revoking individual sessions</td> +</tr> +<tr> +<td><code>syncLdap</code></td> +<td>Synchronizing LDAP data</td> +</tr> +<tr> +<td><code>unlinkLdapGroup</code></td> +<td>Unlinking LDAP groups</td> +</tr> +</tbody> +</table> + +### System Administration Events + +<table style={{width: '84%'}}> +<colgroup> +<col style={{width: '27%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>clearServerBusy</code></td> +<td>Clearing server busy status</td> +</tr> +<tr> +<td><code>completeOnboarding</code></td> +<td>Completing system onboarding</td> +</tr> +<tr> +<td><code>configReload</code></td> +<td>Reloading system configuration</td> +</tr> +<tr> +<td><code>databaseRecycle</code></td> +<td>Recycling database connections</td> +</tr> +<tr> +<td><code>downloadLogs</code></td> +<td>Downloading system logs</td> +</tr> +<tr> +<td><code>getAppliedSchemaMigrations</code></td> +<td>Getting applied schema migrations</td> +</tr> +<tr> +<td><code>getAudits</code></td> +<td>Retrieving audit logs</td> +</tr> +<tr> +<td><code>getConfig</code></td> +<td>Getting system configuration</td> +</tr> +<tr> +<td><code>getLogs</code></td> +<td>Getting system logs</td> +</tr> +<tr> +<td><code>getOnboarding</code></td> +<td>Getting onboarding status</td> +</tr> +<tr> +<td><code>invalidateCaches</code></td> +<td>Invalidating system caches</td> +</tr> +<tr> +<td><code>migrateConfig</code></td> +<td>Migrating configuration</td> +</tr> +<tr> +<td><code>patchConfig</code></td> +<td>Updating configuration properties</td> +</tr> +<tr> +<td><code>queryLogs</code></td> +<td>Querying system logs</td> +</tr> +<tr> +<td><code>restartServer</code></td> +<td>Restarting server</td> +</tr> +<tr> +<td><code>setServerBusy</code></td> +<td>Setting server busy status</td> +</tr> +<tr> +<td><code>updateConfig</code></td> +<td>Updating system configuration</td> +</tr> +<tr> +<td><code>updateViewedProductNotices</code></td> +<td>Updating viewed product notices</td> +</tr> +<tr> +<td><code>upgradeToEnterprise</code></td> +<td>Upgrading to Enterprise edition</td> +</tr> +</tbody> +</table> + +### File Management Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createUpload</code></td> +<td>Creating file uploads</td> +</tr> +<tr> +<td><code>getFile</code></td> +<td>Retrieving files</td> +</tr> +<tr> +<td><code>getFileLink</code></td> +<td>Getting file links</td> +</tr> +<tr> +<td><code>uploadData</code></td> +<td>Uploading data</td> +</tr> +<tr> +<td><code>uploadFileMultipart</code></td> +<td>Uploading multipart files</td> +</tr> +<tr> +<td><code>uploadFileMultipartLegacy</code></td> +<td>Uploading legacy multipart files</td> +</tr> +<tr> +<td><code>uploadFileSimple</code></td> +<td>Uploading simple files</td> +</tr> +</tbody> +</table> + +### OAuth Applications Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>authorizeOAuthApp</code></td> +<td>Authorizing OAuth applications</td> +</tr> +<tr> +<td><code>authorizeOAuthPage</code></td> +<td>OAuth authorization page access</td> +</tr> +<tr> +<td><code>completeOAuth</code></td> +<td>Completing OAuth flow</td> +</tr> +<tr> +<td><code>createOAuthApp</code></td> +<td>Creating OAuth applications</td> +</tr> +<tr> +<td><code>deauthorizeOAuthApp</code></td> +<td>Deauthorizing OAuth applications</td> +</tr> +<tr> +<td><code>deleteOAuthApp</code></td> +<td>Deleting OAuth applications</td> +</tr> +<tr> +<td><code>getAccessToken</code></td> +<td>Getting OAuth access tokens</td> +</tr> +<tr> +<td><code>loginWithOAuth</code></td> +<td>Login with OAuth</td> +</tr> +<tr> +<td><code>mobileLoginWithOAuth</code></td> +<td>Mobile login with OAuth</td> +</tr> +<tr> +<td><code>regenerateOAuthAppSecret</code></td> +<td>Regenerating OAuth app secrets</td> +</tr> +<tr> +<td><code>signupWithOAuth</code></td> +<td>Signup with OAuth</td> +</tr> +<tr> +<td><code>updateOAuthApp</code></td> +<td>Updating OAuth applications</td> +</tr> +</tbody> +</table> + +### Webhooks Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createIncomingHook</code></td> +<td>Creating incoming webhooks</td> +</tr> +<tr> +<td><code>createOutgoingHook</code></td> +<td>Creating outgoing webhooks</td> +</tr> +<tr> +<td><code>deleteIncomingHook</code></td> +<td>Deleting incoming webhooks</td> +</tr> +<tr> +<td><code>deleteOutgoingHook</code></td> +<td>Deleting outgoing webhooks</td> +</tr> +<tr> +<td><code>getIncomingHook</code></td> +<td>Getting incoming webhooks</td> +</tr> +<tr> +<td><code>getOutgoingHook</code></td> +<td>Getting outgoing webhooks</td> +</tr> +<tr> +<td><code>regenOutgoingHookToken</code></td> +<td>Regenerating outgoing webhook tokens</td> +</tr> +<tr> +<td><code>updateIncomingHook</code></td> +<td>Updating incoming webhooks</td> +</tr> +<tr> +<td><code>updateOutgoingHook</code></td> +<td>Updating outgoing webhooks</td> +</tr> +</tbody> +</table> + +### Slash Commands Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createCommand</code></td> +<td>Creating slash commands</td> +</tr> +<tr> +<td><code>deleteCommand</code></td> +<td>Deleting slash commands</td> +</tr> +<tr> +<td><code>executeCommand</code></td> +<td>Executing slash commands</td> +</tr> +<tr> +<td><code>moveCommand</code></td> +<td>Moving slash commands</td> +</tr> +<tr> +<td><code>regenCommandToken</code></td> +<td>Regenerating command tokens</td> +</tr> +<tr> +<td><code>updateCommand</code></td> +<td>Updating slash commands</td> +</tr> +</tbody> +</table> + +### Plugins Events + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>disablePlugin</code></td> +<td>Disabling plugins</td> +</tr> +<tr> +<td><code>enablePlugin</code></td> +<td>Enabling plugins</td> +</tr> +<tr> +<td><code>getFirstAdminVisitMarketplaceStatus</code></td> +<td>Getting first admin visit marketplace status</td> +</tr> +<tr> +<td><code>installMarketplacePlugin</code></td> +<td>Installing marketplace plugins</td> +</tr> +<tr> +<td><code>installPluginFromURL</code></td> +<td>Installing plugins from URL</td> +</tr> +<tr> +<td><code>removePlugin</code></td> +<td>Removing plugins</td> +</tr> +<tr> +<td><code>setFirstAdminVisitMarketplaceStatus</code></td> +<td>Setting first admin visit marketplace status</td> +</tr> +<tr> +<td><code>uploadPlugin</code></td> +<td>Uploading plugins</td> +</tr> +</tbody> +</table> + +### Groups & LDAP Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addGroupMembers</code></td> +<td>Adding members to groups</td> +</tr> +<tr> +<td><code>addUserToGroupSyncables</code></td> +<td>Adding users to group syncables</td> +</tr> +<tr> +<td><code>createGroup</code></td> +<td>Creating new groups</td> +</tr> +<tr> +<td><code>deleteGroup</code></td> +<td>Deleting groups</td> +</tr> +<tr> +<td><code>deleteGroupMembers</code></td> +<td>Removing members from groups</td> +</tr> +<tr> +<td><code>linkGroupSyncable</code></td> +<td>Linking group syncables to teams/channels</td> +</tr> +<tr> +<td><code>patchGroup</code></td> +<td>Updating group properties</td> +</tr> +<tr> +<td><code>patchGroupSyncable</code></td> +<td>Updating group syncable properties</td> +</tr> +<tr> +<td><code>restoreGroup</code></td> +<td>Restoring deleted groups</td> +</tr> +<tr> +<td><code>unlinkGroupSyncable</code></td> +<td>Unlinking group syncables from teams/channels</td> +</tr> +</tbody> +</table> + +### Remote Clusters Events + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '30%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createRemoteCluster</code></td> +<td>Creating remote cluster connections</td> +</tr> +<tr> +<td><code>deleteRemoteCluster</code></td> +<td>Deleting remote cluster connections</td> +</tr> +<tr> +<td><code>generateRemoteClusterInvite</code></td> +<td>Generating invites for remote clusters</td> +</tr> +<tr> +<td><code>inviteRemoteClusterToChannel</code></td> +<td>Inviting remote clusters to channels</td> +</tr> +<tr> +<td><code>patchRemoteCluster</code></td> +<td>Updating remote cluster properties</td> +</tr> +<tr> +<td><code>remoteClusterAcceptInvite</code></td> +<td>Accepting remote cluster invites</td> +</tr> +<tr> +<td><code>remoteClusterAcceptMessage</code></td> +<td>Accepting messages from remote clusters</td> +</tr> +<tr> +<td><code>remoteUploadProfileImage</code></td> +<td>Uploading profile images from remote clusters</td> +</tr> +<tr> +<td><code>uninviteRemoteClusterToChannel</code></td> +<td>Removing remote cluster invites from channels</td> +</tr> +<tr> +<td><code>uploadRemoteData</code></td> +<td>Uploading data from remote clusters</td> +</tr> +</tbody> +</table> + +### Data Retention Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addChannelsToPolicy</code></td> +<td>Adding channels to data retention policies</td> +</tr> +<tr> +<td><code>addTeamsToPolicy</code></td> +<td>Adding teams to data retention policies</td> +</tr> +<tr> +<td><code>createPolicy</code></td> +<td>Creating data retention policies</td> +</tr> +<tr> +<td><code>deletePolicy</code></td> +<td>Deleting data retention policies</td> +</tr> +<tr> +<td><code>patchPolicy</code></td> +<td>Updating data retention policies</td> +</tr> +<tr> +<td><code>removeChannelsFromPolicy</code></td> +<td>Removing channels from data retention policies</td> +</tr> +<tr> +<td><code>removeTeamsFromPolicy</code></td> +<td>Removing teams from data retention policies</td> +</tr> +</tbody> +</table> + +### Jobs Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>cancelJob</code></td> +<td>Canceling background jobs</td> +</tr> +<tr> +<td><code>createJob</code></td> +<td>Creating new background jobs</td> +</tr> +<tr> +<td><code>jobServer</code></td> +<td>Job server operations</td> +</tr> +<tr> +<td><code>updateJobStatus</code></td> +<td>Updating job status/progress</td> +</tr> +</tbody> +</table> + +### Licensing Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addLicense</code></td> +<td>Adding enterprise licenses</td> +</tr> +<tr> +<td><code>localAddLicense</code></td> +<td>Local license addition (cluster mode)</td> +</tr> +<tr> +<td><code>localRemoveLicense</code></td> +<td>Local license removal (cluster mode)</td> +</tr> +<tr> +<td><code>removeLicense</code></td> +<td>Removing enterprise licenses</td> +</tr> +<tr> +<td><code>requestTrialLicense</code></td> +<td>Requesting trial licenses</td> +</tr> +</tbody> +</table> + +### Bot Management Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>assignBot</code></td> +<td>Assigning bots to users</td> +</tr> +<tr> +<td><code>convertBotToUser</code></td> +<td>Converting bot accounts to user accounts</td> +</tr> +<tr> +<td><code>convertUserToBot</code></td> +<td>Converting user accounts to bot accounts</td> +</tr> +<tr> +<td><code>createBot</code></td> +<td>Creating new bot accounts</td> +</tr> +<tr> +<td><code>patchBot</code></td> +<td>Updating bot account properties</td> +</tr> +<tr> +<td><code>updateBotActive</code></td> +<td>Updating bot account active/inactive status</td> +</tr> +</tbody> +</table> + +### Custom Emojis Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createEmoji</code></td> +<td>Creating custom emojis</td> +</tr> +<tr> +<td><code>deleteEmoji</code></td> +<td>Deleting custom emojis</td> +</tr> +</tbody> +</table> + +### Branding Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>deleteBrandImage</code></td> +<td>Deleting brand images</td> +</tr> +<tr> +<td><code>uploadBrandImage</code></td> +<td>Uploading brand images</td> +</tr> +</tbody> +</table> + +### Search Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>purgeBleveIndexes</code></td> +<td>Purging Bleve search indexes</td> +</tr> +<tr> +<td><code>purgeElasticsearchIndexes</code></td> +<td>Purging Elasticsearch search indexes</td> +</tr> +</tbody> +</table> + +### Roles and Schemes Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createScheme</code></td> +<td>Creating permission schemes</td> +</tr> +<tr> +<td><code>deleteScheme</code></td> +<td>Deleting permission schemes</td> +</tr> +<tr> +<td><code>patchRole</code></td> +<td>Updating role permissions</td> +</tr> +<tr> +<td><code>patchScheme</code></td> +<td>Updating permission schemes</td> +</tr> +</tbody> +</table> + +### Preferences Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>deletePreferences</code></td> +<td>Deleting user preferences</td> +</tr> +<tr> +<td><code>updatePreferences</code></td> +<td>Updating user preferences</td> +</tr> +</tbody> +</table> + +### Channel Categories Events + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '6%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th colspan="3"><strong>Event Name</strong> | <strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td colspan="3"><code>createCategoryForTeamForUser</code> | Creating channel categories for users</td> +</tr> +<tr> +<td colspan="2"><code>deleteCategoryForTeamForUser</code></td> +<td>Deleting channel categories for users</td> +</tr> +<tr> +<td colspan="2"><code>updateCategoriesForTeamForUser</code></td> +<td>Updating multiple channel categories for users</td> +</tr> +<tr> +<td colspan="2"><code>updateCategoryForTeamForUser</code></td> +<td>Updating single channel category for users</td> +</tr> +<tr> +<td colspan="2"><code>updateCategoryOrderForTeamForUser</code></td> +<td>Updating channel category order for users</td> +</tr> +</tbody> +</table> + +### Export and Import Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>bulkExport</code></td> +<td>Bulk data export operations</td> +</tr> +<tr> +<td><code>bulkImport</code></td> +<td>Bulk data import operations</td> +</tr> +<tr> +<td><code>deleteExport</code></td> +<td>Deleting export files</td> +</tr> +<tr> +<td><code>deleteImport</code></td> +<td>Deleting import files</td> +</tr> +<tr> +<td><code>generatePresignURLExport</code></td> +<td>Generating presigned URLs for exports</td> +</tr> +<tr> +<td><code>scheduleExport</code></td> +<td>Scheduling export operations</td> +</tr> +<tr> +<td><code>slackImport</code></td> +<td>Slack data import operations</td> +</tr> +</tbody> +</table> + +### Access Control Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>applyIPFilters</code></td> +<td>Applying IP filtering rules</td> +</tr> +<tr> +<td><code>assignAccessPolicy</code></td> +<td>Assigning access policies to users/teams</td> +</tr> +<tr> +<td><code>createAccessControlPolicy</code></td> +<td>Creating new access control policies</td> +</tr> +<tr> +<td><code>deleteAccessControlPolicy</code></td> +<td>Deleting access control policies</td> +</tr> +<tr> +<td><code>unassignAccessPolicy</code></td> +<td>Unassigning access policies from users/teams</td> +</tr> +<tr> +<td><code>updateActiveStatus</code></td> +<td>Updating active status of access control policies</td> +</tr> +</tbody> +</table> + +### User Attributes Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createCPAField</code></td> +<td>Creating custom profile attribute fields</td> +</tr> +<tr> +<td><code>deleteCPAField</code></td> +<td>Deleting custom profile attribute fields</td> +</tr> +<tr> +<td><code>patchCPAField</code></td> +<td>Updating custom profile attribute fields</td> +</tr> +<tr> +<td><code>patchCPAValues</code></td> +<td>Updating custom profile attribute values</td> +</tr> +</tbody> +</table> + +### Outgoing OAuth Connections Events + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createOutgoingOauthConnection</code></td> +<td>Creating outgoing OAuth connections</td> +</tr> +<tr> +<td><code>deleteOutgoingOAuthConnection</code></td> +<td>Deleting outgoing OAuth connections</td> +</tr> +<tr> +<td><code>updateOutgoingOAuthConnection</code></td> +<td>Updating outgoing OAuth connections</td> +</tr> +<tr> +<td><code>validateOutgoingOAuthConnectionCredentials</code></td> +<td>Validating outgoing OAuth connection credentials</td> +</tr> +</tbody> +</table> + +### Terms of Service Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createTermsOfService</code></td> +<td>Creating terms of service</td> +</tr> +<tr> +<td><code>saveUserTermsOfService</code></td> +<td>Saving user acceptance of terms of service</td> +</tr> +</tbody> +</table> + +### Compliance and Audit Events + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '26%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>addAuditLogCertificate</code></td> +<td>Adding audit log certificates</td> +</tr> +<tr> +<td><code>createComplianceReport</code></td> +<td>Creating compliance reports</td> +</tr> +<tr> +<td><code>downloadComplianceReport</code></td> +<td>Downloading compliance reports</td> +</tr> +<tr> +<td><code>getComplianceReport</code></td> +<td>Getting compliance reports</td> +</tr> +<tr> +<td><code>getComplianceReports</code></td> +<td>Getting multiple compliance reports</td> +</tr> +<tr> +<td><code>removeAuditLogCertificate</code></td> +<td>Removing audit log certificates</td> +</tr> +</tbody> +</table> + +### Local Operations Events + +<table style={{width: '86%'}}> +<colgroup> +<col style={{width: '29%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>localCheckIntegrity</code></td> +<td>Local integrity checks</td> +</tr> +<tr> +<td><code>localCreateChannel</code></td> +<td>Local channel creation</td> +</tr> +<tr> +<td><code>localCreateCommand</code></td> +<td>Local command creation</td> +</tr> +<tr> +<td><code>localCreateIncomingHook</code></td> +<td>Local incoming webhook creation</td> +</tr> +<tr> +<td><code>localCreateTeam</code></td> +<td>Local team creation</td> +</tr> +<tr> +<td><code>localDeleteChannel</code></td> +<td>Local channel deletion</td> +</tr> +<tr> +<td><code>localDeletePost</code></td> +<td>Local post deletion</td> +</tr> +<tr> +<td><code>localDeleteTeam</code></td> +<td>Local team deletion</td> +</tr> +<tr> +<td><code>localDeleteUser</code></td> +<td>Local user deletion</td> +</tr> +<tr> +<td><code>localGetClientConfig</code></td> +<td>Local client configuration retrieval</td> +</tr> +<tr> +<td><code>localGetConfig</code></td> +<td>Local configuration retrieval</td> +</tr> +<tr> +<td><code>localInviteUsersToTeam</code></td> +<td>Local user invitation to teams</td> +</tr> +<tr> +<td><code>localMoveChannel</code></td> +<td>Local channel moving</td> +</tr> +<tr> +<td><code>localPatchChannel</code></td> +<td>Local channel patching</td> +</tr> +<tr> +<td><code>localPatchConfig</code></td> +<td>Local configuration patching</td> +</tr> +<tr> +<td><code>localPermanentDeleteAllUsers</code></td> +<td>Local permanent deletion of all users</td> +</tr> +<tr> +<td><code>localRemoveChannelMember</code></td> +<td>Local channel member removal</td> +</tr> +<tr> +<td><code>localRestoreChannel</code></td> +<td>Local channel restoration</td> +</tr> +<tr> +<td><code>localUpdateChannelPrivacy</code></td> +<td>Local channel privacy update</td> +</tr> +<tr> +<td><code>localUpdateConfig</code></td> +<td>Local configuration update</td> +</tr> +</tbody> +</table> + +### AI Recap Events + +Recap events include a `channel_id` in the event parameters, indicating which channel's content was accessed during the recap operation. Use this field when reviewing audit logs for compliance or access monitoring. + +<table style={{width: '75%'}}> +<colgroup> +<col style={{width: '18%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Event Name</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><code>createRecap</code></td> +<td>Creating channel recaps</td> +</tr> +<tr> +<td><code>deleteRecap</code></td> +<td>Deleting channel recaps</td> +</tr> +<tr> +<td><code>getRecap</code></td> +<td>Retrieving channel recaps</td> +</tr> +<tr> +<td><code>getRecaps</code></td> +<td>Retrieving multiple channel recaps</td> +</tr> +<tr> +<td><code>markRecapAsRead</code></td> +<td>Marking channel recaps as read</td> +</tr> +<tr> +<td><code>regenerateRecap</code></td> +<td>Regenerating channel recaps</td> +</tr> +</tbody> +</table> + +<Note> + +This comprehensive list includes all audit events captured by Mattermost across all major system operations. Additional events may be logged depending on your Mattermost version, enabled features, and configuration settings. Enterprise and Enterprise Advanced features may generate additional audit events. + +</Note> + +## JSON data model + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '6%'}} /> +<col style={{width: '15%'}} /> +<col style={{width: '67%'}} /> +<col style={{width: '9%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Name</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +<td></td> +</tr> +<tr> +<td>timestamp</td> +<td>int64</td> +<td colspan="2"><dl><dt>Date/time when event or activity has taken place. |</dt><dd><div class="line-block"></div></dd></dl><p>Mattermost currently supports three log formats: plain, JSON, and | <a href="https://go2docs.graylog.org/current/getting_in_log_data/gelf.html">GELF</a>. | | - Plain log format uses <a href="https://www.rfc-editor.org/rfc/rfc3339">RFC3339</a> by default. | See the <a href="mm-ref:administration-guide%2Fmanage%2Flogging%3Aplain%20log%20format%20configuration%20options">plain log format configuration</a> documentation for supported options. | - JSON log format uses <a href="https://www.rfc-editor.org/rfc/rfc3339">RFC3339</a> by default. | See the <a href="mm-ref:administration-guide%2Fmanage%2Flogging%3Ajson%20log%20format%20configuration%20options">JSON log format configuration</a> documentation for supported options. | | - GELF log format uses <a href="https://www.unixtimestamp.com/">unixtime</a>. | See the <a href="mm-ref:administration-guide%2Fmanage%2Flogging%3Agelf%20log%20format%20configuration%20options">GELF log format configuration</a> documentation for supported options. |</p></td> +</tr> +<tr> +<td>event_name</td> +<td>string</td> +<td>Unique name and identifier of the event type taking place. See the <a href="#audit-event-types">audit event types</a> section for a comprehensive list of all supported event names.</td> +<td></td> +</tr> +<tr> +<td>status</td> +<td>string</td> +<td>Success or failure of the audited event.</td> +<td></td> +</tr> +<tr> +<td>event</td> +<td><a href="#eventdata">EventData</a></td> +<td>Event parameters and object states.</td> +<td></td> +</tr> +<tr> +<td>actor</td> +<td><a href="#eventactor">EventActor</a></td> +<td>User involved with the event.</td> +<td></td> +</tr> +<tr> +<td>meta</td> +<td><a href="#eventmeta">EventMeta</a></td> +<td>Related event metadata.</td> +<td></td> +</tr> +<tr> +<td>error</td> +<td><a href="#eventerror">EventError</a></td> +<td>The resulting error if the status is in a failed state.</td> +<td></td> +</tr> +</tbody> +</table> + +### EventData + +<table style={{width: '87%'}}> +<colgroup> +<col style={{width: '16%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Field name</strong></td> +<td><strong>Data type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>parameters</td> +<td>map</td> +<td>Payload and parameters being processed as part of the request.</td> +</tr> +<tr> +<td>prior_state</td> +<td>map</td> +<td>Prior state of the entity being modified. <code>null</code> if there was no prior state.</td> +</tr> +<tr> +<td>resulting_state</td> +<td>map</td> +<td>Resulting entity after creating or modifying it.</td> +</tr> +<tr> +<td>object_type</td> +<td>string</td> +<td>String representation of the entity type (e.g. post)</td> +</tr> +</tbody> +</table> + +### EventActor + +<table style={{width: '87%'}}> +<colgroup> +<col style={{width: '16%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Field name</strong></td> +<td><strong>Data type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>user_id</td> +<td>string</td> +<td>Unique identifier of the event actor.</td> +</tr> +<tr> +<td>session_id</td> +<td>string</td> +<td>Unique session identifier of the event actor.</td> +</tr> +<tr> +<td>client</td> +<td>string</td> +<td>User agent of the client/platform in use by the event actor.</td> +</tr> +<tr> +<td>ip_address</td> +<td>string</td> +<td>IPv4/IPv6 IP address of the event actor.</td> +</tr> +</tbody> +</table> + +### EventMeta + +<table style={{width: '94%'}}> +<colgroup> +<col style={{width: '24%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Field name</strong></td> +<td><strong>Data type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>api_path</td> +<td>string</td> +<td>The REST endpoint which caused the event.</td> +</tr> +<tr> +<td>cluster_id</td> +<td>integer</td> +<td>Cluster identifier.</td> +</tr> +<tr> +<td>non_channel_member_access</td> +<td>boolean</td> +<td>(Optional) Available from v11.5.0. Set to <code>true</code> when a user | accesses posts or content in a channel they are not a member of.</td> +</tr> +</tbody> +</table> + +### EventError + +<table style={{width: '87%'}}> +<colgroup> +<col style={{width: '16%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Field name</strong></td> +<td><strong>Data type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>description</td> +<td>string</td> +<td>(Optional) Error description.</td> +</tr> +<tr> +<td>status_code</td> +<td>integer</td> +<td>(Optional) Error status code.</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/comply/export-mattermost-channel-data.mdx b/docs/main/administration-guide/comply/export-mattermost-channel-data.mdx new file mode 100644 index 000000000000..00bce4371edd --- /dev/null +++ b/docs/main/administration-guide/comply/export-mattermost-channel-data.mdx @@ -0,0 +1,41 @@ +--- +title: "Export channel data" +--- +<PlanAvailability slug="ent-plus" /> + +Ensure important data isn't trapped in silos by migrating data between systems or backing data up for operational continuity. Once exported, channel data can be analyzed using various tools for insights into team dynamics, productivity, and communication patterns, and to fulfill reporting and auditability requirements. + +## Enable + +<Note> + +For Mattermost Cloud deployments, no setup is required. See the [usage](#usage) section below for details on exporting channel data. + +</Note> + +For self-hosted deployments, a Mattermost system admin must install the Channel Export integration from the in-product App Marketplace: + +1. In Mattermost, from the Product menu <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" />, select **App Marketplace**. +2. Search for or scroll to **Channel Export**, and select **Install**. +3. Once installed, select **Configure**. You're taken to the System Console. +4. On the **Channel Export** configuration page, enable and configure the plugin, and then select **Save**. You can restrict the ability to export channels to system, team, and channel admins only, and you can configure a maximum file size for channel export files. + +## Upgrade + +We recommend upgrading this feature as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-channel-export/releases) for the latest release, available releases, and compatibiilty considerations. + +## Usage + +You need to be a Mattermost system admin to export channel data. + +Use the `/export` slash command in a channel to export the current channel's message data into a CSV-formatted file. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost Channel Export plugin GitHub repository](https://github.com/mattermost/mattermost-plugin-channel-export). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +## Customize this integration + +This plugin contains both a server and web app portion. See the [Channel Export plugin README documentation](https://github.com/mattermost/mattermost-plugin-channel-export?tab=readme-ov-file#development) on GitHub for details. Visit the [Mattermost Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Mattermost Developer environment setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for information about developing, customizing, and extending Mattermost functionality. diff --git a/docs/main/administration-guide/comply/legal-hold.mdx b/docs/main/administration-guide/comply/legal-hold.mdx new file mode 100644 index 000000000000..511e973893d1 --- /dev/null +++ b/docs/main/administration-guide/comply/legal-hold.mdx @@ -0,0 +1,198 @@ +--- +title: "Legal Hold" +--- +<PlanAvailability slug="ent-plus" /> + +A Legal Hold, also known as a litigation hold, is a process that an organization uses to preserve all forms of relevant information when litigation is reasonably anticipated. It's a requirement established by the Federal Rules of Civil Procedure (FRCP) in the United States and similar laws in other jurisdictions. + +Primary use cases include: + +1. **Litigation**: In anticipation or in the event of a lawsuit, organizations need to preserve all relevant documents and electronic data to ensure they can adequately defend their position. A failure to do so could result in court penalties. +2. **Regulatory investigation**: If an organization is being investigated by a regulatory body, it may be required to preserve and produce certain documents or data. +3. **Audits**: During an audit, whether internal or external, an organization might need to put a hold on certain data that is relevant to the audit. +4. **Records management**: In some cases, organizations might use a Legal Hold to temporarily suspend the deletion of data that would otherwise be purged as part of its records management policy. + +Mattermost is used as a secure collaboration hub by technical and operational teams, with critical documents and data shared on a daily basis. Thus, Legal Hold is a key requirement for Enterprises and public sector organizations who have deployed Mattermost for their teams, to meet compliance & auditory requirements while minimizing risk. + +Mattermost Legal Hold can be combined with [eDiscovery](/administration-guide/comply/electronic-discovery) integration and [data retention policies](/administration-guide/comply/data-retention-policy) to customize the data retained and deleted to comply with compliance requirements. + +## Legal Hold demo (Sneak Peek) + +Check out this [YouTube sneak peek demo](https://www.youtube.com/watch?v=86c8NoOxlQw&feature=youtu.be) to learn about Mattermost's Legal Hold workflow. + +<iframe width="560" height="315" src="https://www.youtube.com/embed/86c8NoOxlQw" alt="Mattermost Legal Hold workflow" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> + +Below are step-by-step instructions on how to carry out a Legal Hold for Mattermost using the Mattermost Legal Hold plugin. + +## How to carry out a Legal Hold + +### Step 1: Upgrade to Mattermost Enterprise + +Legal Hold is available in [Mattermost Enterprise](/product-overview/editions-and-offerings#mattermost-enterprise-edition). Learn more about the Enterprise plan & request a quote online at [https://mattermost.com/pricing/](https://mattermost.com/pricing/) + +### Step 2: Establish a Legal Hold policy + +Establish a policy for when to implement a Legal Hold. This should be developed in consultation with your legal counsel and should include procedures for identifying relevant users (those who have potentially relevant information). + +Establishing a Legal Hold policy first enables you to configure the Mattermost system correctly to meet your compliance & auditory requirements, minimizing associated risk. + +### Step 3: Set up the Mattermost Legal Hold plugin + +#### Install the plugin + +1. Log in to your Mattermost [workspace](/end-user-guide/end-user-guide-index) as a system administrator. +2. Download the latest version of the [plugin binary release](https://github.com/mattermost/mattermost-plugin-legal-hold/releases/), compatible with Mattermost v8.0.1 and later. If you are using an earlier version of Mattermost, [follow our documentation](/administration-guide/upgrade/upgrading-mattermost-server) to upgrade to Mattermost v8.0.1 or later. +3. Go to **System Console \> Plugins \> Plugin Management \> Upload Plugin**, and upload the plugin binary you downloaded in the previous step. +4. In the **Installed Plugins** section, scroll to **Legal Hold Plugin**, and select **Enable**. + +#### Configure the plugin + +When the Legal Hold integration is enabled, you can configure when it runs using the format `HH:MM ±HHMM` and `+0000` for UTC. + +You can configure a custom Amazon S3 bucket for Legal Holds by specifying Amazon S3 configuration settings. If no S3 configuration is specified, the Mattermost server file store used. Learn more about file storage configuration options in our [product documentation](/administration-guide/configure/environment-configuration-settings#file-storage). + +#### (Optional) Configure a data retention policy + +You can optionally configure a [data retention policy](/administration-guide/comply/data-retention-policy) to control how long data and file attachments are retained in the Mattermost database. + +### Step 4: Create a Legal Hold + +In Mattermost, create a Legal Hold by completing the following steps: + +1. Go to **System Console \> Plugins \> Legal Hold Plugin**, and select **Create new**. +2. Enter a name for the Legal Hold. +3. Specify the user names or user groups of users you want to place on Legal Hold. +4. (Optional) Public channels are excluded by default. You can choose to include public channels that the specified users or user groups are members of, if preferred; however, doing so will significantly increase the amount of data held based on the number public channels available. +5. Specify the number of days that users are placed in Legal Hold with a start date. An end date is optional. +6. Select **Create Legal Hold**. [Downloadable data](#download-legal-hold-data) won't be available until the next scheduled job runs. + +#### Manage Legal Holds + +While a Legal Hold is in place, you can edit details of the Legal Hold, access the Legal Hold Secret, as well as download a copy of the preserved data to your local machine. + +![An example of the Legal Hold management interface available to Mattermost system admins.](/images/legal-holds.png) + +##### Edit a Legal Hold + +Select the **Edit** <img src="/img/ui/edit-on-github.png" alt="Contribute to Mattermost documentation by selecting the Edit option located in the top right corner of any documentation page." className="theme-icon" /> icon to change the name of the Legal Hold, add or remove users, change the end date, as well as include or exclude public channels. + +##### Access a Legal Hold secret + +A Legal Hold secret enables you to verify the authenticity of the data for a Legal Hold in Mattermost. + +Select the **Show** <img src="/img/ui/eye-outline_F06D0.svg" alt="Review your message text formatting using the Show/Hide preview icon in the message formatting toolbar." className="theme-icon" /> icon to display the Legal Hold secret key. Keep a copy of this key in a secure location. + +![An example of a Legal Hold Secret Key available to Mattermost system admins.](/images/legal-hold-secret.png) + +To verfiy the contents of the files in this Legal Hold, you must append the processor command with the following flag: `--legal-hold-secret <KEY>`. The output verifies the file and returns the authenticity state of files along with the rest of the output for the processor, as follows: + +Success: + +``` text +Secret key was provided, verifying legal holds... +- Verifying Legal Hold *processor9*: Verified +``` + +Error: + +``` text +... +Secret key was provided, verifying legal holds... +- Verifying Legal Hold *processor9*: [Error] hash mismatch for file: legal_hold/processor9_i7k1dbkipiyojeess6ozi4agyr/index.json +... +``` + +##### Download Legal Hold data + +Select the **Download** <img src="/img/ui/download-outline_F0B8F.svg" alt="Use the Download icon to download an attached file to your local system." className="theme-icon" /> icon to download a copy of the preserved data to a location on your local machine. Note, no data will be available to download until at least one scheduled job is completed. This may take up to 24 hours. + +### Step 5: Release a Legal Hold + +Once the Legal Hold has completed, release it to take users off of the Legal Hold by selecting the **Release** option to the right of the Legal Hold task. + +<Important> + +Once a Legal Hold is released, all data is irretrievably deleted from Mattermost and can't be recovered. + +</Important> + +## Frequently asked questions + +### Who can implement Legal Hold? + +Only Mattermost system admins can implement a Legal Hold. + +### Does a user know if they're placed under a Legal Hold in Mattermost? + +No, users won't be notified if they're placed under a Legal Hold, and no reference to Legal Holds will be visible in their Mattermost client or accessible via the Mattermost API. This allows for investigations to be conducted without influencing user behavior and without conflicts of interest. + +### What types of content does Legal Hold cover? + +The Legal Hold covers all messages and file uploads shared in conversations where the Legal Hold is active, including messages posted by plugins, bots or webhooks. This includes messages or files shared in public channels, private channels, direct messages and group messages. + +However, Legal Hold does not apply to reactions, collaborative playbooks, or audio calls. + +### Can users delete their messages while on a Legal Hold? + +Yes, users can delete messages, but they are retained for the purposes of Legal Hold when implemented with the aforementioned steps. + +### Can a Legal Hold be applied retroactively to collect past data? + +Yes, but this is only guaranteed for existing and future messages/files once Legal Hold is activated. It won't recover messages or files that were deleted before the Legal Hold was activated. + +### Is Legal Hold the same as e-discovery? + +No. While they serve a related use case, they are not the same. + +Legal Hold is an initial step to ensure relevant electronically stored information (ESI) is preserved. On the other hand, e-discovery is a multi-step process that uses this preserved data to identify, collect, preserve, process, review, and produce ESI in the context of a legal or investigative process. + +### How do I enable e-discovery for Mattermost? + +Learn more about extracting data for e-discovery in our [product documentation](/administration-guide/comply/electronic-discovery). + +### How do I manage storage costs and version retention in S3? + +If you plan to use an existing S3 bucket for Legal Hold data storage, and your existing S3 bucket has versioning enabled, we strongly recommend using a dedicated S3 bucket with versioning disabled. + +The Legal Hold plugin frequently modifies files in the `legalhold` directory, and when S3 bucket versioning is enabled, each modification creates a new version. This can result in a rapid accumulation of object versions, increased storage costs, potential performance impact, higher S3 API usage, and complicating version management over time. See the [S3 Lifecycle Rules](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html) documentation for additional details. + +### How to view the downloaded Legal Hold zip file + +To make use of the Legal Hold data, you use the [processor tool](https://github.com/mattermost/mattermost-plugin-legal-hold/releases#:~:text=processor%2Dv1.0.2%2Ddarwin%2Damd64) available on the Mattermost GitHub repository. This will output a self-contained HTML site you can open with your browser. + +**Download and setup the processor tool:** + +1. Download the appropriate processor binary for your platform from the [GitHub releases page](https://github.com/mattermost/mattermost-plugin-legal-hold/releases). +2. On macOS and Linux, make the processor executable: + +``` bash +$ chmod +x processor-vX.X.X-<platform> # Replace with the actual filename you downloaded +``` + +**Usage:** + +``` bash +$ ./processor --legal-hold-data ./legalholddata.zip --output-path ./path/to/where/you/want/the/html/output --legal-hold-secret "your secret" +``` + +**Arguments:** + +- `--legal-hold-data`: Path to the Legal Hold zip file downloaded from Mattermost +- `--output-path`: Directory where the HTML output will be generated +- `--legal-hold-secret`: (Optional) Used as a security measure for an operator to ensure the authenticity of a downloaded zip file. The operator can copy the key corresponding to a particular "hold" from the Legal Hold Plugin settings page in the System Console by selecting the **Show** <img src="/img/ui/eye-outline_F06D0.svg" alt="Review your message text formatting using the Show/Hide preview icon in the message formatting toolbar." className="theme-icon" /> icon next to the Legal Hold entry. + +### Is data gathered when a channel has been archived? + +Yes. Filtering isn't done based on archive or deleted status. However, archived channels can be permanently deleted based on Data Retention settings, at which point they will no longer appear in legal hold reports. + +### Is data gathered when a user was a member of a channel for a period of time but has since left the channel? + +Yes. Channels are included when a target user was a member at any time during the legal hold start and end dates. + +### Is data gathered from a direct message or group message with a user who has since been deactivated? + +Yes. Filtering isn't done based on user deactivation state. + +### Is data collected from group messages? + +Yes. Data is collected from group messages like any public or private channel or direct message. diff --git a/docs/main/administration-guide/configure/agents-admin-guide.mdx b/docs/main/administration-guide/configure/agents-admin-guide.mdx new file mode 100644 index 000000000000..e20cbfa6d483 --- /dev/null +++ b/docs/main/administration-guide/configure/agents-admin-guide.mdx @@ -0,0 +1,19 @@ +--- +title: "Mattermost Agents Admin Guide" +--- +<PlanAvailability slug="all-commercial" /> + +{/* TODO: include /agents/docs/admin_guide.md could not be resolved */} + +## Additional configuration guides + +- [Configure Agents with AWS Bedrock](/agents/docs/aws_bedrock_setup) + +<Tip> + +- To access the contents of files using Agents, a Mattermost system admin must [enable document search by content](/administration-guide/configure/environment-configuration-settings#enable-document-search-by-content) in the System Console. +- Looking for demo? [Try it yourself](https://mattermost.com/demo/copilot/)! +- Download the [Mattermost datasheet](https://mattermost.com/mattermost-copilot-datasheet/) to learn more about integrating with industry-leading large language models (LLMs). +- Mattermost Agents is formerly known as Mattermost Copilot. + +</Tip> diff --git a/docs/main/administration-guide/configure/authentication-configuration-settings.mdx b/docs/main/administration-guide/configure/authentication-configuration-settings.mdx new file mode 100644 index 000000000000..0866d1f8ad61 --- /dev/null +++ b/docs/main/administration-guide/configure/authentication-configuration-settings.mdx @@ -0,0 +1,2313 @@ +--- +title: "Authentication configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost supports up to 4 distinct, concurrent methods of user authentication: + +- An OpenID provider +- A SAML provider +- An LDAP instance (e.g., Active Directory, OpenLDAP) +- Email and Password + +Review and manage the following authentication configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Authentication**: + +- [Signup](#signup) +- [Email](#email) +- [Password](#password) +- [MFA](#mfa) +- [AD/LDAP](#ad-ldap) +- [SAML 2.0](#saml-2-0) +- [OAuth 2.0](#oauth-2-0) +- [OpenID Connect](#openid-connect) +- [Guest Access](#guest-access) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `EnableUserCreation` value is under `TeamSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.TeamSettings.EnableUserCreation'` +- When working with the `config.json` file manually, look for an object such as `TeamSettings`, then within that object, find the key `EnableUserCreation`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Signup + +Access the following configuration settings in the System Console by going to **Authentication \> Signup**. + +### Enable account creation + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Anyone can sign up for a user account on this server without needing to be invited. Applies to email-based signups only.</li><li><strong>false</strong>: The ability to create accounts is disabled. Selecting <strong>Create Account</strong> displays an error. Applies to email, OpenID Connect, and OAuth 2.0 user account authentication.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Signup</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableUserCreation</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLEUSERCREATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- LDAP and SAML users can always create a Mattermost account by logging in using LDAP or SAML user credentials, regardless of whether this configuration setting is enabled. - From Mattermost v10.9, email addresses enclosed in angle brackets (e.g., `[billy@example.com](mailto:billy@example.com)`) will be rejected. To avoid issues, ensure all user emails comply with the plain address format (e.g., `billy@example.com`). In addition, we strongly recommend taking proactive steps to audit and update Mattermost user data to align with this product change, as impacted users may face issues accessing Mattermost or managing their user profile. You can update these user emails manually using [mmctl user email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-email). - See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +</Note> + +### Restrict account creation to specified email domains + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This setting limits the email address domains that can be used to create a new account or team. | - System Config path: <strong>Authentication > Signup</strong> | You <strong>must</strong> set <a href="mm-ref:administration-guide%2Fconfigure%2Fauthentication-configuration-settings%3Arequire%20email%20verification">Require Email Verification</a> | - <code>config.json</code> setting: <code>TeamSettings</code> > <code>RestrictCreationToDomains</code> to <code>true</code> for the restriction to function. This setting only affects email login. | - Environment variable: <code>MM_TEAMSETTINGS_RESTRICTCREATIONTODOMAINS</code> |</td> +</tr> +</tbody> +</table> + +### Enable open server + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Users can create accounts on the server without an invitation.</li><li><strong>false</strong>: <strong>(Default)</strong> Users <strong>must</strong> have an invitation to create an account on the server.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Signup</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableOpenServer</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLEOPENSERVER</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable email invitations + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default for Cloud deployments)</strong> Allows users to send email invitations.</li><li><strong>false</strong>: <strong>(Default for self-hosted deployments)</strong> Disables email invitations.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Signup</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableEmailInvitations</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEEMAILINVITATIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Invalidate pending email invites + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This button invalidates email invitations that have not been accepted (by default, invitations expire after 48 hours).</p><p>This option has no <code>config.json</code> setting or environment variable.</p></td> +<td><ul><li>System Config path: <strong>Authentication > Signup</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Email + +Access the following configuration settings in the System Console by going to **Authentication \> Email**. + +### Enable account creation with email + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows creation of team and user accounts with email and password.</li><li><strong>false</strong>: Disables creation of team and user accounts with email and password. Requires a single sign-on (SSO) service to create accounts.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Email</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnableSignUpWithEmail</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLESIGNUPWITHEMAIL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Require email verification + +<table> +<colgroup> +<col style={{width: '47%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default for Cloud deployments)</strong> Requires email verification for new accounts before allowing the user to sign-in.</li><li><strong>false</strong>: <strong>(Default for self-hosted deployments)</strong> Disables email verification. can be used to speed development by skipping the verification process.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Email</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>RequireEmailVerification</code> > <code>false</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_REQUIREEMAILVERIFICATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable sign-in with email + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows users to sign-in with email and password.</li><li><strong>false</strong>: Disables authentication with email and password, and removes the option from the login screen. Use this option to limit authentication to single sign-on services.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Email</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnableSignInWithEmail</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLESIGNINWITHEMAIL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- To provide users with only a single email sign in option on the login page, ensure that the [enable sign-in with username](#enable-sign-in-with-username) configuration setting is set to **false**. - From Mattermost v10.9, email addresses enclosed in angle brackets (e.g., `[billy@example.com](mailto:billy@example.com)`) will be rejected. To avoid issues, ensure all user emails comply with the plain address format (e.g., `billy@example.com`). In addition, we strongly recommend taking proactive steps to audit and update Mattermost user data to align with this product change, as impacted users may face issues accessing Mattermost or managing their user profile. You can update these user emails manually using [mmctl user email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-email). + +</Note> + +### Enable sign-in with username + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows authentication with a username and password for accounts created with an email address. This setting does not affect AD/LDAP sign-in.</li><li><strong>false</strong>: Disables authenticaton with a username and removes the sign in option from. from the login screen.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Email</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnableSignInWithUsername</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLESIGNINWITHUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +We highly recommended that email-based authentication is only used in small teams on private networks. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Password + +Access the following configuration settings in the System Console by going to **Authentication \> Password**. + +<Note> + +From Mattermost v11.0, password hashing uses PBKDF2 for enhanced security. User passwords are automatically migrated when they log in after upgrading to v11.0 or later. This migration is progressive and happens transparently when users authenticate. + +</Note> + +### Minimum password length + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the minimum number of characters in passwords. It must be a whole number greater than or equal to 5 and less than or equal to 72.</p><p>Numerical input. Default is <strong>5</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > Password</strong></li><li><code>config.json</code> setting: <code>PasswordSettings</code> > <code>MinimumLength</code></li><li>Environment variable: <code>MM_PASSWORDSETTINGS_MINIMUMLENGTH</code></li></ul></td> +</tr> +</tbody> +</table> + +### Password requirements + +<table> +<colgroup> +<col style={{width: '34%'}} /> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls password character requirements. By checking the corresponding box, passwords must contain:</p><ul><li><strong>At least one lowercase letter</strong></li><li><strong>At least one uppercase letter</strong></li><li><strong>At least one number</strong></li><li><strong>At least one symbol</strong> out of these: <code>!"#$%&'()*+,-./:;<=>?@[]^_`|~</code>.</li></ul><p>The error message previewed in the System Console will appear if the user attempts to set an invalid password.</p><p>The default for all boxes is unchecked. The default for all settings in <code>config.json</code> is <code>false</code>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > Password</strong></li><li><code>config.json</code> settings: <code>PasswordSettings</code> > <code>Lowercase</code> > <code>false</code>, <code>PasswordSettings</code> > <code>Uppercase</code> > <code>false</code>, <code>PasswordSettings</code> > <code>Number</code> > <code>false</code>, <code>PasswordSettings</code> > <code>Symbol</code> > <code>false</code></li><li>Environment variables: <code>MM_PASSWORDSETTINGS_LOWERCASE</code>, <code>MM_PASSWORDSETTINGS_UPPERCASE</code>, <code>MM_PASSWORDSETTINGS_NUMBER</code>, <code>MM_PASSWORDSETTINGS_SYMBOL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum login attempts + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the number of failed sign-in attempts a user can make before being locked out and required to go through a password reset by email.</p><p>Numerical input. Default is <strong>10</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > Password</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>MaximumLoginAttempts</code> > <code>10</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_MAXIMUMLOGINATTEMPTS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable forgot password link + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Displays the <strong>Forget Password</strong> link on the Mattermost login page.</li><li><strong>false</strong>: Hides the <strong>Forgot Password</strong> link from the Mattermost login page.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Enable forgot password link</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>ForgotPasswordLink</code> > <code>true</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_FORGOTPASSWORDLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +You can customize the **Forgot Password** link URL by going to **Site Configuration \> Customization \> Forgot Password Custom Link**. See the [configuration](/administration-guide/configure/site-configuration-settings#forgot-password-custom-link) documentation for details. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## MFA + +<PlanAvailability slug="all-commercial" /> + +Access the following configuration settings in the System Console by going to **Authentication \> MFA**. + +We recommend deploying Mattermost within your own private network, and using VPN clients for mobile access, so that Mattermost is secured with your existing protocols. If you choose to run Mattermost outside your private network, bypassing your existing security protocols, we recommend adding a multi-factor authentication service specifically for accessing Mattermost. + +### Enable multi-factor authentication + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Users who sign-in with AD/LDAP or an email address have the option to add | - System Config path: <strong>Authentication > MFA</strong> | <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fmulti-factor-authentication">multi-factor authentication</a> to their accounts. | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableMultifactorAuthentication</code> > <code>false</code></li><li><strong>false</strong>: <strong>(Default)</strong> Disables multi-factor authentication. | - Environment variable: <code>MM_SERVICESETTINGS_ENABLEMULTIFACTORAUTHENTICATION</code> |</li></ul></td> +</tr> +</tbody> +</table> + +### Enforce multi-factor authentication + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>- <strong>true</strong>: Requires <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fmulti-factor-authentication">multi-factor authentication (MFA) | - System Config path: **Authentication > MFA** |</a> | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnforceMultifactorAuthentication</code> > <code>false</code></dt><dd><p>for users who sign-in with AD/LDAP or an email address. | - Environment variable: <code>MM_SERVICESETTINGS_ENFORCEMULTIFACTORAUTHENTICATION</code> | New users must set up MFA. Logged in users are redirected to the MFA | | setup page until configuration is complete. | |</p></dd></dl><ul><li><strong>false</strong>: <strong>(Default)</strong> MFA is optional. | |</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If your system has users who authenticate with methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## AD/LDAP + +Access the following configuration settings in the System Console by going to **Authentication \> AD/LDAP**. This opens the AD/LDAP setup wizard with step-by-step sections and testing to help configure each setting. + +The wizard is organized into the following sections: + +- [Connection settings](#connection-settings): Configure server connection details +- [User filters](#user-filters): Set up user identification and filtering +- [Account synchronization](#account-synchronization): Map AD/LDAP attributes to Mattermost user fields +- [Group synchronization](#group-synchronization): Configure group settings and group attributes (if using LDAP groups) +- [Synchronization performance](#synchronization-performance): Adjust synchronization timing and performance settings +- [Synchronization history](#synchronization-history): View synchronization status and manually trigger syncs + +<Note> + +Each section includes a **Test** option you can use to verify your configuration incrementally, helping identify and resolve issues early in the setup process. + +</Note> + +### Connection settings + +Configure your AD/LDAP server connection and basic authentication settings. Use the **Test Connection** button in this section to verify your server connection before proceeding to other configuration steps. + +#### Enable sign-in with AD/LDAP + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows sign-in with AD/LDAP.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables sign-in with AD/LDAP.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Enable synchronization with AD/LDAP + +<PlanAvailability slug="entry-ent" /> + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Mattermost periodically syncs users from AD/LDAP.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables AD/LDAP synchronization.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>EnableSync</code> > <code>false</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_ENABLESYNC</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Synchronization with AD/LDAP settings in the System Console can be used to determine the connectivity and availability of arbitrary hosts. System admins concerned about this can use custom admin roles to limit access to modifying these settings. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration#edit-privileges-of-admin-roles-advanced)) documentation for details. + +</Note> + +#### Login field name + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting will display placeholder text in the login field of the sign-in page. This text can remind users to sign-in with their AD/LDAP credentials.</p><p>String input. Default is <code>AD/LDAP Username</code>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>LoginFieldName</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_LOGINFIELDNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +#### AD/LDAP server + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the domain name or IP address of the AD/LDAP server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>LdapServer</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_LDAPSERVER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Synchronization with AD/LDAP settings in the System Console can be used to determine the connectivity and availability of arbitrary hosts. System admins concerned about this can use custom admin roles to limit access to modifying these settings. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration#edit-privileges-of-admin-roles-advanced)) documentation for details. + +</Note> + +#### AD/LDAP port + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the port Mattermost uses to connect to the AD/LDAP server.</p><p>Numerical input. Default is <strong>389</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>LdapPort</code> > <code>389</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_LDAPPORT</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Bind username + +<table> +<colgroup> +<col style={{width: '68%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the username for the account Mattermost utilizes to perform an AD/LDAP search. This should be an account specific to Mattermost.</p><p>Limit the permissions of the account to read-only access to the portion of the AD/LDAP tree specified in the <strong>Base DN</strong> setting.</p><p>When using Active Directory, <strong>Bind Username</strong> should specify domain in <code>"DOMAIN/username"</code> format.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>BindUsername</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_BINDUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This field is required. Anonymous bind is not currently supported. + +</Note> + +#### Bind password + +<table> +<colgroup> +<col style={{width: '55%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the password for the username given in the <strong>Bind Username</strong> setting.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>BindPassword</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_BINDPASSWORD</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Connection security + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls the type of security Mattermost uses to connect to the AD/LDAP server, with these options:</p><ul><li><strong>None</strong>: <strong>(Default for self-hosted deployments)</strong> No encryption. With this option, it is <strong>highly recommended</strong> that the connection be secured outside of Mattermost, such as by a stunnel proxy. <code>config.json</code> option: <code>""</code></li><li><strong>TLS</strong>: <strong>(Default for Cloud deployments)</strong> Encrypts communication with TLS. <code>config.json</code> option: <code>"TLS"</code></li><li><strong>STARTTLS</strong>: Attempts to upgrade an existing insecure connection to a secure connection with TLS. <code>config.json</code> option: <code>"STARTTLS"</code></li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>ConnectionSecurity</code> > <code>""</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_CONNECTIONSECURITY</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Skip certificate verification + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Disables the certificate verification step for TLS and STARTTLS connections. Use this option for testing. <strong>Do not use</strong> this option when TLS is required in production.</li><li><strong>false</strong>: <strong>(Default)</strong> Enables certification verification.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>SkipCertificateVerification</code> > <code>false</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_SKIPCERTIFICATEVERIFICATION</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Private key + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to upload the private key file from your LDAP authentication provider, if TLS client certificates are the primary authentication mechanism.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>PrivateKeyFile</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_PRIVATEKEYFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Public certificate + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to upload the public TLS certificate from your LDAP authentication provider, if TLS client certificates are the primary authentication mechanism.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>PublicCertificateFile</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_PUBLICCERTIFICATEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Maximum login attempts + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the number of failed sign-in attempts a user can make before being locked out and required to go through a password reset by email.</p><p>You can unlock the account in System Console on the users page. Setting this value lower than your LDAP maximum login attempts ensures that the users won't be locked out of your LDAP server because of failed login attempts in Mattermost.</p><p>Numerical input. Default is <strong>10</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>MaximumLoginAttempts</code> > <code>10</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_MAXIMUMLOGINATTEMPTS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Adjust this value to align with your organization’s authentication policies. +- If a user's account is locked, you can unlock it manually by going to **System console \> User Management \> Users**. + +</Note> + +### User filters + +Define how Mattermost identifies and filters users and groups from your AD/LDAP directory. Use the **Test Filters** button in this section to verify your filters work correctly before proceeding to other configuration steps. + +#### Base DN + +<table> +<colgroup> +<col style={{width: '68%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the <strong>Base Distinguished Name</strong> of the location in the AD/LDAP tree where Mattermost will start searching for users.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>BaseDN</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_BASEDN</code></li></ul></td> +</tr> +</tbody> +</table> + +#### User filter + +<table> +<colgroup> +<col style={{width: '86%'}} /> +<col style={{width: '13%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting accepts a <a href="https://www.ldapexplorer.com/en/manual/109010000-ldap-filter-syntax.htm">general syntax</a> AD/LDAP filter that is applied when searching for user objects. Only the users selected by the query can access Mattermost. For example, to filter out disabled users, the filter is: <code>(&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))</code>.</p><p>To filter by group membership, determine the <code>distinguishedName</code> of the group, then use group membership general syntax to format the filter. For example, if the security group <code>distinguishedName</code> is <code>CN=group1,OU=groups,DC=example,DC=com</code>, then the filter is: <code>(memberOf=CN=group1,OU=groups,DC=example,DC=com)</code>. The user must explicitly belong to this group for the filter to apply.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>UserFilter</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_USERFILTER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This filter uses the permissions of the **Bind Username** account to execute the search. This account should be specific to Mattermost and have read-only access to the portion of the AD/LDAP tree specified in the **Base DN** field. + +</Note> + +#### Group filter + +<PlanAvailability slug="entry-ent" /> + +<table> +<colgroup> +<col style={{width: '79%'}} /> +<col style={{width: '20%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting accepts a <a href="https://www.ldapexplorer.com/en/manual/109010000-ldap-filter-syntax.htm">general syntax</a> AD/LDAP filter that is applied when searching for group objects. Only the groups selected by the query can access Mattermost.</p><p>String input. Default is <code>(|(objectClass=group)(objectClass=groupOfNames)(objectClass=groupOfUniqueNames))</code>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>GroupFilter</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_GROUPFILTER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This filter is only used when AD/LDAP Group Sync is enabled. See [AD/LDAP Group Sync](/administration-guide/onboard/ad-ldap-groups-synchronization) for more information. + +</Note> + +#### Enable admin filter + +<table> +<colgroup> +<col style={{width: '73%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the <strong>Admin Filter</strong> setting that designates system admins using an AD/LDAP filter.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the <strong>Admin Filter</strong> setting.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>EnableAdminFilter</code> > <code>false</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_ENABLEADMINFILTER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If this setting is `false`, no additional users are designated as system admins by the filter. Users that were previously designated as system admins retain this role unless the filter is changed or removed. + +</Note> + +#### Admin filter + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting accepts an AD/LDAP filter that designates the selected users as system admins. Users are promoted to this role on their next sign-in or on the next scheduled AD/LDAP sync.</p><p>If the Admin Filter is removed, users who are currently logged in retain their Admin role until their next sign-in.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>AdminFilter</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_ADMINFILTER</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Guest filter + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting accepts an AD/LDAP filter to apply when searching for external users with Guest Access to Mattermost. Only users selected by the query can access Mattermost as Guests. | - System Config path: <strong>Authentication > AD/LDAP</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>LdapSettings</code> > <code>GuestFilter</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fguest-accounts">Guest Accounts</a> for more information. | - Environment variable: <code>MM_LDAPSETTINGS_GUESTFILTER</code></dt><dd><div class="line-block">                                                              |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +### Account synchronization + +<PlanAvailability slug="entry-ent" /> + +Map AD/LDAP user attributes to Mattermost user profile fields. Use the **Test Attributes** button in this section to verify correct attribute mapping and data synchronization before proceeding to other configuration steps. + +#### ID attribute + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '39%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the attribute in the AD/LDAP server that is serves as a unique user identifier in Mattermost.</p><p>The attribute should have a unique value that does not change, such as <code>objectGUID</code> or <code>entryUUID</code>. Confirm that these attributes are available in your environment before making any changes.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>IdAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_IDATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If a user's ID Attribute changes, a new Mattermost account is created that is not associated with the previous account. If you need to change this field after users have signed-in, use the [mmctl ldap idmigrate](/administration-guide/manage/mmctl-command-line-tool#mmctl-ldap-idmigrate) command. + +</Note> + +#### Login ID attribute + +<table> +<colgroup> +<col style={{width: '71%'}} /> +<col style={{width: '28%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the attribute in the AD/LDAP server that is used for signing-in to Mattermost. This is normally the same as the <strong>Username Attribute</strong>.</p><p>If your team uses <code>domain\username</code> to sign-in to other services with AD/LDAP, you may enter <code>domain\username</code> in this field to maintain consistency between sites.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>LoginIdAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_LOGINIDATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Username attribute + +<table> +<colgroup> +<col style={{width: '78%'}} /> +<col style={{width: '21%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the attribute in the AD/LDAP server that populates the username field in Mattermost.</p><p>This attribute identifies users in the UI. For example, if a Username Attribute is set to <code>john.smith</code>, typing <code>@john</code> will show <code>@john.smith</code> as an auto-complete option, and posting a message with <code>@john.smith</code> will send a notification to that user.</p><p>This is normally the same as the <strong>Login ID Attribute</strong>, but it can be mapped to a different attribute.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>UsernameAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_USERNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Email attribute + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the attribute in AD/LDAP server that populates the email address field in Mattermost.</p><p>Email notifications are sent to this address. The address may be seen by other Mattermost users depending on privacy settings.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting <code>LdapSettings</code> > <code>EmailAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_EMAILATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### First name attribute + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This is the attribute in the AD/LDAP server that populates the first name field in Mattermost. | - System Config path: <strong>Authentication > AD/LDAP</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>LdapSettings</code> > <code>FirstNameAttribute</code> |</div></dd><dt>When set, users cannot edit their first name. | - Environment variable: <code>MM_LDAPSETTINGS_FIRSTNAMEATTRIBUTE</code> |</dt><dd><div class="line-block">                                                                     |</div></dd></dl><p>When not set, users can edit their first name in their | | <a href="mm-doc:%2Fend-user-guide%2Fpreferences%2Fmanage-your-profile">profile settings</a>. | | | String input. | |</p></td> +</tr> +</tbody> +</table> + +#### Last name attribute + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This is the attribute in the AD/LDAP server that populates the last name field in Mattermost. | - System Config path: <strong>Authentication > AD/LDAP</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>LdapSettings</code> > <code>LastNameAttribute</code> |</div></dd><dt>When set, users cannot edit their last name. | - Environment variable: <code>MM_LDAPSETTINGS_LASTNAMEATTRIBUTE</code> |</dt><dd><div class="line-block">                                                                    |</div></dd></dl><p>When not set, users can edit their last name as part of their | | <a href="mm-doc:%2Fend-user-guide%2Fpreferences%2Fmanage-your-profile">profile settings</a>. | | | | String input. | |</p></td> +</tr> +</tbody> +</table> + +#### Nickname attribute + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This is the attribute in the AD/LDAP server that populates the nickname field in Mattermost. | - System Config path: <strong>Authentication > AD/LDAP</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>LdapSettings</code> > <code>NicknameAttribute</code> |</div></dd><dt>When set, users cannot edit their nickname. | - Environment variable: <code>MM_LDAPSETTINGS_NICKNAMEATTRIBUTE</code> |</dt><dd><div class="line-block">                                                                    |</div></dd></dl><p>When not set, users can edit their nickname as part of their | | <a href="mm-doc:%2Fend-user-guide%2Fpreferences%2Fmanage-your-profile">profile settings</a>. | | | String input. | |</p></td> +</tr> +</tbody> +</table> + +#### Position attribute + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This is the attribute in the AD/LDAP server that populates the position field in Mattermost. | - System Config path: <strong>Authentication > AD/LDAP</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>LdapSettings</code> > <code>PositionAttribute</code> |</div></dd><dt>When set, users cannot edit their position. | - Environment variable: <code>MM_LDAPSETTINGS_POSITIONATTRIBUTE</code> |</dt><dd><div class="line-block">                                                                    |</div></dd></dl><p>When not set, users can edit their position as part of their | | <a href="mm-doc:%2Fend-user-guide%2Fpreferences%2Fmanage-your-profile">profile settings</a>. | | | String input. | |</p></td> +</tr> +</tbody> +</table> + +#### Profile picture attribute + +<table> +<colgroup> +<col style={{width: '59%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the attribute in the AD/LDAP server that syncs and locks the profile picture in Mattermost.</p><p>The image is updated when users sign-in, not when Mattermost syncs with the AD/LDAP server.</p><p>The image is not updated if the Mattermost image already matches the AD/LDAP image.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>PictureAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_PICTUREATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Group synchronization + +<PlanAvailability slug="entry-ent" /> + +Configure group mapping for AD/LDAP group synchronization. Use the **Test Group Attributes** button in this section to verify proper group attribute mapping before proceeding to other configuration steps. + +#### Group display name attribute + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is the AD/LDAP Group Display name attribute that populates the Mattermost group name field.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>GroupDisplayNameAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_GROUPDISPLAYNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This attribute is only used when AD/LDAP Group Sync is enabled and it is **required**. See the [AD/LDAP Group Sync documentation](/administration-guide/onboard/ad-ldap-groups-synchronization) for more information. + +</Note> + +#### Group ID attribute + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This is an AD/LDAP Group ID attribute that sets a unique identifier for groups.</p><p>This should be a value that does not change, such as <code>entryUUID</code> or <code>objectGUID</code>.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>GroupIdAttribute</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_GROUPIDATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This attribute is only used when AD/LDAP Group Sync is enabled and it is **required**. See the [AD/LDAP Group Sync documentation](/administration-guide/onboard/ad-ldap-groups-synchronization) for more information. + +</Note> + +### Synchronization performance + +<PlanAvailability slug="entry-ent" /> + +Configure timing and performance settings for AD/LDAP synchronization. These settings control how often Mattermost syncs with your AD/LDAP server. + +#### Synchronization interval (minutes) + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This value determines how often Mattermost syncs with the AD/LDAP server by setting the number of minutes between each sync.</p><p>Syncing with the AD/LDAP server will update Mattermost accounts to match any changes made to AD/LDAP attributes.</p><p>Disabled AD/LDAP accounts become deactivated users in Mattermost, and any active sessions are revoked.</p><p>Use the <strong>AD/LDAP Synchronize Now</strong> button to immediately revoke a session after disabling an AD/LDAP account.</p><p>Numerical input. Default is <strong>60</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>SyncIntervalMinutes</code> > <code>60</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_SYNCINTERVALMINUTES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +LDAP syncs require a large number of database read queries. Monitor database load and adjust the sync interval to minimize performance degradation. + +</Note> + +#### Maximum page size + +<table> +<colgroup> +<col style={{width: '63%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting paginates the results of AD/LDAP server queries. Use this setting if your AD/LDAP server has a page size limit.</p><p>The recommended setting is <strong>1500</strong>. This is the default AD/LDAP <code>MaxPageSize</code>.</p><p>A page size of <strong>0</strong> disables pagination of results.</p><p>Numerical input. Default is <strong>0</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>MaxPageSize</code> > <code>0</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_MAXPAGESIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Query timeout (seconds) + +<table> +<colgroup> +<col style={{width: '67%'}} /> +<col style={{width: '32%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the timeout period, in seconds, for AD/LDAP queries. Increase this value to avoid timeout errors when querying a slow server.</p><p>Numerical input. Default is <strong>60</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>QueryTimeout</code> > <code>60</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_QUERYTIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Synchronization history + +<PlanAvailability slug="entry-ent" /> + +View synchronization status and manually trigger AD/LDAP synchronization. This section includes the **AD/LDAP Synchronize Now** button for immediate synchronization. + +#### AD/LDAP synchronize now + +<table> +<colgroup> +<col style={{width: '67%'}} /> +<col style={{width: '32%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this button to immediately sync with the AD/LDAP server.</p><p>The status of the sync is displayed in the table underneath the button (see the figure below).</p><p>Following a manual sync, the next sync will occur after the time set in the <strong>Synchronization Interval</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If a sync is `Pending` and does not complete, check that **Enable Synchronization with AD/LDAP** is set to `true`. + +</Note> + +<figure> +<img src="../../images/ldap-sync-table.png" alt="../../images/ldap-sync-table.png" /> +</figure> + +### Config settings not available in the AD/LDAP Wizard + +<PlanAvailability slug="entry-ent" /> + +The following AD/LDAP configuration settings are available in the `config.json` file only and aren't available via the AD/LDAP wizard interface in the System Console. + +#### Re-add removed members on sync + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable this setting to re-add members of the LDAP group that were previously removed from group-synchronized teams or channels during LDAP synchronization.</p><ul><li><strong>true</strong>: Members of the LDAP group who were previously removed are re-added to group-synchronized teams or channels during LDAP synchronization.</li><li><strong>false</strong>: <strong>(Default)</strong> Members of the LDAP group who were previously removed are not re-added to group-synchronized teams or channels during LDAP synchronization.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > AD/LDAP</strong></li><li><code>config.json</code> setting: <code>LdapSettings</code> > <code>ReAddRemovedMembers</code></li><li>Environment variable: <code>MM_LDAPSETTINGS_READDREMOVEDMEMBERS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +The [mmctl ldap sync](/administration-guide/manage/mmctl-command-line-tool#mmctl-ldap-sync) command takes precedence over this server configuration setting. If you have this setting disabled, and run the mmctl command with the `--include-removed-members` flag, removed members will be re-added during LDAP synchronization. + +</Note> + +<div id="saml-enterprise"> + +------------------------------------------------------------------------------------------------------------------------ + +</div> + +## SAML 2.0 + +Access the following configuration settings in the System Console by going to **Authentication \> SAML 2.0**. + +See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +<Important> + +In line with Microsoft ADFS guidance, we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). + +</Important> + +### Enable login with SAML + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables sign-in with SAML. See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-saml">SAML Single Sign-On</a> to learn more. | - System Config path: <strong>Authentication > SAML 2.0</strong></li><li><dl><dt><strong>false</strong>: <strong>(Default)</strong> Disables sign-in with SAML. | - <code>config.json</code> setting: <code>SamlSettings</code> > <code>Enable</code> > <code>false</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_SAMLSETTINGS_ENABLE</code> |</div></dd></dl></li></ul></td> +</tr> +</tbody> +</table> + +### Enable synchronizing SAML accounts with AD/LDAP + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Mattermost updates configured Mattermost user attributes (ex. FirstName, Position, Email) with their values from AD/LDAP. From v10.9, Mattermost checks whether a user exists on the connected LDAP server during login. If the user doesn't exist on the LDAP server, login fails.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables syncing of SAML-authenticated Mattermost users with AD/LDAP. From Mattermost v10.9, Mattermost doesn't check whether a user exists on the connected LDAP server during login.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>EnableSyncWithLdap</code> > <code>false</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ENABLESYNCWITHLDAP</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- AD/LDAP synchronization must be enabled and configured through the settings under **Authentication \> AD/LDAP**. +- Prior to Mattermost v10.9, users not present on the LDAP server could log in, but would be deactivated on the next LDAP sync. +- See [AD/LDAP Setup](/administration-guide/onboard/ad-ldap) to learn more about configuring AD/LDAP. + +</Note> + +### Ignore guest users when synchronizing with AD/LDAP + +<PlanAvailability slug="entry-ent" /> + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: When syncing with the AD/LDAP server, Mattermost does not sync any information about SAML-authenticated Guest Users from the AD/LDAP server. Manage guest deactivation manually via <strong>System Console > Users</strong>.</li><li><strong>false</strong>: <strong>(Default)</strong> Syncing Mattermost with the AD/LDAP server updates Guest User attributes and deactivates and removes SAML-authenticated accounts for Guest Users that are no longer active on the AD/LDAP server.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IgnoreGuestsLdapSync</code> > <code>false</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IGNOREGUESTSLDAPSYNC</code></li></ul></td> +</tr> +</tbody> +</table> + +For more information, see [AD/LDAP Setup](/administration-guide/onboard/ad-ldap) for details. + +### Override SAML bind data with AD/LDAP information + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: If the SAML ID attribute is configured, Mattermost overrides the SAML ID attribute with the AD/LDAP ID attribute. If the SAML ID attribute is not present, Mattermost overrides the SAML Email attribute with the AD/LDAP Email attribute.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost uses the email attribute to bind users to SAML.</li></ul><p>This setting is only available when SAML authentication is enabled and AD/LDAP synchronization is enabled.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>EnableSyncWithLdapIncludeAuth</code> > <code>false</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ENABLESYNCWITHLDAPINCLUDEAUTH</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting should be **false** unless LDAP sync is enabled. Changing this setting from **true** to **false** will disable the override. - SAML IDs must match LDAP IDs when the override is enabled. - For more information, see [AD/LDAP Setup](/administration-guide/onboard/ad-ldap) for details. + +</Note> + +### Identity provider metadata URL + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the URL from which Mattermost requests setup metadata from the provider.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IdpMetadataURL</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IDPMETADATAURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### SAML SSO URL + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the URL where Mattermost sends a SAML request to start the login sequence.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IdpURL</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IDPURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Identity provider issuer URL + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the issuer URL for the Identity Provider for SAML requests.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IdpDescriptorURL</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IDPDESCRIPTORURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Identity provider public certificate + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The public authentication certificate issued by your Identity Provider.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IdpCertificateFile</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IDPCERTIFICATEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Verify signature + +<table> +<colgroup> +<col style={{width: '63%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost checks that the SAML Response signature matches the Service Provider Login URL.</li><li><strong>false</strong>: The signature is not verified. This is <strong>not recommended</strong> for production. Use this option for testing only.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>Verify</code> > <code>true</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_VERIFY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Service provider login URL + +<table> +<colgroup> +<col style={{width: '59%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enter the URL of your Mattermost server, followed by <code>/login/sso/saml</code>, i.e. <code>https://example.com/login/sso/saml</code>.</p><p>Use HTTP or HTTPS depending on the configuration of the server.</p><p>This setting is also known as the Assertion Consumer Service URL.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>AssertionConsumerServiceURL</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ASSERTIONCONSUMERSERVICEURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Service provider identifier + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the unique identifier for the Service Provider, which in most cases is the same as the Service Provider Login URL. In ADFS, this must match the Relying Party Identifier.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>ServiceProviderIdentifier</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_SERVICEPROVIDERIDENTIFIER</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable encryption + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost will decrypt SAML Assertions that are encrypted with your Service Provider Public Certificate.</li><li><strong>false</strong>: Mattermost does not decrypt SAML Assertions. Use this option for testing only. It is <strong>not recommended</strong> for production.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>Encrypt</code> > <code>true</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ENCRYPT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Service provider private key + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the private key used to decrypt SAML Assertions from the Identity Provider.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>PrivateKeyFile</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_PRIVATEKEYFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Service provider public certificate + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the certificate file used to sign a SAML request to the Identity Provider for a SAML login when Mattermost is initiating the login as the Service Provider.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>PublicCertificateFile</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_PUBLICCERTIFICATEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Sign request + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Mattermost signs the SAML request with the Service Provider Private Key.</li><li><strong>false</strong>: Mattermost does not sign the SAML request.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>SignRequest</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_SIGNREQUEST</code></li></ul></td> +</tr> +</tbody> +</table> + +### Signature algorithm + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the signature algorithm used to sign the SAML request. Options are: <code>RSAwithSHA1</code>, <code>RSAwithSHA256</code>, <code>RSAwithSHA512</code>.</p><p>String input.</p><Note><p>From Mattermost v11, the default signature algorithm has been updated from <code>RSAwithSHA1</code> to <code>RSAwithSHA256</code> for improved security. Existing configurations will continue to work, but new installations will default to <code>RSAwithSHA256</code>.</p></Note></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>SignatureAlgorithm</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_SIGNATUREALGORITHM</code></li></ul></td> +</tr> +</tbody> +</table> + +### Canonical algorithm + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the canonicalization algorithm. With these options:</p><ul><li><strong>Canonical1.0</strong>: <strong>(Default)</strong> <a href="https://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/">Exclusive XML Canonicalization 1.0 (omit comments)</a> (<code>http://www.w3.org/2001/10/xml-exc-c14n#</code>). <code>config.json</code> setting: <code>Canonical1.0</code>.</li><li><strong>Canonical1.1</strong>: <a href="https://www.w3.org/TR/2008/REC-xml-c14n11-20080502/">Canonical XML 1.1 (omit comments)</a> (<code>http://www.w3.org/2006/12/xml-c14n11</code>). <code>config.json</code> setting: <code>Canonical1.1</code>.</li></ul><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>CanonicalAlgorithm</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_CANONICALALGORITHM</code></li></ul></td> +</tr> +</tbody> +</table> + +### Email attribute + +<table> +<colgroup> +<col style={{width: '68%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the attribute from the SAML Assertion that populates the user email address field in Mattermost.</p><p>Notifications are sent to this email address. This email address may be visible to other users, depending on how the system admin has set-up user privacy.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>EmailAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_EMAILATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Username attribute + +<table> +<colgroup> +<col style={{width: '77%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting determines the SAML Assertion attribute that populates the username field in the Mattermost UI.</p><p>This attribute identifies users in the UI. For example, if a username is set to <code>john.smith</code>, typing <code>@john</code> will show <code>@john.smith</code> as an auto-complete option, and posting a message with <code>@john.smith</code> will send a notification to that user.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>UsernameAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_USERNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Id attribute + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute used to bind users from SAML to users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>IdAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_IDATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Guest attribute + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>(Optional) This setting determines the SAML Assertion attribute used to apply a Guest role to users in Mattermost. | - System Config path: <strong>Authentication > SAML 2.0</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>SamlSettings</code> > <code>GuestAttribute</code>|</div></dd><dt>See the <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fguest-accounts">Guest Accounts documentation</a> for more information. | - Environment variable: <code>MM_SAMLSETTINGS_GUESTATTRIBUTE</code></dt><dd><div class="line-block">                                                                |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +### Enable admin attribute + +<table> +<colgroup> +<col style={{width: '55%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: System admin status is determined by the SAML Assertion attribute set in <strong>Admin attribute</strong>.</li><li><strong>false</strong>: <strong>(Default)</strong> System admin status is <strong>not</strong> determined by the SAML Assertion attribute.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>EnableAdminAttribute</code> > <code>false</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ENABLEADMINATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Admin attribute + +<table> +<colgroup> +<col style={{width: '64%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the attribute in the SAML Assertion for designating system admins.</p><p>Users are automatically promoted to this role when logging in to Mattermost.</p><p>If the Admin attribute is removed, users that are logged in retain Admin status. The role is revoked only when users log out.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>AdminAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_ADMINATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### First name attribute + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute that populates the first name of users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>FirstNameAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_FIRSTNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Last name attribute + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute that populates the last name of users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>LastNameAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_LASTNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Nickname attribute + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute that populates the nickname of users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>NicknameAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_NICKNAMEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Position attribute + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute that populates the position (job title or role at company) of users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>PositionAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_POSITIONATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Preferred language attribute + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) This setting determines the SAML Assertion attribute that populates the language preference of users in Mattermost.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>LocaleAttribute</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_LOCALEATTRIBUTE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Login button text + +<table> +<colgroup> +<col style={{width: '52%'}} /> +<col style={{width: '47%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) The text that appears in the login button on the sign-in page.</p><p>String input. Default is <strong>SAML</strong>.</p></td> +<td><ul><li>System Config path: <strong>Authentication > SAML 2.0</strong></li><li><code>config.json</code> setting: <code>SamlSettings</code> > <code>LoginButtonText</code></li><li>Environment variable: <code>MM_SAMLSETTINGS_LOGINBUTTONTEXT</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## OAuth 2.0 + +Access the following configuration settings in the System Console by going to **Authentication \> OAuth 2.0**. Settings for GitLab OAuth authentication can also be accessed under **Authentication \> GitLab** in self-hosted deployments. + +Use these settings to configure OAuth 2.0 for account creation and login. + +### Select OAuth 2.0 service provider + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to enable OAuth and specify the service provider, with these options:</p><ul><li><strong>Do not allow login via an OAuth 2.0 provider</strong></li><li><strong>GitLab</strong> (Available in all plans; see <a href="#gitlab-oauth-2-0-settings">GitLab 2.0 OAuth settings</a>)</li><li><strong>Google Apps</strong> (Available in Mattermost Enterprise and Professional; see <a href="#google-oauth-2-0-settings">Google OAuth 2.0 settings</a>)</li><li><strong>Entra ID</strong> (Available in Mattermost Enterprise and Professional; see <a href="#entraid-oauth-2-0-settings">Entra ID OAuth 2.0 settings</a>)</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +#### GitLab OAuth 2.0 settings + +<Note> + +For Enterprise subscriptions, GitLab settings can be found under **OAuth 2.0** + +</Note> + +##### Enable OAuth 2.0 authentication with GitLab + +<table> +<colgroup> +<col style={{width: '64%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using GitLab OAuth authentication. Input the <strong>Secret</strong> and <strong>ID</strong> credentials to configure.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables GitLab OAuth authentication.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +##### GitLab OAuth 2.0 Application ID + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the OAuth Application ID from GitLab. Generate the ID by these steps:</p><ol type="1"><li>Login to your GitLab account.</li><li>Go to <strong>Profile Settings > Applications > New Application</strong> and enter a name.</li><li>Enter the Redirect URLs: <code>https://<your-mattermost-url>/login/gitlab/complete</code> and <code>https://<your-mattermost-url>/signup/gitlab/complete</code>.</li><li>Take the Application ID provided by GitLab and enter it in the Mattermost System Console field, <code>config.json</code> setting, or Environment variable.</li></ol><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Id</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_ID</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +GitLab provides the [Application Secret Key](#gitlab-oauth-2-0-application-secret-key) along with the the ID. + +</Note> + +##### GitLab OAuth 2.0 Application secret key + +<table> +<colgroup> +<col style={{width: '75%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the OAuth Application Secret Key from GitLab. The key is generated at the same time as the <strong>Application ID</strong> (see <a href="#gitlab-oauth-2-0-application-id">GitLab OAuth 2.0 Application ID</a>).</p><p>Enter the key provided by GitLab in the Mattermost System Console field, <code>config.json</code> setting, or Environment variable.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Secret</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_SECRET</code></li></ul></td> +</tr> +</tbody> +</table> + +##### GitLab OAuth 2.0 site URL + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td>This setting holds the URL of your GitLab instance, e.g. <code>https://example.com:3000</code>. Use <code>http://</code> if SSL is not enabled on your GitLab instance.</td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +##### GitLab OAuth 2.0 User API endpoint + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the URL of your GitLab User API endpoint, e.g. <code>https://<your-gitlab-url>/api/v3/user</code>. Use <code>http://</code> if SSL is not enabled on your GitLab instance.</p><p>Enter the URL in the Mattermost System Console field, <code>config.json</code> setting, or Environment variable.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>UserAPIEndpoint</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_USERAPIENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### GitLab OAuth 2.0 Auth endpoint + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the URL of your GitLab Auth endpoint, e.g. <code>https://<your-gitlab-url>/oauth/authorize</code>. Use <code>http://</code> if SSL is not enabled on your GitLab instance.</p><p>Enter the URL in the Mattermost System Console field, <code>config.json</code> setting, or Environment variable.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>AuthEndpoint</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_AUTHENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### GitLab OAuth 2.0 Token endpoint + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the URL of your GitLab OAuth Token endpoint, e.g. <code>https://<your-gitlab-url>/oauth/token</code>. Use <code>http://</code> if SSL is not enabled on your GitLab instance.</p><p>Enter the URL in the Mattermost System Console field, <code>config.json</code> setting, or Environment variable.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0 (or GitLab)</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>TokenEndpoint</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_TOKENENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Google OAuth 2.0 settings + +##### Enable OAuth 2.0 authentication with Google + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using Google OAuth authentication. Input the <strong>Client ID</strong> and <strong>Client Secret</strong> credentials to configure. | - System Config path: <strong>Authentication > OAuth 2.0</strong> |</li></ul><dl><dt>- <strong>false</strong>: <strong>(Default)</strong> Disables Google OAuth authentication. | - <code>config.json</code> setting: <code>GoogleSettings</code> > <code>Enable</code> > <code>false</code>|</dt><dd><div class="line-block">- Environment variable: <code>MM_GOOGLESETTINGS_ENABLE</code> |</div></dd></dl><p>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-google">Google Single Sign-On</a> implementation instructions. |</p></td> +</tr> +</tbody> +</table> + +##### Google OAuth 2.0 Client ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the OAuth Client ID from Google. Generate the ID by going to the <strong>Credentials</strong> section of the Google Cloud Platform APIs & Services menu and selecting <strong>Create Credentials > OAuth client ID</strong>. | - System Config path: <strong>Authentication > OAuth 2.0</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>GoogleSettings</code> > <code>Id</code>|</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-google">Google Single Sign-On</a> for instructions that can be used to implement Google OAuth or OpenID authentication. | - Environment variable: <code>MM_GOOGLESETTINGS_ID</code></dt><dd><div class="line-block">                                                      |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Google OAuth 2.0 Client secret + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the OAuth Client Secret from Google. The Secret is generated at the same time as the Client ID.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>GoogleSettings</code> > <code>Secret</code></li><li>Environment variable: <code>MM_GOOGLESETTINGS_SECRET</code></li></ul></td> +</tr> +</tbody> +</table> + +##### Google OAuth 2.0 User API endpoint + +<table> +<colgroup> +<col style={{width: '77%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata</code> as the User API Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with HTTP, or HTTPS, if available on the API server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>GoogleSettings</code> > <code>UserAPIEndpoint</code></li><li>Environment variable: <code>MM_GOOGLESETTINGS_USERAPIENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### Google OAuth 2.0 Auth endpoint + +<table> +<colgroup> +<col style={{width: '73%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://accounts.google.com/o/oauth2/v2/auth</code> as the Auth Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with HTTP, or HTTPS, if available on the server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>GoogleSettings</code> > <code>AuthEndpoint</code></li><li>Environment variable: <code>MM_GOOGLESETTINGS_AUTHENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### Google OAuth 2.0 Token endpoint + +<table> +<colgroup> +<col style={{width: '73%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://www.googleapis.com/oauth2/v4/token</code> as the Token Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with HTTP, or HTTPS, if available on the server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>GoogleSettings</code> > <code>TokenEndpoint</code></li><li>Environment variable: <code>MM_GOOGLESETTINGS_TOKENENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Entra ID OAuth 2.0 settings + +<Note> + +In line with Microsoft ADFS guidance we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). + +</Note> + +##### Enable OAuth 2.0 Authentication with Entra ID + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using Entra ID OAuth authentication.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables Entra ID OAuth authentication.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) documentation for details. + +</Note> + +##### Entra ID OAuth 2.0 Application ID + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the <strong>Application ID</strong> generated when configuring Entra ID as a Single Sign-On service through the Microsoft Azure Portal.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>Id</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_ID</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) documentation for details. + +</Note> + +##### Entra ID OAuth 2.0 Application secret password + +<table> +<colgroup> +<col style={{width: '71%'}} /> +<col style={{width: '28%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the <strong>Application Secret Password</strong> generated when configuring Entra ID as a Single Sign-On service through the Microsoft Azure Portal.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>Secret</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_SECRET</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) documentation for details. + +</Note> + +##### Entra ID OAuth 2.0 Directory (tenant) ID + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting holds the <strong>Directory (tenant) ID</strong> set for Mattermost through the Azure Portal.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>DirectoryId</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_DIRECTORYID</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) documentation for details. + +</Note> + +##### Entra ID OAuth 2.0 User API endpoint + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://graph.microsoft.com/v1.0/me</code> as the User API Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with <code>http</code>, or <code>https</code>, if available on the server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>UserAPIEndpoint</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_USERAPIENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### Entra ID OAuth 2.0 Auth endpoint + +<table> +<colgroup> +<col style={{width: '75%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://login.microsoftonline.com/common/oauth2/v2.0/authorize</code> as the Auth Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with <code>http</code>, or <code>https</code>, if available on the server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>AuthEndpoint</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_AUTHENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### Entra ID OAuth 2.0 Token endpoint + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend <code>https://login.microsoftonline.com/common/oauth2/v2.0/token</code> as the Token Endpoint. Otherwise, enter a custom endpoint in <code>config.json</code> with <code>http</code>, or <code>https</code>, if available on the server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OAuth 2.0</strong></li><li><code>config.json</code> setting: <code>Office365Settings</code> > <code>TokenEndpoint</code></li><li>Environment variable: <code>MM_OFFICE365SETTINGS_TOKENENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## OpenID Connect + +Access the following configuration settings in the System Console by going to **Authentication \> OpenID Connect**. + +### Select OpenID Connect service provider + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to enable OpenID Connect, with these options:</p><ul><li><strong>Do not allow login via an OpenID provider</strong></li><li><strong>GitLab</strong> (<a href="#gitlab-openid-settings">see settings</a>)</li><li><strong>Google Apps</strong> (<a href="#google-openid-settings">see settings</a>)</li><li><strong>Entra ID</strong> (<a href="#entra-id-openid-settings">see settings</a>)</li><li><strong>OpenID Connect (Other)</strong> (<a href="#openid-connect-other-settings">see settings</a>)</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +**GitLab** OpenID is available in all plans. All other providers require Mattermost Enterprise or Professional. + +</Note> + +#### GitLab OpenID settings + +##### Enable OpenID Connect authentication with GitLab + +<table> +<colgroup> +<col style={{width: '55%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using GitLab OpenID Connect authentication.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables GitLab OpenID Connect authentication.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) documentation for details. + +</Note> + +##### GitLab OpenID site URL + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the URL of your GitLab instance, e.g. <strong>https://example.com:3000</strong>.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See **Step 2** of the [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) documentation for details. + +</Note> + +##### GitLab OpenID Discovery endpoint + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is prepopulated with the Discovery Endpoint for GitLab OpenID Connect.</p><p>String input. Default is <code>https://gitlab.com/.well-known/openid-configuration</code></p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>DiscoveryEndpoint</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_DISCOVERYENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See **Step 2** of the [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) documentation for details. + +</Note> + +##### GitLab OpenID Client ID + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the <strong>Application ID</strong> generated by GitLab.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Id</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_ID</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See **Step 2** of the [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) documentation for details. + +</Note> + +##### GitLab OpenID Client secret + +<table> +<colgroup> +<col style={{width: '52%'}} /> +<col style={{width: '47%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the <strong>Application Secret Key</strong> generated by GitLab.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>GitLabSettings</code> > <code>Secret</code></li><li>Environment variable: <code>MM_GITLABSETTINGS_SECRET</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See **Step 2** of the [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) documentation for details. + +</Note> + +##### GitLab OpenID use preferred username + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td colspan="2"><ul><li><strong>true</strong>: Mattermost uses the <code>preferred_username</code> claim from the GitLab OpenID token as the Mattermost | - System Config path: <strong>Authentication > OpenID Connect</strong> | username. | - <code>config.json</code> setting: <code>GitLabSettings</code> > <code>UsePreferredUsername</code> > <code>false</code></li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost does not use the <code>preferred_username</code> claim for username assignment. | - Environment variable: <code>MM_GITLABSETTINGS_USEPREFERREDUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Google OpenID settings + +##### Enable OpenID Connect authentication with Google + +> - **true**: Allow team creation and account signup using Google OpenID Connect. +> - **false**: **(Default)** Google OpenID Connect cannot be used for team creation or account signup. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using Google OpenID authentication. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</li></ul><dl><dt>- <strong>false</strong>: <strong>(Default)</strong> Disables Google OpenID authentication. | - <code>config.json</code> setting: <code>GoogleSettings</code> > <code>Enable</code> > <code>false</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_GOOGLESETTINGS_ENABLE</code> |</div></dd></dl><p>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-google">Google Single Sign-On</a> implementation instructions. |</p></td> +</tr> +</tbody> +</table> + +##### Google OpenID Discovery endpoint + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting is prepopulated with the Discovery Endpoint for Google OpenID Connect. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>GoogleSettings</code> > <code>DiscoveryEndpoint</code> |</div></dd><dt>See <a href="mm-ref:administration-guide%2Fonboard%2Fsso-google%3Astep%203%3A%20configure%20mattermost%20for%20google%20apps%20sso">Configure Mattermost for Google Apps SSO</a>. | - Environment variable: <code>MM_GOOGLESETTINGS_DISCOVERYENDPOINT</code></dt><dd><div class="line-block">                                                                      |</div></dd></dl><p>String input. Default is <code>https://accounts.google.com/.well-known/openid-configuration</code> | |</p></td> +</tr> +</tbody> +</table> + +##### Google OpenID Client ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the Client ID generated by Google. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>GoogleSettings</code> > <code>Id</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-google">Google Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_GOOGLESETTINGS_ID</code></dt><dd><div class="line-block">                                                          |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Google OpenID Client secret + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the Client Secret generated by Google. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>GoogleSettings</code> > <code>Secret</code>|</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-google">Google Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_GOOGLESETTINGS_SECRET</code></dt><dd><div class="line-block">                                                          |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Google OpenID use preferred username + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td colspan="2"><ul><li><strong>true</strong>: Mattermost uses the <code>preferred_username</code> claim from the Google OpenID token as the Mattermost | - System Config path: <strong>Authentication > OpenID Connect</strong> | username. | - <code>config.json</code> setting: <code>GoogleSettings</code> > <code>UsePreferredUsername</code> > <code>false</code></li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost does not use the <code>preferred_username</code> claim for username assignment. | - Environment variable: <code>MM_GOOGLESETTINGS_USEPREFERREDUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Entra ID OpenID settings + +<Note> + +In line with Microsoft ADFS guidance, we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). + +</Note> + +##### Enable OpenID Connect authentication with Entra ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using Entra ID OpenID Connect authentication. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</li></ul><dl><dt>- <strong>false</strong>: <strong>(Default)</strong> Disables Entra ID OpenID Connect authentication. | - <code>config.json</code> setting: <code>Office365Settings</code> > <code>Enable</code> > <code>false</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_OFFICE365SETTINGS_ENABLE</code> |</div></dd></dl><p>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-entraid">Entra ID Single Sign-On</a> implementation instructions. |</p></td> +</tr> +</tbody> +</table> + +##### Entra ID OpenID Directory (tenant) ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting holds the Directory (tenant) ID set for Mattermost through the Microsoft Azure Portal. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>Office365Settings</code> > <code>DirectoryId</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-entraid">Entra ID Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OFFICE365SETTINGS_DIRECTORYID</code></dt><dd><div class="line-block">                                                                   |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Entra ID OpenID Discovery endpoint + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting is prepopulated with the Discovery Endpoint for Entra ID OpenID Connect. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>Office365Settings</code> > <code>DiscoveryEndpoint</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-entraid">Entra ID Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OFFICE365SETTINGS_DISCOVERYENDPOINT</code></dt><dd><div class="line-block">                                                                                                                   |</div></dd></dl><p>String input. Default is <code>https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration</code> | |</p></td> +</tr> +</tbody> +</table> + +##### Entra ID Client ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the <strong>Application (client) ID</strong> generated through the Microsoft Azure Portal. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>Office365Settings</code> > <code>Id</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-entraid">Entra ID Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OFFICE365SETTINGS_ID</code></dt><dd><div class="line-block">                                                          |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Entra ID Client secret + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the <strong>Client Secret</strong> generated through the Microsoft Azure Portal. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>Office365Settings</code> > <code>Secret</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-entraid">Entra ID Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OFFICE365SETTINGS_SECRET</code></dt><dd><div class="line-block">                                                               |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### Entra ID use preferred username + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td colspan="2"><ul><li><strong>true</strong>: Mattermost uses the <code>preferred_username</code> claim from the Entra ID OpenID token as the Mattermost username. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</li><li><dl><dt><strong>false</strong>: <strong>(Default)</strong> Mattermost does not use the <code>preferred_username</code> claim for username assignment. | - <code>config.json</code> setting: <code>Office365Settings</code> > <code>UsePreferredUsername</code> > <code>false</code></dt><dd><div class="line-block">- Environment variable: <code>MM_OFFICE365SETTINGS_USEPREFERREDUSERNAME</code></div></dd></dl></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +To make the `preferred_username` claim available, add it as an optional claim in the Azure Portal under **App registrations \> Token configuration**. See [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) for setup details. + +</Note> + +#### OpenID Connect (other) settings + +##### Enable OpenID Connect authentication with other service providers + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows team and account creation using other OpenID Connect service providers. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</li></ul><dl><dt>- <strong>false</strong>: <strong>(Default)</strong> Disables OpenID Connect authentication with other service providers. | - <code>config.json</code> setting: <code>OpenIdSettings</code> > <code>Enable</code> > <code>false</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_OPENIDSETTINGS_ENABLE</code> |</div></dd></dl><p>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-openidconnect">OpenID Connect Single Sign-On</a> implementation instructions. |</p></td> +</tr> +</tbody> +</table> + +##### OpenID Connect (other) Button name + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the text for the OpenID login button.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>OpenIdSettings</code> > <code>ButtonText</code></li><li>Environment variable: <code>MM_OPENIDSETTINGS_BUTTONTEXT</code></li></ul></td> +</tr> +</tbody> +</table> + +##### OpenID Connect (other) Button color + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is the color of the OpenID login button. Use a hex code with a #-sign before the code, for example <code>#145DBF</code>.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong></li><li><code>config.json</code> setting: <code>OpenIdSettings</code> > <code>ButtonColor</code></li><li>Environment variable: <code>MM_OPENIDSETTINGS_BUTTONCOLOR</code></li></ul></td> +</tr> +</tbody> +</table> + +##### OpenID Connect (other) Discovery endpoint + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This setting stores the Discovery Endpoint URL from the OpenID provider. | - System Config path: <strong>Authentication > OpenID Connect</strong> | The URL should be in the format of <code>https://myopenid.provider.com/{my_organization}/ | -</code>config.json<code>setting:</code>OpenIdSettings<code>></code>DiscoveryEndpoint<code>| .well-known/openid-configuration</code>. | - Environment variable: <code>MM_OPENIDSETTINGS_DISCOVERYENDPOINT</code> | | | See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-openidconnect">OpenID Connect Single Sign-On</a> | implementation instructions. | | | | String input. | |</td> +</tr> +</tbody> +</table> + +<Note> + +The **Discovery Endpoint** setting can be used to determine the connectivity and availability of arbitrary hosts. System admins concerned about this can use custom admin roles to limit access to modifying these settings. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration#edit-privileges-of-admin-roles-advanced)) documentation for details. + +</Note> + +##### OpenID Connect (other) Client ID + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the Client ID from the OpenID provider. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>OpenIdSettings</code> > <code>Id</code> |</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-openidconnect">OpenID Connect Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OPENIDSETTINGS_ID</code></dt><dd><div class="line-block">                                                          |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### OpenID Connect (other) Client secret + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting stores the Client Secret from the OpenID provider. | - System Config path: <strong>Authentication > OpenID Connect</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>OpenIdSettings</code> > <code>Secret</code>|</div></dd><dt>See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-openidconnect">OpenID Connect Single Sign-On</a> implementation instructions. | - Environment variable: <code>MM_OPENIDSETTINGS_SECRET</code></dt><dd><div class="line-block">                                                          |</div></dd></dl><p>String input. | |</p></td> +</tr> +</tbody> +</table> + +##### OpenID Connect (other) use preferred username + +<table> +<colgroup> +<col style={{width: '68%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Mattermost uses the <code>preferred_username</code> claim from the provider's OpenID token as the Mattermost username.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost does not use the <code>preferred_username</code> claim for username assignment.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > OpenID Connect</strong> |</li><li><code>config.json</code> setting: <code>OpenIdSettings</code> > | <code>UsePreferredUsername</code> > <code>false</code> |</li><li>Environment variable: | <code>MM_OPENIDSETTINGS_USEPREFERREDUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Guest access + +Access the following configuration settings in the System Console by going to **Authentication \> Guest Access**. + +### Enable guest access + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the guest account feature.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the guest account feature.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Guest Access</strong></li><li><code>config.json</code> setting: <code>GuestAccountsSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_GUESTACCOUNTSSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Guest billing depends on channel access. Guests in exactly one channel are treated as single-channel guests and don't count toward the primary paid seat count. They're free up to a 1:1 ratio with licensed seats. Guests in multiple channels continue to count as paid active users. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation for full details. + +</Note> + +### Whitelisted guest domains + +<table> +<colgroup> +<col style={{width: '63%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to restrict the creation of guest accounts. When set, guest accounts require a verified email address from one of the listed domains.</p><p>String input of one or more domains, separated by commas.</p></td> +<td><ul><li>System Config path: <strong>Authentication > Guest Access</strong></li><li><code>config.json</code> setting: <code>GuestAccountsSettings</code> > <code>RestrictCreationToDomains</code></li><li>Environment variable: <code>MM_GUESTACCOUNTSSETTINGS_RESTRICTCREATIONTODOMAINS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Show guest tag + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Guest tags are visible in Mattermost.</li><li><strong>false</strong>: Guest tags aren't visible in Mattermost.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Guest Access</strong></li><li><code>config.json</code> setting: <code>GuestAccountsSettings</code> > <code>HideTags</code> > <code>true</code></li><li>Environment variable: <code>MM_GUESTACCOUNTSSETTINGS_HIDETAGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This configuration setting applies to all Mattermost clients, including web, desktop app, and mobile app. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation for details. + +</Note> + +### Enable guest magic link authentication + +<PlanAvailability slug="entry-ent" /> + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables magic link passwordless authentication for guest users.</li><li><strong>false</strong>: <strong>(Default)</strong> Magic link authentication for guest users is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Authentication > Guest Access</strong></li><li><code>config.json</code> setting: <code>GuestAccountsSettings</code> > <code>EnableGuestMagicLink</code> > <code>false</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [guest accounts](/administration-guide/onboard/guest-accounts#configure-magic-links-for-guests) documentation for guest user setup details. + +</Note> diff --git a/docs/main/administration-guide/configure/bleve-search.mdx b/docs/main/administration-guide/configure/bleve-search.mdx new file mode 100644 index 000000000000..545427ac14a7 --- /dev/null +++ b/docs/main/administration-guide/configure/bleve-search.mdx @@ -0,0 +1,64 @@ +--- +title: "Bleve search" +--- +<PlanAvailability slug="all-commercial" /> + +<Important> + +**From Mattermost v11, Bleve search has been deprecated.** + +- **For v11.0 and later**: Use [Elasticsearch](/administration-guide/scale/elasticsearch-setup) or [OpenSearch](/administration-guide/scale/opensearch-setup) for [enterprise search](/administration-guide/scale/enterprise-search) capabilities +- **For pre-v11.0 deployments**: This documentation remains relevant for existing installations that continue using Bleve. + +</Important> + +Bleve is a search engine that uses Lucene-style full-text search and indexing. This style of search and indexing helps overcome limitations of the default database search such as challenges with characters and advanced search capabilities. + +<Note> + +Experimental Bleve search uses the scorch index type on newly-created indexes. This new index type features efficiency improvements and indexes that use significantly less disk space. Go to **System Console \> Experimental \> Bleve** and select **Purge Index** to run a purge operation. When that's complete, select **Index Now** to reindex. Bleve remains compatible with existing indexes, so currently indexed data will continue to work if a purge and reindex isn't run. + +</Note> + +## Configuring Bleve in Mattermost + +<Note> + +The following steps are only valid for Mattermost versions prior to v11.0. For v11.0 and later, consider using Elasticsearch or OpenSearch instead. + +</Note> + +Follow these steps to configure the Mattermost server to use Bleve and generate required indexes. Once the configuration is saved, new posts made to the database will be automatically indexed with Bleve. + +**Note:** During indexing, search results may be incomplete until the indexing job is complete. + +1. Open **System Console \> Experimental \> Bleve**. +2. Set **Enable Bleve Indexing** to **true** to enable the other settings on the page. +3. Set the directory path to use for storing Bleve indexes (e.g.: `/var/opt/mattermost/bleveindexes`). The user running Mattermost should have permissions to access the directory. See our [configuration settings](/administration-guide/configure/deprecated-configuration-settings#bleve-settings) documentation for details. +4. Save the configuration. +5. Select **Index Now**. All users, channels, and posts in the database will be indexed oldest to newest. +6. Set **Enable Bleve for search queries** to **true**. +7. Set **Enable Bleve for autocomplete queries** to **true**. + +<Note> + +Search results for files shared before upgrading to Mattermost Server v5.35 may be incomplete until an extraction command is run using the [mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-extract). After running this command, the search index must be rebuilt. Go to **System Console \> Experimental \> Bleve \> Bulk Indexing**, then select **Index Now** to rebuild the search index to include older file contents. + +</Note> + +## Using Bleve search + +<Note> + +This section applies only to Mattermost versions prior to v11.0. + +</Note> + +The following conditions are applied when using Bleve search: + +- **Unquoted terms:** Search terms that contain non-alphanumeric characters/special characters outside of quotation marks are removed. For example, using `abcd "**" && abc` as a search term will return results for a search for `abcd "**" abc` as the `&&` characters weren't within the quotation marks. +- **Wildcard search:** Wildcard search (e.g., `abc*`) is supported. + +## How does search work with Bleve disabled? + +Mattermost performs full text searches against the database unless you have an [Enterprise license](/product-overview/editions-and-offerings#mattermost-enterprise) and [enterprise search](/administration-guide/scale/enterprise-search) configured. diff --git a/docs/main/administration-guide/configure/calls-deployment-guide.mdx b/docs/main/administration-guide/configure/calls-deployment-guide.mdx new file mode 100644 index 000000000000..5b038e501cd4 --- /dev/null +++ b/docs/main/administration-guide/configure/calls-deployment-guide.mdx @@ -0,0 +1,1013 @@ +--- +title: "Mattermost Calls Deployment Guide" +--- +<PlanAvailability slug="all-commercial" /> + +This guide walks System Administrators step-by-step through deploying Mattermost Calls, from preparation and network readiness through to pilot testing and production rollout. You'll find clear decision points, verification checks, and troubleshooting tips to help you confirm each phase of the deployment is working before you move on. + +No prior experience with Mattermost Calls is required - this guide assumes you're starting fresh and will introduce essential concepts and best practices. + +## Calls Overview + +Mattermost Calls offers self-hosted audio calling and screen sharing, enabling sovereign real-time collaboration fully contained within your infrastructure. This means no call media or metadata traverses third-party systems. + +Calls is uniquely suited for mission-critical operations across defense, intelligence, security and critical infrastructure - where data sovereignty, control, and compliance are non-negotiable. It is designed to function in isolated networks without internet access, supporting deployments that demand full airgap compliance. + +Functionality includes: +- **1:1 and Group Calling**: Initiate real-time voice communication between two or more participants. +- **Screen Sharing**: Share your screen during calls to collaborate visually on tasks, review documents, or troubleshoot live issues. +- **Call Recording and Transcription**: Record voice sessions for asynchronous review. *(Enterprise, Enterprise Advanced)* +- **Live Captioning**: Generate real-time subtitles for accessibility. *(Enterprise, Enterprise Advanced)* + +## Deployment Overview + +This guide is organized into sequential deployment phases with numbered steps. Each phase begins with prerequisites and ends with verification checks. Before you begin any phase, make sure the listed prerequisites are met, then move to the next phase only after the verification checks are passing. This structure helps you catch and fix issues early, when they are easiest to isolate. + +**Deployment Phases:** + +1. [**Preparation and Networking**](#phase-1-preparation-and-networking) + + Choose your deployment architecture, make networking decisions, provision required servers, and confirm the required network ports and paths are open before deployment. + +2. [**Install and Configure Calls**](#phase-2-install-and-configure-calls) + + Complete the installation and configuration for the deployment architecture you selected in Phase 1. You will only follow one path: + + - [**Path A: Configure Integrated Calls**](#path-a-configure-integrated-calls) + + Use the built-in Calls service on the Mattermost server for simpler deployment at small scale. + + - [**Path B: Install and Configure RTCD**](#path-b-install-and-configure-rtcd) (Optional) + + Use the RTCD (Real-Time Communication Daemon) service for larger scale production deployments. RTCD offloads media processing tasks from the Mattermost server for optimized performance and scalability. + +3. [**Install and Configure Recording**](#phase-3-install-and-configure-recording) (Optional) + + Calls Offloader is a service required to deliver recording, transcription and live captions. + +4. [**Pilot Rollout**](#phase-4-pilot-rollout) + + Expand testing to a small group of pilot users to watch for client, network, and environment-specific issues under real usage. + +5. [**Production Rollout**](#phase-5-production-rollout) + + Rollout to all users in controlled waves with appropriate communication and monitoring, and be ready to pause or roll back if needed. + +## Deployment Prerequisites + +Use this checklist to confirm you have the infrastructure, skills, and access required before you begin deploying Calls. Completing these prerequisites now helps prevent delays caused by missing dependencies later in the deployment process. + +#### Deployment Infrastructure Requirements + +- [ ] You have a running Mattermost server on v10.0+. + + _See [System Information](/../../end-user-guide/collaborate/view-system-information) to check your Mattermost edition and version._ + +- [ ] Your Mattermost server is configured to use HTTPS. + + _See [Configure TLS](/../../deployment-guide/server/setup-tls) if you need to set up HTTPS._ + +- [ ] You know how many active users you have in your current Mattermost deployment + + _See [Site Statistics](/../../administration-guide/manage/statistics) to access usage metrics._ + +- [ ] You can provision at least one dedicated Linux server or VM if you plan to use the RTCD service. + + _See [Infrastructure Decisions](#infrastructure-decisions) (Step 1.2) if you're unsure if you need RTCD._ + +- [ ] You can provision a dedicated Linux server or VM for the `calls-offloader` service if you need recording, transcription, or live captions. +- [ ] You are prepared to deploy a TURN server if your users cannot reliably reach the media service on UDP or TCP `8443`. + + _See [Networking Decisions](#networking-decisions) (Step 1.3) if you're unsure if you need a TURN server._ + +- [ ] You have the appropriate [Mattermost edition and license](/../../product-overview/editions-and-offerings) for the features you need: + - **Mattermost Entry or Team Edition**: 1-1 calling and screen sharing (Up to 40 minutes) + - **Mattermost Professional**: Group calling and screen sharing (No time limit) + - **Mattermost Enterprise or Enterprise Advanced**: Required for: + - RTCD service for scale (50+ users) and production reliability. + - Recording, transcription, or live captions. + +#### Skills and Access Requirements + +- [ ] You are comfortable with basic Linux administration, or you have someone available who is. You will need to connect to servers over SSH, edit configuration files, manage systemd services, inspect logs, and run shell commands. +- [ ] You have System Admin access to your Mattermost server. + + _See [Mattermost roles](/../../end-user-guide/collaborate/learn-about-roles) to learn about roles and permissions._ + +#### Networking Requirements + +- [ ] You know how end users will connect to Calls (From private networks, VPN, or from the public internet) + + _This impacts your [networking decisions](#networking-decisions) (Step 1.3)_ + +- [ ] You can open the required inbound and outbound firewall rules, or you can engage the network or security team that manages them. + +#### Validation Resources + +- [ ] You have two test accounts available for smoke testing during Calls installation and configuration. +- [ ] You have a small pilot group (5-10 users) available for validation across the client types and networks you care about. + +#### Contacting Support + +- [ ] You know how to open a [request](https://support.mattermost.com) with Mattermost support if you encounter issues. + + _Please include the exact **step number** (e.g. 2A.2.1) that failed, along with your [Mattermost support packet](/../../administration-guide/manage/admin/generating-support-packet) and [Calls logs](calls-logging.md)._ + +<Note> + +If you need expert help deploying Calls, contact your Account Manager or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to learn about professional service offerings. + +</Note> + +--- + +## Phase 1: Preparation and Networking + +### 1.1 Prerequisites + +Before you start, confirm the following: + +- [ ] You know how many active users you have in your current Mattermost deployment. +- [ ] You know whether recording, transcription, or live captions are required for your deployment. +- [ ] You can provision additional servers if your chosen architecture requires RTCD or Recording services. +- [ ] You can open inbound and outbound network ports on the servers involved in your deployment. + + _If a network or security team manages your firewalls, you'll need to involve them before continuing._ + +### 1.2 Infrastructure Decisions + +Here you will make two important infrastructure decisions: First you'll choose your media processing architecture, then decide whether you need recording. Reference topology for each architecture is provided. + +#### Media Service: RTCD or Integrated + +**Integrated** + +This is the simplest deployment model, since you do not need to provision a separate service to handle media processing. In Integrated mode, the Calls plugin runs its built-in media service directly on the Mattermost server. + +**RTCD** + +RTCD is a dedicated real-time communications service for Mattermost Calls that processes call media outside the main Mattermost server. In most production deployments, **RTCD is the recommended deployment model** because it improves performance, scalability, and stability by isolating call traffic and reducing load on the Mattermost server. + +To determine if you'll need RTCD, start by answering the following questions about your deployment: + +- **Are you deploying Calls on Kubernetes?** + - **Yes:** You'll need to deploy RTCD as it's the only supported way to run Calls. See the [Kubernetes](/../../administration-guide/configure/calls-kubernetes) Calls deployment guide for details. + - **No:** Continue to the next question. +- **What is the *Total User* count of your existing Mattermost deployment?** _(Check [Site Statistics](/../../administration-guide/manage/statistics))_ + - **Up to 50:** You can use the **Integrated** deployment model. + - **More than 50:** You'll need to deploy RTCD to avoid impacting messaging performance of the Mattermost server. + +Use the tabs below to view the reference architecture for each deployment model: + +````{tab} Integrated + +An **Integrated** deployment does not require any additional infrastructure: + +<img src="../../images/calls-deployment-integrated.png" alt="Integrated Calls deployment" /> +**When to use it** + +- You are evaluating Calls for the first time. +- You expect fewer than 50 people to use Calls. +- You want the simplest possible deployment. + +**Components** + +- **Mattermost server**: Calls plugin is pre-installed, and no additional infrastructure is needed. + +**License** + +- **Mattermost Entry**: 1:1 Calls + Screen Sharing (Up to 40 minutes) +- **Mattermost Professional, Enterprise, or Enterprise Advanced**: Group Calls + Screen Sharing (No time limit) + +#### Recording + +The **Recording** service (`calls-offloader`) can optionally be added to an **Integrated** Calls deployment if you need to enable recording, transcription, and live captions. + +Reference architecture when using the Recording service with Integrated Calls: + +<img src="../../images/calls-deployment-integrated-recording-v2.png" alt="Calls deployment with Integrated Calls and recording" /> +**Components** + +- **Mattermost server**: Calls plugin is pre-installed. +- **Calls Offloader**: Job service that manages recording, transcription and live captions. + +**License** + +- **Mattermost Enterprise** or **Enterprise Advanced** + +```` + +````{tab} RTCD + +An **RTCD Server** is added as a dedicated media service that processes all call audio and screen sharing media. + +<img src="../../images/calls-deployment-rtcd.png" alt="Calls deployment with RTCD" /> +The Mattermost server is still responsible for signaling (setting up, managing, and ending calls) and channel state (who is joining or leaving, who has muted, and overall call status), but the call media itself flows directly between clients and the RTCD server, completely bypassing the Mattermost server. + +**When to use it** + +Use RTCD if you need optimized performance, scalability, and the best possible user experience for Mattermost Calls. Specifically: + +- You want to keep call media traffic off your main Mattermost server to improve overall server performance and reduce CPU usage spikes. +- You need your deployment to easily scale as call volume increases; additional RTCD servers can be added for load balancing. +- You want the lowest possible media latency and highest reliability for Calls. +- You are deploying Mattermost on Kubernetes, where RTCD is required. + +**Components** + +- **Mattermost server**: Calls plugin is pre-installed. +- **RTCD Server**: Dedicated media service. Clients connect to it directly for media traffic. + +**License** + +- **Mattermost Enterprise** or **Enterprise Advanced** + +#### Recording + +The **Recording** service (`calls-offloader`) can optionally be added to an **RTCD** Calls deployment if you need to enable recording, transcription, and live captions. + +Reference architecture when using the Recording service with RTCD: + +<img src="../../images/calls-deployment-rtcd-recording.png" alt="Calls deployment with RTCD and recording" /> +**Components** + +- **Mattermost server**: Calls plugin is pre-installed. +- **RTCD Server**: Dedicated media service. Clients connect to it directly for media traffic. +- **Calls Offloader**: Job service that manages recording, transcription and live captions. + +**License** + +- **Mattermost Enterprise** or **Enterprise Advanced** + +<Note> + +For most production deployments that need recording, RTCD plus `calls-offloader` is the recommended combination because it keeps call media off the Mattermost server and scales more predictably. + +</Note> + +```` + +### 1.3 Networking Decisions + +#### 1.3.1 STUN for Public IP Discovery + +STUN is a protocol that helps the media server discover its public IP address automatically so remote clients can connect to Calls. + +Mattermost provides a default STUN server (`stun.global.calls.mattermost.com`). No call media or signaling traffic is sent through this service; it is used only for STUN lookups. Use this decision tree to determine if you need to allow outbound access from your media server to the Mattermost global STUN service for public IP discovery. + +<Note> + +Your media server is the Mattermost server in the case of an **Integrated** Calls deployment, or it's the **RTCD server** in the case of an RTCD Calls deployment. + +</Note> + +**STUN Decision Tree** + +1. **Are all users and your media server in the same private network, VPN, or air-gapped environment, with no outside clients?** + - **Yes**: You do not need STUN for public IP discovery. You will use the private address of your media server for configuration in Phase 2. + - **No**: Continue to the next question. + +2. **Does your media server have a stable public IP address or DNS name that clients on the public internet can reach?** + - **Yes**: You do not need STUN for public IP discovery. You will use the stable public address of your media server for configuration in Phase 2. + - **No**: You will need STUN. You must open outbound UDP 3478 from your media server to `stun.global.calls.mattermost.com`. + +If your deployment requires STUN for public IP discovery, note that now so you can include it when opening ports in Step 1.5. + +#### 1.3.2 TURN Server + +TURN is a relay service used only when clients cannot reach the Calls media service directly. If STUN helps clients discover where to connect, TURN acts as a backup route when direct connectivity is not possible. + +Provisioning a TURN server is necessary if both of these conditions are true: + +- Clients are on networks that cannot directly reach the RTCD Server or Calls plugin over UDP (preferred) on port `8443` for media traffic. +- Clients are on networks that cannot directly reach the RTCD Server or Calls plugin over TCP (fallback) on port `8443` for media traffic. + +TURN is typically a last resort as it adds latency and infrastructure complexity. Only plan to deploy TURN if your answers indicate that you cannot rely on UDP or TCP for media, and users need an alternative route. + +<Important> + +TURN is a fallback service, not a default requirement. If clients can reliably reach the media service over UDP or TCP `8443`, do not deploy TURN. If you do deploy TURN, only open the TURN listener ports and transports you actually use, and scope client access according to your organization's network policy. + +</Important> + +### 1.4 Provision Infrastructure + +Now you'll provision the servers or VMs required to support your Calls deployment. You are only preparing infrastructure here; software installation and service configuration happen in later phases. This step matters because you need the IP addresses or DNS names of these servers before you can finish the networking configurations in the next step. + +Infrastructure requirements depend on the deployment infrastructure you selected in Step 1.2. If you provision additional hardware, write down the IP addresses or DNS names now because you will use them in Step 1.5: + +**Integrated** + +Since the Mattermost server is handling all media processing, you can skip this step and proceed to network configuration in Step 1.5. + +**RTCD** + +You will need to provision a new server for RTCD. Use the [performance baselines](calls-metrics-monitoring.md#performance-baselines) for benchmark examples of hardware sizing. The RTCD service supports [horizontal scaling](calls-rtcd-setup.md#horizontal-scaling), but we recommend starting with one server and then scaling out if your expected workload requires it. + +**Recording** + +You will need to provision a new server for the `calls-offloader` service. The recommended starting point is **8 vCPU / 16 GB RAM**, or you can use these [performance benchmarks](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md) to estimate recording capacity and transcription load. + +**TURN Server** + +If you've determined in Step 1.3.2 that your users cannot reliably reach the media server over UDP or TCP `8443`, you will need to provision your TURN server now. + +Mattermost recommends installing [coturn](https://github.com/coturn/coturn). + +Before moving to Step 1.5, confirm the following: + +- [ ] Every required server or VM has been created. +- [ ] Every required server has the IP address or DNS name you plan to use later in configuration. +- [ ] You have administrative access to every required server. (validate with `ssh <user>@<SERVER_IP>`) + +### 1.5 Network Configuration + +This section lists the network ports that must be opened for each server involved in your Calls deployment. The server instances must exist before you can configure these rules, which is why provisioning in Step 1.4 comes first. + +**How you open ports depends on your environment:** + +- **Cloud deployments (AWS, Azure, GCP):** Configure inbound and outbound rules in your cloud console security group or network ACL for each instance. +- **On-premises or self-managed VMs:** Use `firewalld` (RHEL, Rocky Linux, AlmaLinux) or `ufw` (Ubuntu/Debian) commands directly on each server. +- **Centrally managed firewall:** If a network team manages your firewall, share the tables below with them and request the rules before proceeding. + +Work through one server at a time so you can verify nothing is missed before moving on. + +**Only open the ports relevant for your chosen deployment architecture (Integrated or RTCD):** + +````{tab} Integrated + +##### Mattermost server ports + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 443 | TCP | Inbound | Mattermost clients | Mattermost server | HTTPS and WebSocket signaling. | +| 8443 | UDP | Inbound | Mattermost clients | Mattermost server | Media traffic (Integrated mode). | +| 8443 | TCP | Inbound | Mattermost clients | Mattermost server | Media traffic fallback (Integrated mode). | +| 3478 | UDP | Outbound | Mattermost server | `stun.global.calls.mattermost.com` | (Optional - Step 1.3.1) Public IP discovery using STUN. | + +<Important> + +If you use NGINX as a reverse proxy in front of Mattermost, it should not be used to forward UDP traffic. Port 8443 must be opened directly on the server running the media service (RTCD or Integrated) - not on NGINX. Port 443 is the only port NGINX needs to handle for Calls. + +</Important> + +##### Recording server ports + +If you deployed a calls-offloader server in Step 1.4, open these ports: + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 4545 | TCP | Inbound | Mattermost server | calls-offloader server | Job service API (Internal only. Restrict this rule to the Mattermost server or approved application subnet only.) | +| 8443 | UDP | Outbound | calls-offloader server | Mattermost server | Recorder and transcriber jobs connect to the media service as call participants. | +| 8443 | TCP | Outbound | calls-offloader server | Mattermost server | Media traffic fallback. | +| 443 | TCP | Outbound | calls-offloader server | Mattermost server | Recorder and transcriber jobs post results back to Mattermost. | + +##### TURN server ports + +If you deployed a TURN server in Step 1.4, open only the ports required by the transports you actually configure. If you are using `coturn`, these are common defaults: + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 3478 | UDP / TCP | Inbound | Mattermost clients | TURN server | TURN relay. | +| 5349 | TCP | Inbound | Mattermost clients | TURN server | (Optional) If you configure TURN over TLS. Do not open this port unless you are explicitly using it. | +| 49152-65535 | UDP | Inbound | Mattermost clients | TURN server | TURN relay port range required to relay media. | + +```` + +````{tab} RTCD + +##### Mattermost server ports + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 443 | TCP | Inbound | Mattermost clients | Mattermost server | HTTPS and WebSocket signaling. | + +##### RTCD server ports + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 8443 | UDP | Inbound | Mattermost clients and calls-offloader server | RTCD server | Media traffic. | +| 8443 | TCP | Inbound | Mattermost clients and calls-offloader server | RTCD server | Media traffic fallback. | +| 8045 | TCP | Inbound | Mattermost server | RTCD server | RTCD API (Internal only. Restrict this rule to the Mattermost server or approved application subnet only.) | +| 3478 | UDP | Outbound | RTCD server | `stun.global.calls.mattermost.com` | (Optional - Step 1.3.1) Public IP discovery using STUN. | + +<Important> + +If you use NGINX as a reverse proxy in front of Mattermost, it should not be used to forward UDP traffic. Port 8443 must be opened directly on the server running the media service (RTCD or Integrated) - not on NGINX. Port 443 is the only port NGINX needs to handle for Calls. + +</Important> + +##### Recording server ports + +If you deployed a calls-offloader server in Step 1.4, open these ports: + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 4545 | TCP | Inbound | Mattermost server | calls-offloader server | Job service API (Internal only. Restrict this rule to the Mattermost server or approved application subnet only.) | +| 8443 | UDP | Outbound | calls-offloader server | RTCD server | Recorder and transcriber jobs connect to the media service as call participants. | +| 8443 | TCP | Outbound | calls-offloader server | RTCD server | Media traffic fallback. | +| 443 | TCP | Outbound | calls-offloader server | Mattermost server | Recorder and transcriber jobs post results back to Mattermost. | + +##### TURN server ports + +If you deployed a TURN server in Step 1.4, open these ports. If you are using `coturn`, these are the common defaults: + +| Port | Protocol | Direction | Source | Destination | Notes | +|---|---|---|---|---|---| +| 3478 | UDP / TCP | Inbound | Mattermost clients | TURN server | TURN relay. | +| 5349 | TCP | Inbound | Mattermost clients | TURN server | (Optional) If you configure TURN over TLS. Do not open this port unless you are explicitly using it. | +| 49152-65535 | UDP | Inbound | Mattermost clients | TURN server | TURN relay port range required to relay media. | + +```` + +### 1.6 Networking Checks + +These checks validate firewall rules and network reachability. They do not require the production Calls, RTCD, or `calls-offloader` services to be installed yet. To get reliable results before those services exist, start a temporary listener on the target host before each applicable scan below. This is especially important for UDP checks, where a blocked port and an allowed-but-idle port can otherwise look the same. + +First, install `nmap` on each source machine or client you will run checks from, and install `ncat` on each target host where you will start a temporary listener. For example: + +- Ubuntu or Debian: `sudo apt install nmap ncat` +- RHEL, Rocky Linux, or AlmaLinux: `sudo dnf install nmap nmap-ncat` + +When you execute each check below, `nmap` returns `open`, `closed`, or `filtered`. + +**Pass**: +- `open`: Port is reachable, and the target host was able to bind a temporary listener on that port. + +**Fail**: +- `closed`: Traffic reached the target host, but nothing is listening on that port. Confirm the temporary listener is still running, the port is correct, and the port was not already in use by another process. +- `filtered`: Firewall is blocking the port. Revisit your networking configuration in Step 1.5 before continuing. + +<Note> + +In the commands below, replace `TARGET_IP` with the actual IP address of the server you are testing. Start the server-side `ncat` listener on the target host first, then run the client-side `nmap` command from the source machine. Stop the temporary listener with `Ctrl+C` after the check completes. + +</Note> + +**Integrated deployments** + +Start the temporary listeners on the Mattermost Server, then run `nmap` from any client machine on the same network as your users: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.1 | Mattermost Server: `sudo ncat -u -l -k -p 8443 -c '/bin/cat'`<br />Client: `sudo nmap -sU -p 8443 TARGET_IP` | Mattermost server IP | Clients can send UDP media to the Mattermost server | +| 1.6.2 | Mattermost Server: `sudo ncat -l -k -p 8443`<br />Client: `nmap -p 8443 TARGET_IP` | Mattermost server IP | Clients can reach the Mattermost server for TCP media fallback | + +**RTCD deployments** + +Start the temporary listeners on the RTCD Server, then run `nmap` from any client machine on the same network as your users: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.3 | RTCD Server: `sudo ncat -u -l -k -p 8443 -c '/bin/cat'`<br />Client: `sudo nmap -sU -p 8443 TARGET_IP` | RTCD server IP | Clients can send UDP media to the RTCD server | +| 1.6.4 | RTCD Server: `sudo ncat -l -k -p 8443`<br />Client: `nmap -p 8443 TARGET_IP` | RTCD server IP | Clients can reach the RTCD server for TCP media fallback | + +Start the temporary listener on the RTCD Server, then run `nmap` from the Mattermost server: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.5 | RTCD Server: `sudo ncat -l -k -p 8045`<br />Mattermost Server: `nmap -p 8045 TARGET_IP` | RTCD server IP | Mattermost can reach the RTCD API | + +**Recording deployments** + +Start the temporary listener on the Recording Server (`calls-offloader`), then run `nmap` from the Mattermost server: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.6 | Recording Server: `sudo ncat -l -k -p 4545`<br />Mattermost Server: `nmap -p 4545 TARGET_IP` | calls-offloader server IP | Mattermost can reach the calls-offloader API | + +Start the temporary listeners on the media server (RTCD or Mattermost server if using Integrated mode), then run `nmap` from the Recording server (`calls-offloader`): + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.7 | RTCD or Mattermost Server: `sudo ncat -u -l -k -p 8443 -c '/bin/cat'`<br />Recording Server: `sudo nmap -sU -p 8443 TARGET_IP` | RTCD server IP (or Mattermost server IP if using Integrated mode) | Calls Offloader can send UDP media to the media service to join calls for recording | +| 1.6.8 | RTCD or Mattermost Server: `sudo ncat -l -k -p 8443`<br />Recording Server: `nmap -p 8443 TARGET_IP` | RTCD server IP (or Mattermost server IP if using Integrated mode) | Calls Offloader can reach the media service for TCP media fallback | + +For the next check, use the existing HTTPS listener on your running Mattermost server instead of starting a temporary `ncat` listener: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.9 | Recording Server: `nmap -p 443 TARGET_IP` | Mattermost server IP | Calls Offloader can post recordings back to Mattermost | + +**TURN deployments** + +Start the temporary listeners on the TURN Server, then run `nmap` from any client machine on the same network as your users: + +| Check | Command | `TARGET_IP` | Description | +|---|---|---|---| +| 1.6.10 | TURN Server: `sudo ncat -u -l -k -p 3478 -c '/bin/cat'`<br />Client: `sudo nmap -sU -p 3478 TARGET_IP` | TURN server IP | Clients can reach the TURN server on UDP 3478 | +| 1.6.11 | TURN Server: `sudo ncat -l -k -p 3478`<br />Client: `nmap -p 3478 TARGET_IP` | TURN server IP | Clients can reach the TURN server on TCP 3478 | +| 1.6.12 | TURN Server: `sudo ncat -u -l -k -p 49152 -c '/bin/cat'`<br />Client: `sudo nmap -sU -p 49152 TARGET_IP` | TURN server IP | Spot check of the TURN relay port range | + +### 1.7 Verification Checks + +Before proceeding to Phase 2, confirm all of the following: + +- [ ] You have chosen your deployment architecture and provisioned the required servers. +- [ ] You have confirmed your Mattermost license supports the architecture and features you plan to deploy. +- [ ] Every required firewall rule and network path for your chosen architecture has been opened. +- [ ] Every relevant network check in Step 1.6 returned the expected result (`open`, but not `closed` or `filtered`). +- [ ] If you need STUN, outbound UDP `3478` is allowed to `stun.global.calls.mattermost.com`. + +<Important> + +**Do not proceed to Phase 2 until all checks in this section relevant to your deployment architecture are passing. If any check fails, go to [Appendix A: Troubleshooting](#appendix-a-troubleshooting).** + +</Important> + +--- + +## Phase 2: Install and Configure Calls + +Now you will configure Calls following the relevant path for your deployment architecture. Do not complete both paths for the same deployment. + +- **Path A** if you are using the **Integrated** Calls deployment model. +- **Path B** if you are using the **RTCD** Calls deployment model. + +Select your path in the tab below to follow the appropriate installation and configuration instructions: + +````{tab} Path A: Integrated + +### Path A: Configure Integrated Calls + +#### 2A.1 Prerequisites + +- [ ] Phase 1 verification checks passed +- [ ] Integrated is the base architecture you selected in Step 1.2 +- [ ] Two test accounts on your Mattermost server +- [ ] System Admin permissions on your Mattermost server + +#### 2A.2 Configure the Calls plugin + +The Calls plugin is prepackaged with Mattermost self-hosted deployments. Go to **System Console > Plugins > Calls > Settings** and complete the following steps: + +**2A.2.1: Enable the plugin** + +Set **Enable Plugin** to `true`. This enables editing for the rest of the configuration settings on the page. + +**2A.2.2: Enable test mode** + +Set **Test mode** to `on`, so Calls stays restricted during initial validation. In this mode, System Admins control where Calls is available and can enable it in specific channels for testing. + +**2A.2.3: Configure the host media address** + +Set **ICE Host Override** to the IP address or DNS name clients will use to reach the media service. ICE (Interactive Connectivity Establishment) is the protocol your users' devices use to find a path to the media server. The ICE Host Override tells Calls which address to advertise to them. Base this value on the STUN decision tree from Step 1.3.1. + +- If your users are in a private network, VPN, or air-gapped environment, set it to the private address of the Mattermost server they can reach. +- If your Mattermost server has a stable public IP, set it to that IP. +- Otherwise, leave it empty for automatic public address discovery using STUN. + +**2A.2.4: Configure TURN Servers** + +If TURN is being used, replace or extend the **ICE server configurations** array with your TURN server details: + +```json +[ + { + "urls": ["turn:turn.example.com:3478"], + "username": "<USERNAME>", + "credential": "<PASSWORD>" + } +] +``` + +If your TURN deployment uses short-lived generated credentials, also set **TURN Static Auth Secret** and **TURN Credentials Expiration**. + +**2A.2.5: Save configuration** + +Click **Save** on the Calls settings page. It is also recommended that you restart the plugin after changing media server settings: + +1. Go to **System Console > Plugins > Plugin Management**. +2. Disable **Calls** and wait a few seconds. +3. Enable **Calls** again. + +#### 2A.3 Verification Checks + +Now smoke test your Calls deployment with your test accounts: + +- Create a test channel such as `calls-test`. +- Open the **Channel menu**, then select **Enable calls**. +- Invite your test users into the channel so you can validate a real call. + +| Check | Action | Pass criteria | +|---|---|---| +| 2A.3.1 | Start a call from the test channel with a second user | Both users are in the call | +| 2A.3.2 | Speak during the call | Both users can hear each other clearly | +| 2A.3.3 | Share your screen from a desktop app or supported browser | Screen sharing is visible to the other user | +| 2A.3.4 | End the call | The call indicator disappears from the channel | + +<Important> + +**Do not continue until all of the checks pass. If any check fails, go to [Appendix A: Troubleshooting](#appendix-a-troubleshooting).** + +</Important> + +```` + +````{tab} Path B: Install and Configure RTCD + +### Path B: Install and Configure RTCD + +#### 2B.1 Prerequisites + +- [ ] Phase 1 verification checks passed +- [ ] RTCD is the base architecture you selected in Step 1.2 +- [ ] RTCD server is provisioned (1.4) and RTCD networking checks passed (1.6.3-1.6.5) +- [ ] Mattermost Enterprise or Enterprise Advanced license is active on your server +- [ ] Two test accounts on your Mattermost server +- [ ] System Admin permissions on your Mattermost server + +#### 2B.2 Install RTCD + +Follow the [RTCD Setup and Configuration](calls-rtcd-setup.md) guide for the actual installation. The guide covers: + +- Binary installation +- `rtcd.toml` configuration +- Service setup +- TURN configuration (if applicable) + +<Note> + +If you are deploying on Kubernetes, also use the [Calls Deployment on Kubernetes](calls-kubernetes.md) guide for cluster-specific installation and Helm-based configuration. + +</Note> + +Before proceeding, run these checks from the Mattermost server to confirm RTCD is running and reachable: + +| Check | Command | Pass criteria | +|---|---|---| +| 2B.2.1 | `nmap -p 8045 YOUR_RTCD_SERVER` | `open` - RTCD is running and accepting connections. | +| 2B.2.2 | `curl http://YOUR_RTCD_SERVER:8045/version` | Returns a JSON version string | + +#### 2B.3 Connect Mattermost to RTCD + +Once RTCD is installed, configured, and reachable, update the Calls plugin to use it: + +1. Go to **System Console > Plugins > Calls > Settings**. +2. Set **Enable Plugin** to `true`. This enables editing for the rest of the Calls settings on the page. +3. Set **Test mode** to `on`, so Calls stays restricted during initial validation. In this mode, System Admins control where Calls is available and can enable it in specific channels for testing. +4. Set **RTCD Service URL** to your RTCD address. If RTCD credentials were generated during setup, embed them directly in the URL: + + ``` + http://clientID:authKey@rtcd.internal:8045 + ``` + + Replace `clientID` and `authKey` with the values generated during RTCD setup. The first connection to RTCD self-registers the client and stores the authentication key in the database. + + Alternatively, set credentials via environment variables on the Mattermost server: `MM_CALLS_RTCD_CLIENT_ID` and `MM_CALLS_RTCD_AUTH_KEY`. + +5. Click **Save** and restart the Calls plugin so the change takes effect. + +#### 2B.4 Configure Calls Monitoring + +Before your pilot, set up Calls monitoring so you can see sessions, errors, CPU, and memory while real users are testing. + +Calls monitoring uses Prometheus (a tool that collects metrics from your servers) and Grafana (a dashboard that visualizes those metrics). If you don't have these set up yet, see [Mattermost monitoring setup](../../administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.md) before continuing. If you already have Prometheus and Grafana running, add the following scrape targets and import the dashboard: + +- **RTCD metrics**: `http://YOUR_RTCD_SERVER:8045/metrics` +- **Calls plugin metrics**: `http://YOUR_MATTERMOST_SERVER:8067/plugins/com.mattermost.calls/metrics` +- **Grafana dashboard**: Import dashboard ID `23225` + +See [Calls Metrics and Monitoring](calls-metrics-monitoring.md) for full configuration details. + +#### 2B.5 Verification Checks + +Now smoke test your RTCD deployment with your test accounts: + +- Create a test channel such as `calls-test`. +- Open the **Channel menu**, then select **Enable calls**. +- Invite your test users into the channel so you can validate a real call. + +| Check | Action | Pass criteria | +|---|---|---| +| 2B.5.1 | Start a call from the test channel with a second user | Both users are in the call | +| 2B.5.2 | Speak during the call | Both users can hear each other clearly | +| 2B.5.3 | Share your screen from a desktop app or supported browser | Screen sharing is visible to the other user | +| 2B.5.4 | End the call | The call indicator disappears from the channel | + +If these checks fail, try these troubleshooting techniques first: + +- Re-run checks `2B.2.1` and `2B.2.2` to confirm RTCD is listening and responding. +- Confirm **RTCD Service URL** is correct and includes credentials if your RTCD setup requires them. +- Check that the Mattermost server can reach RTCD on port `8045`, and review RTCD logs before changing other settings. + +<Important> + +**Do not continue until all of the checks pass. If any check fails, go to [Appendix A: Troubleshooting](#appendix-a-troubleshooting).** + +</Important> + +```` + +--- + +## Phase 3: Install and Configure Recording + +Now we will install and configure the `calls-offloader` job service that handles call recording, transcription, and live captions. + +**You can skip this phase if you do not need recording, transcription, or live captions.** + +### 3.1 Prerequisites + +- [ ] `calls-offloader` server is provisioned (1.4) and relevant networking checks passed (1.6.6-1.6.9) +- [ ] If you are using Integrated mode: Phase 2A verification checks passed (2A.3.1-2A.3.4). +- [ ] If you are using RTCD: Phase 2B verification checks passed (2B.5.1-2B.5.4). +- [ ] Mattermost Enterprise or Enterprise Advanced license is active on your server +- [ ] System Admin permissions on your Mattermost server + +### 3.2 Install calls-offloader + +Follow the [Calls Offloader Setup and Configuration](calls-offloader-setup.md) guide for installation. The guide covers: + +- Binary installation +- `config.toml` configuration +- Systemd service setup +- Docker-backed jobs +- Private network overrides +- Air-gapped installation + +Before proceeding, run these checks from the Mattermost server to confirm `calls-offloader` is running and reachable: + +| Check | Command | Pass criteria | +|---|---|---| +| 3.2.1 | `nmap -p 4545 YOUR_OFFLOADER_SERVER` | `open` - calls-offloader is running and accepting connections. | +| 3.2.2 | `curl http://YOUR_OFFLOADER_SERVER:4545/version` | Returns a JSON version string | + +### 3.3 Connect calls-offloader to Mattermost + +1. Go to **System Console > Plugins > Calls > Settings**. +2. Set **Job Service URL** to the calls-offloader address, for example `http://calls-offloader.internal:4545` on a trusted internal network. +3. Enable **Call Recordings** if needed. +4. Enable **Call Transcriptions** if needed. Transcriptions require recordings to be enabled. +5. Enable **Live Captions** if needed. Live captions require both recordings and transcriptions to be enabled. +6. Click **Save** and restart the Calls plugin so the change takes effect. + +### 3.4 Verification Checks + +Now smoke test recording-related features with your test accounts: + +| Check | Action | Pass criteria | +|---|---|---| +| 3.4.1 | Start recording as a call host | Recording starts without error. | +| 3.4.2 | End the call or stop the recording | An MP4 file appears in the call thread after processing completes. | +| 3.4.3 | With transcription enabled, end a recorded call | An MP4 file and transcript file appear in the call thread after processing completes. | +| 3.4.4 | With live captions enabled, start a recorded call | Captions appear during the call within 1-3 seconds after participants speak. | + +If a recording-related check fails, isolate the problem before retrying: + +- **3.4.1 or 3.4.2 fails**: Confirm the **Job Service URL** is correct, the `calls-offloader` service is running, and the Mattermost server can reach port `4545`. +- **3.4.3 fails**: Confirm recordings are enabled first, then confirm transcription is enabled. +- **3.4.4 fails**: Confirm both recordings and transcriptions are enabled before testing live captions. + +<Important> + +**Do not continue until all of the checks pass. If any check fails, go to [Appendix A: Troubleshooting](#appendix-a-troubleshooting).** + +</Important> + +--- + +## Phase 4: Pilot Rollout + +Now that the technical configuration is complete and validated, run a small pilot with real users before broad rollout. The goal is to confirm Calls works reliably across the clients and locations your organization uses, and that your servers stay healthy under normal usage. + +### 4.1 Prerequisites + +- [ ] If using Integrated mode: Phase 2A verification checks passed (2A.3.1-2A.3.4) +- [ ] If using RTCD: Phase 2B verification checks passed (2B.5.1-2B.5.4) +- [ ] If using Recording: Phase 3 verification checks passed (3.4.1-3.4.4) +- [ ] 5 to 10 volunteer pilot users from different locations +- [ ] Access to the metrics dashboard and logs on your Calls infrastructure +- [ ] Pilot users have current [Mattermost desktop and mobile apps](https://mattermost.com/apps/) + +### 4.2 Preparation and Communication + +For a successful pilot, make sure pilot users know what to test, how to start a call, and how to report problems. + +After inviting your pilot users into the `calls-test` channel, post a short message there so everyone is testing the same things. A template is provided below: + +<details open> +<summary>Pilot user communication template</summary> + +```markdown +## Mattermost Calls pilot + +Thank you for volunteering to test Mattermost Calls before a wider rollout. After 3-5 days of pilot testing, we will ask everyone to share their findings and experiences. Please keep track of any issues or feedback so you can summarize them when requested. + +**How to start** + +Calls is enabled in this channel for pilot testing. You can select **Start call** in the channel header to begin, or join an existing call if one is already started. + +You can learn more about Mattermost Calls in the [documentation](https://docs.mattermost.com/end-user-guide/collaborate/make-calls.html). + +**Test Cases** + +| Test | Action | Pass criteria | Client Types | +|---|---|---|---| +| T1 | Group call with 3-5 participants | All participants can hear each other clearly | Web, Desktop, Mobile | +| T2 | Group call lasting 15 minutes or longer | No unexpected drops or audio degradation | Web, Desktop, Mobile | +| T3 | Participants join calls from outside the main office network | Call quality is acceptable from that network | Web, Desktop, Mobile | +| T4 | Participants share screen during a call | Screen sharing works and is visible to all participants | Desktop, Web | +| T5 | Record a group call, if recording is enabled | MP4 and transcription file appear in the call thread after processing completes | Web, Desktop, Mobile | +| T6 | Enable Live Captions during a group call, if captions are enabled | Captions appear during the call within 1-3 seconds after participants speak | Web, Desktop | + +**Reporting Issues** + +If you encounter an issue, please report it by posting in this channel and including: + +- Test number +- Reproduction steps +- What you expected to happen +- What actually happened (with screenshots) +- Your client type (desktop, browser, or mobile) +``` + +</details> + +### 4.3 Verification Checks + +**Monitoring** + +| Check | Action | Pass criteria | +|---|---|---| +| 4.3.1 | Check your metrics dashboard during a pilot call | Active sessions and participants are visible and counted correctly | +| 4.3.2 | If using RTCD, check RTCD error metrics after pilot calls (`rtcd_rtc_errors_total`) | No elevated error counts | +| 4.3.3 | If using RTCD, check CPU and memory metrics during a pilot call (`rtcd_process_cpu_seconds_total`, `rtcd_process_resident_memory_bytes`) | No CPU or memory spikes observed | +| 4.3.4 | Review Mattermost logs, plus RTCD and calls-offloader logs if those services are deployed | No recurring `ERROR` lines, and no unexpected `WARN` patterns | + +**Production readiness** + +Collect feedback from your pilot users after 3-5 business days and use it to evaluate production readiness: + +| Check | Requirement | +|---|---| +| 4.3.5 | Audio quality rated acceptable by 80%+ of pilot users | +| 4.3.6 | No blocking issues found in the pilot test cases | +| 4.3.7 | All pilot users confirm readiness for production rollout | + +If the pilot users find issues, do not expand the rollout yet: + +- Fix the issue in the smallest possible scope. +- Repeat the affected pilot test case. +- Stay in pilot until the failing scenario is consistently passing. + +You can also run `/call stats` in the Mattermost message area after a failed test for additional diagnostic clues. + +<Important> + +**Do not continue to a production rollout until all relevant checks are passing. If any check fails, go to [Appendix A: Troubleshooting](#appendix-a-troubleshooting).** + +</Important> + +--- + +## Phase 5: Production Rollout + +Now you will execute a broader rollout to all users in production. + +### 5.1 Prerequisites + +- [ ] Phase 4 production readiness checks passed (4.3.1-4.3.7) +- [ ] Rollback plan documented and understood +- [ ] System Admin permissions on your Mattermost server +- [ ] Access to the metrics dashboard and logs on your Calls infrastructure + +### 5.2 Rollback plan + +You should be familiar with your rollback options before you begin the staged production rollout. If something goes wrong, choose the smallest rollback that solves the problem: + +**Per-channel rollback** + +Disables Calls in specific channels. + +1. Navigate to the impacted channel. +2. Select the **Channel menu**, then select **Disable calls**. + +**Test mode rollback** + +Restricts Calls to channels where it has been enabled by a System Admin. + +1. Go to **System Console > Plugins > Calls > Settings**. +2. Set **Test Mode** to `on`. + +**Full rollback** + +Disables Calls completely for everyone. + +1. Go to **System Console > Plugins > Plugin Management**. +2. **Disable** the Calls plugin. + +If you have an existing conferencing tool, keep it available until Calls is stable in production. + +### 5.3 Preparation and Communication + +Before announcing Calls to users, create a `calls-support` public channel. This gives users a clear place to report issues and gives your admins a single place to track rollout problems. + +Also prepare a short announcement to share in an all-hands channel or similar high-visibility location. A template is provided below: + +<details open> +<summary>Production rollout communication template</summary> + +```markdown +## Mattermost Calls rollout + +We're enabling Mattermost Calls across this server. Starting today, you can start audio calls in select channels directly within Mattermost - no need to switch to a separate tool. + +We're rolling out gradually, starting with a select set of channels before expanding to everyone. + +**Calls features** + +- Start or join 1:1 and group audio calls +- Share your screen from the desktop app or browser +- Record calls and generate transcripts, if enabled +- Use live captions during recorded calls, if enabled + +You can learn more about Mattermost Calls in the [documentation](https://docs.mattermost.com/end-user-guide/collaborate/make-calls.html). + +**How to start a call** + +Select **Start call** in the channel header. Anyone in the channel can join. + +**Things to know** + +- We recommend updating your [desktop and mobile apps](https://mattermost.com/apps/) to the latest version +- Your browser or desktop app may ask for microphone permission the first time you join a call. +- Screen sharing may also require a screen capture permission prompt. + +**Need help?** + +Post in `~calls-support` and include what you were trying to do, what happened, and a screenshot if possible. +``` +</details> + +### 5.4 Rollout Stages + +We recommend enabling Calls in stages instead of enabling it everywhere at once. This way you can watch real usage, catch problems early, and rollback cleanly if needed. + +| Stage | Channels / departments | Suggested timeline | Rollback approach | +|---|---|---|---| +| Stage 1 | IT and Admin channels | Days 1-3 | Per-channel rollback | +| Stage 2 | Engineering or power user channels | Days 4-7 | Per-channel rollback | +| Stage 3 | Full organization | Day 8+ | Test mode (if issues are isolated) or full rollback | + +If a rollout stage introduces problems, pause the rollout, use the rollback option listed for that stage, fix the issue, and repeat the same stage before moving to the next one. + +### 5.5 Monitor and optimize + +Once Calls is live, monitor it actively for the first two weeks and tune based on what you see. + +**5.5.1: Watch server health during peak call hours** + +Monitor CPU and memory on the media server (RTCD or Mattermost server) daily during peak usage. If CPU utilization consistently exceeds 70%, consider increasing hardware specs, or adding RTCD nodes before the next rollout stage. + +**5.5.2: Review logs daily** + +Check Mattermost, RTCD, and calls-offloader logs each day for recurring `ERROR` or `WARN` lines. Address any patterns before they become user-facing problems. + +**5.5.3: Tune Max Call Participants** + +If you see resource pressure during large calls, lower **Max Call Participants** in **System Console > Plugins > Calls**. By default, there is no participant limit (configured as `0`, which means unlimited). A practical ceiling for most deployments is `50`. + +**5.5.4: Track user-reported issues** + +Monitor `~calls-support` for recurring complaints. + +Check [Appendix A: Troubleshooting](#appendix-a-troubleshooting) for common issues and fixes. + +--- + +## Appendix A: Troubleshooting + +### A.1 The call button is missing + +| Cause | Fix | +|---|---| +| The Calls plugin is disabled | Go to **System Console > Plugins > Plugin Management** and enable Calls | +| The deployment is in test mode | Go to **System Console > Plugins > Calls > Settings** and check the deployment state - Calls must be enabled in specific channels by System Admins in test mode | +| Calls is not enabled for the channel | When test mode is enabled, open the **channel menu** and select **Enable calls** | +| The user is on an older client | Ask the user to update to the current Mattermost desktop or mobile app | + +### A.2 Calls start but audio does not work + +| Cause | Fix | +|---|---| +| UDP `8443` is blocked | Repeat the UDP connectivity check from Phase 1 (check 1.6.1 or 1.6.3) and confirm the firewall rule is applied | +| TCP `8443` is also blocked and fallback is failing | Repeat the TCP check (1.6.2 or 1.6.4) - clients need at least one path to the media service | +| The wrong media address is being advertised | Re-check `ICE Host Override` in Phase 2A (Integrated) or `ice_host_override` in `rtcd.toml` in Phase 2B (RTCD) - the address must be reachable by clients | +| Browser or desktop microphone permissions were denied | Ask the user to check browser or OS microphone permissions and reload the app | + +### A.3 Remote users cannot join from outside the network + +| Cause | Fix | +|---|---| +| External firewall rules are blocking UDP `8443` | Confirm external reachability to UDP `8443` on the media server - cloud security groups and on-prem firewalls both need to allow inbound traffic from the internet | +| The advertised media address is a private IP | Set `ICE Host Override` (Integrated) or `ice_host_override` in `rtcd.toml` to the correct public IP or use STUN (1.3.1) | +| Client networks are too restrictive for direct UDP or TCP | Deploy a TURN server and add it to **ICE server configurations** | + +### A.4 Recording, transcription, or captions are failing + +| Cause | Fix | +|---|---| +| calls-offloader is not running | Run `nmap -p 4545 YOUR_OFFLOADER_SERVER` from the Mattermost server - if the result is `closed`, the service is not running; check the systemd service logs | +| Mattermost cannot reach the Job Service URL | Run `curl http://YOUR_OFFLOADER_SERVER:4545/version` from the Mattermost server and confirm it returns a version string | +| The offloader service account cannot use Docker | Confirm the service account is in the `docker` group on the calls-offloader server | diff --git a/docs/main/administration-guide/configure/calls-kubernetes.mdx b/docs/main/administration-guide/configure/calls-kubernetes.mdx new file mode 100644 index 000000000000..d96e1423c53f --- /dev/null +++ b/docs/main/administration-guide/configure/calls-kubernetes.mdx @@ -0,0 +1,108 @@ +--- +title: "Calls Deployment on Kubernetes" +--- +<PlanAvailability slug="all-commercial" /> + +This guide provides detailed information for deploying Mattermost Calls on Kubernetes environments. + +## Overview + +Mattermost Calls has been designed to integrate with Kubernetes for improved scalability and control over the deployment. Using the RTCD service is the only supported deployment model. + +## Architecture + +![Calls deployed in a Kubernetes cluster](/images/calls-deployment-kubernetes.png) + +This diagram shows how the RTCD standalone service can be deployed in a Kubernetes cluster. In this architecture: + +1. Calls traffic is handled by dedicated RTCD pods +2. Scaling is managed through Kubernetes deployment configurations +3. Call recording and transcription is handled by the calls-offloader service (see [Calls Offloader Setup and Configuration](calls-offloader-setup.md)) + +If Mattermost isn't already deployed in your Kubernetes cluster and you want to use this deployment type, visit the [Kubernetes operator guide](/install/mattermost-kubernetes-operator.md). + +## Helm Chart Deployment + +The recommended way to deploy Calls-related components in a Kubernetes environment is to use the officially provided Helm charts: + +### RTCD Helm Chart + +The RTCD Helm chart deploys the RTCD service needed for call media handling: + +```bash +helm repo add mattermost https://helm.mattermost.com +helm repo update + +helm install mattermost-rtcd mattermost/mattermost-rtcd \ + --set service.annotations."service\\.beta\\.kubernetes\\.io/aws-load-balancer-backend-protocol"=udp +``` + +For complete configuration options, see the [RTCD Helm chart documentation](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-rtcd). + +### Calls-Offloader Helm Chart + +If you need call recording and transcription capabilities, deploy the calls-offloader service: + +```bash +helm install mattermost-calls-offloader mattermost/mattermost-calls-offloader \ + --set ingress.enabled=true \ + --set ingress.host=calls-offloader.example.com +``` + +For complete configuration options, see the [Calls-Offloader Helm chart documentation](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-calls-offloader). + +## Kubernetes-Specific Configuration + +### Network Configuration + +For Kubernetes deployments, you need to ensure specific connectivity paths: + +1. **Client to RTCD connectivity**: UDP and TCP traffic on port 8443 is properly routed from clients to RTCD pods (for media, with TCP acting as a fallback). +2. **Mattermost to RTCD API connectivity**: There needs to be a clear connectivity path between Mattermost and RTCD on the API port (TCP 8045) +3. **Network policies**: Network policies must allow the required communications between Mattermost and RTCD services + +### Resource Requirements + +Resource requirements for RTCD pods depend heavily on the expected call volume, participant count, and whether screen sharing is used. + +We strongly recommend reviewing the [Performance Baselines](calls-metrics-monitoring.md#performance-baselines) to determine the appropriate CPU, memory, and network requests and limits for your specific deployment needs rather than relying on generic defaults. + +### Scaling Considerations + +Horizontal scaling of RTCD pods is possible, but remember: + +1. Each call is hosted entirely on a single RTCD pod +2. DNS A records should be set up for all RTCD pods so server can discover RTCD servers. +3. Health checks should ensure that only healthy pods are reported via DNS +4. Calls remain on their assigned pod for their entire duration + +### Limitations + +Due to the inherent complexities of hosting a WebRTC service, some limitations apply when deploying Calls in a Kubernetes environment. + +One key requirement is that each `rtcd` process must live in a dedicated Kubernetes node. This is necessary to forward the data correctly while allowing for horizontal scaling. Data should generally direct directly to the pod running the `rtcd` process, as routing this traffic through a standard ingress is not recommended for RTCD deployments. + +The general recommendation is to expose one external IP address per `rtcd` instance (Kubernetes node). This makes it simpler to scale as the application is able to detect its own external address (through STUN) and advertise it to clients to achieve connectivity with minimal configuration. + +## Monitoring and Metrics + +For detailed information on metrics collection and monitoring, see the [Calls Metrics and Monitoring](calls-metrics-monitoring.md) guide. + +## Troubleshooting + +For Kubernetes-specific troubleshooting: + +1. Check pod logs: `kubectl logs -f deployment/mattermost-rtcd` +2. Verify service connectivity: `kubectl port-forward service/mattermost-rtcd 8045:8045` +3. Ensure UDP and TCP traffic is properly routed through your load balancer +4. Verify network policies allow required communication paths + +For detailed logging guidance, see the [Calls Logging](calls-logging.md) guide. + +## Other Calls Documentation + +- [Calls Deployment Guide](calls-deployment-guide.md): Overview of deployment options and architecture +- [RTCD Setup and Configuration](calls-rtcd-setup.md): Comprehensive guide for setting up the dedicated RTCD service +- [Calls Offloader Setup and Configuration](calls-offloader-setup.md): Setup guide for call recording and transcription +- [Calls Metrics and Monitoring](calls-metrics-monitoring.md): Guide to monitoring Calls performance using metrics and observability +- [Calls Logging](calls-logging.md): Detailed guidance for collecting Calls logs and client diagnostics diff --git a/docs/main/administration-guide/configure/calls-logging.mdx b/docs/main/administration-guide/configure/calls-logging.mdx new file mode 100644 index 000000000000..cd8f414f0341 --- /dev/null +++ b/docs/main/administration-guide/configure/calls-logging.mdx @@ -0,0 +1,34 @@ +--- +title: "Calls Logging" +--- +<PlanAvailability slug="all-commercial" /> + +When troubleshooting Mattermost Calls, gathering the appropriate log files for analysis is critical. The required logs include: + +## RTCD logs + +The location of the RTCD log file is determined by the settings in your RTCD `config.toml` file. If you are running Calls using the integrated RTCD, these logs are included within the standard Mattermost server logs. + +## Client logs + +You can retrieve basic client logs by running the `/call logs` slash command to output the log for the most recent call. However, capturing the JavaScript console logs is often more helpful. The method for capturing these logs depends on your client: + +- **Desktop App:** While a call is in progress, navigate to **View > Developer Tools > Developer Tools for Call Widget**. Next to the **Filter** field, select **Verbose** from the log level drop-down menu to view the debug output. To save the log, right-click within the console and select **Save as...**. + +![Developer Tools for Call Widget](/images/developer-tools-call-widget.png) + +- **Chrome browser:** Select the **More menu** (three vertical dots) next to the address bar, then go to **More Tools > Developer Tools**. Select the **Console** tab to view the output. Next to the **Filter** field, select **Verbose** from the log level drop-down menu to view the debug output. To save the log, right-click within the console and select **Save as...**. + +## Client statistics + +You can gather client call statistics by running the `/call stats` slash command. While you can run this command during an active call, it is best to run it immediately after a call concludes. This command provides valuable information regarding the negotiated connection between the client and RTCD, as well as statistics on media packets sent and lost. + +## Mattermost server logs + +The Mattermost server logs often contain entries related to the Calls plugin. If you are using an external RTCD instance, these logs are generally less critical than the RTCD and client logs. + +<Note> + +Interpreting RTCD and client logs can be challenging, as the Interactive Connectivity Establishment (ICE) negotiation during call setup often logs expected and benign failure or error messages. We strongly recommend providing the complete set of logs to Mattermost Support for analysis. + +</Note> diff --git a/docs/main/administration-guide/configure/calls-metrics-monitoring.mdx b/docs/main/administration-guide/configure/calls-metrics-monitoring.mdx new file mode 100644 index 000000000000..8456fee5d5be --- /dev/null +++ b/docs/main/administration-guide/configure/calls-metrics-monitoring.mdx @@ -0,0 +1,417 @@ +--- +title: "Calls Metrics and Monitoring" +draft: true +--- +<PlanAvailability slug="ent-plus" /> + +This guide provides detailed information on monitoring Mattermost Calls performance and health through metrics and observability tools. Effective monitoring is essential for maintaining optimal call quality and quickly addressing any issues that arise. + +- [Metrics overview](#metrics-overview) +- [Setting up monitoring](#setting-up-monitoring) +- [Key metrics to monitor](#key-metrics-to-monitor) +- [Performance baselines](#performance-baselines) +- [Troubleshooting metrics collection](#troubleshooting-metrics-collection) + +## Metrics Overview + +Mattermost Calls provides metrics through Prometheus for both the Calls plugin and the RTCD service. These metrics help track: + +- Active call sessions and participants +- Media track statistics +- Connection states and errors +- Resource utilization (CPU, memory, network) +- WebSocket connections and events + +The metrics are exposed through HTTP endpoints: + +- **Calls Plugin**: `/plugins/com.mattermost.calls/metrics` +- **RTCD Service**: `/metrics` (default) or a configured endpoint + +Resource utilization metrics (CPU, memory, network) are mainly provided by an external service ([`node-exporter`](https://prometheus.io/docs/guides/node-exporter/)). + +> Metrics for the calls plugin are exposed through the `/plugins/com.mattermost.calls/metrics` subpath under the existing Mattermost server metrics endpoint. This is controlled by the [Listen address for performance](https://docs.mattermost.com/configure/environment-configuration-settings.html#listen-address-for-performance) configuration setting. It defaults to port 8067. For example: `http://localhost:8067/plugins/com.mattermost.calls/metrics` +> The RTCD Service `/metrics` endpoint is exposed on the HTTP API (e.g. `http://localhost:8045/metrics`). + +## Setting Up Monitoring + +For instructions on deploying Prometheus and Grafana for Mattermost, please refer to the [Deploy Prometheus and Grafana for Performance Monitoring](https://docs.mattermost.com/scale/deploy-prometheus-grafana-for-performance-monitoring.html) guide. + +Once Prometheus and Grafana are set up, you will need to configure Prometheus to scrape metrics from the Calls-related services. + +### Prometheus Scrape Configuration + +Add the following jobs to your `prometheus.yml` configuration: + +```yaml +scrape_configs: + - job_name: 'calls-plugin' + metrics_path: /plugins/com.mattermost.calls/metrics + static_configs: + - targets: ['MATTERMOST_SERVER_IP:8067'] + labels: + service_name: 'calls-plugin' + + - job_name: 'rtcd' + metrics_path: /metrics + static_configs: + - targets: ['RTCD_SERVER_IP:8045'] + labels: + service_name: 'rtcd' + + - job_name: 'rtcd-node-exporter' + metrics_path: /metrics + static_configs: + - targets: ['RTCD_SERVER_IP:9100'] + labels: + service_name: 'rtcd' + + - job_name: 'calls-offloader-node-exporter' + metrics_path: /metrics + static_configs: + - targets: ['CALLS_OFFLOADER_SERVER_IP:9100'] + labels: + service_name: 'offloader' +``` + +Replace the placeholder IP addresses with your actual server addresses: + +- `MATTERMOST_SERVER_IP`: IP address of your Mattermost server +- `RTCD_SERVER_IP`: IP address of your RTCD server +- `CALLS_OFFLOADER_SERVER_IP`: IP address of your calls-offloader server (if deployed) + +<Important> + +**Metrics Configuration Notice**: Use the `service_name` labels as shown in the configuration above. These labels help organize metrics in dashboards and enable proper service identification. + +</Important> + +<Note> + +- **node_exporter**: Optional but recommended for system-level metrics (CPU, memory, disk, network). See [node_exporter setup guide](https://prometheus.io/docs/guides/node-exporter/) for installation instructions. +- **calls-offloader**: Only needed if you have call recording/transcription enabled. + +</Note> + +### Mattermost Calls Grafana Dashboard + +You can use the official [Mattermost Calls Performance Monitoring](https://grafana.com/grafana/dashboards/23225-mattermost-calls-performance-monitoring/) dashboard to visualize these metrics. + +- To import it directly into Grafana, use dashboard ID: `23225`. +- The dashboard is also available as JSON source from the [Mattermost performance assets repository](https://github.com/mattermost/mattermost-performance-assets/blob/master/grafana/mattermost-calls-performance-monitoring.json) for manual import or customization. + +## Key Metrics to Monitor + +### RTCD Metrics + +#### Process Metrics + +These metrics help monitor the health and resource usage of the RTCD process: + +- `rtcd_process_cpu_seconds_total`: Total CPU time spent +- `rtcd_process_open_fds`: Number of open file descriptors +- `rtcd_process_max_fds`: Maximum number of file descriptors +- `rtcd_process_resident_memory_bytes`: Memory usage in bytes +- `rtcd_process_virtual_memory_bytes`: Virtual memory used + +#### WebRTC Connection Metrics + +These metrics track the WebRTC connections and media flow: + +- `rtcd_rtc_conn_states_total{state="X"}`: Count of connections in different states +- `rtcd_rtc_errors_total{type="X"}`: Count of RTC errors by type +- `rtcd_rtc_rtp_tracks_total{direction="X"}`: Count of RTP tracks (incoming/outgoing) +- `rtcd_rtc_sessions_total`: Total number of active RTC sessions + +#### WebSocket Metrics + +These metrics track the signaling channel: + +- `rtcd_ws_connections_total`: Total number of active WebSocket connections. This is about RTCD <-> MM, so the connection count should match the number of MM nodes. +- `rtcd_ws_messages_total{direction="X"}`: Count of WebSocket messages (sent/received) + +### Calls Plugin Metrics + +Similar metrics are available for the Calls plugin with the following prefixes: + +- Process metrics: `mattermost_plugin_calls_process_*` +- WebRTC connection metrics: `mattermost_plugin_calls_rtc_*` +- WebSocket metrics: `mattermost_plugin_calls_websocket_*` +- Store metrics: `mattermost_plugin_calls_store_ops_total` + +## Performance Baselines + +The following performance benchmarks provide baseline metrics for RTCD deployments under various load conditions and configurations. + +**Deployment specifications** + +- 1x r6i.large nginx proxy +- 3x c5.large MM app nodes (HA) +- 2x db.x2g.xlarge RDS Aurora MySQL v8 (one writer, one reader) +- 1x (c7i.xlarge, c7i.2xlarge, c7i.4xlarge) RTCD +- 2x c7i.2xlarge load-test agents + +**App specifications** + +- Mattermost v9.6 +- Mattermost Calls v0.28.0 +- RTCD v0.16.0 +- load-test agent v0.28.0 + +**Media specifications** + +- Speech sample bitrate: 80Kbps +- Screen sharing sample bitrate: 1.6Mbps + +**Results** + +Below are the detailed benchmarks based on internal performance testing: + +<table border="1" class="network-requirements"> +<thead> +<tr> +<th>Calls</th> +<th>Participants/call</th> +<th>Unmuted/call</th> +<th>Screen sharing</th> +<th>CPU (avg)</th> +<th>Memory (avg)</th> +<th>Bandwidth (in/out)</th> +<th>Instance type (RTCD)</th> +</tr> +</thead> +<tbody> +<tr> +<td>1</td> +<td>1000</td> +<td>2</td> +<td>no</td> +<td>47%</td> +<td>1.46GB</td> +<td>1Mbps / 194Mbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>1</td> +<td>800</td> +<td>1</td> +<td>yes</td> +<td>64%</td> +<td>1.43GB</td> +<td>2.7Mbps / 1.36Gbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>1</td> +<td>1000</td> +<td>1</td> +<td>yes</td> +<td>79%</td> +<td>1.54GB</td> +<td>2.9Mbps / 1.68Gbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>10</td> +<td>100</td> +<td>1</td> +<td>yes</td> +<td>74%</td> +<td>1.56GB</td> +<td>18.2Mbps / 1.68Gbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>100</td> +<td>10</td> +<td>2</td> +<td>no</td> +<td>49%</td> +<td>1.46GB</td> +<td>18.7Mbps / 175Mbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>100</td> +<td>10</td> +<td>1</td> +<td>yes</td> +<td>84%</td> +<td>1.73GB</td> +<td>171Mbps / 1.53Gbps</td> +<td>c7i.xlarge</td> +</tr> +<tr> +<td>1</td> +<td>1000</td> +<td>2</td> +<td>no</td> +<td>20%</td> +<td>1.44GB</td> +<td>1.4Mbps / 194Mbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>1</td> +<td>1000</td> +<td>2</td> +<td>yes</td> +<td>49%</td> +<td>1.53GB</td> +<td>3.6Mbps / 1.79Gbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>2</td> +<td>1000</td> +<td>1</td> +<td>yes</td> +<td>73%</td> +<td>2.38GB</td> +<td>5.7Mbps / 3.06Gbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>100</td> +<td>10</td> +<td>2</td> +<td>yes</td> +<td>60%</td> +<td>1.74GB</td> +<td>181Mbps / 1.62Gbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>150</td> +<td>10</td> +<td>1</td> +<td>yes</td> +<td>72%</td> +<td>2.26GB</td> +<td>257Mbps / 2.30Gbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>150</td> +<td>10</td> +<td>2</td> +<td>yes</td> +<td>79%</td> +<td>2.34GB</td> +<td>271Mbps / 2.41Gbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>250</td> +<td>10</td> +<td>2</td> +<td>no</td> +<td>58%</td> +<td>2.66GB</td> +<td>47Mbps / 439Mbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>1000</td> +<td>2</td> +<td>2</td> +<td>no</td> +<td>78%</td> +<td>2.31GB</td> +<td>178Mbps / 195Mbps</td> +<td>c7i.2xlarge</td> +</tr> +<tr> +<td>2</td> +<td>1000</td> +<td>2</td> +<td>yes</td> +<td>41%</td> +<td>2.6GB</td> +<td>7.23Mbps / 3.60Gbps</td> +<td>c7i.4xlarge</td> +</tr> +<tr> +<td>3</td> +<td>1000</td> +<td>2</td> +<td>yes</td> +<td>63%</td> +<td>3.53GB</td> +<td>10.9Mbps / 5.38Gbps</td> +<td>c7i.4xlarge</td> +</tr> +<tr> +<td>4</td> +<td>1000</td> +<td>2</td> +<td>yes</td> +<td>83%</td> +<td>4.40GB</td> +<td>14.5Mbps / 7.17Gbps</td> +<td>c7i.4xlarge</td> +</tr> +<tr> +<td>250</td> +<td>10</td> +<td>2</td> +<td>yes</td> +<td>79%</td> +<td>3.49GB</td> +<td>431Mbps / 3.73Gbps</td> +<td>c7i.4xlarge</td> +</tr> +<tr> +<td>500</td> +<td>2</td> +<td>2</td> +<td>yes</td> +<td>71%</td> +<td>2.54GB</td> +<td>896Mbps / 919Mbps</td> +<td>c7i.4xlarge</td> +</tr> +</tbody> +</table> + +## Troubleshooting Metrics Collection + +### Verify RTCD Metrics are Being Collected + +To verify that Prometheus is successfully collecting RTCD metrics, use this command: + +```bash +curl http://PROMETHEUS_IP:9090/api/v1/label/__name__/values | jq '.' | grep rtcd +``` + +This command queries Prometheus for all available metric names and filters for RTCD-related metrics. + +If no RTCD metrics appear, check: +1. RTCD is running +2. Prometheus is configured to scrape the RTCD metrics endpoint +3. RTCD metrics port is accessible from Prometheus (default: 8045) + +### Check Prometheus Scrape Targets + +To verify all Calls-related services are being scraped successfully: + +1. Open the Prometheus web interface (typically `http://PROMETHEUS_IP:9090`) +2. Navigate to **Status > Targets** +3. Look for your configured Calls services: + - Mattermost server (for Calls plugin metrics) + - RTCD service + +Each target should show status "UP" in green. If a target shows "DOWN" or errors: +- Verify the service is running +- Check network connectivity between Prometheus and the target +- Verify the metrics endpoint is accessible + +## Other Calls Documentation + +- [Calls Deployment Guide](calls-deployment-guide.md): Overview of deployment options and architecture +- [RTCD Setup and Configuration](calls-rtcd-setup.md): Comprehensive guide for setting up the dedicated RTCD service +- [Calls Offloader Setup and Configuration](calls-offloader-setup.md): Setup guide for call recording and transcription +- [Calls Deployment on Kubernetes](calls-kubernetes.md): Detailed guide for deploying Calls in Kubernetes environments +- [Calls Logging](calls-logging.md): Detailed guidance for collecting Calls logs and client diagnostics + +**Note:** +Configure Prometheus storage accordingly to balance disk usage with retention needs. If you need to be tight on storage, you can use a short retention period. If you have lots of storage you can keep the retention length longer. diff --git a/docs/main/administration-guide/configure/calls-offloader-setup.mdx b/docs/main/administration-guide/configure/calls-offloader-setup.mdx new file mode 100644 index 000000000000..9268f9e7cb27 --- /dev/null +++ b/docs/main/administration-guide/configure/calls-offloader-setup.mdx @@ -0,0 +1,504 @@ +--- +title: "Calls Offloader Setup and Configuration" +--- +<PlanAvailability slug="ent-plus" /> + +This guide provides detailed instructions for setting up, configuring, and validating the Mattermost calls-offloader service used for call recording and transcription features. + +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [Installation and deployment](#installation-and-deployment) +- [Configuration](#configuration) +- [Validation and testing](#validation-and-testing) +- [Integration with Mattermost](#integration-with-mattermost) +- [Troubleshooting](#troubleshooting) +- [Air-Gapped Deployments](#air-gapped-deployments) + +## Overview + +The calls-offloader service is a dedicated microservice that handles resource-intensive tasks for Mattermost Calls, including: + +- **Call recording**: Captures audio and screen sharing content from calls +- **Call transcription**: Provides automated transcription of recorded calls +- **Live captions** (Experimental): Real-time transcription during active calls + +By offloading these tasks to a dedicated service, the main Mattermost server and RTCD service can focus on core functionality while maintaining optimal performance. + +## Prerequisites + +Before deploying calls-offloader, ensure you have: + +- A Mattermost Enterprise license +- A properly configured Mattermost Calls deployment (either integrated or with RTCD) +- A moderately powerful server with Docker installed and running +- Sufficient storage space for recordings (see [Storage Requirements](#storage-requirements)) + +### System Requirements + +For detailed system requirements and performance recommendations, refer to the [calls-offloader performance documentation](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md). + +### Storage Requirements + +Call recordings can consume significant storage space. Based on average recording sizes with screen sharing on (including one audio track), storage usage by quality chosen is approximately: + +- **Low**: ~0.5GB/hour (or ~8MB/minute) +- **Medium**: ~0.7GB/hour (or ~12MB/minute) +- **High**: ~1.2GB/hour (or ~20MB/minute) + +*Note: Audio-only recordings consume approximately 1MB per minute per participant.* + +## Installation and Deployment + +### Bare Metal or VM Deployment + +<Tip> + +Looking for an automated setup? Check out these community-maintained [Calls Installation Scripts](https://github.com/bgardner8008/calls-install-scripts) for quick provisioning of the Calls Offloader service on Ubuntu/Debian systems. + +</Tip> + +1. Download the latest release from the [calls-offloader GitHub repository](https://github.com/mattermost/calls-offloader/releases) + +2. Create the necessary directories: + + ```bash + sudo mkdir -p /opt/calls-offloader/data/db + sudo useradd --system --home /opt/calls-offloader calls-offloader + sudo chown -R calls-offloader:calls-offloader /opt/calls-offloader + ``` + +3. Create a configuration file (`/opt/calls-offloader/config.toml`): + + ```toml + [api] + http.listen_address = ":4545" + http.tls.enable = false + http.tls.cert_file = "" + http.tls.cert_key = "" + security.allow_self_registration = true + security.enable_admin = false + security.admin_secret_key = "" + security.session_cache.expiration_minutes = 1440 + + [store] + data_source = "/opt/calls-offloader/data/db" + + [jobs] + api_type = "docker" + max_concurrent_jobs = 100 + failed_jobs_retention_time = "30d" + image_registry = "mattermost" + + [logger] + enable_console = true + console_json = false + console_level = "INFO" + enable_file = true + file_json = true + file_level = "DEBUG" + file_location = "/opt/calls-offloader/calls-offloader.log" + enable_color = true + ``` + +4. Create a systemd service file (`/etc/systemd/system/calls-offloader.service`): + + ```ini + [Unit] + Description=Mattermost Calls Offloader Service + After=network.target docker.service + Requires=docker.service + + [Service] + Type=simple + User=calls-offloader + WorkingDirectory=/opt/calls-offloader + ExecStart=/opt/calls-offloader/calls-offloader --config /opt/calls-offloader/config.toml + Restart=always + RestartSec=10 + LimitNOFILE=65536 + + [Install] + WantedBy=multi-user.target + ``` + +5. Enable and start the service: + + ```bash + sudo systemctl daemon-reload + sudo systemctl enable calls-offloader + sudo systemctl start calls-offloader + ``` + +6. Check the service status: + + ```bash + sudo systemctl status calls-offloader + ``` + +7. Verify the service is responding: + + ```bash + curl http://localhost:4545/version + # Example output: + # {"buildDate":"2025-03-10 19:13","buildVersion":"v0.9.2","buildHash":"a4bd418","goVersion":"go1.23.6"} + ``` + +## Configuration + +### API Configuration + +The API section controls how the service accepts requests: + +- **http.listen_address**: The address and port where the service listens (default: `:4545`) +- **http.tls.enable**: Whether to use TLS encryption for the API +- **security.allow_self_registration**: Allow clients to self-register for job management +- **security.enable_admin**: Enable admin functionality +- **security.admin_secret_key**: Secret key for admin authentication (change from default!) + +### Store Configuration + +Controls persistent data storage: + +- **data_source**: Path to directory for storing client (i.e., connecting Mattermost nodes) IDs and credentials + +### Jobs Configuration + +Controls job processing behavior: + +- **api_type**: Job execution backend (`docker` or `kubernetes`) +- **max_concurrent_jobs**: Maximum number of simultaneous recording/transcription jobs +- **failed_jobs_retention_time**: How long to keep failed job data before cleanup +- **image_registry**: Docker registry for job runner images (typically `mattermost`) + +### Logger Configuration + +Controls logging output: + +- **enable_console**: Log to console output +- **console_json**: Use JSON format for console logs +- **console_level**: Log level for console (DEBUG, INFO, WARN, ERROR) +- **enable_file**: Log to file +- **file_location**: Path to log file +- **enable_color**: Use colored output for console logs + +### Private Network Configuration + +When the Mattermost deployment is running in a private network, additional configuration may be necessary for the jobs spawned by the calls-offloader service to reach the Mattermost server. + +In such cases, you can override the site URL used by recorder jobs or transcriber jobs to connect to Mattermost by setting the following environment variables on the Mattermost server: + +- **MM_CALLS_RECORDER_SITE_URL**: Override the site URL used by recording jobs +- **MM_CALLS_TRANSCRIBER_SITE_URL**: Override the site URL used by transcription jobs + +<Note> + +When these Site URL overrides are used, the `ServiceSettings.AllowCorsFrom` setting on your Mattermost server may need to be adjusted accordingly to ensure CORS does not block requests. + +This override configuration lets the recorder and transcriber jobs connect to mattermost server using HTTP instead of HTTPS, which should only be used in a private network. + +</Note> + +Example configuration: + +Create or edit the Mattermost environment file (`/opt/mattermost/config/mattermost.environment`): + +```bash +MM_CALLS_RECORDER_SITE_URL="http://internal-mattermost-server:8065" +MM_CALLS_TRANSCRIBER_SITE_URL="http://internal-mattermost-server:8065" +``` + +Then ensure your Mattermost systemd service references this environment file: + +```ini +[Unit] +Description=Mattermost +After=network.target + +[Service] +Type=notify +EnvironmentFile=/opt/mattermost/config/mattermost.environment +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost + +[Install] +WantedBy=multi-user.target +``` + +This is particularly useful when: + +- The calls-offloader service runs in a different network segment than clients +- Internal DNS resolution differs from external URLs +- You need to use internal load balancer endpoints for job communication + +## Validation and Testing + +After deploying calls-offloader, validate the installation: + +1. **Check service status**: + + ```bash + # For systemd + sudo systemctl status calls-offloader + ``` + +2. **Test API connectivity**: + + **From the calls-offloader server (localhost test)**: + + ```bash + curl http://localhost:4545/version + # Should return version information + # Example: {"buildDate":"2025-03-10 19:13","buildVersion":"v0.9.2","buildHash":"a4bd418","goVersion":"go1.23.6"} + ``` + + **From the Mattermost server**: + + ```bash + curl http://YOUR_CALLS_OFFLOADER_SERVER:4545/version + # Should return the same version information + # This confirms network connectivity from Mattermost to calls-offloader + ``` + + If the localhost test works but the Mattermost server test fails, check: + + - Firewall rules or SELinux policies on the calls-offloader server (port 4545 must be accessible) + - Network connectivity between Mattermost and calls-offloader servers + +3. **Verify Docker service** (if using docker api_type): + + ```bash + # Check that system user running calls-offloader can access Docker + sudo -u calls-offloader docker ps + ``` + +## Integration with Mattermost + +Once calls-offloader is properly set up and validated, configure Mattermost to use it: + +1. Go to **System Console > Plugins > Calls** + +2. In the **Job Service** section: + + - Set **Job Service URL** to your calls-offloader service (e.g., `http://calls-offloader-server:4545`) + +3. Enable recording and transcription features as needed: + + - **Enable Call Recordings**: Toggle to allow call recordings + - **Enable Call Transcriptions**: Toggle to allow call transcriptions + - **Enable Live Captions** (Experimental): Toggle to allow real-time transcription + +4. Save the configuration + +5. Restart the Calls plugin to re-establish state: + + - Go to **System Console > Plugins > Plugin Management** + - Find the **Calls** plugin and click **Disable** + - Wait a few seconds, then click **Enable** + +6. Test by starting a call and starting a recording + +## Troubleshooting + +### Common Issues + +**"failed to create recording job: max concurrent jobs reached"** + +This error occurs when the calls-offloader service has reached its configured job limit, and it will usually result in a failure message on the Mattermost Calls plugin side (such as a timeout). + +Solutions: + +- Increase `max_concurrent_jobs` in the configuration +- Check if jobs are hanging and restart the service +- Monitor system resources and scale up if needed + +**Jobs not processing** + +Check the following: + +- Verify the calls-offloader service is running: `sudo systemctl status calls-offloader` +- Ensure network connectivity between Mattermost and calls-offloader +- Check Docker daemon is running and accessible by the user running the Calls Offloader service (E.g., user: ``calls-offloader``) +- Verify authentication configuration matches between services +- Review service logs for specific error messages + +**Docker permission issues** + +If using Docker API and seeing permission errors: + +```bash +# Add calls-offloader user to docker group +sudo usermod -a -G docker calls-offloader +sudo systemctl restart calls-offloader +``` + +### Debugging Commands + +Monitor calls-offloader job containers: + +```bash +# View running job containers +docker ps --format "{{.ID}} {{.Image}}" | grep "calls" + +# Follow logs for debugging +docker ps --format "{{.ID}} {{.Image}}" | grep "calls" | awk '{print $1}' | xargs -I {} docker logs -f {} + +# View completed job containers +docker ps -a --filter "status=exited" +``` + +Monitor service health: + +```bash +# Check service version and health +curl http://localhost:4545/version +``` + +Check service logs: + +```bash +# View recent logs +sudo journalctl -u calls-offloader -f + +# View log file (if file logging enabled) +tail -f /opt/calls-offloader/calls-offloader.log +``` + +### Performance Monitoring + +Monitor calls-offloader performance and resource usage to ensure optimal operation. See [Calls Metrics and Monitoring](calls-metrics-monitoring.md) for details on setting up metrics and observability. + +## Air-Gapped Installation of `calls-offloader` + +This guide covers deploying `calls-offloader` in an environment without internet access. The process uses scripts from the [calls-install-scripts](https://github.com/bgardner8008/calls-install-scripts) repository and follows a two-phase workflow: preparing a transfer bundle on an internet-connected machine, then deploying it on the isolated target machine. + +### Overview + +Because `calls-offloader` relies on Docker images for the recorder and transcriber jobs, an air-gapped deployment requires that those images be pre-pulled and packaged alongside the `calls-offloader` binary before being transferred to the target environment. + +The install scripts handle this in two stages: + +1. **Prepare** (internet-connected machine) — `setup-airgap-offloader.sh` pulls the required Docker images and downloads the `calls-offloader` binary, then packages everything into a transfer bundle and generates a ready-to-run deployment script. +2. **Deploy** (air-gapped machine) — Transfer the bundle and run the generated `deploy-airgap-offloader.sh` script, which loads the Docker images into a local registry and installs the service. + +### Prerequisites + +- An internet-connected Linux machine with Docker installed (for the preparation phase) +- A target air-gapped Linux machine with: + - systemd + - Docker installed + - Root or sudo access +- The [calls-install-scripts](https://github.com/bgardner8008/calls-install-scripts) repository cloned on the internet-connected machine + +### Phase 1: Prepare the Transfer Bundle + +On the **internet-connected machine**, run `setup-airgap-offloader.sh` specifying the versions of each component to package: + +```bash +./setup-airgap-offloader.sh \ + --offloader v0.9.5 \ + --recorder v0.9.0 \ + --transcriber v0.3.0 \ + --arch amd64 +``` + +| Flag | Description | Default | +|------|-------------|---------| +| `--offloader VERSION` | `calls-offloader` binary version (e.g. `v0.9.5`) | required | +| `--recorder VERSION` | `calls-recorder` Docker image version | required | +| `--transcriber VERSION` | `calls-transcriber` Docker image version | required | +| `--arch amd64\|arm64` | Target CPU architecture | `amd64` | + +The script will: + +1. Pull the `calls-recorder` and `calls-transcriber` Docker images from Docker Hub +2. Download the `calls-offloader` binary from GitHub releases +3. Save the Docker images as `.tar` archives +4. Generate a `deploy-airgap-offloader.sh` deployment script configured for the selected versions +5. Produce a transfer bundle containing all of the above + +### Phase 2: Transfer to the Air-Gapped Machine + +Copy the generated bundle to the target machine using whatever transfer mechanism is available in your environment (USB drive, secure file transfer, etc.): + +```bash +scp calls-offloader-airgap-bundle.tar.gz user@airgap-host:/tmp/ +``` + +On the air-gapped machine, extract the bundle: + +```bash +tar -xzf calls-offloader-airgap-bundle.tar.gz +cd calls-offloader-airgap-bundle/ +``` + +### Phase 3: Deploy on the Air-Gapped Machine + +Run the generated deployment script with root or sudo privileges: + +```bash +sudo ./deploy-airgap-offloader.sh +``` + +This script will: + +1. Configure the local Docker daemon to use a local image registry +2. Load the packaged Docker images into that registry +3. Install the `calls-offloader` binary to `/usr/local/bin/` +4. Create the `mattermost` system user and add it to the `docker` group +5. Generate and enable a systemd service unit +6. Start the service and verify it is running + +Once complete, verify the service is up: + +```bash +curl http://localhost:4545/version +``` + +### Connecting to Mattermost + +Configure the Mattermost Calls plugin to use the offloader service via **System Console > Plugins > Calls > Job service URL**, setting it to `http://<offloader-host>:4545`. + +> [!NOTE] +> The first time Mattermost connects to the offloader it will self-register and store its authentication key in the database, provided `API_SECURITY_ALLOWSELFREGISTRATION=true` is set (the default in the deployment script). + +### Private Network Considerations + +In air-gapped environments the recorder and transcriber containers typically need to reach the Mattermost server via an internal URL. Set the following environment variables on the **Mattermost server** to override the site URL used by spawned jobs: + +``` +MM_CALLS_RECORDER_SITE_URL=http://internal-mattermost-server:8065 +MM_CALLS_TRANSCRIBER_SITE_URL=http://internal-mattermost-server:8065 +``` + +You may also need to add the internal URL to [`ServiceSettings.AllowCorsFrom`](https://docs.mattermost.com/configure/integrations-configuration-settings.html#enable-cross-origin-requests-from) in the Mattermost server configuration. + +> [!NOTE] +> In particularly restrictive environments (e.g., VMs with strict network isolation), set `DOCKER_NETWORK=host` in the `calls-offloader` service environment so that job containers can reach the Mattermost server via its local address. + +### Custom Docker Registry + +If your air-gapped environment already has an internal Docker registry, you can point `install-offloader.sh` at it directly instead of using the local registry set up by the deployment script: + +```bash +sudo ./install-offloader.sh \ + --binary ./calls-offloader-linux-amd64 \ + --image-registry registry.internal.example.com/mattermost \ + --arch amd64 +``` + +The `--image-registry` flag sets the registry prefix used when the offloader pulls recorder and transcriber images for each job. + +## Other Calls Documentation + +- [Calls Deployment Guide](calls-deployment-guide.md): Overview of deployment options and architecture +- [RTCD Setup and Configuration](calls-rtcd-setup.md): Comprehensive guide for setting up the dedicated RTCD service +- [Calls Metrics and Monitoring](calls-metrics-monitoring.md): Guide to monitoring Calls performance using metrics and observability +- [Calls Deployment on Kubernetes](calls-kubernetes.md): Detailed guide for deploying Calls in Kubernetes environments +- [Calls Logging](calls-logging.md): Detailed guidance for collecting Calls logs and client diagnostics +- [calls-offloader performance documentation](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md): Detailed performance tuning and monitoring recommendations diff --git a/docs/main/administration-guide/configure/calls-rtcd-setup.mdx b/docs/main/administration-guide/configure/calls-rtcd-setup.mdx new file mode 100644 index 000000000000..3dfe0a9639df --- /dev/null +++ b/docs/main/administration-guide/configure/calls-rtcd-setup.mdx @@ -0,0 +1,393 @@ +--- +title: "RTCD Setup and Configuration" +draft: true +--- +<PlanAvailability slug="ent-plus" /> + +This guide provides detailed instructions for setting up, configuring, and validating a Mattermost Calls deployment using the dedicated RTCD service. + +## Prerequisites + +Before deploying RTCD, ensure you have: + +- A Mattermost Enterprise license +- A server or VM with sufficient CPU and network capacity (see the [Performance baselines](calls-metrics-monitoring.md#performance-baselines) section for sizing guidance) + +## Network Requirements + +The following network connectivity is required: + +<style> + table.network-requirements { + border-collapse: collapse; + width: 100%; + font-size: 0.95em; + } + table.network-requirements th, table.network-requirements td { + border: 1px solid #888; + padding: 6px 8px; + vertical-align: top; + } + /* Dark mode border color */ + body:not([data-custom-theme="light"]) table.network-requirements th, + body:not([data-custom-theme="light"]) table.network-requirements td { + border-color: #666; + } + table.network-requirements th { + background: #f2f2f2; + font-weight: bold; + text-align: left; + } + /* Dark mode support for table headers */ + body:not([data-custom-theme="light"]) table.network-requirements th { + background: #444; + color: #fff; + } +</style> + +<table class="network-requirements"> +<thead> +<tr> +<th>Service</th> +<th>Ports</th> +<th>Protocols</th> +<th>Source</th> +<th>Target</th> +<th>Purpose</th> +</tr> +</thead> +<tbody> +<tr> +<td>API (Calls plugin)</td> +<td>80,443</td> +<td>TCP (incoming)</td> +<td>Mattermost clients (web/desktop/mobile)</td> +<td>Mattermost instance (Calls plugin)</td> +<td>To allow for HTTP and WebSocket connectivity from clients to Calls plugin. This API is exposed on the same connection as Mattermost, so there's likely no need to change anything.</td> +</tr> +<tr> +<td>RTC (Calls plugin or <code>rtcd</code>)</td> +<td>8443</td> +<td>UDP (incoming)</td> +<td>Mattermost clients (Web/Desktop/Mobile) and calls-offloader</td> +<td>Mattermost instance or <code>rtcd</code> service</td> +<td>To allow clients to establish connections that transport calls related media (e.g. audio, video). This should be open on any network component (e.g. NAT, firewalls) in between the instance running the plugin (or <code>rtcd</code>) and the clients joining calls so that UDP traffic is correctly routed both ways (from/to clients).</td> +</tr> +<tr> +<td>RTC (Calls plugin or <code>rtcd</code>)</td> +<td>8443</td> +<td>TCP (incoming)</td> +<td>Mattermost clients (Web/Desktop/Mobile) and calls-offloader</td> +<td>Mattermost instance or <code>rtcd</code> service</td> +<td>To allow clients to establish connections that transport calls related media (e.g. audio, video). This should be open on any network component (e.g. NAT, firewalls) in between the instance running the plugin (or <code>rtcd</code>) and the clients joining calls so that TCP traffic is correctly routed both ways (from/to clients). This can be used as a backup channel in case clients are unable to connect using UDP. It requires <code>rtcd</code> version >= v0.11 and Calls version >= v0.17.</td> +</tr> +<tr> +<td>API (<code>rtcd</code>)</td> +<td>8045</td> +<td>TCP (incoming)</td> +<td>Mattermost instance(s) (Calls plugin)</td> +<td><code>rtcd</code> service</td> +<td>To allow for HTTP/WebSocket connectivity from Calls plugin to <code>rtcd</code> service. Can be exposed internally as the service only needs to be reachable by the instance(s) running the Mattermost server.</td> +</tr> +<tr> +<td>STUN (Calls plugin or <code>rtcd</code>)</td> +<td>3478</td> +<td>UDP (outgoing)</td> +<td>Mattermost Instance(s) (Calls plugin) or <code>rtcd</code> service</td> +<td>Configured STUN servers</td> +<td>(Optional) To allow for either Calls plugin or <code>rtcd</code> service to discover their instance public IP. Only needed if configuring STUN/TURN servers. This requirement does not apply when manually setting an IP or hostname through the <a href="https://docs.mattermost.com/configure/plugins-configuration-settings.html#ice-host-override">ICE Host Override</a> config option.</td> +</tr> +</tbody> +</table> + +## Installation and Deployment + +There are multiple ways to deploy RTCD, depending on your environment. We recommend the following order based on production readiness and operational control: + +### Bare Metal or VM Deployment (Recommended) + +This is the recommended deployment method for non-Kubernetes production environments, as it provides the best performance and operational control. For Kubernetes deployments, see the [Calls Deployment on Kubernetes](calls-kubernetes.md) guide. + +<Tip> + +Looking for an automated setup? Check out these community-maintained [Calls Installation Scripts](https://github.com/bgardner8008/calls-install-scripts) for quick provisioning of the RTCD service on Ubuntu/Debian systems. + +</Tip> + +1. **Download and install the RTCD binary**: + + Download the latest release from the [RTCD GitHub repository](https://github.com/mattermost/rtcd/releases): + + ```bash + # Create the RTCD directory structure + sudo mkdir -p /opt/rtcd + + # Download the latest RTCD binary (adjust URL for your architecture) + # For Linux x86_64: + wget https://github.com/mattermost/rtcd/releases/latest/download/rtcd-linux-amd64 + + # Make the binary executable and move it to the installation directory + chmod +x rtcd-linux-amd64 + sudo mv rtcd-linux-amd64 /opt/rtcd/rtcd + ``` + + ```{note} + Replace `rtcd-linux-amd64` with the appropriate binary for your system architecture (e.g., `rtcd-linux-arm64` for ARM64 systems). The binary should be placed at `/opt/rtcd/rtcd` as this is the expected location referenced in systemd service files and other documentation. + ``` + +2. **Create a configuration file** (`/opt/rtcd/rtcd.toml`): + + Mattermost recommends using the official [config.sample.toml](https://github.com/mattermost/rtcd/blob/master/config/config.sample.toml) as a starting point. Download this file and use it as your base configuration. + +3. Create a dedicated user for the RTCD service: + + ```bash + sudo useradd --system --no-create-home --shell /bin/false mattermost + ``` + +4. Create the data directory and set ownership: + + ```bash + sudo mkdir -p /opt/rtcd/data/db + sudo chown -R mattermost:mattermost /opt/rtcd + ``` + +5. Create a systemd service file (`/etc/systemd/system/rtcd.service`): + + ```ini + [Unit] + Description=Mattermost RTCD Server + After=network.target + + [Service] + Type=simple + User=mattermost + Group=mattermost + ExecStart=/opt/rtcd/rtcd --config /opt/rtcd/rtcd.toml + Restart=always + RestartSec=10 + LimitNOFILE=65536 + + [Install] + WantedBy=multi-user.target + ``` + +6. Enable and start the service: + + ```bash + sudo systemctl daemon-reload + sudo systemctl enable rtcd + sudo systemctl start rtcd + ``` + +7. Check the service status: + + ```bash + sudo systemctl status rtcd + ``` + +### Docker Deployment + +Docker deployment is suitable for development, testing, or containerized production environments: + +1. Run the RTCD container with basic configuration: + + ```bash + docker run -d --name rtcd \ + -e "RTCD_LOGGER_ENABLEFILE=true" \ + -p 8443:8443/udp \ + -p 8443:8443/tcp \ + -p 8045:8045/tcp \ + mattermost/rtcd:latest + ``` + + ```{note} + If you optionally use the `RTCD_API_SECURITY_ALLOWSELFREGISTRATION` setting, please note that it defaults to `false`. If enabled, it allows anyone who can connect to the service on the API port (8045) to successfully initiate calls. Understand the security implications of this setting before enabling it. + ``` + +2. For debugging purposes, you can enable more detailed logging: + + ```bash + docker run -d --name rtcd \ + -e "RTCD_LOGGER_ENABLEFILE=true" \ + -e "RTCD_LOGGER_CONSOLELEVEL=DEBUG" \ + -p 8443:8443/udp \ + -p 8443:8443/tcp \ + -p 8045:8045/tcp \ + mattermost/rtcd:latest + ``` + + To view the logs: + + ```bash + docker logs -f rtcd + ``` + +You can also use a mounted configuration file instead of environment variables: + +```bash +docker run -d --name rtcd \ + -p 8045:8045 \ + -p 8443:8443/udp \ + -p 8443:8443/tcp \ + -v /path/to/config.toml:/rtcd/config/config.toml \ + mattermost/rtcd:latest +``` + +For a complete sample configuration file, see the [RTCD config.sample.toml](https://github.com/mattermost/rtcd/blob/master/config/config.sample.toml) in the official repository. + +### Kubernetes Deployment + +For detailed information on deploying RTCD in Kubernetes environments, including Helm chart configurations, resource requirements, and scaling considerations, see the [Calls Deployment on Kubernetes](calls-kubernetes.md) guide. + +## Configuration + +### RTCD Configuration File + +The RTCD service uses a TOML configuration file. Mattermost recommends using the official [config.sample.toml](https://github.com/mattermost/rtcd/blob/master/config/config.sample.toml) as your base configuration file. + +<Note> + +A notable setting to be aware of is `ice_host_override` under the `[rtc]` section. You may need to configure this setting explicitly, particularly when RTCD is deployed behind NAT, in complex network topologies, or when automatic address discovery via STUN is unreliable. Setting `ice_host_override` directly to your server's public IP address or hostname is the preferred approach. + +</Note> + +### TURN Configuration + +For clients behind strict firewalls, you may need to configure TURN servers. In the RTCD configuration file, reference your TURN servers as follows: + +```toml +[rtc] +# TURN server configuration + ice_servers = [ + { urls = ["turn:turn.example.com:3478"], username = "turnuser", credential = "turnpassword" } + ] + +``` + +We recommend using [coturn](https://github.com/coturn/coturn) for your TURN server implementation. + +### System Tuning + +For high-volume deployments, tune your Linux system: + +1. Add the following to `/etc/sysctl.conf`: + + ```bash + # Increase UDP buffer sizes + net.core.rmem_max = 16777216 + net.core.wmem_max = 16777216 + net.core.optmem_max = 16777216 + ``` + +2. Apply the settings: + + ```bash + sudo sysctl -p + ``` + +## Validation and Testing + +After deploying RTCD, validate the installation: + +1. **Check service status and version**: + + ```bash + curl http://YOUR_RTCD_SERVER:8045/version + # Should return a JSON object with service information + # Example: {"build_hash":"abc123","build_date":"2023-01-15T12:00:00Z","build_version":"0.11.0","goVersion":"go1.20.4"} + ``` + +2. **Test UDP connectivity**: + + Before testing, ensure the RTCD service is stopped, as it binds to the same port. + + ```bash + sudo systemctl stop rtcd + ``` + + On the RTCD server: + + ```bash + sudo ncat -u -l -k -p 8443 -c '/bin/cat' + ``` + + On a client machine: + + ```bash + sudo nmap -sU -p 8443 RTCD_SERVER_IP + ``` + + If UDP connectivity is working, `nmap` reports as `open`. + + Restart RTCD after the test: + + ```bash + sudo systemctl start rtcd + ``` + +3. **Test TCP connectivity** (if enabled): + + Run this check from a client machine: + + ```bash + nmap -p 8443 RTCD_SERVER_IP + ``` + + If TCP fallback is enabled and reachable, `nmap` reports as `open`. + +4. **Monitor metrics**: + + Refer to [Calls Metrics and Monitoring](calls-metrics-monitoring.md) for setting up Calls metrics and monitoring. + +## Horizontal Scaling + +To scale RTCD horizontally: + +1. **Deploy multiple RTCD instances**: + + Deploy multiple RTCD servers, each with their own unique IP address. + +2. **Configure DNS record**: + + Set up a DNS record that points to multiple RTCD IP addresses: + + ```bash + rtcd.example.com. IN A 10.0.0.1 + rtcd.example.com. IN A 10.0.0.2 + rtcd.example.com. IN A 10.0.0.3 + ``` + +3. **Configure health checks**: + + Set up health checks to automatically remove unhealthy RTCD instances from DNS. + +4. **Configure Mattermost**: + + In the Mattermost System Console, set the **RTCD Service URL** to your DNS name (e.g., `rtcd.example.com`). + +When a call starts, the Mattermost server examines the available RTCD servers (via the configured DNS record) and starts the call on the RTCD server with the lowest CPU usage. All participants in the call will connect to that RTCD server; a single call cannot be shared across multiple servers. + +## Integration with Mattermost + +Once RTCD is properly set up and validated, configure Mattermost to use it: + +1. Go to **System Console > Plugins > Calls** + +2. Set the **RTCD Service URL** to your RTCD service address (either a single server or DNS load-balanced hostname). Ensure you provide any generated credentials formulated in the URI (e.g., `http://clientID:authKey@rtcd.local`). + +3. Save the configuration + +4. Test by creating a new call in any Mattermost channel + +5. Verify that the call is being routed through RTCD by checking the RTCD logs and metrics + +## Other Calls Documentation + +- [Calls Deployment Guide](calls-deployment-guide.md): Overview of deployment options and architecture +- [Calls Offloader Setup and Configuration](calls-offloader-setup.md): Setup guide for call recording and transcription +- [Calls Metrics and Monitoring](calls-metrics-monitoring.md): Guide to monitoring Calls performance using metrics and observability +- [Calls Deployment on Kubernetes](calls-kubernetes.md): Detailed guide for deploying Calls in Kubernetes environments +- [Calls Logging](calls-logging.md): Detailed guidance for collecting Calls logs and client diagnostics + +For detailed Mattermost Calls configuration options, see the [Calls Plugin Configuration Settings](plugins-configuration-settings.rst#calls) documentation. diff --git a/docs/main/administration-guide/configure/cloud-billing-account-settings.mdx b/docs/main/administration-guide/configure/cloud-billing-account-settings.mdx new file mode 100644 index 000000000000..03f48ccf788c --- /dev/null +++ b/docs/main/administration-guide/configure/cloud-billing-account-settings.mdx @@ -0,0 +1,9 @@ +--- +title: "Cloud workspace subscription, billing, and account settings" +--- +Review and manage the following aspects of your Mattermost cloud-based deployment by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Billing and Account**: + +- Access billing history +- Manage the [product subscription](/product-overview/cloud-subscriptions) and account details for your Mattermost Cloud deployment. +- Review trial details. +- Talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) for assistance. diff --git a/docs/main/administration-guide/configure/compliance-configuration-settings.mdx b/docs/main/administration-guide/configure/compliance-configuration-settings.mdx new file mode 100644 index 000000000000..4cb403ed1c70 --- /dev/null +++ b/docs/main/administration-guide/configure/compliance-configuration-settings.mdx @@ -0,0 +1,533 @@ +--- +title: "Compliance configuration settings" +draft: true +--- +<PlanAvailability slug="ent-plus" /> + +Review and manage the following compliance configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Compliance**: + +- [Data Retention Policies](#data-retention-policies) +- [Compliance Export](#administration-guide/comply/compliance-export) +- [Compliance Monitoring](#compliance-monitoring) +- [Custom Terms of Service](#custom-terms-of-service) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `MessageRetentionHours` value is under `DataRetentionSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.DataRetentionSettings.MessageRetentionHours'` +- When working with the `config.json` file manually, look for an object such as `DataRetentionSettings`, then within that object, find the key `MessageRetentionHours`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Data retention policies + +Changes to properties in this section require a server restart before taking effect. + +<Warning> + +- Once a message or a file is deleted, the action is irreversible. Please be careful when setting up a custom data retention policy. +- From Mattermost v9.5, data retention removes Elasticsearch indexes based on the day of the retention cut-off time. + +</Warning> + +Access the following configuration settings in the System Console by going to **Compliance \> Data Retention Policies**. + +### Global retention policy for messages + +Set how long Mattermost keeps messages across all teams and channels. This value is not used for any teams and channels that have a custom retention policy applied . Requires the [global retention policy for messages](/administration-guide/configure/compliance-configuration-settings#global-retention-policy-for-messages) configuration setting to be set to `true`. + +By default, messages are kept forever. If **Hours**, **Days**, or **Years** is chosen, set how many hours, days, or years messages are kept in Mattermost. Messages older than the duration you set will be deleted nightly. The minimum message retention time is one hour. + +The global retention time for messages can be superseded on a team or channel level by creating custom policies with unique post retention times See the [Custom retention policy](#custom-retention-policy) section below for details. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"MessageRetentionHours": 1</code> with numerical input.</td> +</tr> +</tbody> +</table> + +<Note> + +From Mattermost v9.5, `MessageRetentionDays` has been deprecated in favor of `MessageRetentionHours`. See [deprecated configuration settings](/administration-guide/configure/deprecated-configuration-settings) for details. + +</Note> + +### Global retention policy for files + +Set how long Mattermost keeps files across all teams and channels. Custom policies on team and channel level don't apply to file attachments. The global retention time for files will be used even if a custom policy for messages is in place. Requires the [global retention policy for files](/administration-guide/configure/compliance-configuration-settings#global-retention-policy-for-files) configuration setting to be set to `true`. + +By default, files are kept forever. If **Hours**, **Days**, or **Years** is chosen, set how many hours, days, or years files are kept in Mattermost. Files older than the duration you set will be deleted nightly. The minimum file retention time is one hour. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"FileRetentionHours": 1</code> with numerical input.</td> +</tr> +</tbody> +</table> + +<Note> + +From Mattermost v9.5, `FileRetentionDays` has been deprecated in favor of `FileRetentionHours`. See [deprecated configuration settings](/administration-guide/configure/deprecated-configuration-settings) for details. + +</Note> + +### Preserve pinned posts + +From Mattermost v10.10, controls whether pinned posts are preserved when data retention policies delete messages. When enabled, pinned posts won't be deleted by data retention policies, even if they exceed the configured retention period. + +**True**: Pinned posts are preserved and won't be deleted by data retention policies. + +**False**: **(Default)** Pinned posts are deleted according to the configured data retention policy. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DataRetentionSettings.PreservePinnedPosts": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +- This global configuration setting must be enabled with mmctl using the [mmctl config set](/administration-guide/manage/mmctl-command-line-tool#mmctl-config-set) command. +- This configuration setting applies to team and channel policies as well as data retention, and can't be overridden in those more granular team or channel policies. +- Files attached to the pinned message aren't preserved. +- Only the pinned post is preserved. If it's attached to a thread or if it's the root post of a thread, the other threaded messages aren't preserved. + +</Note> + +### Custom retention policy + +Set how long Mattermost keeps messages across specific teams and channels by specifying a name for the custom retention policy, setting a duration value in days or years, and specifying the teams and channels that will follow this policy. The attachment retention time cannot be set on custom policy levels and the global retention time for attachments is always applied. + +### Data deletion time + +Set the start time of the daily scheduled data retention job. Choose a time when fewer people are using your system. Must be a 24-hour time stamp in the form `HH:MM`. + +This setting is based on the local time of the server. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DeletionJobStartTime": "02:00"</code> with 24-hour timestamp input in the form <code>"HH:MM"</code>.</td> +</tr> +</tbody> +</table> + +### Run deletion job now + +Start a Data Retention deletion job immediately. You can monitor the status of the job in the data deletion job table within the Policy Log section. + +### Time between batches + +The time in milliseconds between batches processed during data retention job execution. This setting helps control the rate at which data is deleted to reduce database load during retention operations. + +Default is 100 milliseconds. Possible values are any non-negative integer (≥ 0). + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"TimeBetweenBatchesMilliseconds": 100</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Retention IDs batch size + +The number of retention IDs to process in a single batch during data retention job execution. This setting controls how many items are processed together for optimal performance. + +Default is 100. Possible values are any non-negative integer (≥ 0). + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RetentionIdsBatchSize": 100</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Boards retention days + +Set how long Mattermost keeps boards data. When set to a value greater than 0, boards data older than the specified number of days will be deleted during retention job execution only when boards deletion is enabled via `EnableBoardsDeletion`. + +Default is 365 days. Possible values are any non-negative integer (≥ 0). + +<table style={{width: '85%'}}> +<colgroup> +<col style={{width: '85%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BoardsRetentionDays": 365</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Enable message deletion + +**True**: Message deletion is enabled during data retention job execution. + +**False**: Messages are not deleted during data retention job execution. + +<table style={{width: '97%'}}> +<colgroup> +<col style={{width: '96%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableMessageDeletion": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +When `EnableMessageDeletion` is set to `false`, messages will not be deleted regardless of other retention policy settings. + +</Note> + +### Enable file deletion + +**True**: File deletion is enabled during data retention job execution. + +**False**: Files are not deleted during data retention job execution. + +<table style={{width: '94%'}}> +<colgroup> +<col style={{width: '94%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableFileDeletion": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +When `EnableFileDeletion` is set to `false`, files will not be deleted regardless of other retention policy settings. + +</Note> + +### Enable boards deletion + +**True**: Boards deletion is enabled during data retention job execution. + +**False**: Boards data is not deleted during data retention job execution. + +<table style={{width: '96%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableBoardsDeletion": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +When `EnableBoardsDeletion` is set to `false`, boards data will not be deleted regardless of other retention policy settings. + +</Note> + +### Batch size + +The number of records to process in a single batch during data retention job execution. This setting controls how many records are processed together for optimal performance. + +Default is 3000. Possible values are any non-negative integer (≥ 0). + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '81%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BatchSize": 3000</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Compliance export + +Access the following configuration settings in the System Console by going to **Compliance \> Compliance Export**. + +### Enable compliance export + +**True**: Mattermost will generate a compliance export file that contains all messages that were posted in the last 24 hours. The export task is scheduled to run once per day. See the [documentation to learn more](/administration-guide/comply/compliance-export). + +**False**: Mattermost doesn't generate a compliance export file. + +<table style={{width: '89%'}}> +<colgroup> +<col style={{width: '89%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableExport": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Compliance export time + +Set the start time of the daily scheduled compliance export job. Choose a time when fewer people are using your system. Must be a 24-hour time stamp in the form `HH:MM`. + +This setting is based on the local time of the server. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DailyRunTime": 01:00</code> with 24-hour timestamp input in the form <code>"HH:MM"</code>.</td> +</tr> +</tbody> +</table> + +### Export file format + +File format of the compliance export. Corresponds to the system that you want to import the data into. + +Currently supported formats are CSV, Actiance XML, and Global Relay EML. + +If Global Relay is chosen, the following options will be presented: + +### Global Relay customer account + +Type of Global Relay customer account your organization has. Can be one of: `A9/Type 9`, `A10/Type 10`, or `Custom`. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"CustomerType": "A9"</code> with options <code>"A9</code>, <code>"A10"</code>, and <code>CUSTOM</code>.</td> +</tr> +</tbody> +</table> + +### Global Relay SMTP username + +The username for authenticating to the Global Relay SMTP server. + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '71%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"SmtpUsername": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Global Relay SMTP password + +The password associated with the Global Relay SMTP username. + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '71%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"SmtpPassword": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Global Relay email address + +The email address your Global Relay server monitors for incoming compliance exports. + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '71%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EmailAddress": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### SMTP server name + +The SMTP server name URL that will receive your Global Relay EML file when a [custom customer account type](#global-relay-customer-account) is configured. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".MessageExportSettings.GlobalRelaySettings.CustomSMTPServerName": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### SMTP server port + +The SMTP server port that will receive your Global Relay EML file when a [custom customer account type](#global-relay-customer-account) is configured. Default is `"25"`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".MessageExportSettings.GlobalRelaySettings.CustomSMTPPort": "25"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Message export batch size + +This setting isn't available in the System Console and can only be set in `config.json`. + +Determines how many new posts are batched together to a compliance export file. + +<table style={{width: '78%'}}> +<colgroup> +<col style={{width: '78%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BatchSize": 10000</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Run compliance export job now + +This button initiates a compliance export job immediately. You can monitor the status of the job in the compliance export job table. + +------------------------------------------------------------------------------------------------------------------------ + +## Compliance monitoring + +Settings used to enable and configure Mattermost compliance reports. + +Access the following configuration settings in the System Console by going to **Compliance \> Compliance Monitoring**. + +### Enable compliance reporting + +**True**: Compliance reporting is enabled in Mattermost. + +**False**: Compliance reporting is disabled. + +<table style={{width: '84%'}}> +<colgroup> +<col style={{width: '84%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Enable": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Compliance report directory + +Sets the directory where compliance reports are written. + +<table style={{width: '75%'}}> +<colgroup> +<col style={{width: '75%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Directory": "./data/"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Enable daily report + +**True**: Mattermost generates a daily compliance report. + +**False**: Daily reports are not generated. + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '88%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableDaily": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Batch size + +Set the size of the batches in which posts will be read from the database to generate the compliance report. This setting is currently not available in the System Console and can only be set in `config.json`. + +<table style={{width: '81%'}}> +<colgroup> +<col style={{width: '80%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BatchSize": 30000</code> with default value <code>30000</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Custom terms of service + +Access the following configuration settings in the System Console by going to **Compliance \> Custom Terms of Service**. + +### Enable custom terms of service + +<Note> + +This configuration setting can only be modified using the System Console user interface. + +</Note> + +**True**: New users must accept the Terms of Service before accessing any Mattermost teams on desktop, web, or mobile. Existing users must accept them after login or a page refresh. To update the Terms of Service link displayed in account creation and login pages, go to **System Console \> Legal and Support \> Terms of Service Link**. + +**False**: During account creation or login, users can review Terms of Service by accessing the link configured via **System Console \> Legal and Support \> Terms of Service link**. + +### Custom terms of service text + +Text that will appear in your custom Terms of Service. Supports Markdown-formatted text. + +### Re-acceptance period + +The number of days before Terms of Service acceptance expires, and the terms must be re-accepted. + +Defaults to 365 days. 0 indicates the terms do not expire. diff --git a/docs/main/administration-guide/configure/configuration-in-your-database.mdx b/docs/main/administration-guide/configure/configuration-in-your-database.mdx new file mode 100644 index 000000000000..2056c43df12a --- /dev/null +++ b/docs/main/administration-guide/configure/configuration-in-your-database.mdx @@ -0,0 +1,175 @@ +--- +title: "Store configuration in your database" +--- +<PlanAvailability slug="all-commercial" /> + +If you have a self-hosted Mattermost deployment, you can use your database as the single source of truth for the active configuration of your Mattermost installation. This changes the Mattermost binary from reading the default `config.json` file to reading the configuration settings stored within a configuration table in the database. Mattermost has been running our [community server](https://community.mattermost.com) on this option since the feature was released, and recommends its use for those on [High Availability deployments](/administration-guide/scale/high-availability-cluster-based-deployment). + +Benefits to using this option: + +- Conveniently manages configuration changes directly from the System Console, even in High Availability deployments and read-only containerized environments. +- Ensures all servers in a High Availability deployment have the same configuration, even when new servers are added to the cluster. +- Automatically deploys SAML certificates and keys to all servers in the cluster. + +<Tip> + +The Mattermost configuration database and Mattermost application database are 2 different entities. It's possible to store Mattermost configuration in one database and Mattermost data in another database. + +To do so, you must update the [Datasource](/administration-guide/configure/environment-configuration-settings#data-source) configuration setting to a new data source name, which can be done while the application is running. Explicitly setting the `MM_SQLSETTINGS_DATASOURCE` environment variable to override what has been defined in the configuration, whether it's in a database, or in a file, allows the correct data source name to be passed to the Mattermost application. + +</Tip> + +## How to migrate configuration to the database + +These instructions cover migrating the Mattermost configuration to your database and updating your `systemd` configuration to load it from the database. + +<Important> + +- These instructions assume you have Mattermost server installed at `/opt/mattermost`. If you're running Mattermost in a different directory you'll have to modify the paths to match your environment. +- If you're running Mattermost in a High Availability cluster-based deployment, you must complete all of the steps below on each server in the cluster. + +</Important> + +### Get your database connection string + +The first step is to get your master database connection string. We recommend accessing your `config.json` file to make a copy of the value in `SqlSettings.DataSource`, or your equivalent environment variable, `MM_SQLSETTINGS_DATASOURCE`. + +<Important> + +- `SqlSettings.DataSource` must start with `postgres://` or `mysql://`. If it doesn't, add it to the beginning based on the database in use. For example: `postgres://mmuser:really_secure_password@localhost:5432/mattermost?sslmode=disable&connect_timeout=10` +- If you see `\u0026`, replace it with `&`. For example: `mysql://mmuser:really_secure_password@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s` + +</Important> + +### Create an environment file + +Create the file `/opt/mattermost/config/mattermost.environment` to set the `MM_CONFIG` environment variable to the database connection string. For example: + +``` text +MM_CONFIG='postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable&connect_timeout=10' +``` + +Run this command to verify the permissions on your Mattermost directory: + +``` sh +sudo chown -R mattermost:mattermost /opt/mattermost +``` + +### Enable local mode + +Edit the `config.json` to enable local mode by setting `EnableLocalMode` to `true`. See the [local mode](/administration-guide/manage/mmctl-command-line-tool#local-mode) documentation for details on activating and using local mode. + +### Restart Mattermost + +Run the following command to restart the Mattermost server and apply the configuration change: + +``` sh +sudo systemctl restart mattermost +``` + +### Migrate configuration from `config.json` + +You can use the [mmctl config migrate](/administration-guide/manage/mmctl-command-line-tool#mmctl-config-migrate) command to migrate the configuration by running the following command: + +``` sh +./bin/mmctl config migrate path/to/config.json "postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable&connect_timeout=10" --local +``` + +<Important> + +- If you're using a High Availability cluster-based deployment, you only need to run this command once and migrate the configuration from one server in the cluster. +- When migrating configuration, Mattermost incorporates configuration from any existing `MM_*` environment variables set in the current shell. See [Environment Variables](/administration-guide/configure/configuration-settings) documentation for details. +- As with the environment file, you'll have to escape any single quotes in the database connection string. +- Any existing SAML certificates will be migrated into the database as well so they are available for all servers in the cluster. When the certificates expire, you can upload new certificates using the System Console or mmctl, which triggers a database update. Replacing the certificate files manually requires a reload of the Mattermost server to re-pull the certificates. Configuration files are stored in the `configurationfiles` table in the database. + +</Important> + +When configuration in the database is enabled, any changes to the configuration are recorded to the `Configurations` and `ConfigurationFiles` tables. Furthermore, `ClusterSettings.ReadOnlyConfig` is ignored, enabling full use of the System Console. + +If you have configuration settings that must be set on a per-server basis you should add them as environment variables to the `mattermost.environment` file. These must be on their own line, and you must escape them properly. + +### Modify the Mattermost `systemd` file + +Find the `mattermost.service` file using the following command: + +``` sh +sudo systemctl status mattermost.service +``` + +The second line of output will have the location of the running `mattermost.service`. + +``` text +Loaded: loaded (/lib/systemd/system/mattermost.service; enabled; vendor preset: enabled) +``` + +Edit this file as *root* to add the below text just above the line that begins with `ExecStart`: + +``` text +EnvironmentFile=/opt/mattermost/config/mattermost.environment +``` + +Here's a complete `mattermost.service` file with the `EnvironmentFile` line added: + +``` text +[Unit] +Description=Mattermost +After=network.target +After=postgresql.service +Requires=postgresql.service + +[Service] +Type=notify +EnvironmentFile=/opt/mattermost/config/mattermost.environment +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost +LimitNOFILE=49152 + +[Install] +WantedBy=postgresql.service +``` + +#### Verify that the configuration was migrated correctly + +Configurations are stored in the `Configurations` table in the database. Run the following query to verify that you've migrated the configuration successfully: + +``` sql +SELECT * FROM Configurations WHERE Active=true; +``` + +There should be exactly one line returned, and the `Value` field for that line should match your `config.json` file. + +### Reload `systemd` files and restart Mattermost + +Run these commands to reload the daemon and restart Mattermost using the new `MM_CONFIG` environment variable. + +``` sh +sudo systemctl daemon-reload +sudo systemctl restart mattermost +``` + +<Important> + +Once you start using configuration in the database, you shouldn't manually edit the active configuration row. You should edit or update the configuration in one of the following ways: + +- Use the System Console to make changes to the configuration. +- Use `mmctl` to make changes to the configuration. + +The Mattermost server keeps active configuration in memory and writes new ones to the database only when there is a change. This way we avoid polling the database to process changes to the configuration. Publishing the changes to the cluster are handled by the application itself. + +</Important> + +## Rolling back + +If you run into issues with your configuration in the database you can roll back to the `config.json` file by commenting out the `MM_CONFIG` line in `/opt/mattermost/config/mattermost.environment` and restarting Mattermost with `systemctl restart mattermost`. + +## Troubleshooting + +### Server fails to start + +Providing the `--disableconfigwatch` flag while not actually pointing at a file will fail to start the server with an appropriate error message. diff --git a/docs/main/administration-guide/configure/configuration-settings.mdx b/docs/main/administration-guide/configure/configuration-settings.mdx new file mode 100644 index 000000000000..7d99e892aadc --- /dev/null +++ b/docs/main/administration-guide/configure/configuration-settings.mdx @@ -0,0 +1,46 @@ +--- +title: "Configuration settings" +--- +<PlanAvailability slug="all-commercial" /> + +System admins for both self-hosted and Cloud Mattermost deployments can manage Mattermost configuration using the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu and selecting **System Console**. + +<Note> + +- In self-hosted Mattermost deployments, configuration settings are maintained in the `config.json` configuration file, located in the `mattermost/config` directory, or [stored in the database](/administration-guide/configure/configuration-in-your-database). System admins managing self-hosted deployments can also modify the `config.json` file directly using a text editor. +- Mattermost requires write permissions to the `config.json` file; otherwise, configuration changes made within the System Console will have no effect. + +</Note> + +Mattermost configuration settings are organized into the following categories within the System Console: + +- [Self-hosted workspace edition and license settings](/administration-guide/configure/self-hosted-account-settings) +- [Cloud workspace subscription, billing, and account settings](/administration-guide/configure/cloud-billing-account-settings) +- [Reporting configuration settings](/administration-guide/configure/reporting-configuration-settings) +- [User management configuration settings](/administration-guide/configure/user-management-configuration-settings) +- [System attributes](/administration-guide/configure/system-attributes) +- [Environment configuration settings](/administration-guide/configure/environment-configuration-settings) +- [Site configuration settings](/administration-guide/configure/site-configuration-settings) +- [Authentication configuration settings](/administration-guide/configure/authentication-configuration-settings) +- [Plugins configuration settings](/administration-guide/configure/plugins-configuration-settings) +- [Integrations configuration settings](/administration-guide/configure/integrations-configuration-settings) +- [Compliance configuration settings](/administration-guide/configure/compliance-configuration-settings) +- [Experimental configuration settings](/administration-guide/configure/experimental-configuration-settings) +- [Deprecated configuration settings](/administration-guide/configure/deprecated-configuration-settings) +- [Bleve search](/administration-guide/configure/bleve-search) + +## Configuration in database + +Self-hosted system configuration can be stored in the database. This changes the Mattermost binary from reading the default `config.json` file to reading the configuration settings stored within a configuration table in the database. See the [Mattermost database configuration](/administration-guide/configure/configuration-in-your-database) documentation for migration details. + +## Environment variables + +You can use [environment variables](/administration-guide/configure/environment-variables) to manage Mattermost configuration for self-hosted deployments. Environment variables override settings in `config.json`. If a change to a setting in `config.json` requires a restart to take effect, then changes to the corresponding environment variable also require a server restart. + +## Configuration reload + +In self-hosted deployments, the “config watcher”, the mechanism that automatically reloads the `config.json` file, has been deprecated in favor of the [mmctl config reload](/administration-guide/manage/mmctl-command-line-tool#mmctl-config-reload) command that you must run to apply configuration changes you've made. This improves configuration performance and robustness. + +## Deprecated configuration settings + +See the [deprecated configuration settings documentation](/administration-guide/configure/deprecated-configuration-settings) for details on all deprecated Mattermost configuration settings that are no longer supported. diff --git a/docs/main/administration-guide/configure/custom-branding-tools.mdx b/docs/main/administration-guide/configure/custom-branding-tools.mdx new file mode 100644 index 000000000000..06b35132afbc --- /dev/null +++ b/docs/main/administration-guide/configure/custom-branding-tools.mdx @@ -0,0 +1,38 @@ +--- +title: "Custom branding tools" +--- +<PlanAvailability slug="all-commercial" /> + +Use custom branding tools to present a Mattermost experience that's tailored to the branding of your organization. + +<figure> +<img src="../../images/custom-branding-tools.png" alt="../../images/custom-branding-tools.png" /> +</figure> + +## Enable custom branding + +1. Go to **System Console \> Site Configuration \> Customization \> Enable Custom Branding** and set the value to **true**. +2. Choose a **Site Name**, upload a **Custom Brand Image**, then enter **Custom Brand Text**. +3. Choose **Save**. + +Users should see your new custom branding on the login page of your Mattermost server the next time they log in. + +You can remove the custom brand image by selecting the **X** in the top right corner of the image. To apply the change, choose **Save**. Note that the value must be set to **true** in order to perform this step. + +More about settings available in **Customization**: + +### Site name + +Choose the name of your Mattermost site to be shown in the UI. The site name appears in the header and footer of the site login page, team selection page, team creation page, account creation page, email invitations, and replaces "Mattermost" on the **About** page. Note that the site name applies to the entire site and not just a specific team on the site. The site name is limited to 30 characters or less. + +### Custom branding image + +Upload a company logo or custom image representative of your site that is displayed on the left side of the site login page. Supported image formats are JPG, PNG, TIFF, and BMP. The recommended image size is 200-500px in width and height, and less than 2 MB since it's loaded for every user who logs in on desktop. + +### Custom brand text + +Write custom text to display your company tagline or a welcome prompt. Custom text will be shown below the custom brand image on the left side of site login page on desktop. You can format this text to a maximum of 500 characters using the same [Markdown formatting syntax](/end-user-guide/collaborate/format-messages) as used in Mattermost messages. + +### Site description + +Use this field to describe the purpose of your site. The site description is shown below the site name on the login page. This text defaults to **All team communication in one place, searchable and accessible anywhere**. This text can be a maximum of 1024 characters and is not formatted with Markdown. diff --git a/docs/main/administration-guide/configure/customize-mattermost.mdx b/docs/main/administration-guide/configure/customize-mattermost.mdx new file mode 100644 index 000000000000..39d12f601689 --- /dev/null +++ b/docs/main/administration-guide/configure/customize-mattermost.mdx @@ -0,0 +1,60 @@ +--- +title: "Customizing Mattermost" +--- +<PlanAvailability slug="all-commercial" /> + +There are several ways to customize your Mattermost server. + +If customizing Mattermost, please avoid branding that could be confused with the Mattermost brand. For example, it's okay to brand as "Healthcare Central" because it's a completely different brand. "Mattermost Healthcare Central" is not okay, because it can potentially be confused with the Mattermost brand. Please see the [Mattermost trademark guidelines](https://mattermost.com/trademark-standards-of-use/) for details. + +While you're welcome to add your own copyright notice in the user interface if you feel it is warranted by your changes, we ask that you do not remove the Mattermost, Inc. copyright notice from the login footer or from the About dialog. + +## Mattermost Web App + +The Mattermost webapp is licensed under the Apache 2.0 license. To modify and use with the Mattermost server, you can: + +1. Install the Mattermost server by following one of our installation guides +2. Fork the [mattermost](https://github.com/mattermost/mattermost) repository +3. Go to the web app code located in the `webapp` directory and make your changes +4. Run `make package` to create `mattermost-webapp.tar.gz` +5. Copy `mattermost-webapp-tar.gz` to the location Mattermost was installed in Step 1 +6. Rename the existing `client` folder to `client-original` +7. Run `tar -xvf mattermost-webapp.tar.gz` to extract your new customized `client` folder +8. If you're installing Mattermost 7.5 - 7.10, copy the `products` folder from `client-original` into `client` +9. Restart your Mattermost server + +It is possible to customize certain parts of the webapp without forking by using our [Custom Branding](/custom-branding-tools) settings. + +To replace the logo in email notifications, change the file located in the `/images` directory. To change the app icon, modify the `/app/components/app_icon.js` file. + +## Mattermost Server + +There are a few things you can customize in the Mattermost server without forking: + +1. Modify text in the Mattermost interface by modifying the `en.json` file. +2. Customize or hide help and support links by modifying your [configuration settings](/administration-guide/configure/site-configuration-settings#customization). +3. Customize the email notifications by editing the HTML files in `/templates`. From Mattermost v11.3.0, changes to HTML templates require a server restart to take effect. + +## Mattermost mobile apps + +The Mattermost mobile apps can be customized if you choose to build the apps yourself. + +To brand the mobile apps: + +1. Fork the [mattermost-mobile](https://github.com/mattermost/mattermost-mobile) repository. +2. Replace the name, images, and any key text strings. +3. Compile the custom apps. +4. Deploy the apps to an app store. + +While most organizations deploy to internal enterprise app stores, you are welcome to deploy to iTunes and Google Play as long as the branding is not confusable with official Mattermost products. + +## Mattermost desktop apps + +The Mattermost desktop apps can be customized if you choose to build the apps yourself. + +To brand the desktop apps: + +1. Fork the [mattermost/desktop](https://github.com/mattermost/desktop) repository +2. Replace the name, images, and any key text strings +3. Refer to [the Mattermost Developer documentation](https://developers.mattermost.com/contribute/more-info/desktop/) for help with compiling the apps +4. Share the desktop application with your users diff --git a/docs/main/administration-guide/configure/deprecated-configuration-settings.mdx b/docs/main/administration-guide/configure/deprecated-configuration-settings.mdx new file mode 100644 index 000000000000..df17c6dbd243 --- /dev/null +++ b/docs/main/administration-guide/configure/deprecated-configuration-settings.mdx @@ -0,0 +1,1360 @@ +--- +title: "Deprecated configuration settings" +draft: true +--- +The following Mattermost configuration settings are deprecated and are no longer supported in current Mattermost releases: + +- [Bleve settings](#bleve-settings) +- [Elasticsearch settings](#elasticsearch-settings) +- [Service settings](#service-settings) +- [Database settings](#database-settings) +- [Data retention settings](#data-retention-settings) +- [Users and teams settings](#users-and-teams-settings) +- [SAML 2.0 settings](#saml-2-0-settings) +- [Legacy sidebar settings](#legacy-sidebar-settings) +- [Town Square channel settings](#town-square-channel-settings) +- [Custom emoji settings](#custom-emoji-settings) +- [Timezone settings](#timezone-settings) +- [High availablity settings](#high-availability-settings) +- [Rest API V3 settings](#rest-api-v3-settings) +- [Integrations settings](#integrations-settings) +- [Permission policy settings](#permission-policy-settings) +- [Image settings](#image-settings) +- [Experimental display settings](#experimental-display-settings) +- [Experimental API endpoint settings](#experimental-api-endpoint-settings) +- [Shared channels settings](#shared-channels-settings) +- [User satisfaction survey plugin settings](#user-satisfaction-surveys-plugin-settings) +- [Other deprecated settings](#other-deprecated-settings) + +------------------------------------------------------------------------------------------------------------------------ + +## Bleve settings + +*Bleve search has been deprecated from Mattermost v11.0. We recommend using Elasticsearch or OpenSearch for enterprise search capabilities.* + +### Enable Bleve indexing + +*Deprecated from Mattermost v11.0* + +This setting was available in the System Console by going to **Experimental \> Bleve**, or by editing the `config.json` file. + +**True**: The indexing of new posts occurs automatically. + +**False**: The indexing of new posts does not occur automatically. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableIndexing": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Index directory + +*Deprecated from Mattermost v11.0* + +This setting was available in the System Console by going to **Experimental \> Bleve**, or by editing the `config.json` file. + +Directory path to use for storing bleve indexes. + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"IndexDir": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Bulk index now + +Select **Index Now** to index all users, channels, and posts in the database from oldest to newest. Bleve is available during indexing, but search results may be incomplete until the indexing job is complete. + +### Purge indexes + +Select **Purge Index** to remove the contents of the Bleve index directory. Search results may be incomplete until a bulk index of the existing database is rebuilt. + +### Enable Bleve for search queries + +*Deprecated from Mattermost v11.0* + +This setting was available in the System Console by going to **Experimental \> Bleve**, or by editing the `config.json` file. + +**True**: Search queries will use bleve search. + +**False**: Search queries will not use bleve search. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '92%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableSearching": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable Bleve for autocomplete queries + +*Deprecated from Mattermost v11.0* + +This setting was available in the System Console by going to **Experimental \> Bleve**, or by editing the `config.json` file. + +**True**: Autocomplete queries will use bleve search. + +**False**: Autocomplete queries will not use bleve search. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableAutocomplete": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Bulk Indexing Time Window Seconds + +*Removed in May 16, 2022 release* + +This setting isn't available in the System Console and can only be set in `config.json`. + +Determines the maximum time window for a batch of posts being indexed by the Bulk Indexer. This setting serves as a performance optimization for installs with over ~10 million posts in the database. You can approximate this value based on the average number of seconds for 2,000 posts to be added to the database on a typical day in production. Setting this value too low will cause bulk indexing jobs to run slowly. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '91%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BulkIndexingTimeWindowSeconds": 3600</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Elasticsearch settings + +### Bulk Indexing Time Window + +*Removed in May 16, 2022 release* + +This setting isn't available in the System Console and can only be set in `config.json`. + +Determines the maximum time window for a batch of posts being indexed by the Bulk Indexer. This setting serves as a performance optimization for installs with over ~10 million posts in the database. You can approximate this value based on the average number of seconds for 2,000 posts to be added to the database on a typical day in production. Setting this value too low will cause bulk indexing jobs to run slowly. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"BulkIndexingTimeWindowSeconds": 3600</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Service settings + +### Enable reliable websockets + +*This configuration setting has been deprecated, and the ability to buffer messages during a connection loss has been promoted to general availability from Mattermost v6.3. This setting is enabled for older clients to maintain backwards compatibility.* + +This setting isn't available in the System Console and can only be set in `config.json`. + +Enable this setting to make websocket messages more reliable by buffering messages during a connection loss and then re-transmitting all unsent messages when the connection is revived. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableReliableWebsockets": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Data prefetch + +*Removed in February 16, 2021 release* + +**True**: Messages in all unread channels are pre-loaded from the server whenever the client reconnects to the network to eliminate loading time when users switch to unread channels. + +**False**: Messages are fetched on-demand from the server when users switch channels. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalDataPrefetch": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Segment write key + +*Removed in March 16, 2017 release* + +For deployments seeking additional tracking of system behavior using Segment.com, you can enter a Segment `WRITE_KEY` using this field. This value works like a tracking code and is used in client-side JavaScript and will send events to Segment.com attributed to the account you used to generate the `WRITE_KEY`. + +<table style={{width: '78%'}}> +<colgroup> +<col style={{width: '77%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"SegmentDeveloperKey": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Limit access to config settings prior to login + +*Removed in December 16, 2018 release* + +Enable this setting to limit the number of config settings sent to users prior to login. + +Supported for Mattermost server v5.1.0 and later, and Mattermost Mobile apps v1.10.0 and later. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalLimitClientConfig": "false"</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Disable legacy MFA API endpoint + +Deprecated. Not used in Mattermost v6.0 and later. + +------------------------------------------------------------------------------------------------------------------------ + +## Database settings + +### At rest encrypt key + +*Removed in August 23, 2018 release* + +This setting isn't available in the System Console and can only be set in `config.json`. It's a legacy setting used to encrypt data stored at rest in the database, and no fields are encrypted using `AtRestEncryptKey`. + +A 32-character key for encrypting and decrypting sensitive fields in the database. When using high availability, this value must be identical in each instance of Mattermost. + +<table style={{width: '76%'}}> +<colgroup> +<col style={{width: '75%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AtRestEncryptKey": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Amazon S3 bucket endpoint + +*Removed in November 16th, 2016 release* + +Set an endpoint URL for Amazon S3 buckets. + +<table style={{width: '80%'}}> +<colgroup> +<col style={{width: '80%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AmazonS3BucketEndpoint": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Amazon S3 Location Constraint + +*Removed in November 16th, 2016 release* + +**True**: S3 region is location constrained. + +**False**: S3 region is not location constrained. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AmazonS3LocationConstraint": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Amazon S3 lowercase bucket + +*Removed in November 16th, 2016 release* + +**True**: S3 bucket names are fully lowercase. + +**False**: S3 bucket names may contain uppercase and lowercase letters. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AmazonS3LowercaseBucket": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Data retention settings + +### MessageRetentionDays + +*Deprecated in Mattermost v9.5 release in favor of MessageRetentionHours* + +Set how long Mattermost keeps messages across all teams and channels. This setting doesn't apply to custom retention policies. The minimum time is 1 hour. + +From Mattermost v9.5, this setting has been replaced by [MessageRetentionHours](/administration-guide/configure/compliance-configuration-settings#global-retention-policy-for-messages) which provides more granular control over message retention periods. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"MessageRetentionDays": 365</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### FileRetentionDays + +*Deprecated in Mattermost v9.5 release in favor of FileRetentionHours* + +Set how long Mattermost keeps files across all teams and channels. This setting doesn't apply to custom retention policies. The minimum time is 1 hour. + +From Mattermost v9.5, this setting has been replaced by [FileRetentionHours](/administration-guide/configure/compliance-configuration-settings#global-retention-policy-for-files) which provides more granular control over file retention periods. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"FileRetentionDays": 365</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Users and teams settings + +### Enable team directory + +*Removed in May 16th, 2016 release* + +**True**: Teams that are configured to appear in the team directory will appear on the system main page. Teams can configure this setting from **Team Settings \> Include this team in the Team Directory**. + +**False**: Team directory on the system main page is disabled. + +<table style={{width: '93%'}}> +<colgroup> +<col style={{width: '93%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableTeamListing": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Allow team admins to edit others' posts + +Deprecated. Not used in Mattermost v6.0 and later. + +### Enable team creation + +Deprecated. Not used in Mattermost v6.0 and later. + +------------------------------------------------------------------------------------------------------------------------ + +## SAML 2.0 settings + +### Use new SAML library + +*Removed in December 16, 2020 release* + +**True**: Enable an updated SAML Library, which does not require the XML Security Library (xmlsec1) to be installed. + +**False**: Continue using the existing implementation which uses the XML Security Library (xmlsec1). + +<table style={{width: '93%'}}> +<colgroup> +<col style={{width: '93%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"UseNewSAMLLibrary": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Legacy sidebar settings + +### Enable legacy sidebar + +Deprecated. Not used in Mattermost v6.0 and later. + +### Experimental sidebar features + +*Deprecated. Not used in Mattermost v5.32 and later* + +<Note> + +This experimental configuration setting has been deprecated, and the ability to organize channels in the sidebar has been promoted to general availability from Mattermost v5.32. See the [Organizing Your Sidebar documentation](/end-user-guide/preferences/customize-your-channel-sidebar) for details on customizing the sidebar. + +</Note> + +**Disabled**: Users cannot access the experimental channel sidebar feature set. + +**Enabled (Default On)**: Enables the experimental sidebar features for all users on this server. Users can disable the features in **Settings \> Sidebar \> Experimental Sidebar Features**. Features include custom collapsible channel categories, drag and drop to reorganize channels, and unread filtering. + +**Enabled (Default Off)**: Users must enable the experimental sidebar features in **Settings**. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalChannelSidebarOrganization": off</code> with options <code>off</code>, <code>default_on</code> and <code>default_off</code>.</td> +</tr> +</tbody> +</table> + +### Sidebar organization + +Deprecated. Not used in Mattermost v6.0 and later. + +### Enable X to leave channels from left hand sidebar + +Deprecated. Not used in Mattermost v6.0 and later. + +### Autoclose direct messages in sidebar + +Deprecated. Not used in Mattermost v6.0 and later. + +------------------------------------------------------------------------------------------------------------------------ + +## Town Square channel settings + +### Town Square is hidden in left hand sidebar + +Deprecated. Not used in Mattermost v6.0 and later. + +### Town Square is read-only + +From Mattermost v.6.0, this feature has been deprecated in favor of [advanced access controls](/administration-guide/manage/team-channel-members#advanced-access-controls) which allows you to set any channel as read-only, including Town Square. + +------------------------------------------------------------------------------------------------------------------------ + +## Custom emoji settings + +### Restrict custom emoji creation + +Deprecated. Not used in Mattermost v6.0 and later. + +------------------------------------------------------------------------------------------------------------------------ + +## Timezone settings + +### Timezone + +*This configuration setting has been promoted to General Availability and is no longer configurable in Mattermost v6.0 and later.* + +Select the timezone used for timestamps in the user interface and email notifications. + +**True**: The **Timezone** setting is visible in the Settings and a timezone is automatically assigned in the next active session. + +**False**: The **Timezone** setting is hidden in the Settings. + +<table style={{width: '96%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalTimezone": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## High availability settings + +### Inter-node listen address + +*Deprecated. Not used in Mattermost v4.0 and later* + +The address the Mattermost Server will listen on for inter-node communication. When setting up your network you should secure the listen address so that only machines in the cluster have access to that port. This can be done in different ways, for example, using IPsec, security groups, or routing tables. + +<table style={{width: '85%'}}> +<colgroup> +<col style={{width: '85%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"InterNodeListenAddress": ":8075"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Inter-Node URLs + +*Deprecated. Not used in Mattermost v4.0 and later* + +A list of all the machines in the cluster, such as `["http://10.10.10.2", "http://10.10.10.4"]`. It is recommended to use the internal IP addresses so all the traffic can be secured. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"InterNodeUrls": []</code> with string array input consisting of the machines in the cluster.</td> +</tr> +</tbody> +</table> + +### Use gossip + +*Removed in Mattermost v6.0* + +**True**: The server attempts to communicate via the gossip protocol over the gossip port specified. + +**False**: The server attempts to communicate over the streaming port. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '92%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature’s config.json setting is <code>"UseExperimentalGossip": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Streaming port + +*Deprecated. Not used in Mattermost v6.0 and later* + +The port used for streaming data between servers. + +<table style={{width: '77%'}}> +<colgroup> +<col style={{width: '76%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"StreamingPort": ":8075"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Maximum idle connections for high availability + +*Deprecated. Not used in Mattermost v7.0 and later* + +<table> +<colgroup> +<col style={{width: '47%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of idle connections held open from one server to all others in the cluster.</p> +<p>Numerical input. Default is <strong>100</strong>.</p></td> +<td><ul> +<li>System Config path: N/A</li> +<li><code>config.json</code> setting: <code>".ClusterSettings.MaxIdleConns: 100,</code></li> +<li>Environment variable: <code>MM_CLUSTERSETTINGS_MAXIDLECONNS</code></li> +</ul></td> +</tr> +</tbody> +</table> + +### Maximum idle connections per host + +*Deprecated. Not used in Mattermost v7.0 and later* + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of idle connections held open from one server to another server in the cluster.</p> +<p>Numerical input. Default is <strong>128</strong>.</p></td> +<td><ul> +<li>System Config path: N/A</li> +<li><code>config.json</code> setting: <code>".ClusterSettings.MaxIdleConnsPerHost: 128",</code></li> +<li>Environment variable: <code>MM_CLUSTERSETTINGS_MAXIDLECONNSPERHOST</code></li> +</ul></td> +</tr> +</tbody> +</table> + +### Idle connection timeout + +*Deprecated. Not used in Mattermost v7.0 and later* + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The amount of time, in milliseconds, to leave an idle connection open between servers in the cluster.</p> +<p>Numerical input. Default is <strong>90000</strong>.</p></td> +<td><ul> +<li>System Config path: N/A</li> +<li><code>config.json</code> setting: <code>".ClusterSettings.IdleConnTimeoutMilliseconds: 90000",</code></li> +<li>Environment variable: <code>MM_CLUSTERSETTINGS_IDLECONNTIMEOUTMILLISECONDS</code></li> +</ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## REST API V3 settings + +### Allow use of API v3 endpoints + +*Removed in June 16, 2018 release* + +Set to `false` to disable all version 3 endpoints of the REST API. Integrations that rely on API v3 will fail and can then be identified for migration to API v4. API v3 is deprecated and will be removed in the near future. See [https://api.mattermost.com](https://api.mattermost.com) for details. + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '88%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableAPIv3": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Integrations settings + +### Restrict managing integrations to Admins + +Deprecated. Not used in Mattermost v6.0 and later. + +### Patch React DOM used by plugins + +*Deprecated. Not used in Mattermost v8.0 and later* + +This setting enables the patching of the React DOM library when loading web app plugins so that the plugin uses the version matching the web app. This should only be needed temporarily after upgrading to Mattermost v7.7 for plugins that have not been updated yet. Changes to this setting require a server restart before taking effect. + +See the [Important Upgrade Notes](/administration-guide/upgrade/important-upgrade-notes) for more information. + +**True**: Web app plugins that package their own version of React DOM are patched to instead use the version of React DOM provided by the web app. + +**False**: Web app plugins are loaded as normal. + +<table style={{width: '96%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"PatchPluginsReactDOM": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Permission policy settings + +*Removed in June 16, 2018 release* + +<Note> + +From Mattermost v5.0, these settings are found in the [Advanced Permissions](/administration-guide/onboard/advanced-permissions) page instead of configuration settings. + +</Note> + +### Enable sending team invites from + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Set policy on who can invite others to a team using the **Send Email Invite**, **Get Team Invite Link**, and **Add Members to Team** options on the product menu. If **Get Team Invite Link** is used to share a link, you can expire the invite code from **Team Settings \> Invite Code** after the desired users have joined the team. Options include: + +**All team members**: Allows any team member to invite others using an email invitation, team invite link, or by adding members to the team directly. + +**Team and System Admins**: Hides the email invitation, team invite link, and the add members to team buttons in the product menu from users who are not team admins or system admins. + +**System Admins**: Hides the email invitation, team invite link, and add members to team buttons in the product menu from users who are not system admins. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictTeamInvite": "all"</code> with options <code>"all"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable public channel creation for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to create public channels. + +**All team members**: Allow all team members to create public channels. + +**Team Admins and System Admins**: Restrict creating public channels to team admins and system admins. + +**System Admins**: Restrict creating public channels to system admins. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPublicChannelCreation": "all"</code> with options <code>"all"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable public channel renaming for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to rename and set the header or purpose for Public channels. + +**All channel members**: Allow all channel members to rename Public channels. + +**Channel Admins, Team Admins, and System Admins**: Restrict renaming public channels to channel admins, team admins, and system admins who are members of the channel. + +**Team Admins and System Admins**: Restrict renaming public channels to Team Admins and system admins who are members of the channel. + +**System Admins**: Restrict renaming public channels to system admins who are members of the channel. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPublicChannelManagement": "all"</code> with options <code>"all"</code>, <code>"channel_admin"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable public channel deletion for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to delete Public channels. Deleted channels can be recovered from the database using a [command line tool](/administration-guide/manage/command-line-tools). + +**All channel members**: Allow all channel members to delete public channels. + +**Channel Admins, Team Admins, and System Admins**: Restrict deleting public channels to channel admins, team admins, and system admins who are members of the channel. + +**Team Admins and System Admins**: Restrict deleting public channels to team admins and system admins who are members of the channel. + +**System Admins**: Restrict deleting public channels to system admins who are members of the channel. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPublicChannelDeletion": "all"</code> with options <code>"all"</code>, <code>"channel_admin"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable private channel creation for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to create private channels. + +**All team members**: Allow all team members to create private channels. + +**Team Admins and System Admins**: Restrict creating private channels to team admins and system admins. + +**System Admins**: Restrict creating private channels to system admins. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPrivateChannelCreation": "all"</code> with options <code>"all"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable private channel renaming for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to rename and set the header or purpose for Private channels. + +**All channel members**: Allow all channel members to rename private channels. + +**Channel Admins, Team Admins, and System Admins**: Restrict renaming private channels to channel admins, team admins, and system admins who are members of the private channel. + +**Team Admins and System Admins**: Restrict renaming private channels to team admins and system admins who are members of the private channel. + +**System Admins**: Restrict renaming private channels to system admins who are members of the private channel. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPrivateChannelManagement": "all"</code> with options <code>"all"</code>, <code>"channel_admin"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable managing of private channel members for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Set policy on who can add and remove members from Private channels. + +**All team members**: Allow all team members to add and remove members. + +**Team Admins, Channel Admins, and System Admins**: Allow only team admins, channel admins, and system admins to add and remove members. + +**Team Admins, and System Admins**: Allow only team admins and system admins to add and remove members. + +**System Admins**: Allow only system admins to add and remove members. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPrivateChannelManageMembers": "all"</code> with options <code>"all"</code>, <code>"channel_admin"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Enable private channel deletion for + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to delete Private channels. Deleted channels can be recovered from the database using a [command line tool](/administration-guide/manage/command-line-tools). + +**All channel members**: Allow all channel members to delete private channels. + +**Channel Admins, Team Admins, and System Admins**: Restrict deleting private channels to channel admins, team admins, and system admins who are members of the Private channel. + +**Team Admins and System Admins**: Restrict deleting private channels to Team Admins and system admins who are members of the Private channel. + +**System Admins**: Restrict deleting private channels to system admins who are members of the private channel. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPrivateChannelDeletion": "all"</code> with options <code>"all"</code>, <code>"channel_admin"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Allow which users to delete messages + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Restrict the permission level required to delete messages. Team admins, channel admins, and system admins can delete messages only in channels where they are members. Messages can be deleted any time. + +**Message authors can delete their own messages, and Administrators can delete any message**: Allow authors to delete their own messages, and allow team admins, channel admins, and system admins to delete any message. + +**Team Admins and System Admins**: Allow only team admins and system admins to delete messages. + +**System Admins**: Allow only system admins to delete messages. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictPostDelete": "all"</code> with options <code>"all"</code>, <code>"team_admin"</code>, and <code>"system_admin"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Allow users to edit their messages + +*Removed in June 16, 2018 release* + +<Note> + +From v5.0 this has been replaced by advanced permissions which offers Admins a way to restrict actions in Mattermost to authorized users only. See the [Advanced Permissions documentation](/administration-guide/onboard/advanced-permissions) for more details. + +</Note> + +Set the time limit that users have to edit their messages after posting. + +**Any time**: Allow users to edit their messages at any time after posting. + +**Never**: Do not allow users to edit their messages. + +**{n} seconds after posting**: Users can edit their messages within the specified time limit after posting. The time limit is applied using the `config.json` setting `PostEditTimeLimit` described below. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AllowEditPost": "always"</code> with options <code>"always"</code>, <code>"never"</code>, and <code>"time_limit"</code> for the above settings, respectively.</td> +</tr> +</tbody> +</table> + +### Post edit time limit + +When post editing is permitted, setting this to `-1` allows editing any time, and setting this to a positive integer restricts editing time in seconds. If post editing is disabled, this setting does not apply. + +**Note:** This setting does not affect plugins, shared channels, integration actions, or Mattermost products. + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '82%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"PostEditTimeLimit": -1</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Image settings + +### Attachment thumbnail width + +*Removed in July 16th, 2017 release* + +Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past. + +<table style={{width: '77%'}}> +<colgroup> +<col style={{width: '76%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ThumbnailWidth": 120</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Attachment thumbnail height + +*Removed in July 16th, 2017 release* + +Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past. + +<table style={{width: '78%'}}> +<colgroup> +<col style={{width: '77%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ThumbnailHeight": 100</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Image preview width + +*Removed in July 16th, 2017 release* + +Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past. + +<table style={{width: '76%'}}> +<colgroup> +<col style={{width: '75%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"PreviewWidth": 1024</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Image preview height + +*Removed in July 16th, 2017 release* + +Maximum height of preview image. Setting this value to `0` instructs Mattermost to auto-size the preview image height based on the source image aspect ratio and the preview image width. Updating this value changes how preview images render in future, but does not change images created in the past. + +<table style={{width: '74%'}}> +<colgroup> +<col style={{width: '74%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"PreviewHeight": 0</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Profile picture width + +*Removed in July 16th, 2017 release* + +The width to which profile pictures are resized after being uploaded via **Account Settings \> Profile**. + +<table style={{width: '75%'}}> +<colgroup> +<col style={{width: '75%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ProfileWidth": 128</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Profile picture height + +*Removed in July 16th, 2017 release* + +The height to which profile pictures are resized after being uploaded via **Account Settings \> Profile**. + +<table style={{width: '76%'}}> +<colgroup> +<col style={{width: '75%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ProfileHeight": 128</code> with numerical input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Experimental display settings + +### Supported timezones path + +*Removed in April 16, 2019 release* + +Set the path of the JSON file that lists supported timezones when `ExperimentalTimezone` is set to `true`. + +The file must be in the same directory as your `config.json` file if you set a relative path. Defaults to `timezones.json`. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"SupportedTimezonesPath": "timezones.json"</code> with string input.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Shared channels settings + +### Enable remote cluster service (Experimental) + +Deprecated in November 16th, 2024 release in favor of [Connected Workspaces](/administration-guide/configure/site-configuration-settings#enable-connected-workspaces) configuration settings + +This setting isn't available in the System Console and can only be set in `config.json`. + +Enable this setting to add, remove, and view remote clusters for shared channels. + +**True**: System admins can manage remote clusters using the System Console. + +**False**: (**Default**) Remote cluster management is disabled. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.EnableRemoteClusters": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable shared channels (Experimental) + +Deprecated in November 16th, 2024 release in favor of [Connected Workspaces](/administration-guide/configure/site-configuration-settings#enable-connected-workspaces) configuration settings + +This setting isn't available in the System Console and can only be set in `config.json`. + +Enable the ability to establish secure connections between Mattermost instances, and invite secured connections to shared channels where secure connections can participate as they would in any public and private channel. + +**True**: System admins can establish secure connections between Mattermost instances. + +**False**: (**Default**) The ability to establish secure connections is disabled. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.EnableSharedChannels": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## User satisfaction surveys plugin settings + +<Important> + +This plugin is deprecated from Mattermost v10.11, and is no longer included as a pre-packaged plugin for new Mattermost deployments. For new installations, we strongly recommend using the [Mattermost User Survey integration](/administration-guide/configure/manage-user-surveys) instead. + +</Important> + +This plugin enables Mattermost to send user satisfaction surveys to gather feedback and improve product quality directly from your Mattermost users. Please refer to the [Mattermost Privacy Policy](https://mattermost.com/privacy-policy/) for more information on the collection and use of information received through Mattermost services. + +Access the following configuration settings in the System Console by going to **Plugins \> User Satisfaction Surveys**. + +### Enable plugin + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul> +<li><strong>true</strong>: (Default) Enables the Mattermost User Satisfaction Surveys plugin on your Mattermost workspace.</li> +<li><strong>false</strong>: Disables the Mattermost User Satisfaction Surveys plugin on your Mattermost workspace.</li> +</ul></td> +<td><ul> +<li>System Config path: <strong>Plugins > User Satisfaction Surveys</strong></li> +<li><code>config.json</code> setting: <code>PluginSettings.PluginStates.com.mattermost.user-survey.Enable</code></li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +</tbody> +</table> + +### Enable user satisfaction survey + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul> +<li><strong>true</strong>: A survey is sent to all users every quarter. Results are used by Mattermost, Inc. to improve the product.</li> +<li><strong>false</strong>: (Default) User satisfaction surveys are disabled.</li> +</ul></td> +<td><ul> +<li>System Config path: <strong>Plugins > User Satisfaction Surveys</strong></li> +<li><code>config.json</code> setting: <code>PluginSettings.Plugins.com.mattermost.user-survey.systemconsolesetting.EnableSurvey</code></li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +<tr> +<td colspan="2"><strong>Note</strong>: See the <a href="https://mattermost.com/privacy-policy/">Mattermost Privacy Policy</a> for more information on the collection and use of information by Mattermost.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Other deprecated settings + +### Disable Post Metadata + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Disabling post metadata is only recommended if you are experiencing a significant decrease in performance around channel and post load times. + +**False**: Load channels with more accurate scroll positioning by loading post metadata. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DisablePostMetadata": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable AD/LDAP group sync + +**True**: Enables AD/LDAP Group Sync configurable under **User Management \> Groups**. + +**False**: Disables AD/LDAP Group Sync and removes **User Management \> Groups** from the System Console. + +For more information on AD/LDAP Group Sync, please see the [AD/LDAP Group Sync documentation](/administration-guide/onboard/ad-ldap-groups-synchronization). + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalLdapGroupSync": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Disable inactive server email notifications + +This setting isn't available in the System Console and can only be set in `config.json`. + +This configuration setting disables the ability to send inactivity email notifications to Mattermost System Admins. + +<table style={{width: '97%'}}> +<colgroup> +<col style={{width: '96%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableInactivityEmail": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Disable Apps Bar + +This setting is enabled for all customers by default from Mattermost v8.0. This setting disables the Apps Bar and moves all Mattermost integration icons from the vertical pane on the far right back to the channel header. + +### Enable OpenTracing (Experimental) + +*Removed in March 16, 2025 release* + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: A Jaeger client is instantiated and is used to trace each HTTP request as it goes through App and Store layers. Context is added to App and Store and is passed down the layer chain to create OpenTracing 'spans'. + +By default, in order to avoid leaking sensitive information, no method parameters are reported to OpenTracing. Only the name of the method is reported. + +**False**: OpenTracing is not enabled. + +<table style={{width: '93%'}}> +<colgroup> +<col style={{width: '93%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableOpenTracing": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/email-templates.mdx b/docs/main/administration-guide/configure/email-templates.mdx new file mode 100644 index 000000000000..3573f763da6d --- /dev/null +++ b/docs/main/administration-guide/configure/email-templates.mdx @@ -0,0 +1,953 @@ +--- +title: "Email templates" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost has a few email templates that are sent out when a specific event occurs. Most of the time these templates do not need to be modified. In case additional modifications are necessary, all available props in each email are listed below. The 'Content'-Field is just to give a quick description of the prop. Please check the i18n strings for the exact wording. + +The email templates are located in the Mattermost server directory in the `templates` folder. The corresponding strings for each prop can be found in the `i18n` folder. + +<Note> + +\- The props between different email templates are not interchangeable without additional server code changes. - Always back up changes to the `templates` and `i18n` folders before upgrading the server to avoid losing customizations. - From Mattermost v11.3, changes to HTML templates require a server restart to take effect. + +</Note> + +## Available templates + +### Email footer + +**Purpose**: This is appended to all outgoing emails sent by Mattermost. + +**Props**: + +<table style={{width: '68%'}}> +<colgroup> +<col style={{width: '12%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>Footer</td> +<td>Message intro</td> +<td>api.templates.email_footer</td> +</tr> +<tr> +<td>Organization</td> +<td>Name of Organization</td> +<td>api.templates.email_organization</td> +</tr> +<tr> +<td>EmailInfo1</td> +<td>First line of footer</td> +<td>api.templates.email_info1</td> +</tr> +<tr> +<td>EmailInfo2</td> +<td>Second line of footer</td> +<td>api.templates.email_info2</td> +</tr> +<tr> +<td>EmailInfo3</td> +<td>Third line of footer</td> +<td>api.templates.email_info3</td> +</tr> +<tr> +<td>SupportEmail</td> +<td>Email for Mattermost support</td> +<td>--</td> +</tr> +</tbody> +</table> + +### SendChangeUsernameEmail + +**Purpose**: Sent to the user when username has been changed. + +**Body Props**: + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '37%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.username_change_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.username_change_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendEmailChangeVerifyEmail + +**Purpose**: Sent to the user when an email change has been requested. Contains verification link and button. + +**Body Props**: + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '12%'}} /> +<col style={{width: '26%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.email_change_verify_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.email_change_verify_body.info</td> +</tr> +<tr> +<td>VerifyUrl</td> +<td>URL for email verification</td> +<td>--</td> +</tr> +<tr> +<td>VerifyButton</td> +<td>Button for email verification</td> +<td>api.templates.email_change_verify_body.button</td> +</tr> +</tbody> +</table> + +### SendEmailChangeEmail + +**Purpose**: Sent to the user when the email has been changed successfully. + +**Body Props**: + +<table style={{width: '69%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.email_change_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.email_change_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendVerifyEmail + +**Purpose**: Sent to the user upon account creation to verify email address. + +**Body Props**: + +<table style={{width: '66%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.verify_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.verify_body.info</td> +</tr> +<tr> +<td>VerifyUrl</td> +<td>URL for email verification</td> +<td>--</td> +</tr> +<tr> +<td>Button</td> +<td colspan="2">Button for email verification | api.templates.verify_body.button</td> +</tr> +</tbody> +</table> + +### SendSignInChangeEmail + +**Purpose**: Sent to the user when the login method has been changed (i.e. from email to LDAP, etc.) + +**Body Props**: + +<table style={{width: '75%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.signin_change_email.body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.signin_change_email.body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendWelcomeEmail + +**Purpose**: Sent to the user when the account has been created. May also contain download links to Apps as well as email verification links. + +**Body Props**: + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '15%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.welcome_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.welcome_body.info</td> +</tr> +<tr> +<td>Button</td> +<td>Button for confirmation</td> +<td>api.templates.welcome_body.button</td> +</tr> +<tr> +<td>Info2</td> +<td>Continuation of message body</td> +<td>api.templates.welcome_body.info2</td> +</tr> +<tr> +<td>Info3</td> +<td>Continuation of message body</td> +<td>api.templates.welcome_body.info3</td> +</tr> +</tbody> +</table> + +**Optional Props**: + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '15%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>AppDownloadInfo</td> +<td>Info for App Downloads</td> +<td>api.templates.welcome_body.app_download_info</td> +</tr> +<tr> +<td>AppDownloadLink</td> +<td>Download link for Apps</td> +<td>--</td> +</tr> +<tr> +<td>VerifyUrl</td> +<td>Link for verification</td> +<td>--</td> +</tr> +</tbody> +</table> + +### SendPasswordChangeEmail + +**Purpose**: Sent to the user when password has been changed. + +**Body Props**: + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '37%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.password_change_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.password_change_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendAccessTokenEmail + +**Purpose**: Sent to the user when an access token has been added to the account. + +**Body Props**: + +<table style={{width: '74%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.user_access_token_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.user_access_token_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendPasswordResetEmail + +**Purpose**: Sent to the user when password request has been initiated. + +**Body Props**: + +<table style={{width: '64%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.reset_body.title</td> +</tr> +<tr> +<td>Info1</td> +<td>Message body</td> +<td>api.templates.reset_body.info1</td> +</tr> +<tr> +<td>Info2</td> +<td>Continuation of message body</td> +<td>api.templates.reset_body.info2</td> +</tr> +<tr> +<td>ResetUrl</td> +<td>URL to reset password</td> +<td>--</td> +</tr> +<tr> +<td>Button</td> +<td>Button for confirmation</td> +<td>api.templates.reset_body.button</td> +</tr> +</tbody> +</table> + +### SendMfaChangeEmail + +**Purpose**: Sent to the user when multi-factor authentication method has been changed. + +**Body Props when MFA is activated**: + +<table style={{width: '70%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.mfa_activated_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.mfa_activated_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +**Body Props when MFA is deactivated**: + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '37%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.mfa_deactivated_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.mfa_deactivated_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.email_warning</td> +</tr> +</tbody> +</table> + +### SendDeactivateAccountEmail + +**Purpose**: Sent to the user when account has been deactivated. + +**Body Props**: + +<table style={{width: '68%'}}> +<colgroup> +<col style={{width: '8%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.deactivate_body.title</td> +</tr> +<tr> +<td>Info</td> +<td>Message body</td> +<td>api.templates.deactivate_body.info</td> +</tr> +<tr> +<td>Warning</td> +<td>Warning text</td> +<td>api.templates.deactivate_body.warning</td> +</tr> +</tbody> +</table> + +### SendInviteEmails + +**Purpose**: Sent to the user when team invite via email has been used. + +**Body Props**: + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '56%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Title</td> +<td>Message heading</td> +<td>api.templates.invite_body.title</td> +</tr> +<tr> +<td>Info1</td> +<td>Message body</td> +<td>api.templates.invite_body.info</td> +</tr> +<tr> +<td>Button</td> +<td>Button for confirmation</td> +<td>api.templates.invite_body.button</td> +</tr> +<tr> +<td>ExtraInfo</td> +<td>Additional info about Mattermost</td> +<td>api.templates.invite_body.extra_info</td> +</tr> +<tr> +<td>TeamURL</td> +<td>URL to the team the user has been invited to</td> +<td>--</td> +</tr> +<tr> +<td>Link</td> +<td>URL for team invite confirmation (not to be confused with TeamURL)</td> +<td>--</td> +</tr> +</tbody> +</table> + +### NotificationEmailBody + +**Purpose**: Sent to the user as a notification for new messages or mentions. + +**Body Props**: + +<table style={{width: '63%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '28%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>SiteURL</td> +<td>URL of the Mattermost server</td> +<td>--</td> +</tr> +<tr> +<td>Button</td> +<td>Button to post</td> +<td>api.templates.post_body.button</td> +</tr> +<tr> +<td>TeamLink</td> +<td>URL to Team</td> +<td>--</td> +</tr> +</tbody> +</table> + +This email can change depending on the settings and type of channel the notification is sent for. + +**For group channels**: + +**With full notification contents enabled**: + +<table style={{width: '68%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '15%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>Message intro</td> +<td>app.notification.body.intro.group_message.full</td> +</tr> +<tr> +<td>Info1</td> +<td>Channel name</td> +<td>app.notification.body.text.group_message.full</td> +</tr> +<tr> +<td>Info2</td> +<td>Message contents</td> +<td>app.notification.body.text.group_message.full2</td> +</tr> +<tr> +<td>SenderName</td> +<td>Name of sender</td> +<td>--</td> +</tr> +</tbody> +</table> + +**Without**: + +<table style={{width: '67%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>Message intro</td> +<td>app.notification.body.intro.group_message.generic</td> +</tr> +<tr> +<td>Info</td> +<td>Timestamp</td> +<td>app.notification.body.text.group_message.generic</td> +</tr> +</tbody> +</table> + +**For direct messages**: + +**With full notification contents enabled**: + +<table style={{width: '69%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>Message intro</td> +<td>app.notification.body.intro.direct.full</td> +</tr> +<tr> +<td>Info1</td> +<td>Empty for direct messages</td> +<td>--</td> +</tr> +<tr> +<td>Info2</td> +<td>Message contents</td> +<td>app.notification.body.text.direct.full</td> +</tr> +<tr> +<td>SenderName</td> +<td>Name of sender</td> +<td>--</td> +</tr> +</tbody> +</table> + +**Without**: + +<table style={{width: '60%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '37%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>Message intro</td> +<td>app.notification.body.intro.direct.generic</td> +</tr> +<tr> +<td>Info</td> +<td>Timestamp</td> +<td>app.notification.body.text.direct.generic</td> +</tr> +</tbody> +</table> + +**Notifications**: + +**With full notification contents enabled**: + +<table style={{width: '67%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '15%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>Message intro</td> +<td>app.notification.body.intro.notification.full</td> +</tr> +<tr> +<td>Info1</td> +<td>Channel name</td> +<td>app.notification.body.text.notification.full</td> +</tr> +<tr> +<td>Info2</td> +<td>Message contents</td> +<td>app.notification.body.text.notification.full2</td> +</tr> +<tr> +<td>SenderName</td> +<td>Name of sender</td> +<td>--</td> +</tr> +</tbody> +</table> + +**Without**: + +<table style={{width: '78%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<thead> +<tr> +<th>Prop</th> +<th>Content</th> +<th>i18n String</th> +</tr> +</thead> +<tbody> +<tr> +<td>BodyText</td> +<td>URL of the Mattermost server</td> +<td>app.notification.body.intro.notification.generic</td> +</tr> +<tr> +<td>Info</td> +<td>Message heading</td> +<td>app.notification.body.text.notification.generic</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/enabling-chinese-japanese-korean-search.mdx b/docs/main/administration-guide/configure/enabling-chinese-japanese-korean-search.mdx new file mode 100644 index 000000000000..b731c21c4e7b --- /dev/null +++ b/docs/main/administration-guide/configure/enabling-chinese-japanese-korean-search.mdx @@ -0,0 +1,167 @@ +--- +title: "Chinese, Japanese and Korean search" +--- +<PlanAvailability slug="all-commercial" /> + +<Important> + +Starting on Mattermost v11.5, searching for Chinese, Japanese or Korean (CJK) characters can be enabled with the [feature flag](https://developers.mattermost.com/contribute/more-info/server/feature-flags/#changing-feature-flag-values) `MM_FEATUREFLAGS_CJKSEARCH`. + +The general recommendation of [using either Elasticsearch or Opensearch once the server reaches 2.5 million posts](https://docs.mattermost.com/administration-guide/scale/enterprise-search.html#do-i-need-to-use-elasticsearch-or-aws-opensearch) still applies. + +What follows is the special configuration required for versions older than v11, where MySQL was still supported. + +</Important> + +See [database requirements documentation](/deployment-guide/software-hardware-requirements) for how to set up search for these languages. + +Below is additional information on how to configure the database for different languages. + +## 中文 / Chinese + +尽管在 Mattermost 8.0 更新后,官方推荐为了更好的性能请使用 PostgreSQL 作为后端数据库。 + +但就目前而言,使用 MySQL 能够更容易的实现中文语言的全文搜索功能,在妥善配置 ngram 后,根据官方数据库构造重新生成索引即可达成。 具体的操作方式,可参考: [Cannot search CJK contents](https://github.com/mattermost/mattermost/issues/2033#issuecomment-182336690)。 + +有关 PostgreSQL 的配置方式,请参考以下流程: + +### 配置 SCWS + +``` sh +# 取得 SCWS 代码 +wget http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2 +# 解压缩 +tar xvjf scws-1.2.3.tar.bz2 +# 进入解压后的目录 +cd scws-1.2.3 +# 执行配置脚本、编译并安装 +./configure --prefix=/usr/local/scws ; make ; make install + +# 可选:检查文件是否存在 +ls -al /usr/local/scws/lib/libscws.la +/usr/local/scws/bin/scws -h +# 可选:将词典安装在 /usr/local/scws/etc 中 +cd /usr/local/scws/etc +wget http://www.xunsearch.com/scws/down/scws-dict-chs-gbk.tar.bz2 +wget http://www.xunsearch.com/scws/down/scws-dict-chs-utf8.tar.bz2 +tar xvjf scws-dict-chs-gbk.tar.bz2 +tar xvjf scws-dict-chs-utf8.tar.bz2 +``` + +### 配置 Zhparser + +``` sh +# 下载 Zhparser 源代码 +git clone https://github.com/amutu/zhparser.git +# 进入下载后的目录 +cd zhparser +# 编译并安装 +SCWS_HOME=/usr/local/scws make && make install +``` + +<Note> + +自 Mattermost 6.0 起,官方已不再使用 mattermost/mattermost-prod-db 作为数据库镜像,你可以直接使用安装在服务器上的 PostgreSQL 数据库,或者使用 PostgreSQL 官方的 Docker 镜像。 + +如果使用 Docker 镜像作为数据库,可以预先执行以下命令,安装依赖(请根据实际的 PostgreSQL 版本选择)。 + +``` sh +# 更新本地缓存 +apt update +# 配置 SCWS 时需要的依赖 +apt install wget make gcc +# 配置 Zhparser 时需要的依赖 +apt install git postgresql-server-dev-13 +``` + +</Note> + +### 创建 extension 并增加解析配置 + +``` sql +-- 创建 extension +CREATE EXTENSION zhparser +-- 创建 text search configuration +CREATE TEXT SEARCH CONFIGURATION simple_zh_cfg (PARSER = zhparser); +-- 配置 token mapping +ALTER TEXT SEARCH CONFIGURATION simple_zh_cfg ADD MAPPING FOR n,v,a,i,e,l WITH simple; +``` + +### 更新 PostgreSQL 配置 + +将 postgresql.conf 中的 default_text_search_config 的值更改为 simple_zh_cfg。 + +更改后,需要重启数据库方可生效。 + +<Note> + +配置完成后,需根据 Mattermost 官方仓库中的 SQL 建表语句重新创建索引,方可正式启用中文语言的全文搜索功能。 + +未尽事宜,可以参考以下链接: + +- SCWS 官方文档 +- [Zhparser 官方文档](https://github.com/amutu/zhparser/blob/master/README.md) +- [Mattermost 建表语句](https://github.com/mattermost/mattermost/tree/master/server/channels/db/migrations/postgres) + +</Note> + +## 日本語 / Japanese + +日本語翻訳の改善は大歓迎です。自由に変更していただいて結構です。 + +### 検索設定 + +Mattermost で日本語検索をするためにはデータベースの設定変更が必要です + +- [MySQL](/deployment-guide/software-hardware-requirements#database-software) +- [Postgres](/deployment-guide/software-hardware-requirements#database-software) + +日本語(CJK)検索設定のドキュメントの改善にご協力ください + +### ガイド + +Qiita上で Mattermost のインストールおよび構成のガイドを提供しています。詳細については、\`こちら \[https://qiita.com/tags/mattermost\](https://qiita.com/tags/mattermost\)\`\_ をご覧ください。 + +## 한국어 / Korean + +이 문제에 대한 논의는 이 [이슈](https://github.com/mattermost/mattermost/issues/2033) 에서 시작되었습니다. + +한국어 버전 이용 시 문제점을 발견하면 [Localization 채널](https://community.mattermost.com/core/channels/localization) 또는 [한국어 채널](https://community.mattermost.com/core/channels/i18n-korean) 에서 의견을 제시할 수 있습니다. + +### 검색을 위한 데이터베이스 설정 + +PostgreSQL: PostgreSQL 데이터베이스에서는 따로 설정이 필요하지 않습니다. + +MySQL: MySQL에서는 전문 검색(Full-text search) 기능에 제한이 있기 때문에 추가적인 작업이 필요합니다. + +### MySQL 해결 방법 + +1. n-gram parser 를 이용하기 위해서는 MySQL의 버전이 5.7.6 이상이어야 합니다. +2. MySQL의 구성 파일에서 n-gram의 최소 토큰 크기를 다음과 같이 설정합니다. + +``` sql +[mysqld] +ft_min_word_len = 2 +innodb_ft_min_token_size = 2 +``` + +3. 데이터베이스를 재시작합니다. (이 과정은 반드시 필요합니다.) +4. 일부 테이블의 전문 검색 색인을 다음과 같이 재구성합니다. + +- 게시물 검색을 위한 설정 ( [참조](https://github.com/mattermost/mattermost/issues/2033#issuecomment-182336690) ) + +``` sql +DROP INDEX idx_posts_message_txt ON Posts; +CREATE FULLTEXT INDEX idx_posts_message_txt ON Posts (Message) WITH PARSER ngram; +``` + +- 해시 태그 검색을 위한 설정 ( [참조](https://github.com/mattermost/mattermost/pull/4555) ) + +``` sql +DROP INDEX idx_posts_hashtags_txt ON Posts; +CREATE FULLTEXT INDEX idx_posts_hashtags_txt ON Posts (Hashtags) WITH PARSER ngram; +``` + +- 사용자 검색을 위한 설정 + + `Users.idx_users_txt_all` 과 `Users.idx_users_names_all` 을 n-gram 없이 재구성합니다. diff --git a/docs/main/administration-guide/configure/environment-configuration-settings.mdx b/docs/main/administration-guide/configure/environment-configuration-settings.mdx new file mode 100644 index 000000000000..43ab0a2c1975 --- /dev/null +++ b/docs/main/administration-guide/configure/environment-configuration-settings.mdx @@ -0,0 +1,3897 @@ +--- +title: "Environment configuration settings" +draft: true +--- +import Inc0_push_notification_server_configuration_settings from './push-notification-server-configuration-settings.mdx'; +import Inc1_rate_limiting_configuration_settings from './rate-limiting-configuration-settings.mdx'; + +<PlanAvailability slug="all-commercial" /> + +Review and manage the following environmental configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Environment**: + +- [Web server](#web-server) +- [Database](#database) +- [Enterprise search](#enterprise-search) +- [File storage](#file-storage) +- [Image proxy](#image-proxy) +- [SMTP](#smtp) +- [Push notification server](#push-notification-server) +- [High availability](#high-availability) +- [Rate limiting](#rate-limiting) +- [Logging](#logging) +- [Session lengths](#session-lengths) +- [Performance monitoring](#performance-monitoring) +- [Developer](#developer) +- [Mobile security](#mobile-security) +- [config.json-only settings](#config-json-only-settings) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `SiteURL` value is under `ServiceSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.ServiceSettings.SiteURL'` +- When working with the `config.json` file manually, look for an object such as `ServiceSettings`, then within that object, find the key `SiteURL`. + +</Tip> + +## Web server + +With self-hosted deployments, you can configure the network environment in which Mattermost is deployed by going to **System Console \> Environment \> Web Server**, or by updating the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +### Site URL + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The URL that users use to access Mattermost. The port number is required if it’s not a standard port, such as 80 or 443. This field is required.</p><p>Select the <strong>Test Live URL</strong> button in the System Console to validate the Site URL.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SiteURL</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SITEURL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- The URL may contain a subpath, such as `https://example.com/company/mattermost`. +- If you change the Site URL value, log out of the Desktop App, and sign back in using the new domain. +- If Site URL is not set: + - Email notifications will contain broken links, and email batching will not work. + - Authentication via OAuth 2.0, including GitLab, Google, and Entra ID, will fail. + - Plugins may not work as expected. + +</Note> + +### Maximum URL length + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The longest URL, in characters, including query parameters, accepted by the Mattermost server. Longer URLs are rejected, and API calls fail with an error.</p><p>Numeric value. Default is <strong>2048</strong> characters.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>MaximumURLLength</code> > <code>2048</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_MAXIMUMURLLENGTH</code></li></ul></td> +</tr> +</tbody> +</table> + +### Web server listen address + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The address and port to which to bind and listen. Specifying <code>:8065</code> will bind to all network interfaces. Specifying <code>127.0.0.1:8065</code> will only bind to the network interface having that IP address.</p><p>If you choose a port of a lower level (called “system ports” or “well-known ports”, in the range of 0-1023), you must have permissions to bind to that port.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ListenAddress</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_LISTENADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Web server uses `address:port` (e.g., `":8065"`), while [Metrics](/administration-guide/configure/environment-configuration-settings#listen-address) uses a port number only (e.g., `8067`). + +</Note> + +### Forward port 80 to 443 + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Forward insecure traffic from port 80 to port 443.</p><ul><li><strong>true</strong>: Forwards all insecure traffic from port 80 to secure port 443.</li><li><strong>false</strong>: <strong>(Default)</strong> When using a proxy such as NGINX in front of Mattermost this setting is unnecessary and should be set to false.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>Forward80To443</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_FORWARD80TO443</code></li></ul></td> +</tr> +</tbody> +</table> + +### Web server connection security + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Connection security between Mattermost clients and the server.</p><ul><li><strong>Not specified</strong>: Mattermost will connect over an unsecure connection.</li><li><strong>TLS</strong>: Encrypts the communication between Mattermost clients and your server.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ConnectionSecurity</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_CONNECTIONSECURITY</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [setting up TLS for Mattermost](/deployment-guide/server/setup-tls) for details. + +### TLS certificate file + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The path to the certificate file to use for TLS connection security.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSCertFile</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSCERTFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### TLS key file + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The path to the TLS key file to use for TLS connection security.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSKeyFile</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSKEYFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Use Let's Encrypt + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable the automatic retrieval of certificates from Let’s Encrypt.</p><ul><li><strong>true</strong>: The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.</li><li><strong>false</strong>: <strong>(Default)</strong> Manual certificate specification based on the TLS Certificate File and TLS Key File specified above.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>UseLetsEncrypt</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_USELETSENCRYPT</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [setting up TLS for Mattermost](/deployment-guide/server/setup-tls) for details on setting up Let's Encrypt. + +### Let's Encrypt certificate cache file + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The path to the file where certificates and other data about the Let’s Encrypt service will be stored.</p><p>File path input.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>LetsEncryptCertificateCacheFile</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_LETSENCRYPTCERTIFICATECACHEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Read timeout + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Maximum time allowed from when the connection is accepted to when the request body is fully read.</p><p>Numerical input in seconds. Default is <strong>300</strong> seconds.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ReadTimeout</code> > <code>300</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_READTIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Write timeout + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li>If using HTTP (insecure), this is the maximum time allowed from the end of reading the request headers until the response is written.</li><li>If using HTTPS, it's the total time from when the connection is accepted until the response is written.</li></ul><p>Numerical input in seconds. Default is <strong>300</strong> seconds.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>WriteTimeout</code> > <code>300</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_WRITETIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Idle timeout + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set an explicit idle timeout in the HTTP server. This is the maximum time allowed before an idle connection is disconnected.</p><p>Numerical input in seconds. Default is <strong>300</strong> seconds.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>IdleTimeout</code> > <code>300</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_IDLETIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Webserver mode + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend gzip to improve performance unless your environment has specific restrictions, such as a web proxy that distributes gzip files poorly.</p><ul><li><strong>gzip</strong>: <strong>(Default)</strong> The Mattermost server will serve static files compressed with gzip to improve performance. gzip compression applies to the HTML, CSS, Javascript, and other static content files that make up the Mattermost web client.</li><li><strong>Uncompressed</strong>: The Mattermost server will serve static files uncompressed.</li><li><strong>Disabled</strong>: The Mattermost server will not serve static files.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>WebserverMode</code> > <code>"gzip"</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_WEBSERVERMODE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable insecure outgoing connections + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to allow insecure outgoing connections.</p><ul><li><strong>true</strong>: Outgoing HTTPS requests, including S3 clients, can accept unverified, self-signed certificates. For example, outgoing webhooks to a server with a self-signed TLS certificate, using any domain, will be allowed, and will skip TLS verification.</li><li><strong>false</strong>: <strong>(Default)</strong> Only secure HTTPS requests are allowed.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableInsecureOutgoingConnections</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEINSECUREOUTGOINGCONNECTIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Warning> + +Enabling this feature makes these connections susceptible to man-in-the-middle attacks. + +</Warning> + +### Managed resource paths + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>A comma-separated list of paths within the Mattermost domain that are managed by a third party service instead of Mattermost itself.</p><p>Links to these paths will be opened in a new tab/window by Mattermost apps.</p><p>For example, if Mattermost is running on <code>https://mymattermost.com</code>, setting this to conference will cause links such as <code>https://mymattermost.com/conference</code> to open in a new window.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ManagedResourcePaths</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_MANAGEDRESOURCEPATHS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +When using the Mattermost Desktop App, additional configuration is required to open the link within the Desktop App instead of in a browser. See the [desktop managed resources](/deployment-guide/desktop/desktop-app-managed-resources) documentation for details. + +</Note> + +### Reload configuration from disk + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '47%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>You must change the database line in the <code>config.json</code> file, and then reload configuration to fail over without taking the server down.</p><p>Select the <strong>Reload configuration from disk</strong> button in the System Console after changing your database configuration. Then, go to <strong>Environment > Database</strong> and select <strong>Recycle Database Connections</strong> to complete the reload.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Purge all caches + +<table> +<colgroup> +<col style={{width: '47%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Purge all in-memory caches for sessions, accounts, and channels.</p><p>Select the <strong>Purge All Caches</strong> button in the System Console to purge all caches.</p></td> +<td><ul><li>System Config path: <strong>Environment > Web Server</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Purging the caches may adversely impact performance. [high availability cluster-based deployments](/administration-guide/scale/high-availability-cluster-based-deployment) will attempt to purge all the servers in the cluster. + +</Note> + +### Websocket URL + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>You can configure the server to instruct clients on where they should try to connect websockets to.</p><p>String input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>WebsocketURL</code> > <code>""</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_WEBSOCKETURL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +We strongly recommend configuring a single websocket URL that matches the [Site URL](#site-url) configuration setting. + +</Note> + +### License file location + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The path and filename of the license file on disk. On startup, if Mattermost can't find a valid license in the database from a previous upload, it looks in this path for the license file.</p><p>String input. Can be an absolute path or a path relative to the <code>mattermost</code> directory.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>LicenseFileLocation</code> > <code>""</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_LICENSEFILELOCATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### TLS minimum version + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The minimum TLS version used by the Mattermost server.</p><p>String input. Default is <strong>1.2</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSMinVer</code> > <code>1.2</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSMINVER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting only takes effect if you are using the built-in server binary directly, and not using a reverse proxy layer, such as NGINX. + +</Note> + +### Trusted proxy IP header + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specified headers that will be checked, one by one, for IP addresses (order is important). All other headers are ignored.</p><p>String array input consisting of header names, such as <code>["X-Forwarded-For", "X-Real-Ip"]</code>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TrustedProxyIPHeader</code> > <code>[]</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- The default value of `[]` means that no header will be trusted. +- We recommend keeping the default setting when Mattermost is running without a proxy to avoid the client sending the headers and bypassing rate limiting and/or the audit log. +- For environments that use a reverse proxy, this issue does not exist, provided that the headers are set by the reverse proxy. In those environments, only explicitly whitelist the header set by the reverse proxy and no additional values. + +</Note> + +### Enable Strict Transport Security (HSTS) + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Adds the Strict Transport Security (HSTS) header to all responses, forcing the browser to request all resources via HTTPS.</li><li><strong>false</strong>: <strong>(Default)</strong> No restrictions on TLS transport. Strict Transport Security (HSTS) header isn't added to responses.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSStrictTransport</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSSTRICTTRANSPORT</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) documentation for details. + +### Secure TLS transport expiry + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The time, in seconds, that the browser remembers a site is only to be accessed using HTTPS. After this period, a site can't be accessed using HTTP unless <code>TLSStrictTransport</code> is set to <code>true</code>.</p><p>Numerical input. Default is <strong>63072000</strong> (2 years).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSStrictTransportMaxAge</code> > <code>63072000</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSSTRICTTRANSPORTMAXAGE</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) documentation for details. + +### TLS cipher overwrites + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set TLS ciphers overwrites to meet requirements from legacy clients which don't support modern ciphers, or to limit the types of accepted ciphers.</p><p>If none specified, the Mattermost server assumes a set of currently considered secure ciphers, and allows overwrites in the edge case.</p><p>String array input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TLSOverwriteCiphers</code> > <code>[]</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TLSOVERWRITECIPHERS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting only takes effect if you are using the built-in server binary directly and not using a reverse proxy layer, such as NGINX. +- See the `ServerTLSSupportedCiphers` variable in [/model/config.go](https://github.com/mattermost/mattermost/blob/master/server/public/model/config.go) for a list of ciphers considered secure. + +</Note> + +### Goroutine health threshold + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set a threshold on the number of goroutines when the Mattermost system is considered to be in a healthy state.</p><p>When goroutines exceed this limit, a warning is returned in the server logs.</p><p>Numeric input. Default is <strong>-1</strong> which turns off checking for the threshold.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>GoroutineHealthThreshold</code> > <code>-1</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_GOROUTINEHEALTHTHRESHOLD</code></li></ul></td> +</tr> +</tbody> +</table> + +### Allow cookies for subdomains + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows cookies for subdomains by setting the domain parameter on Mattermost cookies.</li><li><strong>false</strong>: Cookies aren't allowed for subdomains.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>AllowCookiesForSubdomains</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ALLOWCOOKIESFORSUBDOMAINS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Cluster log timeout + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Define the frequency, in milliseconds, of cluster request time logging for performance monitoring.</p><p>Numerical input. Default is <strong>2000</strong> milliseconds (2 seconds).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ClusterLogTimeoutMilliseconds</code> > <code>2000</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_CLUSTERLOGTIMEOUTMILLISECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) documentation for details. + +### Maximum payload size + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum payload size in bytes for all APIs except APIs that receive a file as an input.</p><p>For example, the upload attachment API or the API to upload a custom emoji.</p><p>Numerical value. Default is <strong>300000</strong> (300 kB).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>MaximumPayloadSizeBytes</code> > <code>300000</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_MAXIMUMPAYLOADSIZEBYTES</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Database + +With self-hosted deployments, you can configure the database environment in which Mattermost is deployed by going to **System Console \> Environment \> Database**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +### Driver name + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The type of database. Can be either:</p><ul><li><strong>mysql</strong>: <strong>(Default)</strong> Enables driver to MySQL database.</li><li><strong>postgres</strong>: Enables driver to PostgreSQL database.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>DriverName</code></li><li>Environment variable: <code>MM_SQLSETTINGS_DRIVERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Data source + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The connection string to the master database.</p><p>String input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>DataSource</code></li><li>Environment variable: <code>MM_SQLSETTINGS_DATASOURCE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### PostgreSQL databases + +When **Driver Name** is set to postgres, use a connection string in the form of: `postgres://mmuser:password@hostname_or_IP:5432/mattermost_test?sslmode=disable&connect_timeout=10` + +**To use TLS with PostgreSQL databases** + +The parameter to encrypt connection against a PostgreSQL server is sslmode. The library used to interact with PostgreSQL server is [pq](https://pkg.go.dev/github.com/lib/pq). Currently, it's not possible to use all the values that you could pass to a standard PostgreSQL Client `psql "sslmode=value"` See the [SSL Mode Descriptions](https://www.postgresql.org/docs/current/libpq-ssl.html) documentation for details. + +Your database admin must configure the functionality according to the supported values described below. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '30%'}} /> +<col style={{width: '13%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<thead> +<tr> +<th>Short description of the <code>sslmode</code> parameter</th> +<th>Value</th> +<th>Example of a data source name</th> +</tr> +</thead> +<tbody> +<tr> +<td><p>Don't use TLS / SSL encryption against the PostgreSQL server.</p><p>Default value in file <code>config.json</code></p></td> +<td><code>disable</code></td> +<td><code>postgres://mmuser:password@hostname_or_IP:5432/mattermost_test ?sslmode=disable&connect_timeout=10</code></td> +</tr> +<tr> +<td><p>The data is encrypted and the network is trusted.</p><p>Default value is <code>sslmode</code> when omitted.</p></td> +<td><code>require</code></td> +<td><code>postgres://mmuser:password@hostname_or_IP:5432/mattermost_test ?sslmode=require&connect_timeout=10</code></td> +</tr> +<tr> +<td>The data is encrypted when connecting to a trusted server.</td> +<td><code>verify-ca</code></td> +<td><code>postgres://mmuser:password@hostname_or_IP:5432/mattermost_test ?sslmode=verify-ca&connect_timeout=10</code></td> +</tr> +<tr> +<td>The data is encrypted when connecting to a trusted server.</td> +<td><code>verify-full</code></td> +<td><code>postgres://mmuser:password@hostname_or_IP:5432/mattermost_test ?sslmode=verify-full&connect_timeout=10</code></td> +</tr> +</tbody> +</table> + +#### MySQL Databases + +When Driver Name is set to mysql, we recommend using collation over using charset. + +To specify collation: + +``` text +"SqlSettings": { + "DataSource": "<mmuser:password>@tcp(hostname or IP:3306)/mattermost?charset=utf8mb4,utf8&collation=utf8mb4_general_ci", + [...] +} +``` + +If collation is omitted, the default collation, `utf8mb4_general_ci` is used: + +``` text +"SqlSettings": { + "DataSource": "<mmuser:password>@tcp(hostname or IP:3306)/mattermost?charset=utf8mb4,utf8", + [...] +} +``` + +<Note> + +If you’re using MySQL 8.0 or later, the default collation has changed to `utf8mb4_0900_ai_ci`. See our [Database Software Requirements](/deployment-guide/software-hardware-requirements) documentation for details on MySQL 8.0 support. + +</Note> + +**To use TLS with MySQL Databases** + +The parameter to encrypt connection against a MySQL server is `tls`. + +The library used to interact with MySQL is [Go-MySQL-Driver](https://pkg.go.dev/github.com/go-sql-driver/mysql). + +For the moment, it's not possible to use all the values that you could pass to a standard MySQL Client `mysql --ssl-mode=value`. See [Connection-Encryption Option Summary](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode) documentation for a version 8.0 example. + +Your database admin must configure the functionality according to supported values described below. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '14%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<thead> +<tr> +<th>Short description of the <code>tls</code> parameter</th> +<th>Value</th> +<th>Example of a data source name</th> +</tr> +</thead> +<tbody> +<tr> +<td>Don't use TLS / SSL encryption against MySQL server.</td> +<td><code>false</code></td> +<td><code>"<mmuser:password>@tcp(hostname or IP:3306)/mattermost_test ?charset=utf8mb4,utf8&writeTimeout=30s&tls=false"</code></td> +</tr> +<tr> +<td>Use TLS / SSL encryption against MySQL server.</td> +<td><code>true</code></td> +<td><code>"<mmuser:password>@tcp(hostname or IP:3306)/mattermost_test ?charset=utf8mb4,utf8&writeTimeout=30s&tls=true"</code></td> +</tr> +<tr> +<td>Use TLS / SSL encryption with a self-signed certificate against MySQL server.</td> +<td><code>skip-verify</code></td> +<td><code>"<mmuser:password>@tcp(hostname or IP:3306)/mattermost_test ?charset=utf8mb4,utf8&writeTimeout=30s&tls=skip-verify"</code></td> +</tr> +<tr> +<td>Use TLS / SSL encryption if server advertises a possible fallback; unencrypted if it's not advertised.</td> +<td><code>preferred</code></td> +<td><code>"<mmuser:password>@tcp(hostname or IP:3306)/mattermost_test ?charset=utf8mb4,utf8&writeTimeout=30s&tls=preferred"</code></td> +</tr> +</tbody> +</table> + +#### AWS High Availablity RDS cluster deployments + +For an AWS High Availability RDS cluster deployment, point this configuration setting to the write/read endpoint at the **cluster** level to benefit from the AWS failover handling. AWS takes care of promoting different database nodes to be the writer node. Mattermost doesn't need to manage this. See the [high availablility database configuration](/administration-guide/scale/high-availability-cluster-based-deployment#database-configuration) documentation for details. + +### Maximum open connections + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of open connections to the database.</p><p>Numerical input. Default is <strong>100</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>MaxOpenConns</code> > <code>100</code></li><li>Environment variable: <code>MM_SQLSETTINGS_MAXOPENCONNS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum idle connections + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of idle connections held open to the database.</p><p>Numerical input. Default is <strong>50</strong>. A 2:1 ratio with MaxOpenConns is recommended.</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>MaxIdleConns</code> > <code>50</code></li><li>Environment variable: <code>MM_SQLSETTINGS_MAXIDLECONNS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Query timeout + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The amount of time to wait, in seconds, for a response from the database after opening a connection and sending the query.</p><p>Numerical input in seconds. Default is <strong>30</strong> seconds.</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>QueryTimeout</code> > <code>30</code></li><li>Environment variable: <code>MM_SQLSETTINGS_QUERYTIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum connection lifetime + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Maximum lifetime for a connection to the database, in milliseconds. Use this setting to configure the maximum amount of time a connection to the database may be reused</p><p>Numerical input in milliseconds. Default is <strong>3600000</strong> milliseconds (1 hour).</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>ConnMaxLifetimeMilliseconds</code> > <code>3600000</code></li><li>Environment variable: <code>MM_SQLSETTINGS_CONNMAXLIFETIMEMILLISECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum connection idle timeout + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Maximum time a database connection can remain idle, in milliseconds.</p><p>Numerical input in milliseconds. Default is <strong>300000</strong> (5 minutes).</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>ConnMaxIdleTimeMilliseconds</code> > <code>300000</code></li><li>Environment variable: <code>MM_SQLSETTINGS_CONNMAXIDLETIMEMILLISECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Minimum hashtag length + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td>Minimum number of characters in a hashtag. This value must be greater than or equal to <strong>2</strong>.</td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>MinimumHashtagLength</code> > <code>3</code></li><li>Environment variable: <code>MM_SQLSETTINGS_MINIMUMHASHTAGLENGTH</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +MySQL databases must be configured to support searching strings shorter than three characters. See the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/fulltext-fine-tuning.html) for details. + +</Note> + +### SQL statement logging + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Executed SQL statements can be written to the log for development.</p><ul><li><strong>true</strong>: Executing SQL statements are written to the log.</li><li><strong>false</strong>: <strong>(Default)</strong> SQL statements aren't written to the log.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>Trace</code> > <code>false</code></li><li>Environment variable: <code>MM_SQLSETTINGS_TRACE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Recycle database connections + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Select the <strong>Recycle Database Connections</strong> button to manually recycle the connection pool by closing the current set of open connections to the database within 20 seconds, and then creating a new set of connections.</p><p>To fail over without stopping the server, change the database line in the <code>config.json</code> file, select <strong>Reload Configuration from Disk</strong> via <strong>Environment > Web Server</strong>, then select <strong>Recycle Database Connections</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > Database</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Disable database search + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>When <a href="mm-doc:%2Fadministration-guide%2Fscale%2Fenterprise-search">enterprise-scale search</a>, | - System Config path: <strong>Environment > Database</strong> database search can be disabled from performing searches. | - <code>config.json</code> setting: <code>SqlSettings</code> > <code>DisableDatabaseSearch</code> > <code>false</code> | | - Environment variable: <code>MM_SQLSETTINGS_DISABLEDATABASESEARCH</code> | - <strong>true</strong>: Disables the use of the database to perform | | searches. If another search engine isn't configured, | | setting this value to <code>true</code> will result in empty search | | results. | | - <strong>false</strong>: <strong>(Default)</strong> Database search isn't disabled. | |</td> +</tr> +</tbody> +</table> + +Search behavior in Mattermost depends on which search engines are enabled: + +- When [Elasticsearch](/administration-guide/scale/elasticsearch-setup) or [AWS OpenSearch](/administration-guide/scale/opensearch-setup) is enabled, Mattermost will try to use it first. +- If Elasticsearch fails or is disabled, Mattermost will attempt to use Bleve search, if enabled. Bleve search has been deprecated in Mattermost v11.0. We recommend using Elasticsearch or OpenSearch for enterprise search capabilities. +- If these fail or are disabled, Mattermost tries to search the database directly, if this is enabled. +- If all of the above methods fail or are disabled, the search results will be empty. + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas: + +- **Reduced Database Load**: When database search is enabled, every search query executed by users needs to interact with the database, leading to additional load on the database server. By disabling database search, you can avoid these queries, thereby reducing the database load. +- **Improved Response Time**: Database searches can be time-consuming, especially with large datasets. Disabling database search can result in faster response times because the system no longer spends time fetching and processing search results from the database. +- **Offloading Search to Indexing Services**: Disabling database search often means that searches are offloaded to specialized indexing services like Elasticsearch, which are optimized for search operations. These services can provide faster and more efficient search capabilities compared to traditional database searches. +- **Lower Resource Consumption**: Running search queries directly against the database can be resource-intensive (using CPU and memory). With database search disabled, these resources can be allocated to other critical functions, improving overall system performance. +- **Enhanced Scalability**: As the number of users and data volume grow, database search can become less efficient. Specialized search services are designed to scale more effectively, enhancing overall system scalability and performance. + +However, the ability to perform database searches in Mattermost is a critical feature for many users, particularly when other search engines aren't enabled. Disabling this feature will result in users seeing an error if they attempt to use the Mattermost Search box. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Applied schema migrations + +A list of all migrations that have been applied to the data store based on the version information available in the `db_migrations` table. Select **About Mattermost** from the Product <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu to review the current database schema version applied to your deployment. + +### Active search backend + +Read-only display of the currently active backend used for search. Values can include `none`, `database`, `elasticsearch`, or `bleve`. + +### Read replicas + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Specifies the connection strings for the read replica databases.</td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>DataSourceReplicas</code> > <code>[]</code></li><li>Environment variable: <code>MM_SQLSETTINGS_DATASOURCEREPLICAS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Each database connection string in the array must be in the same form used for the [Data source](#data-source) setting. +- Space separate multiple read replicas in the array to allow Mattermost to load balance read queries across multiple database instances. For example, `MM_SQLSETTINGS_DATASOURCEREPLICAS=dc-1 dc-2` + +</Note> + +#### AWS High Availability RDS cluster deployments + +For an AWS High Availability RDS cluster deployment, point this configuration setting directly to the underlying read-only node endpoint within the RDS cluster to circumvent the failover/load balancing that AWS/RDS takes care of (except for the write traffic). Mattermost has its own method of balancing the read-only connections and can also balance those queries to the data source/write+read connection should those nodes fail. See the [high availablility database configuration](/administration-guide/scale/high-availability-cluster-based-deployment#database-configuration) documentation for details. + +### Search replicas + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td>Specifies the connection strings for the search replica databases. A search replica is similar to a read replica, but is used only for handling search queries.</td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>DataSourceSearchReplicas</code> > <code>[]</code></li><li>Environment variable: <code>MM_SQLSETTINGS_DATASOURCESEARCHREPLICAS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Each database connection string in the array must be in the same form used for the [Data source](#data-source) setting. + +</Note> + +#### AWS High Availability RDS cluster deployments + +For an AWS High Availability RDS cluster deployment, point this configuration setting directly to the underlying read-only node endpoint within the RDS cluster to circumvent the failover/load balancing that AWS/RDS takes care of (except for the write traffic). Mattermost has its own method of balancing the read-only connections and can also balance those queries to the data source/write+read connection should those nodes fail. See the [high availablility database configuration](/administration-guide/scale/high-availability-cluster-based-deployment#database-configuration) documentation for details. + +### Replica lag settings + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>String array input specifies a connection string and user-defined SQL queries on the database to measure replica lag for a single replica instance.</p><p>These settings monitor absolute lag based on binlog distance/transaction queue length, and the time taken for the replica to catch up.</p><p>String array input consists of:</p><ul><li><code>DataSource</code>: The database credentials to connect to the database instance.</li><li><code>QueryAbsoluteLag</code>: A plain SQL query that must return a single row. The first column must be the node value of the Prometheus metric, and the second column must be the value of the lag used to measure absolute lag.</li><li><code>QueryTimeLag</code>: A plain SQL query that must return a single row. The first column must be the node value of the Prometheus metric, and the second column must be the value of the lag used to measure the time lag.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>ReplicaLagSettings</code> > <code>[]</code></li><li>Environment variable: <code>MM_SQLSETTINGS_REPLICALAGSETTINGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- The `QueryAbsoluteLag` and `QueryTimeLag` queries must return a single row. +- To properly monitor this, you must set up [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) for Mattermost. + +</Note> + +1. Configure the replica lag metric based on your database type. See the following tabs for details on configuring this for each database type. + +> <div class="tab"> +> +> AWS Aurora +> +> Add the configuration highlighted below to your `SqlSettings.ReplicaLagSettings` array. You only need to add this once because replication statistics for AWS Aurora nodes are visible across all server instances that are members of the cluster. Be sure to change the `DataSource` to point to a single node in the group. +> +> For more information on Aurora replication stats, see the [AWS Aurora documentaion](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora_global_db_instance_status.html). +> +> Example +> +> ``` json +> { +> "SqlSettings": { +> "ReplicaLagSettings": [ +> { +> "DataSource": "replica-1", +> "QueryAbsoluteLag": "select server_id, highest_lsn_rcvd-durable_lsn as bindiff from aurora_global_db_instance_status() where server_id=<>", +> "QueryTimeLag": "select server_id, visibility_lag_in_msec from aurora_global_db_instance_status() where server_id=<>" +> } +> ] +> } +> } +> ``` +> +> </div> +> +> <div class="tab"> +> +> MySQL Group Replication +> +> Add the configuration highlighted below to your `SqlSettings.ReplicaLagSettings` array. You only need to add this once because replication statistics for all nodes are shared across all server instances that are members of the MySQL replication group. Be sure to change the `DataSource` to point to a single node in the group. +> +> For more information on group replication stats, see the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/group-replication-replication-group-member-stats.html). +> +> Example +> +> ``` json +> { +> "SqlSettings": { +> "ReplicaLagSettings": [ +> { +> "DataSource": "replica-1", +> "QueryAbsoluteLag": "select member_id, count_transactions_remote_in_applier_queue FROM performance_schema.replication_group_member_stats where member_id=<>", +> "QueryTimeLag": "" +> } +> ] +> } +> } +> ``` +> +> </div> +> +> <div class="tab"> +> +> PostgreSQL replication slots +> +> 1. Add the configuration highlighted below to your `SqlSettings.ReplicaLagSettings` array. This query should run against the **primary** node in your cluster, to do this change the `DataSource` to match the [SqlSettings.DataSource](#data-source) setting you have configured. +> +> For more information on pg_stat_replication, see the [PostgreSQL documentation](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW). +> +> > **Example:** +> > +> > ``` json +> > { +> > "SqlSettings": { +> > "ReplicaLagSettings": [ +> > { +> > "DataSource": "postgres://mmuser:password@localhost:5432/mattermost_test?sslmode=disable&connect_timeout=10.", +> > "QueryAbsoluteLag": "select usename, pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) as metric from pg_stat_replication;", +> > "QueryTimeLag": "" +> > } +> > ] +> > } +> > } +> > ``` +> +> 2. Grant permissions to the database user for `pg_monitor`. This user should be the same user configured above in the `DataSource` string. +> +> > For more information on roles, see the [PostgreSQL documentation](https://www.postgresql.org/docs/10/default-roles.html). +> > +> > ``` sh +> > sudo -u postgres psql +> > postgres=# GRANT pg_monitor TO mmuser; +> > ``` +> +> </div> + +2. Save the config and restart all Mattermost nodes. +3. Navigate to your Grafana instance monitoring Mattermost and open the [Mattermost Performance Monitoring v2](https://grafana.com/grafana/dashboards/15582-mattermost-performance-monitoring-v2/) dashboard. +4. The `QueryTimeLag` chart is already setup for you utilizing the existing `Replica Lag` chart. If using `QueryAbsoluteLag` metric clone the `Replica Lag` chart and edit the query to use the below absolute lag metrics and modify the title to be `Replica Lag Absolute`. + +> ``` text +> mattermost_db_replica_lag_abs{instance=~"$server"} +> ``` +> +> ![A screenshot showing how to clone a chart within Grafana](/images/database-configuration-settings-replica-lag-grafana-1.jpg) +> +> ![A screenshot showing the specific edits to make to the cloned grafana chart.](/images/database-configuration-settings-replica-lag-grafana-2.jpg) + +### Replica monitor interval (seconds) + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specifies how frequently unhealthy replicas will be monitored for liveness check. Mattermost will dynamically choose a replica if it's alive.</p><p>Numerical input. Default is 5 seconds.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>SqlSettings</code> > <code>ReplicaMonitorIntervalSeconds</code> > <code>5</code></li><li>Environment variable: <code>MM_SQLSETTINGS_REPLICAMONITORINTERVALSECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This configuration setting is applicable to self-hosted deployments only. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Enterprise search + +<PlanAvailability slug="ent-plus" /> + +Core database search happens in a relational database and is intended for deployments under about 2–3 million posts and file entries. Beyond that scale, enabling enterprise search with Elasticsearch or AWS OpenSearch is highly recommended for optimum search performance before reaching 3 million posts. + +For self-hosted deployments with over 3 million posts, Elasticsearch or AWS OpenSearch is required to avoid significant performance issues, such as timeouts, with [message searches](/end-user-guide/collaborate/search-for-messages) and [@mentions](/end-user-guide/collaborate/mention-people). + +You can configure Mattermost enterprise search by going to **System Console \> Environment \> Elasticsearch**. The following configuration settings apply to both Elasticsearch and AWS OpenSearch. You can also edit the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +### Enable Elasticsearch indexing + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to index new posts automatically.</p><ul><li><strong>true</strong>: Indexing of new messages occurs automatically.</li><li><strong>false</strong>: <strong>(Default)</strong> Indexing of new messages is disabled, and new messages aren't indexed.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>EnableIndexing</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_ENABLEINDEXING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If indexing is disabled and then re-enabled after an index is created, purge and rebuild the index to ensure complete search results. + +</Note> + +### Backend type + +Both [Elasticsearch](/administration-guide/scale/elasticsearch-setup) and [AWS OpenSearch](/administration-guide/scale/opensearch-setup) provide enterprise-scale deployments with optimized search performance and prevents performance degradation and timeouts. Learn more about [enterprise search](/administration-guide/scale/enterprise-search) in our product documentation. + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The type of search backend.</p><ul><li><code>elasticsearch</code> - (<strong>Default</strong>)</li><li><code>opensearch</code> - Required for AWS OpenSearch.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>Backend</code> > <code>"elasticsearch"</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_BACKEND</code></li></ul></td> +</tr> +</tbody> +</table> + +Learn more about [enterprise search version support](/administration-guide/scale/enterprise-search#supported-paths). + +### Server connection address + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>The address of the Elasticsearch or AWS OpenSearch server.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>ConnectionUrl</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CONNECTIONURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### CA path + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Optional path to the Custom Certificate Authority certificates for the Elasticsearch or AWS OpenSearch server.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>CA</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CA</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Available from Mattermost v7.8. The certificate path should be `/opt/mattermost/data/elasticsearch/` or `/opt/mattermost/data/opensearch` and configured in the System Console as `./elasticsearch/cert.pem` or `./opensearch/cert.pem`. +- Can be used in conjunction with basic authentication credentials or can replace them. Leave this setting blank to use the default Certificate Authority certificates for the operating system. + +</Note> + +### Client certificate path + +Available from Mattermost v7.8. Can be used in conjunction with basic auth credentials or to replace them. + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Optional client certificate for the connection to the Elasticsearch or AWS OpenSearch server in the PEM format.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>ClientCert</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CLIENTCERT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Client certificate key path + +Available from Mattermost v7.8. Can be used in conjunction with basic auth credentials or to replace them. + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Optional key for the client certificate in the PEM format.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>ClientKey</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CLIENTKEY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Skip TLS verification + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The certificate step for TLS connections can be skipped.</p><ul><li><strong>true</strong>: Skips the certificate verification step for TLS connections.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost requires certificate verification.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>SkipTLSVerification</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_SKIPTLSVERIFICATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Server username + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) The username to authenticate to the Elasticsearch or AWS OpenSearch server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>UserName</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_USERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Server password + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>(Optional) The password to authenticate to the Elasticsearch or AWS OpenSearch server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>Password</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_PASSWORD</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable cluster sniffing + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to automatically find and connect to all data nodes in a cluster.</p><ul><li><strong>true</strong>: Sniffing finds and connects to all data nodes in your cluster automatically.</li><li><strong>false</strong>: <strong>(Default)</strong> Cluster sniffing is disabled.</li></ul><p>Do not enable cluster sniffing when using cloud-hosted search providers such as Amazon OpenSearch Service.</p></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>Sniff</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_SNIFF</code></li></ul></td> +</tr> +</tbody> +</table> + +Select the **Test Connection** button in the System Console to validate the connection between Mattermost and the Elasticsearch or AWS OpenSearch server. + +### Bulk indexing + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td>Configure Mattermost to start a bulk index of all existing posts in the database, from oldest to newest.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Always [purge indexes](#purge-indexes) before bulk indexing. +- Select the **Index Now** button in the System Console to start a bulk index of all posts, and review all index jobs in progress. +- Elasticsearch or AWS OpenSearch is available during indexing, but search results may be incomplete until the indexing job is complete. +- If an in-progress indexing job is canceled, the index and search results will be incomplete. + +</Note> + +### Rebuild channels index + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td>Purge the channels index adn re-index all channels in the database, from oldest to newest.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +Select the **Rebuild Channels Index** button in the System Console to purge the channels index. Ensure no other indexing jobs are in progress via the **Bulk Indexing** table before starting this process. During indexing, channel auto-complete is available, but search results may be incomplete until the indexing job is complete. + +### Purge indexes + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td>Purge the entire Elasticsearch index.</td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +Select the **Purge Indexes** button in the System Console to purge the index. After purging the index, create a new index by selecting the **Index Now** button. + +### Indexes to skip while purging + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify index names to ignore while purging indexes. Separate multiple index names with commas.</p><p>Use an asterisk (*) to match a sequence of index name characters.</p></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>IgnoredPurgeIndexes</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_IGNOREDPURGEINDEXES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable Elasticsearch for search queries + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to use Elasticsearch or AWS OpenSearch for all search queries using the latest index.</p><ul><li><strong>true</strong>: Elasticsearch or AWS OpenSearch is used for all search queries using the latest index. Search results may be incomplete until a bulk index of the existing message database is completed.</li><li><strong>false</strong>: <strong>(Default)</strong> Database search is used for search queries.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>EnableSearching</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_ENABLESEARCHING</code></li></ul></td> +</tr> +</tbody> +</table> + +If indexing is disabled and then re-enabled after an index is created, purge and rebuild the index to ensure complete search results. + +### Enable Elasticsearch for autocomplete queries + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to use Elasticsearch or AWS OpenSearch for all autocompletion queries on users and channels using the latest index.</p><ul><li><strong>true</strong>: Elasticsearch or AWS OpenSearch will be used for all autocompletion queries on users and channels using the latest index.</li><li><strong>false</strong>: <strong>(Default)</strong> Database autocomplete is used.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>EnableAutocomplete</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_ENABLEAUTOCOMPLETE</code></li></ul></td> +</tr> +</tbody> +</table> + +Autocompletion results may be incomplete until a bulk index of the existing users and channels database is finished. + +### Allow searching public channels without membership + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Allow users to search for messages in public channels they have not joined.</p><p>When enabled for the first time, existing posts are updated in the background with channel type information. This backfill process is throttled to ~10,000 posts per second to avoid impacting search performance.</p><ul><li><strong>true</strong>: Users can find messages in public channels they haven't joined, scoped to teams they belong to.</li><li><strong>false</strong>: <strong>(Default)</strong> Users can only search messages in channels they are a member of.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Elasticsearch</strong></li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>EnableSearchPublicChannelsWithoutMembership</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_ENABLESEARCHPUBLICCHANNELSWITHOUTMEMBERSHIP</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting has no effect when [Compliance Mode](/administration-guide/configure/compliance-configuration-settings#enable-compliance-reporting) is enabled. When Compliance Mode is active, search results are always restricted to channels the user is a member of. + +</Note> + +### Post index replicas + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of replicas to use for each post index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>PostIndexReplicas</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_POSTINDEXREPLICAS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- If this setting is changed, the changed configuration only applies to newly-created indexes. To apply the change to existing indexes, purge and rebuild the index after changing this setting. +- If there are `n` data nodes, the number of replicas per shard for each index should be `n-1`. +- If the number of nodes in an Elasticsearch or AWS OpenSearch cluster changes, this configuration setting, as well as [Channel Index Replicas](#channel-index-replicas) and [User Index Replicas](#user-index-replicas) must also be updated accordingly. + +</Note> + +### Post index shards + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of shards to use for each post index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>PostIndexShards</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_POSTINDEXSHARDS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If this configuration setting is changed, the changed configuration only applies to newly-created indexes. To apply the change to existing indexes, purge and rebuild the index after changing this setting. + +</Note> + +### Channel index replicas + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of replicas to use for each channel index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>ChannelIndexReplicas</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CHANNELINDEXREPLICAS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If there are `n` data nodes, the number of replicas per shard for each index should be `n-1`. If the number of nodes in an Elasticsearch or AWS OpenSearch cluster changes, this configuration setting, as well as [Post Index Replicas](#post-index-shards) and [User Index Replicas](#user-index-replicas) must also be updated accordingly. + +</Note> + +### Channel index shards + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of shards to use for each channel index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>ChannelIndexShards</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_CHANNELINDEXSHARDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### User index replicas + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of replicas to use for each user index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>UserIndexReplicas</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_USERINDEXREPLICAS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If there are `n` data nodes, the number of replicas per shard for each index should be `n-1`. If the number of nodes in an Elasticsearch or AWS OpenSearch cluster changes, this configuration setting, as well as [Post Index Replicas](#post-index-shards) and [User Index Replicas](#user-index-replicas) must also be updated accordingly. + +</Note> + +### User index shards + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of shards to use for each user index.</p><p>Numerical input. Default is <strong>1</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>UserIndexShards</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_USERINDEXSHARDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Aggregate search indexes + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Elasticsearch or AWS OpenSearch indexes older than the age specified by this setting, in days, will be aggregated during the daily scheduled job.</p><p>Numerical input. Default is <strong>365</strong> days.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>AggregatePostsAfterDays</code> > <code>365</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_AGGREGATEPOSTSAFTERDAYS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If you’re using [data retention](/administration-guide/comply/data-retention-policy) and [enterprise search](/administration-guide/scale/enterprise-search), configure this with a value greater than your data retention policy. + +</Note> + +### Post aggregator start time + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The start time of the daily scheduled aggregator job.</p><p>Must be a 24-hour time stamp in the form <code>HH:MM</code> based on the local time of the server.</p><p>Default is <strong>03:00</strong> (3 AM)</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>PostsAggregatorJobStartTime</code> > <code>"03:00"</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_POSTSAGGREGATORJOBSTARTTIME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Index prefix + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td>The prefix added to the Elasticsearch or AWS OpenSearch index name.</td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>IndexPrefix</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_INDEXPREFIX</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +When this setting is used, all Elasticsearch or AWS OpenSearch indexes created by Mattermost are given this prefix. You can set different prefixes so that multiple Mattermost deployments can share an Elasticsearch or AWS OpenSearch cluster without the index names colliding. + +</Note> + +### Global search prefix + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable global search across multiple Elasticsearch indices with the same <a href="#index-prefix">index prefix</a>.</p><p>This is helpful for setups with multiple data centers where Elasticsearch instances share data using cross-cluster replication. It allows for easier and unified searching across distributed indices.</p><p>Value must be a prefix of <code>IndexPrefix</code>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>GlobalSearchPrefix</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_GLOBALSEARCHPREFIX</code></li></ul></td> +</tr> +</tbody> +</table> + +### Live indexing batch size + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of new posts needed before those posts are added to the Elasticsearch or AWS OpenSearch index. Once added to the index, the post becomes searchable.</p><p>On servers with more than 1 post per second, we suggest setting this value to the average number of posts over a 20 second period of time.</p><p>Numerical input. Default is <strong>1</strong>. Every post is indexed synchronously as they are created.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>LiveIndexingBatchSize</code> > <code>1</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_LIVEINDEXINGBATCHSIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +It may be necessary to increase this value to avoid hitting the rate limit or resource limit of your Elasticsearch or AWS OpenSearch cluster on installs handling more than 1 post per second. + +</Note> + +**What exactly happens when I increase this value?** + +The primary impact is that a post will be indexed into Elasticsearch or AWS OpenSearch after the threshold of posts is met, which then makes the posts searchable within Mattermost. So, if you set this based on recommendations for larger servers, and you make a post, you cannot find it via search for ~10–20 seconds, on average. Realistically, no users should see or feel this impact due to the limited number of users who are actively **searching** for a post this quickly. You can set this value to a lower or higher average depending on your Elasticsearch or AWS OpenSearch server specifications. + +During busy periods, this delay will be faster as more traffic is occurring, causing more posts and a quicker time to hit the index number. During slower periods, expect the reverse. + +**How to find the right number for your server** + +1. You must understand how many posts your server makes every minute. Run the query below to calculate your server's average posts per minute. + + > Note that this query can be heavy, so we recommend that you run it during non-peak hours. Additionally, you can adjust the `WHERE` clause to see the posts per minute over a different time period. Right now `31536000000` represents the number of milliseconds in a year. + > + > ``` SQL + > SELECT + > AVG(postsPerMinute) as averagePostsPerMinute + > FROM ( + > SELECT + > count(*) as postsPerMinute, + > date_trunc('minute', to_timestamp(createat/1000)) + > FROM posts + > WHERE createAt > ( (extract(epoch from now()) * 1000 ) - 31536000000) + > GROUP BY date_trunc('minute', to_timestamp(createat/1000)) + > ) as ppm; + > ``` + +2. Decide the acceptable index window for your environment, and divide your average posts per minute by that. We suggest 10-20 seconds. Assuming you have `600` posts per minute on average, and you want to index every 20 seconds (`60 seconds / 20 seconds = 3`<code>) you would calculate </code><code>600 / 3</code><code> to come to the number </code><code>200</code>\`. After 200 posts, Mattermost will index the posts into Elasticsearch or AWS OpenSearch. So, on average, there would be a 20-second delay in searchability. + +3. Edit the `config.json` or run mmctl to modify the `LiveIndexingBatchSize` setting + + > **In the \`\`config.json\`\`** + > + > ``` JSON + > { + > "ElasticsearchSettings": { + > "LiveIndexingBatchSize": 200 + > } + > } + > ``` + > + > **Via mmctl** + > + > ``` sh + > mmctl config set ElasticsearchSettings.LiveIndexingBatchSize 200 + > ``` + > + > **Via an environment variable** + > + > ``` sh + > MM_ELASTICSEARCHSETTINGS_LIVEINDEXINGBATCHSIZE = 200 + > ``` + +4. Restart the Mattermost server. + +### Batch size + +<table> +<colgroup> +<col style={{width: '34%'}} /> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of posts for a single batch during a bulk indexing job.</p><p>Numerical input. Default is <strong>10000</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>BatchSize</code> > <code>10000</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_BATCHSIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Request timeout + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The timeout, in seconds, for Elasticsearch or AWS OpenSearch calls.</p><p>Numerical input in seconds. Default is <strong>30</strong> seconds.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>RequestTimeoutSeconds</code> > <code>30</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_REQUESTTIMEOUTSECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Trace + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Options for printing Elasticsearch or AWS OpenSearch trace errors.</p><ul><li><strong>error</strong>: Creates the error trace when initializing the Elasticsearch or AWS OpenSearch client and prints any template creation or search query that returns an error as part of the error message.</li><li><strong>all</strong>: Creates the three traces (error, trace and info) for the driver and doesn’t print the queries because they will be part of the trace log level of the driver.</li><li><strong>not specified</strong>: <strong>(Default)</strong> No error trace is created.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>Trace</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_TRACE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable CJK analyzers + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>When enabled, Mattermost uses language-specific analyzer plugins to improve search results for Korean, Japanese, and Chinese content. The required analyzer plugins must be installed on the Elasticsearch or AWS OpenSearch server before enabling this setting.</p><p>Supported plugins:</p><ul><li><code>analysis-nori</code> (Korean)</li><li><code>analysis-kuromoji</code> (Japanese)</li><li><code>analysis-smartcn</code> (Chinese)</li><li><strong>true</strong>: CJK language-specific analyzers are enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Standard analyzers are used.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ElasticsearchSettings</code> > <code>EnableCJKAnalyzers</code> > <code>false</code></li><li>Environment variable: <code>MM_ELASTICSEARCHSETTINGS_ENABLECJKANALYZERS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Available from Mattermost v11.6. The required analyzer plugins should be installed on the Elasticsearch or AWS OpenSearch server before enabling this setting for full analysis support. If no plugin is detected, a warning will be logged. See the [Elasticsearch setup](/administration-guide/scale/elasticsearch-setup) and [AWS OpenSearch setup](/administration-guide/scale/opensearch-setup) documentation for plugin installation instructions. + +If you enable this setting on a server that was previously running Elasticsearch or AWS OpenSearch, you must purge and rebuild the search indexes for existing content to be properly searchable with the new analyzers. See the [Elasticsearch setup](/administration-guide/scale/elasticsearch-setup) documentation for instructions on purging and rebuilding indexes. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## File storage + +With self-hosted deployments, you can configure file storage settings by going to **System Console \> Environment \> File Storage**, or by editing the `config.json` file as described in the following tables. + +<Note> + +Mattermost currently supports storing files on the local filesystem and Amazon S3 or S3-compatible containers. We have tested Mattermost with [Digital Ocean Spaces](https://docs.digitalocean.com/products/spaces/), but not all S3-compatible containers on the market. If you are looking to use other S3-compatible containers, we recommend completing your own testing. You can also use local storage or a network drive using NFS. + +</Note> + +### File storage system + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The type of file storage system used. Can be either Local File System or Amazon S3.</p><ul><li><strong>local</strong>: <strong>(Default)</strong> Files and images are stored in the specified local file directory.</li><li><strong>amazons3</strong>: Files and images are stored on Amazon S3 based on the access key, bucket, and region fields provided. The driver is compatible with other S3-compatible services, such as Digital Ocean Spaces.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>DriverName</code> > <code>"local"</code></li><li>Environment variable: <code>MM_FILESETTINGS_DRIVERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Local storage directory + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The local directory to which files are written when the <strong>File storage system</strong> is set to <strong>local</strong>. Can be any directory writable by the user Mattermost is running as, and is relative to the directory where Mattermost is installed.</p><p>Defaults to <strong>./data/</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>Directory</code></li><li>Environment variable: <code>MM_FILESETTINGS_DIRECTORY</code></li></ul></td> +</tr> +</tbody> +</table> + +When **File storage system** is set to **amazons3**, this setting has no effect. + +### Maximum file size + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum file size for message attachments and plugin uploads. This value must be specified in mebibytes in the System Console, and in bytes in the <code>config.json</code> file.</p><p>The default is <code>104857600</code> bytes (<strong>100</strong> mebibytes).</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>MaxFileSize</code> > <code>104857600</code></li><li>Environment variable: <code>MM_FILESETTINGS_MAXFILESIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Verify server memory can support your setting choice. Large file sizes increase the risk of server crashes and failed uploads due to network disruptions. +- When [uploading plugin files](/administration-guide/configure/plugins-configuration-settings#upload-plugin), a `Received invalid response from the server` error typically indicates that `MaxFileSize` isn't large enough to support the plugin file upload, and/or that proxy settings may not be sufficient. +- If you use a proxy or load balancer in front of Mattermost, the following proxy settings must be adjusted accordingly: + - For NGINX, use `client_max_body_size`. + - For Apache, use `LimitRequestBody`. + +</Note> + +### Enable document search by content + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable users to search the contents of documents attached to messages.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Documents are searchable by their content.</li><li><strong>false</strong>: Documents aren’t searchable by their content. When document content search is disabled, users can search for files by file name only.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>ExtractContent</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_EXTRACTCONTENT</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enabling document search by content is required when extracting content from files. Both Mattermost [file search](/end-user-guide/collaborate/search-for-messages) and [Mattermost Agents](/end-user-guide/agents) can access files and their content, when enabled with the necessary dependencies. Document content search results for files shared before upgrading to Mattermost Server v5.35 may be incomplete until an extraction command is executed using the [mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-extract). If this command is not run, users can search older files based on file name only. + +You can optionally install the following [dependencies](https://github.com/sajari/docconv#dependencies) to extend content searching support in Mattermost to include file formats beyond PDF, DOCX, and ODT, such as DOC, RTF, XML, and HTML: + +- **tidy**: Used to search the contents of HTML documents. +- **wv**: Used to search the contents of DOC documents. +- **poppler-utils**: Used to significantly improve server performance when extracting the contents of PDF documents. +- **unrtf**: Used to search the contents of RTF documents. +- **JusText**: Used to search HTML documents. See the [JusText Python package](https://pypi.org/project/jusText/) for deployment information. + +If you choose not to install these dependencies, you’ll see log entries for documents that couldn’t be extracted. Any documents that can’t be extracted are skipped and logged so that content extraction can proceed. + +</Note> + +### Enable searching content of documents within ZIP files + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enables users to search the contents of compressed ZIP files attached to messages.</p><ul><li><strong>true</strong>: Contents of documents within ZIP files are returned in search results. This may have an impact on server performance for large files. the specified local file directory.</li><li><strong>false</strong>: <strong>(Default)</strong> The contents of documents within ZIP files aren’t returned in search results.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>ArchiveRecursion</code> > <code>false</code></li><li>Environment variable: <code>MM_FILESETTINGS_ARCHIVERECURSION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- You can search for document content within ZIP files when using Mattermost in a web browser or the desktop app. +- Searching document contents adds load to your server. +- This setting applies only to standard ZIP files. 7zip (`.7z`) files are blocked for security reasons and are not searchable. +- For large deployments, or teams that share many large, text-heavy documents, we recommend you review our [hardware requirements](/deployment-guide/software-hardware-requirements#hardware-requirements), and test enabling this feature in a staging environment before enabling it in a production environment. + +</Note> + +### Amazon S3 bucket + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The name of the bucket for your S3-compatible object storage instance.</p><p>A string with the S3-compatible bucket name.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3Bucket</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3BUCKET</code></li></ul></td> +</tr> +</tbody> +</table> + +### Amazon S3 path prefix + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The prefix you selected for your <strong>Amazon S3 bucket</strong> in AWS.</p><p>A string containing the path prefix.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3PathPrefix</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3PATHPREFIX</code></li></ul></td> +</tr> +</tbody> +</table> + +### Amazon S3 region + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The AWS region you selected when creating your <strong>Amazon S3 bucket</strong> in AWS.</p><p>A string with the AWS region containing the bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, and sets it to <strong>us-east-1</strong> if none found.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>`".FileSettings.AmazonS3Region",</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3REGION</code></li></ul></td> +</tr> +</tbody> +</table> + +For Digital Ocean Spaces or other S3-compatible services, leave this setting empty. + +### Amazon S3 access key ID + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td>A string with the access key for the S3-compatible storage instance. Your EC2 administrator can supply you with the Access Key ID.</td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3AccessKeyId</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3ACCESSKEYID</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This is required for access unless you are using an [Amazon S3 IAM Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) with Amazon S3. + +</Note> + +### Amazon S3 endpoint + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The hostname of your S3-compatible instance.</p><p>A string with the hostname of the S3-compatible storage instance. Defaults to <strong>s3.amazonaws.com</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3Endpoint</code> > <code>"s3.amazonaws.com"</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3ENDPOINT</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +For Digital Ocean Spaces, the hostname should be set to **\<region\>.digitaloceanspaces.com**, where **\<region\>** is the abbreviation for the region you selected when setting up the Space. It can be **nyc3**, **ams3**, or **sgp1**. + +</Note> + +### Amazon S3 secret access key + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The secret access key associated with your Amazon S3 Access Key ID.</p><p>A string with the secret access key for the S3-compatible storage instance.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3SecretAccessKey</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable secure Amazon S3 connections + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable secure Amazon S3 connections.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables only secure Amazon S3 connections.</li><li><strong>false</strong>: Allows insecure connections to Amazon S3.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3SSL</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3SSL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Amazon S3 signature v2 + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>By default, Mattermost uses Signature v4 to sign API calls to AWS, but under some circumstances, v2 is required.</p><ul><li><strong>true</strong>: Use Signature v2 signing process.</li><li><strong>false</strong>: <strong>(Default)</strong> Use Signature v4 signing process.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3SignV2</code> > <code>false</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3SIGNV2</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) documentation for information about when to use the Signature v2 signing process. + +### Enable server-side encryption for Amazon S3 + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable server-side encryption for Amazon S3.</p><ul><li><strong>true</strong>: Encrypts files in Amazon S3 using server-side encryption with Amazon S3-managed keys.</li><li><strong>false</strong>: <strong>(Default)</strong> Doesn’t encrypt files in Amazon S3.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3SSE</code> > <code>false</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3SSE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This configuration setting is available for self-hosted deployments only. + +</Note> + +### Enable Amazon S3 debugging + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable Amazon S3 debugging to capture additional debugging information in system logs.</p><ul><li><strong>true</strong>: Log additional debugging information is logged to the system logs.</li><li><strong>false</strong>: <strong>(Default)</strong> No Amazon S3 debugging information is included in the system logs. Typically set to <strong>false</strong> in production.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3Trace</code> > <code>false</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3TRACE</code></li></ul></td> +</tr> +</tbody> +</table> + +Select the **Test Connection** button in the System Console to validate the settings and ensure the user can access the server. + +### Amazon S3 storage class + +Some Amazon S3-compatible storage solutions require the storage class parameter to be present in upload requests, otherwise they will be rejected. Configure this storage class as the storage class required by your S3-compatible solution. + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The storage class to use for uploads to S3-compatible storage solutions.</p><p>String input. Default is an empty string <code>""</code>. Select <strong>Test Connection</strong> to test the configured connection.</p></td> +<td><ul><li>System Config path: <strong>Environment > File Storage</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3StorageClass</code> > <code>""</code>,</li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3STORAGECLASS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Most Amazon S3-compatible storage solutions assign a default storage class of `STANDARD` when no storage class is provided. See the [Amazon S3 storage class](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html#AmazonS3-PutObject-request-header-StorageClass) documentation for details about supported storage classes. + +</Note> + +### Export Amazon S3 storage class + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The storage class to use for exports to S3-compatible storage solutions.</p><p>String input. Default is an empty string <code>""</code>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>ExportAmazonS3StorageClass</code> > <code>""</code></li><li>Environment variable: <code>MM_FILESETTINGS_EXPORTAMAZONS3STORAGECLASS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Most Amazon S3-compatible storage solutions assign a default storage class of `STANDARD` when no storage class is provided. See the [Amazon S3 storage class](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html#AmazonS3-PutObject-request-header-StorageClass) documentation for details about supported storage classes. + +</Note> + +### Amazon S3 request timeout + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The amount of time, in milliseconds, before requests to Amazon S3 storage time out.</p><p>Default is 30000 (30 seconds).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3RequestTimeoutMilliseconds</code> > <code>30000</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3REQUESTTIMEOUTMILLISECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Amazon S3 upload part size + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The size, in bytes, of each part in a multi-part upload to Amazon S3.</p><p>Numeric value. Default is 5242880 (5MB).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3UploadPartSizeBytes</code> > <code>5242880</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3UPLOADPARTSIZEBYTES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +A smaller part size can result in more requests and an increase in latency, while a larger part size can result in more memory being allocated. + +</Note> + +### Amazon S3 exported upload part size + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The size, in bytes, of each part in a multi-part exported to Amazon S3.</p><p>Numeric value. Default is 104857600 (100MB).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>ExportAmazonS3UploadPartSizeBytes</code> > <code>104857600</code></li><li>Environment variable: <code>MM_FILESETTINGS_EXPORTAMAZONS3UPLOADPARTSIZEBYTES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +A smaller part size can result in more requests and an increase in latency, while a larger part size can result in more memory being allocated. + +</Note> + +### Amazon S3 request timeout + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The amount of time, in milliseconds, before requests to Amazon S3 storage time out.</p><p>Default is 30000 (30 seconds).</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>AmazonS3RequestTimeoutMilliseconds</code> > <code>30000</code></li><li>Environment variable: <code>MM_FILESETTINGS_AMAZONS3REQUESTTIMEOUTMILLISECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Initial font + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The font used in auto-generated profile pictures with colored backgrounds and username initials.</p><p>A string with the font file name. Default is <strong>nunito-bold.ttf</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>InitialFont</code> > <code>"nunito-bold.ttf"</code></li><li>Environment variable: <code>MM_FILESETTINGS_INITIALFONT</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Image proxy + +With self-hosted deployments, an image proxy can be used by Mattermost apps to prevent them from connecting directly to remote self-hosted servers. Configure an image proxy by going to **System Console \> Environment \> Image Proxy**, or by editing the `config.json` file as described in the following tables. + +### Enable image proxy + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>An image proxy anonymizes Mattermost app connections and prevents them from accessing insecure content.</p><ul><li><strong>true</strong>: Enables an image proxy for loading external images.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the image proxy.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Image Proxy</strong></li><li><code>config.json</code> setting: <code>ImageProxySettings</code> > <code>Enable</code> > <code>true</code></li><li>Environment variable: <code>MM_IMAGEPROXYSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [image proxy](/deployment-guide/server/image-proxy) documentation to learn more. + +### Image proxy type + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The type of image proxy used by Mattermost.</p><ul><li><strong>local</strong>: <strong>(Default)</strong> The Mattermost server itself acts as the image proxy.</li><li><strong>atmos/camo</strong>: An external atmos/camo image proxy is used.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Image Proxy</strong></li><li><code>config.json</code> setting: <code>ImageProxySettings</code> > <code>ImageProxyType</code> > <code>"local"</code></li><li>Environment variable: <code>MM_IMAGEPROXYSETTINGS_IMAGEPROXYTYPE</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [image proxy](/deployment-guide/server/image-proxy) documentation to learn more. + +### Remote image proxy URL + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td>The URL of the atmos/camo proxy. This setting isn't needed when using the <strong>local</strong> image proxy.</td> +<td><ul><li>System Config path: <strong>Environment > Image Proxy</strong></li><li><code>config.json</code> setting: <code>ImageProxySettings</code> > <code>RemoteImageProxyURL</code></li><li>Environment variable: <code>MM_IMAGEPROXYSETTINGS_REMOTEIMAGEPROXYURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Remote image proxy options + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td>The URL signing key passed to an atmos/camo image proxy. This setting isn't needed when using the <strong>local</strong> image proxy type.</td> +<td><ul><li>System Config path: <strong>Environment > Image Proxy</strong></li><li><code>config.json</code> setting: <code>ImageProxySettings</code> > <code>RemoteImageProxyOptions</code></li><li>Environment variable: <code>MM_IMAGEPROXYSETTINGS_REMOTEIMAGEPROXYOPTIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [image proxy](/deployment-guide/server/image-proxy) documentation to learn more. + +------------------------------------------------------------------------------------------------------------------------ + +## SMTP + +With self-hosted deployments, you can configure SMTP email server settings by going to **System Console \> Environment \> SMTP**, or by editing the `config.json` file as described in the following tables. + +### SMTP server + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td>The location of the SMTP email server used for email notifications.</td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SMTPServer</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SMTPSERVER</code></li></ul></td> +</tr> +</tbody> +</table> + +### SMTP server port + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The port of SMTP email server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>"SMTPPort"</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SMTPPORT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable SMTP authentication + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable SMTP authentication.</p><ul><li><strong>true</strong>: SMTP username and password are used for authenticating to the SMTP server.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost doesn’t attempt to authenticate to the SMTP server.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnableSMTPAuth</code> > <code>false</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLESMTPAUTH</code></li></ul></td> +</tr> +</tbody> +</table> + +### SMTP server username + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The username for authenticating to the SMTP server.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SMTPUsername</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SMTPUSERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### SMTP server password + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The password associated with the SMTP username.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SMTPPassword</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SMTPPASSWORD</code></li></ul></td> +</tr> +</tbody> +</table> + +### SMTP connection security + +<table> +<colgroup> +<col style={{width: '47%'}} /> +<col style={{width: '52%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify connection security for emails sent using SMTP.</p><ul><li><strong>Not specified</strong>: <strong>(Default)</strong> Send email over an unsecure connection.</li><li><strong>TLS</strong>: Communication between Mattermost and your email server is encrypted.</li><li><strong>STARTTLS</strong>: Attempts to upgrade an existing insecure connection to a secure connection using TLS.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>ConnectionSecurity</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_CONNECTIONSECURITY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Skip server certificate verification + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to skip the verification of the email server certificate.</p><ul><li><strong>true</strong>: Mattermost won't verify the email server certificate.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost verifies the email server certificate.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SkipServerCertificateVerification</code> > <code>false</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SKIPSERVERCERTIFICATEVERIFICATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable security alerts + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable security alerts.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> System admins are notified by email if a relevant security fix alert is announced. Requires email to be enabled.</li><li><strong>false</strong>: Security alerts are disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableSecurityFixAlert</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLESECURITYFIXALERT</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [Telemetry](/administration-guide/manage/telemetry#security-update-check-feature) documentation to learn more. + +### SMTP server timeout + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum amount of time, in seconds, allowed for establishing a TCP connection between Mattermost and the SMTP server.</p><p>Numerical value in seconds.</p></td> +<td><ul><li>System Config path: <strong>Environment > SMTP</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SMTPServerTimeout</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SMTPSERVERTIMEOUT</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Push notification server + +<Inc0_push_notification_server_configuration_settings /> + +------------------------------------------------------------------------------------------------------------------------ + +## High availability + +<PlanAvailability slug="ent-plus" /> + +With self-hosted deployments, you can configure Mattermost as a [high availability cluster-based deployment](/administration-guide/scale/high-availability-cluster-based-deployment) by going to **System Console \> Environment \> High Availability**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +In a Mattermost high availability cluster-based deployment, the System Console is set to read-only, and settings can only be changed by editing the `config.json` file directly. However, to test a high availability cluster-based environment, you can disable `ClusterSettings.ReadOnlyConfig` in the `config.json` file by setting it to `false`. This allows changes applied using the System Console to be saved back to the configuration file. + +### Enable high availability mode + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>You can enable high availability mode.</p><ul><li><strong>true</strong>: The Mattermost server will attempt inter-node communication with the other servers in the cluster that have the same cluster name. This sets the System Console to read-only mode to keep the servers' <code>config.json</code> files in sync.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost high availability mode is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Cluster name + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The cluster to join by name in a high availability cluster-based deployment.</p><p>Only nodes with the same cluster name will join together. This is to support blue-green deployments or staging pointing to the same database.</p></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>ClusterName</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_CLUSTERNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Override hostname + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>You can override the hostname of this server.</p><ul><li>This property can be set to a specific IP address if needed; however, we don’t recommend overriding the hostname unless it's necessary.</li><li>If left blank, Mattermost attempts to get the hostname from the operating system or uses the IP address.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>OverrideHostname</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_OVERRIDEHOSTNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [high availability cluster-based deployment](/administration-guide/scale/high-availability-cluster-based-deployment) documentation for details. + +### Use IP address + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>You can configure your high availability cluster-based deployment to communicate using the hostname instead of the IP address.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> The cluster attempts to communicate using the IP address specified.</li><li><strong>false</strong>: The cluster attempts to communicate using the hostname.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>UseIPAddress</code> > <code>true</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_USEIPADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable gossip encryption + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Gossip encryption uses AES-256 by default, and this value isn't configurable by design.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> The server attempts to communicate via the gossip protocol over the gossip port specified.</li><li><strong>false</strong>: The server attempts to communicate over the streaming port.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>EnableGossipEncryption</code> > <code>true</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_ENABLEGOSSIPENCRYPTION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- The Gossip protocol is based on principles outlined in the [SWIM protocol developed by researchers at Cornell University](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf). The gossip protocol is a communication mechanism in distributed systems where nodes randomly exchange information to ensure data consistency across the network. It is decentralized, scalable, and fault-tolerant, making it ideal for systems with numerous nodes. Information is spread in a manner similar to social gossip, with nodes periodically "gossiping" updates to random peers until the network converges to a consistent state. Widely used in distributed databases, blockchain networks, and peer-to-peer systems, the protocol is simple to implement and resilient to node failures. However, it can suffer from redundancy and propagation delays in large networks. +- Alternatively, you can manually set the `ClusterEncryptionKey` row value in the **Systems** table. A key is a byte array converted to base64. Set this value to either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 respectively. +- From Mattermost v10.11, gossip encryption is enabled by default for all new deployments. For existing deployments, all communication using the gossip protocol remains unencrypted unless you manually enable encryption. Prior to v10.11, gossip encryption is enabled by default for Cloud deployments and disabled by default for self-hosted deployments. + +</Note> + +### Enable gossip compression + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>We recommend that you disable this configuration setting for better performance.</p><ul><li><strong>true</strong>: <strong>(Default for self-hosted deployments)</strong> All communication through the cluster uses gossip compression. This setting is enabled by default to maintain compatibility with older servers.</li><li><strong>false</strong>: <strong>(Default for Cloud deployments)</strong> All communication using the gossip protocol remains uncompressed.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>EnableGossipCompression</code> > <code>true</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_ENABLEGOSSIPCOMPRESSION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Gossip port + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The port used for the gossip protocol. Both UDP and TCP should be allowed on this port.</p><p>Numerical input. Default is <strong>8074</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > High Availability</strong></li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>GossipPort</code> > <code>8074</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_GOSSIPPORT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Read only config + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Changes made to settings in the System Console are ignored.</li><li><strong>false</strong>: Changes made to settings in the System Console are written to <code>config.json</code>.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>ReadOnlyConfig</code> > <code>true</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_READONLYCONFIG</code></li></ul></td> +</tr> +</tbody> +</table> + +### Network interface + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>An IP address used to identify the device that does automatic IP detection in high availability cluster-based deployments.</p><p>String input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>NetworkInterface</code> > <code>""</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_NETWORKINTERFACE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Bind address + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>An IP address used to bind cluster traffic to a specific network device.</p><p>This setting is used primarily for servers with multiple network devices or different Bind Address and Advertise Address like in deployments that involve NAT (Network Address Translation).</p><p>String input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>BindAddress</code> > <code>""</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_BINDADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Advertise address + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The IP address used to access the server from other nodes. This settings is used primary when cluster nodes are not in the same network and involve NAT (Network Address Translation).</p><p>String input.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ClusterSettings</code> > <code>AdvertiseAddress</code> > <code>""</code></li><li>Environment variable: <code>MM_CLUSTERSETTINGS_ADVERTISEADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Rate limiting + +<Inc1_rate_limiting_configuration_settings /> + +------------------------------------------------------------------------------------------------------------------------ + +## Logging + +Mattermost provides 3 independent logging systems for self-hosted deployments that can be configured separately with separate log files and rotation policies to meet different operational and compliance needs: + +- [Log Settings](#log-settings) +- [Notification Log Settings](#notification-logging) +- [Audit Log Settings](#audit-logging) + +By default, all Mattermost editions write logs to both the console and to the `mattermost.log` file in a machine-readable JSON format. Mattermost Enterprise and Professional customers can additionally log directly to syslog and TCP socket destination targets. + +### Log settings + +Configure general logging by going to **System Console \> Environment \> Logging**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +#### Output logs to console + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output general logs to the console.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Output log messages are written to the console based on the <a href="#console-log-level">console log level</a> configuration. The server writes messages to the standard output stream (stdout).</li><li><strong>false</strong>: Output log messages aren’t written to the console.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableConsole</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLECONSOLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +From Mattermost v11.0, notification logs are automatically included in the main console logs. + +</Note> + +#### Console log level + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The level of detail in general log events written when Mattermost outputs log messages to the console.</p><ul><li><strong>DEBUG</strong>: <strong>(Default)</strong> Outputs verbose detail for developers debugging issues.</li><li><strong>ERROR</strong>: Outputs only error messages.</li><li><strong>INFO</strong>: Outputs error messages and information around startup and initialization.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>ConsoleLevel</code> > <code>"DEBUG"</code></li><li>Environment variable: <code>MM_LOGSETTINGS_CONSOLELEVEL</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output console logs as JSON + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output general console logs as JSON.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written in a machine-readable JSON format.</li><li><strong>false</strong>: Logged events are written in plain text.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>ConsoleJson</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_CONSOLEJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +Typically set to **true** in a production environment. + +#### Colorize plain text console logs + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enables system admins to display plain text general log level details in color.</p><ul><li><strong>true</strong>: When logged events are output to the console as plain text, colorize log levels details.</li><li><strong>false</strong>: <strong>(Default)</strong> Plain text log details aren't colorized in the console.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableColor</code> > <code>false</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLECOLOR</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output logs to file + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output general console logs to a file.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written based on the <a href="#file-log-level">file log level</a> configuration to a <code>mattermost.log</code> file located in the directory configured via <code>file location</code>.</li><li><strong>false</strong>: Logged events aren’t written to a file.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableFile</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- From Mattermost v11.0, notification logs are automatically included in the main file logs. +- This setting is typically set to **true** in a production environment. When enabled, you can download the `mattermost.log` file locally by going to **System Console \> Reporting \> Server Logs**, and selecting **Download Logs**. + +</Note> + +#### File log directory + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The location of the general log files.</p><p>String input. If left blank, log files are stored in the <code>./logs</code> directory.</p></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>FileLocation</code> > <code>""</code></li><li>Environment variable: <code>MM_LOGSETTINGS_FILELOCATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- The path you configure must exist, and Mattermost must have write permissions for this directory. +- From Mattermost v11.4, you can use the `MM_LOG_PATH` environment variable to restrict log file locations to a designated root directory. This security enhancement ensures that all log files configured via `LogSettings.FileLocation` or `LogSettings.AdvancedLoggingJSON` remain within an authorized logging directory. + - If `MM_LOG_PATH` isn't set, the default `logs` directory is used. Paths outside the root directory generate error logs and are excluded from [support packet](/administration-guide/manage/admin/generating-support-packet) downloads. See the [log path restrictions](/administration-guide/manage/logging#log-path-restrictions) documentation for details. + +</Note> + +#### File log level + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The level of detail in general log events when when Mattermost outputs log messages to a file.</p><ul><li><strong>DEBUG</strong>: Outputs verbose detail for developers debugging issues.</li><li><strong>ERROR</strong>: Outputs only error messages.</li><li><strong>INFO</strong>: <strong>(Default)</strong> Outputs error messages and information around startup and initialization.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>FileLevel</code> > <code>"INFO"</code></li><li>Environment variable: <code>MM_LOGSETTINGS_FILELEVEL</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output file logs as JSON + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output general file logs as JSON.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written in a machine-readable JSON format.</li><li><strong>false</strong>: Logged events are written in plain text.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>FileJson</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_FILEJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +Typically set to **true** in a production environment. + +#### Enable webhook debugging + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to capture the contents of general incoming webhooks to console and/or file logs for debugging.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> The contents of incoming webhooks are printed to log files for debugging.</li><li><strong>false</strong>: The contents of incoming webhooks aren’t printed to log files.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableWebhookDebugging</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLEWEBHOOKDEBUGGING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enable debug logs by changing the [file log level](#file-log-level) to `DEBUG` to include the request body of incoming webhooks in logs. + +</Note> + +#### Output logs to multiple targets + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to allow any combination of console, local file, syslog, and TCP socket targets, and send general log records to multiple targets.</p><p>String input can contain a filespec to another configuration file, a database DSN, or JSON.</p></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>AdvancedLoggingJSON</code> > <code>": ""</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ADVANCEDLOGGINGJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- See the [Mattermost logging](/administration-guide/manage/logging) documentation for details. These targets have been chosen as they support the vast majority of log aggregators, and other log analysis tools, without needing additional software installed. +- Logs are recorded asynchronously to reduce latency to the caller. +- Advanced logging supports hot-reloading of logger configuration. +- From Mattermost v11.4, file paths specified in `AdvancedLoggingJSON` configurations should be within the directory specified by the `MM_LOG_PATH` environment variable. See [log path restrictions](/administration-guide/manage/logging#log-path-restrictions) for details. + +</Note> + +#### Maximum field size + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enables system admins to limit the size of general log fields during logging.</p><p>Numerical value. Default is <strong>2048</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>MaxFieldSize</code> > <code>2048</code></li><li>Environment variable: <code>MM_LOGSETTINGS_MAXFIELDSIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Enable diagnostics and error reporting + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Whether or not general diagnostics and error reports are sent to Mattermost, Inc.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Send diagnostics and error reports.</li><li><strong>false</strong>: Diagnostics and error reports aren't sent.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Logging</strong></li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableDiagnostics</code> > <code>""</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLEDIAGNOSTICS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [telemetry](/administration-guide/manage/telemetry#error-and-diagnostics-reporting-feature) docummentation for details on the information Mattermost collects. + +</Note> + +#### Enable verbose diagnostics + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Whether or not verbose general diagnostics information is sent.</p><ul><li><strong>true</strong>: Send verbose diagnostics information.</li><li><strong>false</strong>: <strong>(Default)</strong> Verbose diagnostics information isn't sent.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>VerboseDiagnostics</code> > <code>false</code></li><li>Environment variable: <code>MM_LOGSETTINGS_VERBOSEDIAGNOSTICS</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Enable Sentry reporting + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Whether or not general error reports are sent to Sentry.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Send error reports to Sentry. Default matches the EnableDiagnostics setting.</li><li><strong>false</strong>: Error reports are not sent to Sentry.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>LogSettings</code> > <code>EnableSentry</code> > <code>true</code></li><li>Environment variable: <code>MM_LOGSETTINGS_ENABLESENTRY</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +### Notification logging + +<Important> + +**From Mattermost v11, notification log settings have been consolidated into the standard console logs and mattermost.log file**. You can no longer disable notification logging without using advanced logging settings, as the main log level setting now controls both server and notification logs. + +You can use the `AdvancedLoggingJSON` configuration with discrete notification log levels: `NotificationError`, `NotificationWarn`, `NotificationInfo`, `NotificationDebug`, and `NotificationTrace` to split notification logs into separate files and reduce troubleshooting noise. See [Advanced Logging](/administration-guide/manage/logging#advanced-logging) for details. + +</Important> + +The following configuration settings apply only to Mattermost server versions prior to v11.0. + +You can configure logging specifically for Mattermost notifications by editing the `config.json` file as described in the following tables. These settings operate independently from the main `LogSettings` and allow you to customize logging behavior specifically for the notification subsystem. Changes to these configuration settings require a server restart before taking effect. + +#### Output logs to console + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output notification logs to the console.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Output log messages are written to the console based on the <a href="#console-log-level">console log level</a> configuration. The server writes messages to the standard output stream (stdout).</li><li><strong>false</strong>: Output log messages aren't written to the console.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>EnableConsole</code> > <code>true</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_ENABLECONSOLE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Console log level + +<table> +<colgroup> +<col style={{width: '34%'}} /> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The level of detail in notification log events written when Mattermost outputs log messages to the console.</p><ul><li><strong>DEBUG</strong>: <strong>(Default)</strong> Outputs verbose detail for developers debugging issues.</li><li><strong>ERROR</strong>: Outputs only error messages.</li><li><strong>INFO</strong>: Outputs error messages and information around startup and initialization.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>ConsoleLevel</code> > <code>"DEBUG"</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_CONSOLELEVEL</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output console logs as JSON + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output notification console logs as JSON.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written in a machine-readable JSON format.</li><li><strong>false</strong>: Logged events are written in plain text.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>ConsoleJson</code> > <code>true</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_CONSOLEJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +Typically set to **true** in a production environment. + +#### Colorize plain text console logs + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enables system admins to display plain text notification log level details in color.</p><ul><li><strong>true</strong>: When logged events are output to the console as plain text, colorize log levels details.</li><li><strong>false</strong>: <strong>(Default)</strong> Plain text log details aren't colorized in the console.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>EnableColor</code> > <code>false</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_ENABLECOLOR</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output logs to file + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output notification console logs to a file.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written based on the <a href="#file-log-level">file log level</a> configuration to a <code>notifications.log</code> file located in the directory configured via <code>file location</code>.</li><li><strong>false</strong>: Logged events aren't written to a file.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>EnableFile</code> > <code>true</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_ENABLEFILE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### File log directory + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The location of the notification log files.</p><p>String input. If left blank, log files are stored in the <code>./logs</code> directory.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>FileLocation</code> > <code>""</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_FILELOCATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +The path you configure must exist, and Mattermost must have write permissions for this directory. + +</Note> + +#### File log level + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The level of detail in notification log events when Mattermost outputs log messages to a file.</p><ul><li><strong>DEBUG</strong>: Outputs verbose detail for developers debugging issues.</li><li><strong>ERROR</strong>: Outputs only error messages.</li><li><strong>INFO</strong>: <strong>(Default)</strong> Outputs error messages and information around startup and initialization.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>FileLevel</code> > <code>"INFO"</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_FILELEVEL</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output file logs as JSON + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to output notification file logs as JSON.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Logged events are written in a machine-readable JSON format.</li><li><strong>false</strong>: Logged events are written in plain text.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>FileJson</code> > <code>true</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_FILEJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output logs to multiple targets + +<table> +<colgroup> +<col style={{width: '33%'}} /> +<col style={{width: '66%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to allow any combination of console, local file, syslog, and TCP socket targets, and send notification log records to multiple targets.</p><p>String input can contain a filespec to another configuration file, a database DSN, or JSON.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NotificationLogSettings</code> > <code>AdvancedLoggingJSON</code> > <code>": ""</code></li><li>Environment variable: <code>MM_NOTIFICATIONLOGSETTINGS_ADVANCEDLOGGINGJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +### Audit logging + +<PlanAvailability slug="ent-plus" /> + +Configure audit logging by going to **System Console \> Compliance \> Audit Logging**, or by editing the `config.json` file as described in the following tables. These settings operate independently from the main `LogSettings` and allow you to customize logging behavior specifically for the audit subsystem. Changes to these configuration settings require a server restart before taking effect. + +#### Output audit logs to file + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Whether to write audit log files to disk.</p><ul><li><strong>true</strong>: Logged events are written to the file specified by the audit file name configuration setting.</li><li><strong>false</strong>: <strong>(Default)</strong> Audit log files aren't written.</li></ul></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileEnabled</code> > <code>false</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +When `FileEnabled` is set to **true**, then the [audit file name](#auditlog-filename) must be set. + +</Note> + +#### Audit file name + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The name of the audit log files.</p><p>The path that you set to the audit file must exist and Mattermost must have write permissions in it.</p><p><strong>Example:</strong> <code>/var/log/mattermost_audit.log</code></p></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileName</code> > <code>""</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILENAME</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +The file name must be set to [enable](#auditlog-fileenabled) audit logging. + +</Note> + +#### Maximum file size + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum size in megabytes for audit log files before they are rotated.</p><p>Numerical input. Default is <strong>100</strong> MB.</p></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileMaxSizeMB</code> > <code>100</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILEMAXSIZEMB</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Maximum file age + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum age in days for audit log files before they are deleted.</p><p>Numerical input. Default is <strong>0</strong> (no limit).</p></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileMaxAgeDays</code> > <code>0</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILEMAXAGEDAYS</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Maximum file backups + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of audit log file backups to retain.</p><p>Numerical input. Default is <strong>0</strong> (no limit).</p></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileMaxBackups</code> > <code>0</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILEMAXBACKUPS</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Compress audit log files + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Whether to compress rotated audit log files.</p><ul><li><strong>true</strong>: Rotated audit log files are compressed.</li><li><strong>false</strong>: <strong>(Default)</strong> Rotated audit log files aren't compressed.</li></ul></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileCompress</code> > <code>false</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILECOMPRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Audit log queue size + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of audit log entries that can be queued.</p><p>Numerical input. Default is <strong>1000</strong>.</p></td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>FileMaxQueueSize</code> > <code>1000</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_FILEMAXQUEUESIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Audit log certificate + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Certificate configuration for audit logging.</p><p>String input. Default is blank.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>Certificate</code> > <code>""</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_CERTIFICATE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Output audit logs to multiple targets + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td>Configures Mattermost to output audit log records to multiple targets.</td> +<td><ul><li>System Config path: <strong>Compliance > Audit Logging</strong></li><li><code>config.json</code> setting: <code>ExperimentalAuditSettings</code> > <code>AdvancedLoggingJSON</code> > <code>{}</code></li><li>Environment variable: <code>MM_EXPERIMENTALAUDITSETTINGS_ADVANCEDLOGGINGJSON</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- See the [Mattermost logging](/administration-guide/manage/logging) documentation for details on advanced logging configuration. These targets have been chosen as they support the vast majority of log aggregators, and other log analysis tools, without needing additional software installed. +- Audit logs are recorded asynchronously to reduce latency to the caller. +- Advanced audit logging supports hot-reloading of logger configuration. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Session lengths + +With self-hosted deployments, user sessions are cleared when a user tries to log in, and sessions are cleared every 24 hours from the sessions database table. Configure session lengths by going to **System Console \> Environment \> Session Lengths**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +### Extend session length with activity + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Improves the user experience by extending sessions and keeping users logged in if they are active in their Mattermost apps.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Sessions are automatically extended when users are active in their Mattermost client. User sessions only expire when users aren’t active in their Mattermost client for the entire duration of the session lengths defined.</li><li><strong>false</strong>: Sessions won't extend with activity in Mattermost. User sessions immediately expire at the end of the session length or based on the <a href="#session-idle-timeout">session idle timeout</a> configured.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ExtendSessionLengthWithActivity</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_EXTENDSESSIONLENGTHWITHACTIVITY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Terminate sessions on password change + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable session revocation when a user's password changes.</p><ul><li><strong>true</strong>: <strong>(Default for new deployments)</strong> Session revocation is enabled. All sessions of a user expire if their password is changed (by themselves or by a system admin). If the password change is initiated by the user, their current session isn't terminated.</li><li><strong>false</strong>: <strong>(Default for existing deployments)</strong> Session revocation is disabled. When users change their password, only the user's current session is revoked. When a system admin changes the user's password, none of the user's sessions are revoked.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>TerminateSessionsOnPasswordChange</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_TERMINATESESSIONSONPASSWORDCHANGE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Session length for AD/LDAP and email + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the number of hours counted from the last time a user entered their credentials into the web app or the desktop app to the expiry of the user’s session on email and AD/LDAP authentication.</p><p>Numerical input in hours. Default is <strong>720</strong> hours.</p></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SessionLengthWebInHours</code> > <code>720</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SESSIONLENGTHWEBINHOURS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +After changing this setting, the new session length takes effect after the next time the user enters their credentials. + +</Note> + +### Session length for mobile + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the number of hours counted from the last time a user entered their credential into the mobile app to the expiry of the user’s session.</p><p>Numerical input in hours. Default is <strong>720</strong> hours.</p></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SessionLengthMobileInHours</code> > <code>720</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SESSIONLENGTHMOBILEINHOURS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +After changing this setting, the new session length takes effect after the next time the user enters their credentials. + +</Note> + +### Session length for SSO + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the number of hours from the last time a user entered their SSO credentials to the expiry of the user’s session. This setting defines the session length for SSO authentication, such as SAML, GitLab, and OAuth 2.0.</p><p>Numerical input in hours. Default is <strong>720</strong> hours. Numbers as decimals are also valid values for this configuration setting.</p></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SessionLengthSSOInHours</code> > <code>720</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SESSIONLENGTHSSOINHOURS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- After changing this setting, the new session length takes effect after the next time the user enters their credentials. +- If the authentication method is SAML, GitLab, or OAuth 2.0, users may automatically be logged back in to Mattermost if they are already logged in to SAML, GitLab, or with OAuth 2.0. + +</Note> + +### Session cache + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the number of minutes to cache a session in memory.</p><p>Numerical input in minutes. Default is <strong>10</strong> minutes.</p></td> +<td><ul><li>System Config path: <strong>Environment > Session Lengths</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SessionCacheInMinutes</code> > <code>10</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SESSIONCACHEINMINUTES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Session idle timeout + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of minutes from the last time a user was active on the system to the expiry of the user’s session. Once expired, the user will need to log in to continue.</p><p>Numerical input in minutes. Default is <strong>43200</strong> (30 days). Minimum value is <strong>5</strong> minutes, and a value of <strong>0</strong> sets the time as unlimited.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>SessionIdleTimeoutInMinutes</code> > <code>43200</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_SESSIONIDLETIMEOUTINMINUTES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting has no effect when [extend session length with activity](#extend-session-length-with-activity) is set to **true**. +- This setting applies to the webapp and the desktop app. For mobile apps, use an [EMM provider](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) to lock the app when not in use. | +- In [high availability mode](/administration-guide/scale/high-availability-cluster-based-deployment), enable IP hash load balancing for reliable timeout measurement. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Performance monitoring + +<PlanAvailability slug="entry-ent" /> + +With self-hosted deployments, you can configure performance monitoring by going to **System Console \> Environment \> Performance Monitoring**, or by editing the `config.json` file as described in the following tables. + +``` json +{ + "MetricsSettings": { + "Enable": false, + "BlockProfileRate": 0, + "ListenAddress": :8067, + "EnableClientMetrics": false, + "EnableNotificationMetrics": true, + "ClientSideUserIds": "" + } +} +``` + +Changes to configuration settings in this section require a server restart before taking effect. + +See the [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) documentation to learn more about setting up performance monitoring with Prometheus and Grafana. See the [collect performance metrics](/administration-guide/scale/collect-performance-metrics) documentation to learn more about using the Mattermost Metrics plugin. + +### Enable performance monitoring + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable performance monitoring.</p><ul><li><strong>true</strong>: Performance monitoring data collection and profiling is enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost performance monitoring is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Performance Monitoring</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) documentation to learn more. + +### Enable client performance monitoring + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable client performance monitoring.</p><ul><li><strong>true</strong>: Client performance monitoring data collection and profiling is enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Mattermost client performance monitoring is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Performance Monitoring</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>EnableClientMetrics</code> > <code>false</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_ENABLECLIENTMETRICS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Client side user ids + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>A list of comma-separated user IDs you want to track for client-side webapp metrics.</p><p>Limited to 5 user IDs. Blank by default.</p></td> +<td><ul><li>System Config path: <strong>Environment > Performance Monitoring</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>ClientSideUserIds</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_CLIENTSIDEUSERIDS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting only applies when `EnableClientMetrics` is set to `true`. +- Each user ID should correspond to a valid user in the Mattermost system. For example, `MM_METRICSSETTINGS_CLIENTSIDEUSERIDS="user1,user2,user3"`. +- The total number of user IDs is limited to 5 to ensure performance. Adding more IDs can overwhelm Prometheus due to high label cardinality. To avoid performance issues, we recommend minimizing changes to this list. + +</Note> + +### Listen address + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The port the Mattermost server will listen on to expose performance metrics, when enabled.</p><p>Numerical input. Default is <strong>8067</strong>.</p></td> +<td><ul><li>System Config path: <strong>Environment > Performance Monitoring</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>ListenAddress</code> > <code>8067</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_LISTENADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- `ListenAddress` accepts a port only. It doesn’t take an IP/host. If you need to restrict interfaces, do so via your OS firewall or reverse proxy. +- The address uses a `host:port` format. Use `:8067` to listen on all interfaces on port **8067**, or use `localhost:8067` to restrict to **localhost** only. + +</Note> + +### Block profile rate + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Control how often Mattermost collects data about delays caused by blocking operations within Mattermost (such as when one part of the program has to wait for another). Default is <strong>0</strong> (profiling is disabled).</p><p>The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked.</p><p>Default is <strong>0</strong>.</p></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>BlockProfileRate</code> > <code>0</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_BLOCKPROFILERATE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting isn't available in the System Console and can only be set in `config.json`. +- Only adjust this if you’re diagnosing performance issues and know how to analyze profiling data. The value represents how frequently Mattermost records blocking events in its performance profile: + - Set to 0 to record no blocking events (profiling is disabled). + - Set to 1 to record every blocking event (profiling is fully enabled). + - Set to a higher number to record only a fraction of events (useful for sampling instead of full profiling). + +</Note> + +### Enable notification monitoring + +<table> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '67%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable notification metrics data collection.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost notification data collection is enabled for client-side web and desktop app users.</li><li><strong>false</strong>: Mattermost notification data collection is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>EnableNotificationMetrics</code> > <code>true</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_ENABLENOTIFICATIONMETRICS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- `MetricsSettings.Enable` must be set to `true` +- The `NotificationMonitoring` feature flag must be set to `true` + +</Note> + +See the [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring#getting-started) documentation to learn more about Mattermost Notification Health metrics. + +------------------------------------------------------------------------------------------------------------------------ + +## Developer + +With self-hosted deployments, you can configure developer mode by going to **System Console \> Environment \> Developer**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +### Enable testing commands + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable the <code>/test</code> slash command.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> The <code>/test</code> slash command is enabled to load test accounts and test data. Use this setting only in isolated non-production environments and never in production.</li><li><strong>false</strong>: The <code>/test</code> slash command is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Developer</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableTesting</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLETESTING</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable developer mode + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable developer mode.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Javascript errors are shown in a banner at the top of Mattermost the user interface. Not recommended for use in production.</li><li><strong>false</strong>: Users are not alerted to Javascript errors.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Developer</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableDeveloper</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEDEVELOPER</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable client debugging + +<table> +<colgroup> +<col style={{width: '34%'}} /> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable client-side debugging settings found in <strong>Settings > Advanced > Debugging</strong> for individual users.</p><ul><li><strong>true</strong>: Those settings are visible and can be enabled by users.</li><li><strong>false</strong>: <strong>(Default)</strong> Those settings are hidden and disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Developer</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableClientPerformanceDebugging</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLECLIENTPERFORMANCEDEBUGGING</code></li></ul></td> +</tr> +</tbody> +</table> + +See the [client debugging](/end-user-guide/preferences/manage-advanced-options#performance-debugging) documentation to learn more. + +### Allow untrusted internal connections + +<Warning> + +This setting is intended to prevent users located outside your local network from using the Mattermost server to request confidential data from inside your network. Care should be used when configuring this setting to prevent unintended access to your local network. + +</Warning> + +<table> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '67%'}} /> +</colgroup> +<tbody> +<tr> +<td>Limit the ability for the Mattermost server to make untrusted requests within its local network. A request is considered “untrusted” when it’s made on behalf of a client.</td> +<td><ul><li>System Config path: <strong>Environment > Developer</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>AllowedUntrustedInternalConnections</code> > <code>""</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ALLOWEDUNTRUSTEDINTERNALCONNECTIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +This setting is a whitelist of local network addresses that can be requested by the Mattermost server. It’s configured as a whitespace-separated list of hostnames, IP addresses, and CIDR ranges that can be accessed. + +Requests that can only be configured by system admins are considered trusted and won't be affected by this setting. Trusted URLs include ones used for OAuth login or for sending push notifications. + +The following features make untrusted requests and are affected by this setting: + +- Integrations using webhooks, slash commands, or message actions. This prevents them from requesting endpoints within the local network. +- Link previews. When a link to a local network address is posted in a chat message, this prevents a link preview from being displayed. +- The local [image proxy](/deployment-guide/server/image-proxy). If the local image proxy is enabled, images located on the local network cannot be used by integrations or posted in chat messages. + +Some examples of when you may want to modify this setting include: + +- When installing a plugin that includes its own images, such as [Matterpoll](https://github.com/matterpoll/matterpoll), you'll need to add the Mattermost server’s domain name to this list. +- When running a bot or webhook-based integration on your local network, you’ll need to add the hostname of the bot/integration to this list. +- If your network is configured in such a way that publicly-accessible web pages or images are accessed by the Mattermost server using their internal IP address, the hostnames for those servers must be added to this list. + +<Note> + +- The public IP of the Mattermost application server itself is also considered a reserved IP. +- Use whitespaces instead of commas to list the hostnames, IP addresses, or CIDR ranges. For example: `webhooks.internal.example.com`, `127.0.0.1`, or `10.0.16.0/28`. +- IP address and domain name rules are applied before host resolution. +- CIDR rules are applied after host resolution, and only CIDR rules require DNS resolution. +- Mattermost attempts to match IP addresses and hostnames without even resolving. If that fails, Mattermost resolve using the local resolver (by reading the `/etc/hosts` file first), then checking for matching CIDR rules. For example, if the domain “webhooks.internal.example.com” resolves to the IP address `10.0.16.20`, a webhook with the URL `https://webhooks.internal.example.com/webhook` can be whitelisted using `webhooks.internal.example.com`, or `10.0.16.16/28`, but not `10.0.16.20`. + +</Note> + +## Mobile security + +<PlanAvailability slug="ent-adv" /> + +From Mattermost v10.7 and mobile app v2.27, you can configure biometric authentication, prevent Mattermost use on jailbroken or rooted devices, and can block screen captures without relying on an EMM Provider. Configure these options by going to **System Console \> Environment \> Mobile Security**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart and require users to restart their mobile app or log out and back in before taking effect. + +### Enable biometric authentication + +<table> +<colgroup> +<col style={{width: '34%'}} /> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enforce biometric authentication, with PIN/passcode fallback, before accessing the app. Users will be prompted based on session activity and server switching rules.</p><ul><li><strong>true</strong>: Biometric authentication is enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Biometric authentication is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Mobile Security</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>MobileEnableBiometrics</code> > <code>false</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_MOBILEENABLEBIOMETRICS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Changing this configuration setting takes effect when mobile users restart their Mattermost mobile app or log out and log back in. +- Users must authenticate in the following situations: + - Adding a new server: When a new server is added to the mobile app and biometric authentication is enabled. + - Opening the mobile app: At app launch when the active server requires authentication. + - Returning after background use: After the app has been in the background for 5 minutes or more and the active server requires authentication. + - Using multiple servers: When accessing a server for the first time, after 5 minutes of inactivity on a server, and when the last authentication attempt fails. + +</Note> + +### Enable jailbreak/root protection + +<table> +<colgroup> +<col style={{width: '33%'}} /> +<col style={{width: '66%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Prevent access to the app on devices detected as jailbroken or rooted. If a device fails the security check, users will be denied access or prompted to switch to a compliant server.</p><ul><li><strong>true</strong>: Jailbreak/Root protection is enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Jailbreak/Root protection is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Mobile Security</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>MobileJailbreakProtection</code> > <code>false</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_MOBILEJAILBREAKPROTECTION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Changing this configuration setting takes effect when mobile users restart their Mattermost mobile app or log out and log back in. +- See the [Expo SDK documentation](https://docs.expo.dev/versions/latest/sdk/device/#deviceisrootedexperimentalasync) to learn more about how checks are performed for this functionality. + +</Note> + +### Prevent screen capture + +<table> +<colgroup> +<col style={{width: '33%'}} /> +<col style={{width: '66%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Block screenshots and screen recordings when using the mobile app. Screenshots will appear blank, and screen recordings will blur (iOS) or show a black screen (Android). Also applies when switching apps.</p><ul><li><strong>true</strong>: Screen capture blocking is enabled.</li><li><strong>false</strong>: <strong>(Default)</strong> Screen capture blocking is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Mobile Security</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>MobilePreventScreenCapture</code> > <code>false</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_MOBILEPREVENTSCREENCAPTURE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Changing this configuration setting takes effect when mobile users restart their Mattermost mobile app or log out and log back in. + +</Note> + +### Enable secure file preview on mobile + +This setting improves an organization's mobile security posture by restricting file access while still allowing essential file viewing capabilities. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Prevents file downloads, previews, and sharing for most file types, | - System Config path: <strong>Site Configuration > File sharing and downloads</strong> | even when the | - <code>config.json</code> setting: <code>FileSettings</code> > <code>MobileEnableSecureFilePreview</code> > <code>false</code> | <a href="mm-ref:administration-guide%2Fconfigure%2Fsite-configuration-settings%3Aallow%20file%20downloads%20on%20mobile">Allow file downloads on mobile</a> | - Environment variable: <code>MM_FILESETTINGS_MOBILEENABLESECUREFILEPREVIEW</code> configuration setting is enabled. Allows in-app previews for PDFs, | | videos, and images only. Files are stored temporarily in the app's cache and cannot be exported or shared. | |</li><li><strong>false</strong>: <strong>(Default)</strong> Secure file preview mode is disabled. | |</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Changing this configuration setting takes effect when mobile users restart their Mattermost mobile app or log out and log back in. + +</Note> + +### Allow PDF link navigation on mobile + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables tapping links inside PDFs on mobile when Secure File Preview Mode is active. Links will open in the device browser or supported app.</li><li><strong>false</strong>: Disables link navigation in PDFs when Secure File Preview Mode is active.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > File sharing and downloads</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>MobileAllowPdfLinkNavigation</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_MOBILEALLOWPDFLINKNAVIGATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Changing this configuration setting takes effect when mobile users restart their Mattermost mobile app or log out and log back in. +- This setting has no effect when the [Secure file preview on mobile](#enable-secure-file-preview-on-mobile) configuration setting is disabled. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## config.json-only settings + +The following self-hosted deployment settings are only configurable in the `config.json` file and are not available in the System Console. + +### Disable Customer Portal requests + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable customer portal requests.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Server-side requests made to the customer portal are disabled.</li><li><strong>false</strong>: Server-side requests made to the Mattermost Customer Portal are enabled, but will always fail in air-gapped and restricted deployment environments.</li></ul></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CloudSettings</code> > <code>Disable</code> > <code>true,</code></li><li>Environment variable: <code>MM_CLOUDSETTINGS_DISABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can’t modify this configuration setting. + +</Note> + +### Enable API team deletion + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Allow permanent team deletion via API.</p><ul><li><strong>true</strong>: Team and system admins (or users with appropriate permissions) can call <code>api/v4/teams/{teamid}?permanent=true</code> or use <code>mmctl team delete</code> to permanently delete a team.</li><li><strong>false</strong>: <strong>(Default)</strong> Endpoint not available; <code>api/v4/teams/{teamid}</code> still soft deletes a team.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableAPITeamDeletion</code> > <code>false</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting isn’t available in the System Console and can only be set in `config.json`. + +</Note> + +### Enable API user deletion + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Allow permanent user deletion via API.</p><ul><li><strong>true</strong>: System admins (or users with appropriate permissions) can call <code>api/v4/users/{userid}?permanent=true</code> or use <code>mmctl user delete</code> to permanently delete a user.</li><li><strong>false</strong>: <strong>(Default)</strong> Endpoint not available; <code>api/v4/users/{userid}</code> still soft deletes a user.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableAPIUserDeletion</code> > <code>false</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting isn’t available in the System Console and can only be set in `config.json`. + +</Note> + +### Enable API channel deletion + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Allow permanent channel deletion via API.</p><ul><li><strong>true</strong>: System admins (or users with appropriate permissions) can call <code>api/v4/channels/{channelid}?permanent=true</code> or use <code>mmctl channel delete</code> to permanently delete a channel.</li><li><strong>false</strong>: <strong>(Default)</strong> Endpoint not available; <code>api/v4/channels/{channelid}</code> still soft deletes a channel.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableAPIChannelDeletion</code> > <code>false</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting isn’t available in the System Console and can only be set in `config.json`. + +</Note> + +### Enable desktop app developer mode + +From Desktop App v5.10, this setting enables developer debugging options available by going to the **View \> Developer Tools** menu in the Mattermost desktop app. + +This setting isn't available in the System Console and can only be enabled in `config.json` by setting the environment variable `MM_DESKTOP_DEVELOPER_MODE` to `true`. This setting is disabled by default. + +- **True**: Unlocks the following options in the Desktop App for the purposes of troubleshooting and debugging. You should only enable this setting if instructed to by a Mattermost developer: + - **Browser Mode Only**: Completely disables the preload script and stops web app components from knowing they're in the desktop app. This option should be the best indicator of whether a web app component is causing performance and/or memory retention issues. This option disables notifications, cross-tab navigation, unread/mentions badges, the calls widget, and breaks resizing on macOS. + - **Disable Notification Storage**: Turns off maps that hold references to unread notifications until they've been selected & read. This option is good for debugging in cases where Mattermost is holding onto too many references to unused notifications. + - **Disable User Activity Monitor**: Turns off the interval that checks whether the user is away or not. This option is good for debugging whether a user's availability status is causing unexpected desktop app behavior. + - **Disable Context Menu**: Turns off the context menu attached to the BrowserViews. This option is good as a library santity check. + - **Force Legacy Messaging API**: Forces the app to revert back to the old messaging API instead of the newer contextBridge API. This option is a good santity check to confirm whether the new API is responsible for holding onto memory. + - **Force New Messaging API**: Forces the app to use the contextBridge API and completely disables the legacy one. This option forces off listeners for the legacy API. +- **False**: **(Default)** Developer debugging options are locked and unavailable in the Desktop App. + +### Redis cache backend + +<PlanAvailability slug="ent-adv" /> + +From Mattermost v10.4, Mattermost Enterprise customers with self-hosted deployments can configure [Redis](https://redis.io/) (Remote Dictionary Server) as an alternative cache backend. Redis is an open-source, in-memory data structure store that can be used as a database, cache, and message broker. It supports various data structures and is a top choice for its performance because its able to store data in memory and provide very quick data access. + +Using Redis as a caching solution can help ensure that Mattermost for enterprise-level deployments with high concurrency and large user bases remains performant and efficient, even under heavy usage. + +Configure a Redis cache by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +#### Cache type + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Define the cache type.</p><ul><li><strong>lru</strong>: <strong>(Default)</strong> Mattermost uses the in-memory cache store.</li><li><strong>redis</strong>: Mattermost uses the configured Redis cache store.</li></ul></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>CacheType,</code> > <code>lru</code></li><li>Environment variable: <code>MM_CACHESETTINGS_CACHETYPE</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Redis address + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The hostname of the Redis host.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>RedisAddress,</code></li><li>Environment variable: <code>MM_CACHESETTINGS_REDISADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Redis password + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The password of the Redis host.</p><p>String input. Leave blank if there is no password.</p></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>RedisPassword,</code></li><li>Environment variable: <code>MM_CACHESETTINGS_REDISPASSWORD</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Redis database + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The database of the Redis host.</p><p>Zero-indexed number up to 15. Typically set to <code>0</code>. Redis allows a maximum of 16 databases.</p></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>RedisDB,</code></li><li>Environment variable: <code>MM_CACHESETTINGS_REDISDB</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Disable client cache + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Disables the client-side cache of Redis.</p><ul><li><strong>true</strong>: Client-side cache of Redis is disabled. Typically used as a test option, and not in production environments.</li><li><strong>false</strong>: <strong>(Default)</strong> Client-side cache of Redis is enabled.</li></ul></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>DisableClientCache,</code> > <code>false</code></li><li>Environment variable: <code>MM_CACHESETTINGS_REDISDB</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Redis cache prefix + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td>Adds a prefix to all Redis cache keys.</td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>CacheSettings</code> > <code>RedisCachePrefix</code></li><li>Environment variable: <code>MM_CACHESETTINGS_REDISCACHEPREFIX</code></li></ul></td> +</tr> +</tbody> +</table> + +<Tip> + +Adding a prefix to all Redis cache keys reduces key collisions, simplifies debugging, isolates data, and provides a clear structure for managing and scaling Redis-based systems. In environments where multiple systems or tenants use the same Redis instance, prefixes become critical for maintaining data integrity and operational efficiency. + +</Tip> + +### Enable webhub channel iteration + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Control the performance of websocket broadcasting in channels.</p><p>When enabled, improves websocket broadcasting performance; however, performance may decrease when users join or leave a channel.</p><p>Not recommended unless you have at least 200,000 concurrent users actively using Mattermost.</p><p>Disabled by default.</p></td> +<td><ul><li>System Config path: <strong>N/A</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableWebHubChannelIteration,</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEWEBHUBCHANNELITERATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable dedicated export filestore target + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>Enables the ability to specify an alternate filestore | - System Config path: <strong>N/A</strong> | target for Mattermost | - <code>config.json</code> setting: <code>FileSettings</code> > <code>DedicatedExportStore</code> | <a href="mm-doc:%2Fadministration-guide%2Fmanage%2Fbulk-export-tool">bulk exports</a> and | - Environment variable: <code>MM_FILESETTINGS_DEDICATEDEXPORTSTORE</code> | <a href="mm-doc:%2Fadministration-guide%2Fcomply%2Fcompliance-export">compliance exports</a>. | | | | - <strong>True</strong>: A new <code>ExportFileBackend()</code> is generated | | under <code>FileSettings</code> using new configuration values | | for the following configuration settings: | | | | - <code>ExportDriverName</code> | | - <code>ExportDirectory</code> | | - <code>ExportAmazonS3AccessKeyId</code> | | - <code>ExportAmazonS3SecretAccessKey</code> | | - <code>ExportAmazonS3Bucket</code> | | - <code>ExportAmazonS3PathPrefix</code> | | - <code>ExportAmazonS3Region</code> | | - <code>ExportAmazonS3Endpoint</code> | | - <code>ExportAmazonS3SSL</code> | | - <code>ExportAmazonS3SignV2</code> | | - <code>ExportAmazonS3SSE</code> | | - <code>ExportAmazonS3Trace</code> | | - <code>ExportAmazonS3RequestTimeoutMilliseconds</code> | | - <code>ExportAmazonS3PresignExpiresSeconds</code> | | | | - <strong>False</strong>: (<strong>Default</strong>) Standard | | <a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Afile%20storage">file storage | |</a> | is used. Standard file storage will also be used when the configuration setting | | or value is omitted. | |</td> +</tr> +</tbody> +</table> + +<Note> + +- When an alternate filestore target is configured, Mattermost Cloud admins can generate an S3 presigned URL for exports using the `/exportlink [job-id|zip file|latest]` slash command. See the [Mattermost data migration](/administration-guide/manage/cloud-data-export#create-the-export) documentation for details. Alternatively, Cloud and self-hosted admins can use the [mmctl export generate-presigned-url](/administration-guide/manage/mmctl-command-line-tool#mmctl-export-generate-presigned-url) command to generate a presigned URL directly from mmctl. +- Generating an S3 presigned URL requires the feature flag `EnableExportDirectDownload` to be set to `true`, the storage must be compatible with generating an S3 link, and this experimental configuration setting must be set to `true`. Presigned URLs for exports aren't supported for systems with shared storage. + +</Note> diff --git a/docs/main/administration-guide/configure/environment-variables.mdx b/docs/main/administration-guide/configure/environment-variables.mdx new file mode 100644 index 000000000000..6ee7d16d7228 --- /dev/null +++ b/docs/main/administration-guide/configure/environment-variables.mdx @@ -0,0 +1,47 @@ +--- +title: "Environment variables" +--- +<PlanAvailability slug="all-commercial" /> + +You can use environment variables to manage the configuration. Environment variables override settings in `config.json`. If a change to a setting in `config.json` requires a restart for it to take effect, then changes to the corresponding environment variable also require a server restart. + +The name of the environment variable for any setting can be derived from the name of that setting in `config.json`. For example, to derive the name of the Site URL setting: + +1. Find the setting in `config.json`. In this case, *ServiceSettings.SiteURL*. +2. Add `MM_` to the beginning and convert all characters to uppercase and replace the `.` with `_`. For example, *MM_SERVICESETTINGS_SITEURL*. +3. The setting becomes `export MM_SERVICESETTINGS_SITEURL="http://example.com"`. + +<Note> + +- If Mattermost is run from an initialization file, environment variables can be set via `Environment=<>`, or `EnvironmentFile=<path/to/file>`. In the second case, the file specified contains the list of environment variables to set. +- From Mattermost v7.5, environment configuration parsing supports JSON for `MM_PLUGINSETTINGS_PLUGINS` and `MM_PLUGINSETTINGS_PLUGINSTATES`. This is especially helpful for Helm configuration files, provided all plugins are configured at the same time. For example, `MM_PLUGINSETTINGS_PLUGINSTATES="{\"com.mattermost.calls\":{\"Enable\":true},\"com.mattermost.nps\":{\"Enable\":true}}"`. +- When settings are configured through an environment variable, system admins can't modify them in the System Console. If a setting is configured through an environment variable, and any other changes are made in the System Console, the value stored of the environment variable will be written back to the `config.json` as that setting's value. +- For any setting that's not set in `config.json` or in environment variables, the Mattermost server uses the setting's default value as documented in the sections below on this page. + +</Note> + +<Warning> + +- Environment variables for Mattermost settings that are set within the active shell will take effect when migrating configuration. For more information, see the [configuration in a database](/administration-guide/configure/configuration-in-your-database) documentation. +- Database connection strings for the database read and search replicas need to be formatted using [URL encoding](https://www.w3schools.com/tags/ref_urlencode.asp). Incorrectly formatted strings may cause some characters to terminate the string early, resulting in issues when the connection string is parsed. + +</Warning> + +## Override Mattermost license file + +You can use an environment variable to override any license in the database or file configuration without replacing those licenses. When starting the server, specify the license key as `MM_LICENSE` with the contents of a license file. + +<Note> + +If `MM_LICENSE` is set to a non-empty string, but the license specified is not valid, the Mattermost server will be started without a license. + +In a High Availability deployment, using an environment variable to override a server license only affects the individual app server and doesn't propagate to other servers in the cluster. + +</Note> + +## Load custom configuration defaults + +This custom configuration applies only if the values are not already present in the current server configuration. + +1. Create a JSON file that contains the custom configuration defaults. For example, `custom.json`. +2. When starting the server, point the custom defaults environment variable to the defaults file: `MM_CUSTOM_DEFAULTS_PATH=custom.json`. diff --git a/docs/main/administration-guide/configure/experimental-configuration-settings.mdx b/docs/main/administration-guide/configure/experimental-configuration-settings.mdx new file mode 100644 index 000000000000..f60ec43dfd0a --- /dev/null +++ b/docs/main/administration-guide/configure/experimental-configuration-settings.mdx @@ -0,0 +1,1751 @@ +--- +title: "Experimental configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Review and manage the following [experimental](/administration-guide/manage/feature-labels#experimental) configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Experimental \> Features**: + +- [Experimental System Console configuration settings](#experimental-system-console-configuration-settings) +- [Experimental audit logging configuration settings](#experimental-audit-logging-configuration-settings) +- [Experimental job configuration settings](#experimental-job-configuration-settings) +- [Experimental configuration settings for self-hosted deployments only](#experimental-configuration-settings-for-self-hosted-deployments-only) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, one `LoginButtonColor` value is under `LdapSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.LdapSettings.LoginButtonColor'` +- When working with the `config.json` file manually, look for an object such as `LdapSettings`, then within that object, find the key `LoginButtonColor`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Experimental System Console configuration settings + +### AD/LDAP login button color + +Specify the color of the AD/LDAP login button for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### AD/LDAP login button border color + +Specify the color of the AD/LDAP login button border for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonBorderColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### AD/LDAP login button text color + +Specify the color of the AD/LDAP login button text for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonTextColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Change authentication method + +**True**: Users can change their sign-in method to any that is enabled on the server, either via their Profile or the APIs. + +**False**: Users cannot change their sign-in method, regardless of which authentication options are enabled. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalEnableAuthenticationTransfer": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Link metadata timeout + +Adds a configurable timeout for requests made to return link metadata. If the metadata is not returned before this timeout expires, the message will post without requiring metadata. This timeout covers the failure cases of broken URLs and bad content types on slow network connections. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LinkMetadataTimeoutMilliseconds</code>: 5000`` with numerical input.</td> +</tr> +</tbody> +</table> + +### Email batching buffer size + +Specify the maximum number of notifications batched into a single email. + +<Note> + +- We recommend increasing the buffer size from the default value if you see the following error in the Mattermost logs: `Email batching job's receiving buffer was full. Please increase the EmailBatchingBufferSize. Falling back to sending immediate mail.` Increasing this value will ensure emails are queued up, without impacting server performance. +- Notifications will be sent instantly if the queue of emails exceeds the [email batching interval](#id1) configured. + +</Note> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>EmailBatchingBufferSize</code>: 256`` with numerical input.</td> +</tr> +</tbody> +</table> + +### Email batching interval + +Specify the maximum frequency, in seconds, which the batching job checks for new notifications. + +<Note> + +- We recommend decreasing the email batching interval from the default value if you see the following error in the Mattermost logs: `Email batching job's receiving buffer was full. Please increase the EmailBatchingBufferSize. Falling back to sending immediate mail.`. +- Longer batching intervals may increase performance. +- Notifications will be sent instantly if the [queue of emails](#email-batching-buffer-size) exceeds the email batching interval configured. + +</Note> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>EmailBatchingInterval": 30</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Email login button color + +Specify the color of the email login button for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Email login button border color + +Specify the color of the email login button border for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonBorderColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Email login button text color + +Specify the color of the email login button text for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonTextColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Enable account deactivation + +**True**: Ability for users to deactivate their own account from **Settings \> Advanced \> Deactivate Account**. If a user deactivates their own account, they will get an email notification confirming they were deactivated. Available only when authentication is set to use email/password. Not available when authentication uses SAML or AD/LDAP. + +**False**: Ability for users to deactivate their own account is disabled. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableUserDeactivation": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable automatic replies + +**True**: Users can enable Automatic Replies in **Settings \> Notifications**. Users set a custom message that will be automatically sent in response to Direct Messages. + +**False**: Disables the Automatic Direct Message Replies feature and hides it from **Settings**. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalEnableAutomaticReplies": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable channel viewed websocket messages + +This setting determines whether `channel_viewed WebSocket` events are sent, which synchronize unread notifications across clients and devices. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableChannelViewedMessages": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this experimental configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Database Load: When channel_viewed events are disabled, the server no longer needs to log these events in the database. This reduces the number of write and update operations, which can be substantial in a busy server with many users frequently switching channels. +- Decreased Network Traffic: Disabling these events means there are fewer messages sent between the server and clients. This reduction in network traffic can lower latency and improve the overall responsiveness of the server, especially for users with slower connections. +- Lower Server CPU Usage: Processing channel_viewed events requires CPU resources to handle database transactions and network communication. Without these events, the server's CPU can be utilized more efficiently for other tasks, improving the overall performance. +- Improved User Experience: With reduced server load and network traffic, users may experience faster loading times and a more fluid interaction with the application. +- However, disabling this configuration setting affects some functionality, such as accurate tracking of read and unread messages in channels. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable default channel leave/join system messages + +This setting determines whether team leave/join system messages are posted in the default `town-square` channel. + +**True**: Enables leave/join system messages in the default `town-square` channel. + +**False**: Disables leave/join messages from the default `town-square` channel. These system messages won't be added to the database either. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalEnableDefaultChannelLeaveJoinMessages": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable hardened mode + +**True**: Enables a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. + +**False**: Disables hardened mode. + +Changes made when hardened mode is enabled: + +- Failed login returns a generic error message instead of a specific message for username and password. +- If [multi-factor authentication (MFA)](/administration-guide/onboard/multi-factor-authentication) is enabled, the route to check if a user has MFA enabled always returns true. This causes the MFA input screen to appear even if the user does not have MFA enabled. The user may enter any value to pass the screen. Note that hardened mode does not affect user experience when MFA is enforced. +- Password reset does not inform the user that they can not reset their SSO account through Mattermost and instead claims to have sent the password reset email. +- Mattermost sanitizes all 500 errors before returned to the client. Use the supplied `request_id` to match user facing errors with the server logs. +- Standard users authenticated via username and password can't use post props reserved for integrations, such as `override_username` or `override_icon_url`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalEnableHardenedMode": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable theme selection + +**True**: Enables the **Display \> Theme** tab in **Settings** so users can select their theme. + +**False**: Users cannot select a different theme. The **Display \> Theme** tab is hidden in **Settings**. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableThemeSelection": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Allow custom themes + +**True**: Enables the **Display \> Theme \> Custom Theme** section in **Settings**. + +**False**: Users cannot use a custom theme. The **Display \> Theme \> Custom Theme** section is hidden in **Settings**. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '92%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AllowCustomThemes": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Default theme + +Set a default theme that applies to all new users on the system. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DefaultTheme": "default"</code> with options <code>"default"</code>, <code>"organization"</code>, <code>"mattermostDark"</code>, and <code>"windows10"</code>.</td> +</tr> +</tbody> +</table> + +### Enable tutorial + +**True**: Users are prompted with a tutorial when they open Mattermost for the first time after account creation. + +**False**: The tutorial is disabled. Users are placed in Town Square when they open Mattermost for the first time after account creation. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ServiceSettings.EnableTutorial": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable onboarding flow + +**True**: New Mattermost users are shown key tasks to complete as part of initial onboarding. + +**False**: User onboarding tasks are disabled. Users are placed in Town Square when they open Mattermost for the first time after account creation. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ServiceSettings.EnableOnboardingFlow": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable user typing messages + +This setting determines whether "user is typing..." messages are displayed below the message box when using Mattermost in a web browser or the desktop app. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableUserTypingMessages": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this experimental configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Server Load: Typing events generate additional websocket traffic. Disabling them can reduce the amount of data that needs to be handled by the server, improving the overall response time and decreasing server load. +- Lower Network Traffic: When typing events are enabled, every keystroke generates a network event. This can lead to a significant amount of network traffic, particularly in busy channels. Disabling these events reduces the amount of information transmitted over the network. +- Client Performance: On the client side, processing typing events requires resources. By not having to handle these events, the client can be more responsive and use less memory and CPU. + +</Note> + +### User typing timeout + +This setting defines how frequently "user is typing..." messages are updated, measured in milliseconds. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '99%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"TimeBetweenUserTypingUpdatesMilliseconds": 5000</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### User's status and profile fetching poll interval + +This setting configures the number of milliseconds to wait between fetching user statuses and profiles periodically. Set to `0` to disable. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.UsersStatusAndProfileFetchingPollIntervalMilliseconds": 3000</code> with numerical input.</td> +</tr> +</tbody> +</table> + +<Note> + +Decrease this configuration setting value to increase how often Mattermost checks for and retrieves updated user profile datails. Reducing this value can be particularly helpful to reduce the likelyhood of usernames being displayed in channels as **Someone** due to outdated or missing data. + +</Note> + +### Primary team + +The primary team of which users on the server are members. When a primary team is set, the options to join other teams or leave the primary team are disabled. + +If the team URL of the primary team is `https://example.mattermost.com/myteam/`, then set the value to `myteam` in `config.json`. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalPrimaryTeam": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### SAML login button color + +Specify the color of the SAML login button for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### SAML login button border color + +Specify the color of the SAML login button border for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonBorderColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### SAML login button text color + +Specify the color of the SAML login button text for white labeling purposes. Use a hex code with a \#-sign before the code. This setting only applies to the mobile app. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LoginButtonTextColor": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Use channel name in email notifications + +**True**: Channel and team name appears in email notification subject lines. Useful for servers using only one team. + +**False**: Only team name appears in email notification subject line. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"UseChannelInEmailNotifications": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### User status away timeout + +This setting defines the number of seconds after which the user's status indicator changes to "Away", when they are away from Mattermost. + +<table style={{width: '82%'}}> +<colgroup> +<col style={{width: '82%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"UserStatusAwayTimeout": 300</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Disable data refetching on browser refocus + +This setting disables re-fetching of channel and channel members on browser focus. + +**True**: Mattermost won't refetch channels and channel members when the browser regains focus. This may result in improved performance for users with many channels and channel members. + +**False**: (Default) Mattermost will refetch channels and channel members when the browser regains focus. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.DisableRefetchingOnBrowserFocus": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Disable wake up reconnect handler + +This setting disables attempts to detect when the computer has woken up and refetch data. + +**True**: Mattermost won't attempt to detect when the computer has woken up and refetch data. This might reduce the amount of regular network traffic the app is sending. + +**False**: (**Default**) Mattermost attempts to detect when the computer has woken up and refreshes data. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.DisableWakeUpReconnectHandler": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Delay channel autocomplete + +This setting controls whether or not the channel link autocomplete triggers immediately when after a tilde is typed when composing a message. This setting makes the channel autocomplete, such as `~town-square`, less obtrusive for people who use tildes `~` as punctuation. + +**True**: The autocomplete appears after the user types a tilde followed by two or more characters. For example, typing `~to` will show the autocomplete, but typing `~` will not. + +**False**: **(Default)** The autocomplete appears immediately after the user types a tilde. For example, typing `~` will show the autocomplete. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.DelayChannelAutocomplete": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### YouTube referrer policy + +This setting resolves issues where YouTube video previews display as unavailable. + +**True**: The referrer policy for embedded YouTube videos is set to `strict-origin-when-cross-origin`. + +**False**: (Default) The referrer policy is set to `no-referrer` which enhances user privacy by not disclosing the source URL, but limits the ability to track user engagement and traffic sources in analytics tools. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalSettings.YoutubeReferrerPolicy": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Experimental Bleve configuration settings + +<PlanAvailability slug="all-commercial" /> + +<Important> + +**From Mattermost v11, Bleve search has been deprecated.** These configuration settings are only available for Mattermost versions prior to v11.0. For v11.0 and later, [Elasticsearch](/administration-guide/scale/elasticsearch-setup) or [OpenSearch](/administration-guide/scale/opensearch-setup) for [enterprise search](/administration-guide/scale/enterprise-search) capabilities. + +</Important> + +Access the following configuration settings in the System Console by going to **Experimental \> Bleve**, or by editing the `config.json` file as described in the following tables: + +### Enable Bleve indexing + +**True**: The indexing of new posts occurs automatically. Search queries will not use bleve search until [Enable Bleve for search queries](/administration-guide/configure/experimental-configuration-settings#enable-bleve-for-search-queries) is enabled. + +**False**: The indexing of new posts does not occur automatically. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableIndexing": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Index directory + +Directory path to use for storing bleve indexes. + +<Tip> + +The bleve index directory path isn't required to exist within the `mattermost` directory. When it exists outside of the `mattermost` directory, no additional steps are needed to preserve or reindex these files as part of a Mattermost upgrade. See our [Upgrading Mattermost Server](/administration-guide/upgrade/upgrading-mattermost-server) documentation for details. + +</Tip> + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"IndexDir": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Bulk index now + +Select **Index Now** to index all users, channels, and posts in the database from oldest to newest. Bleve is available during indexing, but search results may be incomplete until the indexing job is complete. + +### Purge indexes + +Select **Purge Index** to remove the contents of the Bleve index directory. Search results may be incomplete until a bulk index of the existing database is rebuilt. + +### Enable Bleve for search queries + +**True**: Search queries will use bleve search. + +**False**: Search queries will not use bleve search. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '92%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableSearching": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable Bleve for autocomplete queries + +**True**: Autocomplete queries will use bleve search. + +**False**: Autocomplete queries will not use bleve search. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableAutocomplete": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Experimental audit logging configuration settings + +Enable the following settings to output audit events in the System Console by going to **Compliance \> Audit Logging**, or in the `config.json` file. + +<Note> + +The ability to enable and configure audit logging is currently in [Beta](/administration-guide/manage/feature-labels#beta). + +</Note> + +### Advanced logging + +<PlanAvailability slug="entry-ent" /> + +Output log and audit records to any combination of console, local file, syslog, and TCP socket targets for a Mattermost Cloud deployment. See the [advanced logging](/administration-guide/manage/logging#advanced-logging) documentation for details about logging options. + +### Enable audit logging + +<PlanAvailability slug="ent-plus" /> + +When audit logging is enabled in a self-hosted instance, you can specify size, backup interval, compression, maximium age to manage file rotation, and timestamps for audit logging, as defined below. You can specify these settings independently for audit events and AD/LDAP events. + +**True**: Audit logging files are enabled, and audit files are written locally to a file for a self-hosted deployment. + +**False**: Audit logging files aren't enabled, and audit logs aren't written locally to a file for a self-hosted deployment. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileEnabled": false",</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### File name + +<PlanAvailability slug="ent-plus" /> + +Specify the path to the audit file for a self-hosted deployment. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileName": ""</code> with string input consisting of a user-defined path (e.g. <code>/var/log/mattermost_audit.log</code>).</td> +</tr> +</tbody> +</table> + +### Max file size + +<PlanAvailability slug="ent-plus" /> + +This is the maximum size, in megabytes, that the file can grow before triggering rotation for a self-hosted deployment. The default setting is `100`. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '98%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileMaxSizeMB": 100</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Max file age + +<PlanAvailability slug="ent-plus" /> + +This is the maximum age, in days, a file can reach before triggering rotation for a self-hosted deployment. The default value is `0`, indicating no limit on the age. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileMaxAgeDays": 0</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Maximum file backups + +<PlanAvailability slug="ent-plus" /> + +This is the maximum number of rotated files kept for a self-hosted deployment. The oldest is deleted first. The default value is `0`, indicating no limit on the number of backups. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileMaxBackups": 0</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### File compression + +<PlanAvailability slug="ent-plus" /> + +When `true`, rotated files are compressed using `gzip` in a self-hosted deployment. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileCompress": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Maximum file queue + +<PlanAvailability slug="ent-plus" /> + +This setting determines how many audit records can be queued/buffered at any point in time when writing to a file for a self-hosted deployment. The default is `1000` records. This setting can be left as default unless you are seeing audit write failures in the server log and need to adjust the number accordingly. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>".ExperimentalAuditSettings.FileMaxQueueSize": 1000</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Certificate + +Cloud Enterprise customers can upload and manage a certificate for audit logging encryption on Syslog or TCP logging targets. The ability to upload a certificate is only available when the feature flag `ExperimentalAuditSettingsSystemConsoleUI` is enabled. + +Upload the certificate PEM file in the System Console by going to **System Console \> Audit Log Settings \> Certificate** and selecting **File/Remove Certificate**. The certificate file can be stored in the filestore or stored locally on the filesystem. + +## Experimental configuration settings for self-hosted deployments only + +Access the following self-hosted configuration settings by editing the `config.json` file as described in the following tables. These configuration settings are not accessible through the System Console. + +<Tip> + +Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `SiteURL` value is under `ServiceSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.ServiceSettings.SiteURL'` +- When working with the `config.json` file manually, look for the key `ServiceSettings`, then within that object, find the key `SiteURL`. + +</Tip> + +### Allowed themes + +This setting isn't available in the System Console and can only be set in `config.json`. + +Select the themes that can be chosen by users when `EnableThemeSelection` is set to `true`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AllowedThemes": []</code> with string array input consisting of the options <code>"default"</code>, <code>"organization"</code>, <code>"mattermostDark"</code>, and <code>"windows10"</code>, such as <code>["mattermostDark", "windows10"]</code>.</td> +</tr> +</tbody> +</table> + +### File Location + +<PlanAvailability slug="ent-plus" /> + +This setting isn't available in the System Console and can only be set in `config.json`. + +Set the file location of the compliance exports. By default, they are written to the `exports` subdirectory of the configured [Local Storage directory](/administration-guide/configure/environment-configuration-settings#local-storage-directory). + +<table style={{width: '77%'}}> +<colgroup> +<col style={{width: '76%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"FileLocation": "export"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Push notification buffer + +This setting isn't available in the System Console and can only be set in `config.json`. + +Used to control the buffer of outstanding Push Notification messages to be sent. If the number of messages exceeds that number, then the request making the Push Notification will be blocked until there's room. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature’s <code>config.json</code> setting is <code>"PushNotificationBuffer": 1000"</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Restrict system admin + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: **(Default for Cloud deployments)** Restricts the system admin from viewing and modifying a subset of server configuration settings from the System Console. Not recommended for use in on-prem installations. This is intended to support Mattermost Private Cloud in giving the system admin role to users but restricting certain actions only for Cloud Admins. + +**False**: **(Default for self-host deployments)** No restrictions are applied to the system admin role. + +<table style={{width: '97%'}}> +<colgroup> +<col style={{width: '96%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RestrictSystemAdmin": "false"</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +The ability to restrict the system admin from viewing and modifying a subset of server configuration settings is currently in [Beta](/administration-guide/manage/feature-labels#beta). + +</Note> + +### Enable client-side certification + +<PlanAvailability slug="ent-plus" /> + +<Important> + +**Certificate-based authentication has been deprecated from Mattermost v11.0.** This setting must be set to `false` to start the server from v11. Setting this to `true` will prevent the server from starting. + +</Important> + +**True**: Enables client-side certification for your Mattermost server. See [the documentation](/administration-guide/onboard/certificate-based-authentication) to learn more. + +**False**: **(Default)** Client-side certification is disabled. + +<table style={{width: '96%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ClientSideCertEnable": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Client-side certification login method + +<PlanAvailability slug="ent-plus" /> + +<Important> + +**Certificate-based authentication has been deprecated from Mattermost v11.0.** This setting is no longer functional from Mattermost v11.0 and should be left at the default value. + +</Important> + +This configuration setting is used in combination with the `ClientSideCertEnable` configuration setting and has the following possible values: + +**Primary**: After the client side certificate is verified, user's email is retrieved from the certificate and is used to log in without a password. + +**Secondary**: **(Default)** After the client side certificate is verified, user's email is retrieved from the certificate and matched against the one supplied by the user. If they match, the user logs in with regular email/password credentials. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ClientSideCertCheck": "secondary"</code> with options <code>"primary"</code> and <code>"secondary"</code>.</td> +</tr> +</tbody> +</table> + +### Export output directory + +This setting isn't available in the System Console and can only be set in `config.json`. + +The directory where the exported files are stored. The path is relative to the `FileSettings` directory. By default, exports are stored under `./data/export`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting under the <code>ExportSettings</code> section is <code>Directory: ./export</code> with string input.</td> +</tr> +</tbody> +</table> + +### Export retention days + +This setting isn't available in the System Console and can only be set in `config.json`. + +The number of days to retain the exported files before deleting them. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting under the <code>ExportSettings</code> section is <code>RetentionDays: 30</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Maximum image resolution + +This setting isn't available in the System Console and can only be set in `config.json`. + +Maximum image resolution size for message attachments in pixels. + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '87%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"MaxImageResolution": 33177600</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Maximum image decoder concurrency + +This setting isn't available in the System Console and can only be set in `config.json`. + +Indicates how many images can be decoded concurrently at once. The default value of `-1` configures Mattermost to automatically use the number of CPUs present. + +<Note> + +- This configuration setting affects the total memory consumption of the server. The maximum memory of a single image is dictated by `MaxImageResolution * 24 bytes`, where the default maximum image resolution value is 33MB. +- Therefore, a good rule of thumb to follow is that `33MB * MaxImageDecoderConcurrency * 24` should be less than the total memory for the server. +- For example, if you have a 4-core server, you should leave aside at least `33 * 4 * 24 = 3168MB` memory for image processing. Otherwise, adjust the [MaxImageResolution](#maximum-image-resolution) configuration setting to adjust the amount of memory needed for image processing. + +</Note> + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '87%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"MaxImageDecoderConcurrency": "-1"</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Initial font + +This setting isn't available in the System Console and can only be set in `config.json`. + +Font used in auto-generated profile pics with colored backgrounds. + +<table style={{width: '80%'}}> +<colgroup> +<col style={{width: '80%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"InitialFont": "luximbi.ttf"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Amazon S3 signature v2 + +This setting isn't available in the System Console and can only be set in `config.json`. + +By default, Mattermost uses Signature V4 to sign API calls to AWS, but under some circumstances, V2 is required. For more information about when to use V2, see [https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html). + +**True**: Use Signature Version 2 Signing Process. + +**False**: Use Signature Version 4 Signing Process. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AmazonS3SignV2": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Amazon S3 path + +This setting isn't available in the System Console and can only be set in `config.json`. + +Allows using the same S3 bucket for multiple deployments. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature’s <code>config.json</code> setting is <code>"AmazonS3PathPrefix: ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### GitLab scope + +This setting isn't available in the System Console and can only be set in `config.json`. + +Standard setting for OAuth to determine the scope of information shared with OAuth client. Not currently supported by GitLab OAuth. + +<table style={{width: '66%'}}> +<colgroup> +<col style={{width: '65%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Scope": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Global relay SMTP server timeout + +<PlanAvailability slug="ent-plus" /> + +This setting isn't available in the System Console and can only be set in `config.json`. + +The number of seconds that can elapse before the connection attempt to the SMTP server is abandoned. The default value is 1800 seconds. This setting is currently not available in the System Console and can only be set in `config.json`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"GlobalRelaySettings.SMTPServerTimeout": "1800"</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Google scope + +This setting isn't available in the System Console and can only be set in `config.json`. + +Standard setting for OAuth to determine the scope of information shared with OAuth client. Recommended setting is `profile email`. + +<table style={{width: '77%'}}> +<colgroup> +<col style={{width: '76%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Scope": "profile email"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Import input directory + +This setting isn't available in the System Console and can only be set in `config.json`. + +The directory where the imported files are stored. The path is relative to the `FileSettings` directory. By default, imports are stored under `./data/import`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting under the <code>ImportSettings</code> section is <code>Directory: ./import</code> with string input.</td> +</tr> +</tbody> +</table> + +### Import retention days + +This setting isn't available in the System Console and can only be set in `config.json`. + +The number of days to retain the imported files before deleting them. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting under the <code>ImportSettings</code> section is <code>RetentionDays: 30</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Export from timestamp + +<PlanAvailability slug="ent-plus" /> + +This setting isn't available in the System Console and can only be set in `config.json`. + +Set the Unix timestamp (seconds since epoch, UTC) to export data from. + +<table style={{width: '79%'}}> +<colgroup> +<col style={{width: '79%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExportFromTimestamp": 0</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Entra ID Scope + +This setting isn't available in the System Console and can only be set in `config.json`. + +Standard setting for OAuth to determine the scope of information shared with OAuth client. Recommended setting is `User.Read`. + +<table style={{width: '73%'}}> +<colgroup> +<col style={{width: '73%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Scope": "User.Read"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Enable plugin uploads + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Enables plugin uploads by system admins at **Plugins \> Management**. If you do not plan to upload a plugin, set to `false` to control which plugins are installed on your server. See [documentation](https://developers.mattermost.com/integrate/admin-guide/admin-plugins-beta/) to learn more. + +**False**: Disables plugin uploads on your Mattermost server. + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableUploads": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Allow insecure download URL + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Enables downloading and installing a plugin from a remote URL. + +**False**: Disables downloading and installing a plugin from a remote URL. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AllowInsecureDownloadUrl": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable plugin health check + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Enables plugin health check to ensure all plugins are periodically monitored, and restarted or deactivated based on their health status. The health check runs every 30 seconds. If the plugin is detected to fail 3 times within an hour, the Mattermost server attempts to restart it. If the restart fails 3 successive times, it's automatically disabled. + +**False**: Disables plugin health check on your Mattermost server. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '92%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableHealthCheck": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Plugin directory + +This setting isn't available in the System Console and can only be set in `config.json`. + +The location of the plugin files. If blank, they are stored in the `./plugins` directory. The path that you set must exist and Mattermost must have write permissions in it. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"Directory": "./plugins"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Client plugin directory + +This setting isn't available in the System Console and can only be set in `config.json`. + +The location of client plugin files. If blank, they are stored in the `./client/plugins` directory. The path that you set must exist and Mattermost must have write permissions in it. + +<table style={{width: '95%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ClientDirectory": "./client/plugins"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Scoping IDP provider ID + +This setting isn't available in the System Console and can only be set in `config.json`. + +Allows an authenticated user to skip the initial login page of their federated Azure AD server, and only require a password to log in. + +<table style={{width: '78%'}}> +<colgroup> +<col style={{width: '78%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ScopingIDPProviderId": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Scoping IDP provider name + +This setting isn't available in the System Console and can only be set in `config.json`. + +Adds the name associated with a user's Scoping Identity Provider ID. + +<table style={{width: '73%'}}> +<colgroup> +<col style={{width: '73%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ScopingIDPName": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Group unread channels + +This setting isn't available in the System Console and can only be set in `config.json`. + +This setting applies to the new sidebar only. You must disable the [Enable Legacy Sidebar](/administration-guide/configure/deprecated-configuration-settings#enable-legacy-sidebar) configuration setting to see and enable this functionality in the System Console. + +**Default Off**: Disables the unread channels sidebar section for all users by default. Users can enable it in **Settings \> Sidebar \> Group unread channels separately**. + +**Default On**: Enables the unread channels sidebar section for all users by default. Users can disable it in **Settings \> Sidebar \> Group unread channels separately**. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalGroupUnreadChannels": "default_off"</code> with options <code>"default_off"</code> and <code>"default_on"</code>.</td> +</tr> +</tbody> +</table> + +### Enable channel category sorting + +From Mattermost v10.10, when this [experimental](/administration-guide/manage/feature-labels#experimental) feature is enabled, users can assign channels to new or existing channel categories when creating or renaming channels. + +**This configuration setting applies only to cloud-based deployments.** + +**True**: Users can assign channels to new or existing channel categories when creating or renaming channels. + +**False**: **(Default)** Disables the ability to automatically assign channels to new or existing channel categories. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalEnableChannelCategorySorting": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Strict CSRF token enforcement + +This setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Enables CSRF protection tokens for additional hardening compared to the currently used custom header. When the user logs in, an additional cookie is created with the CSRF token contained. + +**False**: Disables CSRF protection tokens and enables legacy X-Requested-With header fallback for backward compatibility. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalStrictCSRFEnforcement": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Developer flags + +This setting isn't available in the System Console and can only be set in `config.json`. + +This configuration setting specifies a list of strings where each string is a flag used to set the content security policy (CSP) for the Mattermost Web App. Each flag must be in the format `flag=true` (e.g. `unsafe-eval=true,unsafe-inline=true`). Not recommended for production environments. + +The following values are currently supported: + +- `unsafe-eval`: Adds the `unsafe-eval` CSP directive to the root webapp, allowing increased debugging in developer environments. +- `unsafe-inline`: Adds the `unsafe-inline` CSP directive to the root webapp, allowing increased debugging in developer environments. + +This configuration setting is disabled by default and requires [developer mode](/administration-guide/configure/environment-configuration-settings#enable-developer-mode) to be enabled. + +<table style={{width: '74%'}}> +<colgroup> +<col style={{width: '74%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DeveloperFlags": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### Enable post search + +This setting isn't available in the System Console and can only be set in `config.json`. + +If this setting is enabled, users can search for messages in their Mattermost instance. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '91%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnablePostSearch": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this experimental configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Database Load: When post search is enabled, every search query adds additional load to the database. Disabling search reduces these queries, leading to better database performance and lower response times for other operations. +- Lower Memory Usage: Search functionality often requires indexing of posts, which consumes memory. By disabling search, the memory required for maintaining these indexes is freed up for other uses, improving overall system performance. +- Faster Write Operations: When post search is enabled, indexing has to be updated with every new post, edit, or deletion. Disabling search avoids this overhead, allowing for faster write operations. +- Performance Consistency: Without the search feature, the application avoids potential performance bottlenecks and can maintain more consistent performance levels, especially under heavy usage scenarios with a high number of posts. +- Simplified System Maintenance: Managing search indexes can be complex and resource-intensive. Disabling search simplifies this aspect of system maintenance, potentially reducing the risk of performance issues related to search index corruption or degradation. +- However, the ability to search messages in Mattermost is a critical feature for many users, and disabling this feature will result in users seeing an error if they attempt to use the Mattermost Search box. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable file search + +This setting isn't available in the System Console and can only be set in `config.json`. + +<Important> + +This experimental configuration setting enables users to search documents attached to messages by filename. To enable users to search documents by their content, you must also enable the `ExtractContent` configuration setting. See our [Enable Document Search by Content](/administration-guide/configure/environment-configuration-settings#enable-document-search-by-content) documentation for details. Document content search is available in Mattermost Server from v5.35, with mobile support coming soon. + +</Important> + +**True**: Supported document types are searchable by their filename. + +**False**: File-based searches are disabled. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '91%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableFileSearch": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this experimental configuration setting in larger deployments may improve server performance in the following areas: + +- Less Data to Index: Indexing files in addition to messages adds to the amount of data that needs to be processed and stored in the search index. +- Fewer Complex Queries: Searching through files can require more complex queries, which can be more resource-intensive and time-consuming as compared to searching through messages alone. +- Lower IO Operations: Searching files can generate more input/output operations, impacting the overall disk performance, especially if the system handles a large volume of file uploads and searches. +- However, the ability to search for files in Mattermost is a critical feature for many users, and disabling this feature will result in users seeing an error if they attempt to use the Mattermost Search box. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable user status updates + +This setting isn't available in the System Console and can only be set in `config.json`. + +Turn status updates off to improve performance. When status updates are off, users appear online only for brief periods when posting a message, and only to members of the channel in which the message is posted. + +<table style={{width: '93%'}}> +<colgroup> +<col style={{width: '93%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableUserStatuses": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Websocket secure port + +This setting isn't available in the System Console and can only be set in `config.json`. Changes to this setting require a server restart before taking effect. + +(Optional) This setting defines the port on which the secured WebSocket is listening using the `wss` protocol. Defaults to `443`. When the client attempts to make a WebSocket connection it first checks to see if the page is loaded with HTTPS. If so, it will use the secure WebSocket connection. If not, it will use the unsecure WebSocket connection. IT IS HIGHLY RECOMMENDED PRODUCTION DEPLOYMENTS ONLY OPERATE UNDER HTTPS AND WSS. + +<table style={{width: '81%'}}> +<colgroup> +<col style={{width: '80%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"WebsocketSecurePort": 443</code> with numerical input.</td> +</tr> +</tbody> +</table> + +<Note> + +This is a client only override that doesn't affect the listening port of the server process which is controlled by the [Web server listen address](/administration-guide/configure/environment-configuration-settings#web-server-listen-address) setting. + +</Note> + +### Websocket port + +This setting isn't available in the System Console and can only be set in `config.json`. Changes to this setting require a server restart before taking effect. + +(Optional) This setting defines the port on which the unsecured WebSocket is listening using the `ws` protocol. Defaults to `80`. When the client attempts to make a WebSocket connection it first checks to see if the page is loaded with HTTPS. If so, it will use the secure WebSocket connection. If not, it will use the unsecure WebSocket connection. IT IS HIGHLY RECOMMENDED PRODUCTION DEPLOYMENTS ONLY OPERATE UNDER HTTPS AND WSS. + +<table style={{width: '74%'}}> +<colgroup> +<col style={{width: '74%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>WebsocketPort": 80</code> with numerical input.</td> +</tr> +</tbody> +</table> + +<Note> + +This is a client only override that doesn't affect the listening port of the server process which is controlled by the [Web server listen address](/administration-guide/configure/environment-configuration-settings#web-server-listen-address) setting. + +</Note> + +### Enable local mode for mmctl + +This self-hosted deployment setting isn't available in the System Console and can only be set in `config.json`. + +**True**: Enables local mode for mmctl. + +**False**: Prevents local mode for mmctl. + +<table style={{width: '92%'}}> +<colgroup> +<col style={{width: '91%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableLocalMode": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Tip> + +When trying to use local mode with mmctl, ensure you're using the same user when running the server and mmctl, or clean up the socket file before switching to a new user. If you encounter an error like `socket file "/var/tmp/mattermost_local.socket" doesn't exists, please check the server configuration for local mode`, this can be resolved by setting this configuration setting to `true`. + +</Tip> + +### Enable local mode socket location + +This self-hosted deployment setting isn't available in the System Console and can only be set in `config.json`. + +The path for the socket that the server will create for mmctl to connect and communicate through local mode. If the default value for this key is changed, you will need to point mmctl to the new socket path when in local mode, using the `--local-socket-path /new/path/to/socket` flag in addition to the `--local` flag. + +If nothing is specified, the default path that both the server and mmctl assumes is `/var/tmp/mattermost_local.socket`. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"LocalModeSocketLocation": "/var/tmp/mattermost_local.socket"</code> with string input.</td> +</tr> +</tbody> +</table> + +### Default channels + +This setting isn't available in the System Console and can only be set in `config.json`. + +Default channels every user is added to automatically after joining a new team. Only applies to Public channels, but affects all teams on the server. + +When not set, every user is added to the `town-square` channel by default. + +<Note> + +Even if `town-square` isn't listed, every user is added to that channels automatically when joining a new team. + +</Note> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ExperimentalDefaultChannels": []</code> with string array input consisting of channel names, such as <code>["announcement", "developers"]</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Experimental job configuration settings + +With self-hosted deployments, you can configure how Mattermost schedules and completes periodic tasks such as the deletion of old posts with Data Retention enabled or indexing posts with Elasticsearch. These settings control which Mattermost servers are designated as a Scheduler, a server that queues the tasks at the correct times, and as a Worker, a server that completes the given tasks. + +When running Mattermost on a single machine, both `RunJobs` and `RunScheduler` should be enabled. Without both of these enabled, Mattermost will not function properly. + +When running Mattermost in High Availability mode, `RunJobs` should be enabled on one or more servers while `RunScheduler` should be enabled on all servers under normal circumstances. A High Availability cluster-based deployment will have one Scheduler and one or more Workers. See the below sections for more information. + +### Run jobs + +This setting isn't available in the System Console and can only be set in `config.json`. + +Set whether or not this Mattermost server will handle tasks created by the Scheduler. When running Mattermost on a single machine, this setting should always be enabled. + +When running Mattermost in [High Availablity mode](/administration-guide/scale/high-availability-cluster-based-deployment), one or more servers should have this setting enabled. We recommend that your High Availability cluster-based deployment has one or more dedicated Workers with this setting enabled while the remaining Mattermost app servers have it disabled. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RunJobs": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Run scheduler + +This setting isn't available in the System Console and can only be set in `config.json`. + +Set whether or not this Mattermost server will schedule tasks that will be completed by a Worker. When running Mattermost on a single machine, this setting should always be enabled. + +When running Mattermost in [High Availablity mode](/administration-guide/scale/high-availability-cluster-based-deployment), this setting should always be enabled. In a High Availability cluster-based deployment, exactly one of the servers will be designated as the Scheduler at a time to ensure that duplicate tasks aren't created. See [High Availability documentation](/administration-guide/scale/high-availability-cluster-based-deployment) for more details. + +<Warning> + +We strongly recommend that you not change this setting from the default setting of `true` as this prevents the `ClusterLeader` from being able to run the scheduler. As a result, recurring jobs such as LDAP sync, Compliance Export, and data retention will no longer be scheduled. In previous Mattermost Server versions, and this documentation, the instructions stated to run the Job Server with `RunScheduler: false`. The cluster design has evolved and this is no longer the case. + +</Warning> + +<Tip> + +From Mattermost v11.4, debug-level log messages are available to help verify that specific Recurring Tasks (Scheduled Posts, Post Reminders, and DND Status Reset) are executing correctly in a cluster. Non-leader nodes log messages when they skip execution of these Recurring Tasks, confirming that leader election is functioning as expected. These debug messages do not apply to other job types such as Elasticsearch indexing, SAML sync, or LDAP sync. See [Cluster job execution debug messages](/administration-guide/manage/logging#cluster-job-execution-debug-messages) for details. + +</Tip> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"RunScheduler": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Clean up old database jobs + +This setting isn't available in the System Console and can only be set in `config.json`. + +Defines the threshold in days beyond which older completed database jobs are removed. This setting is disabled by default, and must be set to a value greater than or equal to `0` to be enabled. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"JobSettings.CleanupJobsThresholdDays": -1</code> with numerical input.</td> +</tr> +</tbody> +</table> + +### Clean up outdated database entries + +This setting only applies to configuration in the database. It isn't available in the System Console and can be set via mmctl or changed in the database. + +Defines the threshold in days beyond which outdated configurations are removed from the database. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"JobSettings.CleanupConfigThresholdDays": 30</code> with numerical input.</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/install-boards.mdx b/docs/main/administration-guide/configure/install-boards.mdx new file mode 100644 index 000000000000..d46f9d94442d --- /dev/null +++ b/docs/main/administration-guide/configure/install-boards.mdx @@ -0,0 +1,40 @@ +--- +title: "Install Mattermost Boards" +--- +<PlanAvailability slug="entry-ent" /> + +Mattermost Boards is not enabled by default for new Mattermost Enterprise instances. If the Mattermost Boards plugin isn't enabled for your Mattermost workspace, self-hosted Enterprise customers can install this plugin by manually uploading the binary release file into the System Console and enabling it. + +Mattermost Cloud Enterprise customers can request the Boards plugins be enabled by contacting their Mattermost Account Manager or by [creating a support ticket](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=11184911962004) request. + +<Note> + +The Mattermost Boards plugin is currently in maintenance mode. While adoption of this plugin is still supported for Enterprise customers, we recommend system admins proceed at their own risk. Mattermost is no longer actively developing new features or future improvements for the Boards plugin, beyond addressing bug fixes reported by Enterprise customers and any necessary security patches. + +In the future, Mattermost plans to deliver a core Boards feature as part of the platform. Migration from the Boards plugin to this upcoming feature will be required, which could potentially involve downtime or data migration complexities. Keep this in mind when deploying the Boards plugin in production environments. + +</Note> + +## Install the plugin + +The following steps apply to customers in fully connected environments as well as Denied, Disrupted, Intermittent, and Limited (DDIL) environments. A Mattermost system admin must perform the following steps in Mattermost. + +1. Download the latest Mattermost Boards plugin binary file from the [Mattermost Boards Releases](https://github.com/mattermost/mattermost-plugin-boards/releases) page. +2. Log in to your Mattermost System Console as a system admin. +3. Go to **Plugins \> Plugin Management**. +4. Select **Upload Plugin** to upload the Boards plugin binary file you downloaded from the Mattermost Releases page. + +## Mattermost configuration + +1. Go to **Plugins \> Mattermost Boards**. +2. Select **Enable Plugin** to enable the plugin. +3. You can optionally enable **Enable Publicly-Shared Boards** so that board editors can share boards with people outside of your Mattermost instance, who can view the board without needing a Mattermost account. +4. Select **Save** to save your changes. + +## Access + +See the [navigate boards](/end-user-guide/project-management/navigate-boards) documentation to learn how to create and access boards. + +## Work with boards + +See the [project and task management](/end-user-guide/project-task-management) end user documentation to learn how to align, define, organize, track, and manage work across teams. diff --git a/docs/main/administration-guide/configure/integrations-configuration-settings.mdx b/docs/main/administration-guide/configure/integrations-configuration-settings.mdx new file mode 100644 index 000000000000..f448928dc365 --- /dev/null +++ b/docs/main/administration-guide/configure/integrations-configuration-settings.mdx @@ -0,0 +1,450 @@ +--- +title: "Integrations configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Review and manage the following integration configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Integrations**: + +- [Integrations management](#integrations-management) +- [Bot Accounts](#bot-acocunts) +- [GIF](#gif) +- [CORS](#cors) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `EnableIncomingWebhooks` value is under `ServiceSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.ServiceSettings.EnableIncomingWebhooks'` +- When working with the `config.json` file manually, look for an object such as `ServiceSettings`, then within that object, find the key `EnableIncomingWebhooks`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Integrations management + +Access the following configuration settings in the System Console by going to **Integrations \> Integration Management**. + +### Enable incoming webhooks + +Developers building integrations can create webhook URLs for public channels and private channels. See the [incoming webhooks](https://developers.mattermost.com/integrate/webhooks/incoming/) developer documentation to learn about creating webhooks, viewing samples, and letting community know about integrations you've built. + +**True**: Incoming webhooks are allowed. To manage incoming webhooks, select **Integrations** from the Mattermost Product menu. The webhook URLs created can be used by external applications to create posts in any public or private channels that you have access to. + +**False**: The **Integrations \> Incoming Webhooks** section of the Mattermost Product menu is hidden and all incoming webhooks are disabled. + +<Important> + +Security note: By enabling this feature, users may be able to perform [phishing attacks](https://en.wikipedia.org/wiki/Phishing) by attempting to impersonate other users. To combat these attacks, a BOT tag appears next to all posts from a webhook. Enable at your own risk. + +</Important> + +<table style={{width: '97%'}}> +<colgroup> +<col style={{width: '96%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableIncomingWebhooks": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable outgoing webhooks + +Developers building integrations can create webhook tokens for public channels. Trigger words are used to fire new message events to external integrations. For security reasons, outgoing webhooks are only available in public channels. See the [outgoing webhooks](https://developers.mattermost.com/integrate/webhooks/outgoing/) developer documentation to learn about creating webhooks and viewing samples. + +**True**: Outgoing webhooks will be allowed. To manage outgoing webhooks, select **Integrations** from the Mattermost Product menu. + +**False**: The **Integrations \> Outgoing Webhooks** of the Mattermost Product menu is hidden and all outgoing webhooks are disabled. + +<Important> + +Security note: By enabling this feature, users may be able to perform [phishing attacks](https://en.wikipedia.org/wiki/Phishing) by attempting to impersonate other users. To combat these attacks, a BOT tag appears next to all posts from a webhook. Enable at your own risk. + +</Important> + +<table style={{width: '97%'}}> +<colgroup> +<col style={{width: '96%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableOutgoingWebhooks": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Network Traffic: Outgoing webhooks generate network requests to external services. Disabling them reduces the amount of traffic and resource usage related to those requests. +- Decreased Load on Server: Handling webhook events and managing connections to external services uses server resources. By disabling outgoing webhooks, the server workload is reduced, allowing it to allocate more resources to other important tasks. +- Improved Response Time: When outgoing webhooks are enabled, the server waits for the external services to return responses, potentially slowing down the performance if the external services are slow or unresponsive. Disabling them removes this dependency, leading to faster response times for user requests. +- Lower Memory Usage: Webhooks need memory to process and store data about the requests and responses. Disabling them can free up memory which can be used to improve overall server performance. +- Simplified Error Handling: Managing errors and retries for outgoing webhook failures can add complexity and overhead. Disabling outgoing webhooks can simplify error handling and reduce the processing overhead associated with it. +- However, outgoing webhooks are often essential for integrating Mattermost with other services and workflows. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable custom slash commands + +Slash commands send events to external integrations that send a response back to Mattermost. + +**True**: Allow users to create custom slash commands from **Main Menu \> Integrations \> Commands**. + +**False**: Slash commands are hidden in the **Integrations** user interface. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableCommands": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable OAuth 2.0 service provider + +**True**: Mattermost acts as an OAuth 2.0 service provider allowing Mattermost to authorize API requests from external applications. + +**False**: Mattermost does not function as an OAuth 2.0 service provider. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableOAuthServiceProvider": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Enable dynamic client registration + +**True**: Enables Dynamic Client Registration (DCR) allowing applications to programmatically register OAuth 2.0 clients without manual admin intervention via the `POST /api/v4/oauth/apps/register` endpoint. + +**False**: Dynamic Client Registration is disabled. OAuth 2.0 applications must be registered manually through the System Console. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableDynamicClientRegistration": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Important> + +**Security Warning**: When enabled, the DCR endpoint (`/api/v4/oauth/apps/register`) is **publicly accessible without authentication**. Any user or application can register OAuth clients on your Mattermost server. Only enable this setting if you understand and accept this security model, or have additional network-level access controls in place. + +</Important> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### DCR redirect URI allowlist + +A comma-separated list of permitted redirect URIs for OAuth Dynamic Client Registration (DCR). When configured, only OAuth clients that register via the DCR endpoint (`POST /api/v4/oauth/apps/register`) with a redirect URI matching an entry in this list will be accepted. Leave blank to allow any redirect URI. + +In the System Console, enter URIs as a comma-separated list. When setting this value directly in `config.json` or via environment variable, provide URIs as a JSON string array (for example, `["https://example.com/callback", "https://app.example.com/oauth"]`). + +This setting applies only when [Enable dynamic client registration](/administration-guide/configure/integrations-configuration-settings#enable-dynamic-client-registration) is enabled. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DCRRedirectURIAllowlist": []</code> with string array input, such as <code>["https://example.com/callback", "https://app.example.com/oauth"]</code>. |</td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Integration request timeout + +The number of seconds to wait for external integration HTTP requests, before timing out, including [custom slash commands](https://developers.mattermost.com/integrate/slash-commands/custom/), [outgoing webhooks](https://developers.mattermost.com/integrate/webhooks/outgoing/), [interactive messages](https://developers.mattermost.com/integrate/plugins/interactive-messages/), and [interactive dialogs](https://developers.mattermost.com/integrate/plugins/interactive-dialogs/). Increase this value if you have external integrations that can take some time to generate an HTTP response, or experience delayed responses due to latency. + +<table style={{width: '81%'}}> +<colgroup> +<col style={{width: '80%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"OutgoingIntegrationRequestsDefaultTimeout": 3</code>.</td> +</tr> +</tbody> +</table> + +### Enable integrations to override usernames + +**True**: Webhooks, slash commands, OAuth 2.0 apps, and other integrations, will be allowed to change the username they are posting as. If no username is present, the username for the post is the same as it would be for a setting of `False`. + +**False**: **(Default)** Custom slash commands can only post as the username of the user who used the slash command. OAuth 2.0 apps can only post as the username of the user who set up the integration. For incoming webhooks and outgoing webhooks, the username is "webhook". See [https://developers.mattermost.com/integrate/other-integrations/](https://developers.mattermost.com/integrate/other-integrations/) for more details. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnablePostUsernameOverride": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable integrations to override profile picture icons + +**True**: Webhooks, slash commands, and other integrations, will be allowed to change the profile picture they post with. + +**False**: **(Default)** Webhooks, slash commands, and OAuth 2.0 apps can only post with the profile picture of the account they were set up with. See [https://developers.mattermost.com/integrate/other-integrations/](https://developers.mattermost.com/integrate/other-integrations/) for more details. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnablePostIconOverride": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enable personal access tokens + +**True**: Users can create [personal access tokens](https://developers.mattermost.com/integrate/admin-guide/admin-personal-access-token/) for integrations in **Profile \> Security**. They can be used to authenticate against the API and give full access to the account. + +To manage who can create personal access tokens or to search users by token ID, go to the **System Console \> Users** page. + +**False**: Personal access tokens are disabled on the server. + +<table style={{width: '98%'}}> +<colgroup> +<col style={{width: '97%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableUserAccessTokens": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Enforce incoming webhook channel locking + +When enabled, this setting enforces that all incoming webhooks must be locked to their designated channel and cannot post messages to other channels. This provides administrators with greater control over webhook security and ensures that webhooks can only post to their intended channels. + +**True**: Incoming webhooks are required to be locked to their specific channel. The **Lock to this channel** option is automatically enabled and cannot be disabled when creating or editing webhooks. + +**False**: **(Default)** Incoming webhook creators can choose whether to lock webhooks to a specific channel by selecting **Lock to this channel**, or allow the webhook to post to any public channel or private channel the webhook creator is a member of. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnforceIncomingWebhookChannelLocking": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Bot accounts + +Access the following configuration settings in the System Console by going to **Integrations \> Bot Accounts**. + +### Enable bot account creation + +**True**: **(Default for Cloud deployments)** Users can create bot accounts for integrations in **Integrations \> Bot Accounts**. Bot accounts are similar to user accounts except they cannot be used to log in. See [documentation](https://developers.mattermost.com/integrate/admin-guide/admin-bot-accounts/) to learn more. + +**False**: **(Default for self-hosted deployments)** Bot accounts cannot be created through the user interface or the RESTful API. Plugins can still create and manage bot accounts. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '99%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableBotAccountCreation": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Disable bot accounts when owner is deactivated + +**True**: When a user is deactivated, disables all bot accounts managed by the user. To re-enable bot accounts, go to **Integrations \> Bot Accounts**. + +**False**: When a user is deactivated, all bot accounts managed by the user remain active. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"DisableBotsWhenOwnerIsDeactivated": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## GIF + +Access the following configuration settings in the System Console by going to **Integrations \> GIF**. + +### Enable GIF picker + +**True**: Allow users to select GIFs from the emoji picker via a GIPHY integration. + +**False**: GIFs cannot be selected in the emoji picker. + +<table style={{width: '91%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"EnableGifPicker": true</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +<Important> + +[Link previews](/administration-guide/configure/site-configuration-settings#enable-message-link-previews) must be enabled in order to display GIF link previews. Mattermost deployments restricted to access behind a firewall must open port 443 (for all request types) for this feature to work. + +</Important> + +------------------------------------------------------------------------------------------------------------------------ + +## CORS + +The following configuration settings are applicable only to self-hosted deployments. Access the following configuration settings in the System Console by going to **Integrations \> CORS**. + +### Enable cross-origin requests from + +Enable HTTP cross-origin requests from specific domains. + +- Type `*` to allow CORS from any domain. +- Enter a specific domain or multiple domains separated by spaces. +- Type `null` to prevent CORS from any domain. +- Leave blank to disable it and use the Mattermost **Site URL** instead. + +<Note> + +Ensure you've entered your [Site URL](/administration-guide/configure/environment-configuration-settings#site-url) before enabling this setting to prevent losing access to the System Console after saving. If you lose access to the System Console after changing this setting, you can set your Site URL through the `config.json` file. + +</Note> + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '72%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"AllowCorsFrom": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### CORS exposed headers + +Whitelist of headers that will be accessible to the requester. + +<table style={{width: '77%'}}> +<colgroup> +<col style={{width: '76%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"CorsExposedHeaders": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +### CORS allow credentials + +**True**: Requests that pass validation will include the `Access-Control-Allow-Credentials` header. + +**False**: Requests won't include the `Access-Control-Allow-Credentials` header. + +<table style={{width: '96%'}}> +<colgroup> +<col style={{width: '95%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"CorsAllowCredentials": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +### CORS debug + +**True**: Prints messages to the logs to help when developing an integration that uses CORS. These messages will include the structured key value pair `"source": "cors"`. + +**False**: Debug messages not printed to the logs. + +<table style={{width: '87%'}}> +<colgroup> +<col style={{width: '86%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"CorsDebug": false</code> with options <code>true</code> and <code>false</code>.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Embedding + +The following configuration settings are applicable only to self-hosted deployments. Access the following configuration settings in the System Console by going to **Integrations \> Embedding**. + +### Frame ancestors + +Enter a space-separated list of domains that are allowed to embed the Mattermost web client via an iFrame. Leave blank to disallow embedding. Leave blank to disable embedding. Blank by default. + +<table style={{width: '56%'}}> +<colgroup> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"FrameAncestors".</code></td> +</tr> +</tbody> +</table> + +<Note> + +Embedding Mattermost via an iFrame can provide seamless integration for collaboration into an organization’s existing tools and workflows. However, you must ensure that correct configurations are in place to allow communication between the iframe and the parent domain without violating security. + +</Note> diff --git a/docs/main/administration-guide/configure/manage-user-surveys.mdx b/docs/main/administration-guide/configure/manage-user-surveys.mdx new file mode 100644 index 000000000000..c962dfddd131 --- /dev/null +++ b/docs/main/administration-guide/configure/manage-user-surveys.mdx @@ -0,0 +1,81 @@ +--- +title: "Manage user surveys" +--- +<PlanAvailability slug="all-commercial" /> + +In a self-hosted Mattermost deployment, you can use the Mattermost User Survey integration to gather direct feedback from your Mattermost users to identify what's working well and what's not with your Mattermost instance. + +All user responses are stored in and remain within your self-hosted deployment, and no telemetry data is sent back to Mattermost. You can export a CSV report of NPS scores and user responses for further analysis, or to share your feedback data with Mattermost. You can schedule when each survey begins, define how long each survey lasts, specify teams excluded from the survey, as well as customize both a welcome message and a user question you want feedback on. + +<Important> + +The User Satisfaction Survey Plugin is the recommended approach for gathering user feedback, replacing the deprecated [User Satisfaction Survey Plugin](/administration-guide/manage/user-satisfaction-surveys) for new deployments. + +</Important> + +## Setup + +You must be a Mattermost system admin to [upload the plugin](#upload) to your Mattermost self-hosted deployment [enable it](#enable), [create surveys](#create-surveys), and [export survey responses](#export-survey-responses) using the System Console. + +The User Survey integration is compatible with Mattermost v9.11.2 or later. + +## Install + +From Mattermost v9.11.2 (ESR) and Mattermost Cloud v10, this plugin is pre-packaged with the Mattermost Server. If your Mattermost deployment is on a prior release, download the [latest plugin binary release](https://github.com/mattermost/mattermost-plugin-user-survey/releases), and upload it to your server via **System Console \> Plugin Management**. + +### Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. + +Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-user-survey/releases) for the latest release, available releases, and compatibiilty considerations. + +## Enable + +Go to **System Console \> Plugins \> User Survey** to enable this integration. + +Once the integration is installed and enabled, create surveys by completing configuration in the System Console, as described below. + +### Create surveys + +Under **Survey setup**, specify the date, time, and details for a new survey: + +1. **Send next survey at**: Specify the date and time when the survey will begin rolling out to users. + +> <div class="note"> +> +> <div class="title"> +> +> Note +> +> </div> +> +> A single survey can be active at a time. If you already have an active survey running, you'll need to reschedule your new survey to start on a date after the current survey expires. Alternatively, you can end the active survey early by selecting **End survey**. +> +> </div> + +2. **Survey expiry (days)**: Specify how long the survey will be open to responses in days. +3. **Exclude specific teams**: Specify who will receive the survey. You can send the survey to all users, to all users on specific teams, or omit all users from specific teams. + +![An example of the System Console configuration screen for scheduling a new user survey.](/images/survey-schedule.png) + +4. **Survey message text**: Customize the introductory message text users see when prompted to complete the survey. +5. **Linear scale question (1-10)**: This question is required that helps calculate the NPS score. +6. **Textual question**: This question is required that helps gather user feedback. +7. **Textual question (Optional)**: You can optionally specify a text-based question for your survey. +8. Select **Save**. Your new survey is scheduled, and displays under **Active and past surveys** once the survey is shared with users. + +![An example of the System Console configuration screen for defining the contents of a new user survey.](/images/survey-contents.png) + +## Active surveys + +When a survey starts, all users recieve a direct message from a feedback bot containing the active survey. The survey includes one mandatory scale-based question, and optional text-based questions. + +![An example of the user survey provided to users.](/images/user-feedback.png) + +Users must answer all required questions in order to submit their response. When a user selects **Submit**, their responses are recorded. + +## Export survey responses + +Select **Export responses** to download a CSV file containing NPS scores and user responses gatherered through the survey. You can export data from active surveys which will contain data collected so far. + +![An example of the System Console configuration page where all active and past surveys are available for export.](/images/active-past-surveys.png) diff --git a/docs/main/administration-guide/configure/optimize-your-workspace.mdx b/docs/main/administration-guide/configure/optimize-your-workspace.mdx new file mode 100644 index 000000000000..83b0feb8f33a --- /dev/null +++ b/docs/main/administration-guide/configure/optimize-your-workspace.mdx @@ -0,0 +1,131 @@ +--- +title: "Optimize your Mattermost workspace" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +With workspace optimizations, system admins can review their workspace health and growth scores, then take advantage of recommended actions for ensuring their workspace is running smoothly and teams are maximizing productivity. + +System admins can access their workspace optimization page in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and going to **Reporting \> Workspace Optimization**. + +![Review your workspace health and growth scores, then take advantage of recommended optimizations.](/images/workspace-optimization.png) + +## How is the overall score calculated? + +The highest score possible is 100. Your score is calculated based on the type of issue reported and the level of potential security risk introduced to your Mattermost deployment if ignored. + +Each item on the dashboard is calculated based on its individual impact score. These differ depending on whether they're problems, warnings, or suggestions. For example, if SSL encryption isn't configured in your workspace, Mattermost reports that as a problem, which reduces your score until it's addressed. + +Warnings impact your score less than problems, and suggestions have the least impact on your score. + +Want to improve your overall workspace optimization score? Take action towards the problems, warnings, and suggestions reported on this dashboard. We recommend the following workspace optimizations. + +## Recommendations + +The following optimization areas can alert you to workspace suggestions, warnings, or problems that may require your attention: + +<table style={{width: '100%'}}> +<colgroup> +<col style={{width: '7%'}} /> +<col style={{width: '34%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td rowspan="2"><blockquote> +<p>Optimization category</p> +</blockquote> +<dl> +<dt>=======================</dt> +<dd> +<p>Mattermost release</p> +</dd> +</dl></td> +<td rowspan="2"><blockquote> +<p>Suggestions, Warnings, or Problems Detected</p> +</blockquote> +<dl> +<dt>==========================================================================================================</dt> +<dd> +<p>Are you on the latest Mattermost release?</p> +</dd> +</dl></td> +<td rowspan="2"><blockquote> +<p>Additional Information |</p> +</blockquote> +<dl> +<dt>======================================================================================================================================================================+</dt> +<dd> +<p>You're notified when updates are available. | See the <a href="mm-doc:%2Fadministration-guide%2Fupgrade%2Fupgrading-mattermost-server">Upgrade Mattermost</a> product documentation for details on upgrading your workspace. |</p> +</dd> +</dl></td> +</tr> +<tr> +</tr> +<tr> +<td>Configuration issues</td> +<td><ul> +<li><strong>SSL</strong>: Should your workspace be more secure with SSL?</li> +<li><strong>Session Length</strong>: The default value may not provide an optimal user experience.</li> +<li><strong>File Storage</strong>: Write access to the configured file storage location is required.</li> +</ul></td> +<td><dl> +<dt>See the product documentation to learn more: |</dt> +<dd> +<div class="line-block"></div> +</dd> +</dl> +<ul> +<li><a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fssl-client-certificate">Set up SSL</a> |</li> +<li><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Asession%20lengths">Configure session length</a></li> +<li><dl> +<dt><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Afile%20storage">Configure file storage</a></dt> +<dd> +<h3 id="section">|</h3> +</dd> +</dl></li> +</ul></td> +</tr> +<tr> +<td>Workspace access</td> +<td>Is the Mattermost workspace accessible to users?</td> +<td>If your web server settings don't pass a live URL test, your workspace may not be accessible to others. | See the <a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Aweb%20server">Web server configuration settings</a> product documentation to learn more:</td> +</tr> +<tr> +<td>Search performance</td> +<td>As your user base grows, is search getting slower?</td> +<td>See the <a href="mm-doc:%2Fadministration-guide%2Fscale%2Fenterprise-search">Enterprise search</a> product documentation to learn more. |</td> +</tr> +<tr> +<td>Data privacy</td> +<td>Do you need more control and insights into your data?</td> +<td><dl> +<dt>See the product documentation to learn more: |</dt> +<dd> +<div class="line-block"></div> +</dd> +</dl> +<ul> +<li><a href="mm-doc:%2Fadministration-guide%2Fcomply%2Fdata-retention-policy">Data Retention</a> |</li> +<li><a href="mm-doc:%2Fadministration-guide%2Fcomply%2Fcompliance-export">Compliance Export</a> |</li> +</ul></td> +</tr> +<tr> +<td>User authentication</td> +<td><ul> +<li><strong>AD/LDAP</strong>: As your user base grows, would you benefit from easier onboarding, automated deactivations, and role assignments?</li> +<li><strong>Guest accounts</strong>: Do you want to control user access to channels and teams with guest accounts?</li> +</ul></td> +<td><dl> +<dt>See the product documentation to learn more: |</dt> +<dd> +<div class="line-block"></div> +</dd> +</dl> +<ul> +<li><a href="mm-ref:administration-guide%2Fconfigure%2Fauthentication-configuration-settings%3Aad%2Fldap">AD/LDAP</a></li> +<li><a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fguest-accounts">Guest accounts</a> |</li> +</ul></td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/plugins-configuration-settings.mdx b/docs/main/administration-guide/configure/plugins-configuration-settings.mdx new file mode 100644 index 000000000000..95fc8380948d --- /dev/null +++ b/docs/main/administration-guide/configure/plugins-configuration-settings.mdx @@ -0,0 +1,1876 @@ +--- +title: "Plugins configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Review and manage the following plugin configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Plugins**: + +- [Plugin management](#plugin-management) +- [Calls](#calls) +- [AI Agents](#ai-agents) +- [GitLab](#gitlab) +- [GitHub](#github) +- [Jira](#jira) +- [Legal Hold](#legal-hold) +- [Microsoft Calendar Integration](#microsoft-calendar) +- [MS Teams](#ms-teams) +- [Performance metrics](#performance-metrics) +- [Collaborative playbooks](#collaborative-playbooks) +- [User satisfaction surveys](#user-satisfaction-surveys) +- [ServiceNow](#servicenow) +- [Zoom](#zoom) +- [config.json-only settings](#config-json-only-settings) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `Enable` value is under `PluginSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.PluginSettings.Enable'` +- When working with the `config.json` file manually, look for an object such as `PluginSettings`, then within that object, find the key `Enable`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Plugin management + +Access the following configuration settings in the System Console by going to **Plugins \> Plugin Management**. + +### Enable plugins + +<table> +<colgroup> +<col style={{width: '75%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables plugins on your Mattermost server. See the <a href="https://developers.mattermost.com/integrate/plugins/using-and-managing-plugins/">Use plugins with Mattermost</a> documentation for details.</li><li><strong>false</strong>: Disables plugins on your Mattermost server.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Enable</code> > <code>true</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas: + +- Resource Consumption: Plugins consume system resources such as CPU, memory, and disk. Disabling them frees up these resources, allowing the core Mattermost application to run more efficiently. +- Reduced Complexity: Each plugin can add additional logic and processing requirements. By reducing the number of active plugins, you lower the complexity and potential points of failure in the system. +- Faster Load Times: Disabling plugins can lead to faster server startup and lower latency during user interactions, as there are fewer components for the system to initialize and manage. +- Stability: Some plugins may have bugs or performance issues that can affect the overall performance and stability of the Mattermost instance. Disabling problematic or under-utilized plugins can enhance the stability of the system. +- Maintenance and Updates: Managing fewer plugins reduces the overhead associated with maintaining and updating them, which can contribute to smoother operation and less downtime +- However, plugins are often essential for integrating Mattermost with other services and workflows. It's important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Require plugin signature + +<table> +<colgroup> +<col style={{width: '67%'}} /> +<col style={{width: '32%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables plugin signature validation for managed and unmanaged plugins.</li><li><strong>false</strong>: Disables plugin signature validation for managed and unmanaged plugins.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>RequirePluginSignature</code> > <code>true</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_REQUIREPLUGINSIGNATURE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable to self-hosted deployments only. - From Mattermost server v10.11, pre-packaged plugins require signature validation on startup. Distributions that bundle custom pre-packaged plugins must configure custom public keys via `PluginSettings.SignaturePublicKeyFiles` to validate their signatures. - **Mattermost server v10.10 and earlier**: Pre-packaged plugins are not subject to signature validation. - Plugins installed through the Marketplace are always subject to signature validation at the time of download. - Enabling this configuration will result in [plugin file uploads](#upload-plugin) being disabled in the System Console. + +</Note> + +### Automatic prepackaged plugins + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost automatically installs and upgrades any enabled pre-packaged plugins. If a newer version is installed, no changes are made.</li><li><strong>false</strong>: Mattermost does not automatically install or upgrade pre-packaged plugins. Pre-packaged plugins may be installed manually from the Marketplace, even when offline.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>AutomaticPrepackagedPlugins</code> > <code>true</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_AUTOMATICPREPACKAGEDPLUGINS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +**Prepackaged Plugin Installation Behavior**: When system administrators drop plugin files (with their `.sig` signature files) into the `prepackaged_plugins` directory, the plugins won't install automatically. Prepackaging makes the plugin available for "offline" installation. The plugin will automatically install only when a system admin pre-configures the `config.json` with that plugin enabled. + +</Note> + +### Upload Plugin + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables you to upload plugins from the local computer to the Mattermost server.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables uploading of plugins from the local computer to the Mattermost server.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>EnableUploads</code> > <code>false</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_ENABLEUPLOADS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable to self-hosted deployments only. - When plugin uploads are enabled, the error `Received invlaid response from the server` when uploading a plugin file typically indicates that the [MaxFileSize](/administration-guide/configure/environment-configuration-settings#maximum-file-size) configuration setting isn't large enough to support the plugin file upload. Additional proxy setting updateds may also be required. - The ability to upload plugin files is disabled when the [Require plugin signature](#require-plugin-signature) configuration setting is enabled. + +</Note> + +### Enable Marketplace + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables the plugin Marketplace on your Mattermost server for all system admins.</li><li><strong>false</strong>: Disables the plugin Marketplace on your Mattermost server for all system admins.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>EnableMarketplace</code> > <code>true</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_ENABLEMARKETPLACE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable remote Marketplace + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost attempts to connect to the endpoint set in <strong>Marketplace URL</strong>. If the connection fails, an error is displayed, and the Marketplace only shows pre-packaged and installed plugins.</li><li><strong>false</strong>: Mattermost does not attempt to connect to a remote Marketplace. The Marketplace shows only pre-packaged and installed plugins. Use this setting if your Mattermost server cannot connect to the Internet.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>EnableRemoteMarketplace</code> > <code>true</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_ENABLEREMOTEMARKETPLACE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- From Mattermost v9.1, set this configuration setting value to `true` to access a configured remote marketplace URL. - For Mattermost v9.0, the `MM_FEATUREFLAGS_STREAMLINEDMARKETPLACE` feature flag must be set to `false`, and this configuration setting must be set to `true` to access a configured remote marketplace URL. - Each Mattermost host must have network access to the endpoint set in MarketplaceURL. + +</Note> + +### Marketplace URL + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores the URL for the remote Markeplace.</p><p>String input. Default is <strong>https://api.integrations.mattermost.com</strong></p></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>MarketplaceURL</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_MARKETPLACEURL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Installed plugin state + +<table> +<colgroup> +<col style={{width: '75%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting is a list of installed plugins and their status as enabled or disabled.</p><p>The <code>config.json</code> setting is an object. The object keys are plugin IDs, e.g. <code>com.mattermost.apps</code>. Each key maps to an object that contains an <code>Enable</code> key that can be set as <code>true</code> or <code>false</code>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>PluginStates</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_PLUGINSTATES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Plugin settings + +<table> +<colgroup> +<col style={{width: '73%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting contains plugin-specific data.</p><p>The <code>config.json</code> setting is an object. The object keys are plugin IDs, e.g. <code>com.mattermost.apps</code>. Each key maps to an object that contains plugin-specific data.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Plugin Management</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_PLUGINS</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Calls + +Access the following configuration settings in the System Console by going to **Plugins \> Calls**. + +### Enable plugin + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: (Default) Enables the Calls plugin on your Mattermost workspace.</li><li><strong>false</strong>: Disables the Calls plugin on your Mattermost workspace.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>PluginStates</code> > <code>com.mattermost.calls</code> > <code>Enable</code></li><li>Environment variable: <code>MM_PLUGINSETTINGS_PLUGINSTATES_COM_MATTERMOST_CALLS</code></li></ul></td> +</tr> +</tbody> +</table> + +### RTC server address (UDP) + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls the IP address the RTC server listens for UDP connections. All calls UDP traffic will be served through this IP.</p><p>Changing this setting requires a plugin restart to take effect. If left unset (default value) the service will listen on all the available interfaces.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>udpserveraddress</code></li><li>Environment variable: <code>MM_CALLS_UDP_SERVER_ADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only, and only when not running calls through the standalone `rtcd` service. + +</Note> + +### RTC server address (TCP) + +<table> +<colgroup> +<col style={{width: '52%'}} /> +<col style={{width: '47%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls the IP address the RTC server listens for TCP connections. All calls TCP traffic will be served through this IP.</p><p>Changing this setting requires a plugin restart to take effect. If left unset (default value) the service will listen on all the available interfaces.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>tcpserveraddress</code></li><li>Environment variable: <code>MM_CALLS_TCP_SERVER_ADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is available starting in plugin version 0.17, and is only applicable for self-hosted deployments when not running calls through the standalone `rtcd` service. + +</Note> + +### RTC server port (UDP) + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls the UDP port listened on by the RTC server. All calls UDP traffic will be served through this port.</p><p>Changing this setting requires a plugin restart to take effect.</p><p>Default is <strong>8443</strong>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>udpserverport</code></li><li>Environment variable: <code>MM_CALLS_UDP_SERVER_PORT</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is only applicable for self-hosted deployments when not running calls through the standalone `rtcd` service. + +</Note> + +### RTC server port (TCP) + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls the TCP port listened on by the RTC server. All calls TCP traffic will be served through this port.</p><p>Changing this setting requires a plugin restart to take effect.</p><p>Default is <strong>8443</strong>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>tcpserverport</code></li><li>Environment variable: <code>MM_CALLS_TCP_SERVER_PORT</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is available starting in plugin version 0.17, and is only applicable for self-hosted deplyoments when not running calls through the standalone `rtcd` service. + +</Note> + +### Enable on specific channels + +*Admins can't configure this setting from Mattermost v7.7; it's hidden and always enabled for self-hosted deployments* + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Channel admins can enable or disable calls on specific channels. Participants in DMs/GMs can also enable or disable calls.</li><li><strong>false</strong>: Only system admins can enable or disable calls on specific channels.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>allowenablecalls</code></li><li>Environment variable: <code>MM_CALLS_ALLOW_ENABLE_CALLS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Test mode + +*This setting was called Enable on all channels until Mattermost v7.7. It was renamed to defaultenabled in code and Test Mode in-product and is only applicable to self-hosted deployments.* + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>false</strong>: Test mode is enabled and only system admins can start calls in channels.</li><li><strong>true</strong>: Live mode is enabled and all team members can start calls in channels.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>defaultenabled</code></li><li>Environment variable: <code>MM_CALLS_DEFAULT_ENABLED</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Use this setting as a system admin to confirm calls work as expected. When **false**, users attempting to start calls are prompted to contact a system admin, and system admins are prompted to confirm that calls are working as expected before switching to live mode. + +</Note> + +### ICE host override + +<table> +<colgroup> +<col style={{width: '59%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting can be used to override the host addresses that get advertised to clients when connecting to calls. The accepted formats are the following:</p><ul><li>A single IP address (e.g. <code>10.0.0.1</code>).</li><li>A single hostname or FQDN (e.g. <code>calls.myserver.tld</code>).</li><li>(starting in v0.17.0) A comma separated list of externalAddr/internalAddr mappings (e.g. <code>10.0.0.1/172.0.0.1,10.0.0.2/172.0.0.2</code>).</li></ul><p>This is an optional field. Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>icehostoverride</code></li><li>Environment variable: <code>MM_CALLS_ICE_HOST_OVERRIDE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is only applicable for self-hosted deployments when not running calls through the standalone `rtcd` service. - Depending on the network infrastructure (e.g. instance behind a NAT device) it may be necessary to set this field to the client facing external IP for clients to connect. When empty or unset, the RTC service will attempt to find the instance's public IP through STUN. - A hostname (e.g. domain name) can be specified in this setting, but an IP address will be passed to clients. This means that a DNS resolution happens on the Mattermost instance which could result in a different IP address from the one the clients would see, causing connectivity to fail. When in doubt, we recommend using an IP address directly or confirming that the resolution on the host side reflects the one on the client. + +</Note> + +### ICE host port override + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting can be used to override the port used in the ICE host candidates that get advertised to clients when connecting to calls.</p><p>This can be useful in case there are additional network components (e.g. NLBs) in front of the RTC server that may route the calls traffic through a different port. Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>icehostportoverride</code></li><li>Environment variable: <code>MM_CALLS_ICE_HOST_PORT_OVERRIDE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This value will apply to both UDP and TCP host candidates. + +</Note> + +### RTCD service URL + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The URL to a running <a href="https://github.com/mattermost/rtcd">rtcd</a> service instance that will host the calls.</p><p>When set (non empty) all the calls will be handled by this external service.</p><p>This is an optional field. Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>rtcdserviceurl</code></li><li>Environment variable: <code>MM_CALLS_RTCD_SERVICE_URL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The environment variable `MM_CALLS_RTCD_URL` is deprecated in favor of `MM_CALLS_RTCD_SERVICE_URL`. - The client will self-register the first time it connects to the service and store the authentication key in the database. If no client ID is explicitly provided, the diagnostic ID of the Mattermost installation will be used. - The service URL supports credentials in the form `http://clientID:authKey@hostname`. Alternatively these can be passed through environment overrides to the Mattermost server, namely `MM_CALLS_RTCD_CLIENT_ID` and `MM_CALLS_RTCD_AUTH_KEY` - The client will self-register the first time it connects to the service and store the authentication key in the database. If no client ID is explicitly provided, the diagnostic ID of the Mattermost installation will be used. - The service URL supports credentials in the form `http://clientID:authKey@hostname`. Alternatively these can be passed through environment overrides to the Mattermost server, namely `MM_CALLS_RTCD_CLIENT_ID` and `MM_CALLS_RTCD_AUTH_KEY` + +</Note> + +### Max call participants + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting limits the number of participants that can join a single call.</p><p>Default is <strong>0</strong> (no limit).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>maxcallparticipants</code></li><li>Environment variable: <code>MM_CALLS_MAX_CALL_PARTICIPANTS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The environment variable `MM_CALLS_MAX_PARTICIPANTS` is deprecated in favor of `MM_CALLS_MAX_CALL_PARTICIPANTS`. - This setting is optional, but the recommended maximum number of participants is **50**. Call participant limits greatly depends on instance resources. See the [Calls deployment guide](/administration-guide/configure/calls-deployment-guide) documentation for details. + +</Note> + +### ICE servers configurations + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting stores a list of ICE servers (STUN/TURN) in JSON format to be used by the service.</p><p>This is an optional field. Changing this setting may require a plugin restart to take effect.</p><p>Default is <code>[{"urls": ["stun:stun.global.calls.mattermost.com:3478"]}]</code></p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>iceserversconfigs</code></li><li>Environment variable: <code>MM_CALLS_ICE_SERVERS_CONFIGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The configurations above, containing STUN and TURN servers, are sent to the clients and used to generate local candidates. - If hosting calls through the plugin (i.e. not using the [RTCD service](/administration-guide/configure/calls-deployment-guide)) any configured STUN server may also be used to find the instance's public IP when none is provided through the [ICE Host Override](/administration-guide/configure/plugins-configuration-settings#ice-host-override) option. + +</Note> + +**Example** + +> ``` json +> [ +> { +> "urls":[ +> "stun:stun.global.calls.mattermost.com:3478" +> ] +> }, +> { +> "urls":[ +> "turn:turn.example.com:3478" +> ], +> "username":"webrtc", +> "credentials":"turnpassword" +> } +> ] +> ``` + +**Example (Using generated TURN credentials)** + +> ``` json +> [{ +> "urls": ["turn:turn.example.com:443"] +> }] +> ``` + +<Note> + +To get TURN generated credentials to work you must provide a secret through the *TURN static auth secret* setting below. + +</Note> + +### TURN static auth secret + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>A static secret used to generate short-lived credentials for TURN servers.</p><p>This is an optional field.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>turnstaticauthsecret</code></li><li>Environment variable: <code>MM_CALLS_TURN_STATIC_AUTH_SECRET</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### TURN credentials expiration + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The expiration, in minutes, of the short-lived credentials generated for TURN servers.</p><p>Default is <strong>1440</strong> (one day).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>turncredentialsexpirationminutes</code></li><li>Environment variable: <code>MM_CALLS_TURN_CREDENTIALS_EXPIRATION_MINUTES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### Server side TURN + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: The RTC server will use the configured TURN candidates for server-initiated connections.</li><li><strong>false</strong>: TURN will be used only on the client-side.</li></ul><p>Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>serversideturn</code></li><li>Environment variable: <code>MM_CALLS_SERVER_SIDE_TURN</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### Allow screen sharing + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Call participants will be allowed to share their screen.</li><li><strong>false</strong>: Call participants won't be allowed to share their screen.</li></ul><p>Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>allowscreensharing</code></li><li>Environment variable: <code>MM_CALLS_ALLOW_SCREEN_SHARING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### Enable simulcast for screen sharing (Experimental) + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables simulcast for screen sharing. This can help to improve screen sharing quality.</li><li><strong>false</strong>: Disables simulcast for screen sharing.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enablesimulcast</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_SIMULCAST</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This experimental setting is applicable only to self-hosted deployments. +- This functionality requires Calls plugin version \>= v0.16.0 and `rtcd` version \>= v0.10.0 (when in use). +- Avoid enabling both this experimental configuration setting and the [Enable AV1](#enable-av1-experimental) experimental configuration setting at the same time. + +</Note> + +### Enable call recordings + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows call hosts to record meeting video and audio.</li><li><strong>false</strong>: <strong>(Default)</strong> Call recording functionality is not available to hosts.</li></ul><p>Recordings include the entire call window view along with participants' audio track and any shared screen video. Recordings are stored in Mattermost.</p><p>Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enablerecordings</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_RECORDINGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### Job service URL + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The URL to a running job service where all the processing related to recordings happens. The recorded files produced are stored in Mattermost.</p><p>This is a required field. Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>jobserviceurl</code></li><li>Environment variable: <code>MM_CALLS_JOB_SERVICE_URL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting is applicable only to self-hosted deployments. +- The client will self-register the first time it connects to the service and store the authentication key in the database. If no client ID is explicitly provided, the diagnostic ID of the Mattermost installation will be used. +- The service URL supports credentials in the form `http://clientID:authKey@hostname`. Alternatively these can be passed through environment overrides to the Mattermost server, namely `MM_CALLS_JOB_SERVICE_CLIENT_ID` and `MM_CALLS_JOB_SERVICE_AUTH_KEY`. +- As of Calls v0.25 it's possible to override the site URL used by jobs to connect by setting the `MM_CALLS_RECORDER_SITE_URL` or `MM_CALLS_TRANSCRIBER_SITE_URL` environment variables respectively. This can be helpful to avoid the jobs from connecting through the public Site URL configured in Mattermost and thus potentially bypass the public network. + +</Note> + +### Maximum call recording duration + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '52%'}} /> +<col style={{width: '47%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum duration of a call recording in minutes.</p><p>The default is <strong>60</strong>. The maximum is <strong>180</strong>. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>maxrecordingduration</code></li><li>Environment variable: <code>MM_CALLS_MAX_RECORDING_DURATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### Call recording quality + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The audio and video quality of call recordings. Available options are: <em>Low</em>, <em>Medium</em> and <em>High</em>.</p><p>The default is <strong>Medium</strong>. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>recordingquality</code></li><li>Environment variable: <code>MM_CALLS_RECORDING_QUALITY</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The quality setting will affect the performance of the job service and the file size of recordings. Refer to the [Calls deployment guide](/administration-guide/configure/calls-deployment-guide) documentation for more information. + +</Note> + +### Enable call transcriptions + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '67%'}} /> +<col style={{width: '32%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables automatic transcriptions of calls.</li><li><strong>false</strong>: <strong>(Default)</strong> Call transcriptions functionality is disabled.</li></ul><p>Transcriptions are generated from the call participants' audio tracks and the resulting files are attached to the call thread when the recording ends. Captions will be optionally rendered on top of the recording file video player.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enabletranscriptions</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_TRANSCRIPTIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The ability to enable call transcriptions in Mattermost calls is currently in [Beta](/administration-guide/manage/feature-labels#beta). - This server-side configuration setting is available from plugin version 0.22. - Call transcriptions require [call recordings](/administration-guide/configure/plugins-configuration-settings#enable-call-recordings) to be enabled. + +</Note> + +### Transcriber model size + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The speech-to-text model size to use. Heavier models will produce more accurate results at the expense of processing time and resources usage. Available options are: <em>Tiny</em>, <em>Base</em> and <em>Small</em>.</p><p>The default is <strong>Base</strong>. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>transcribermodelsize</code></li><li>Environment variable: <code>MM_CALLS_TRANSCRIBER_MODEL_SIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This setting is available starting in plugin version 0.22. The model size setting will affect the performance of the job service. Refer to the [Calls deployment guide](/administration-guide/configure/calls-deployment-guide) documentation for more information. + +</Note> + +### Call transcriber threads + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '67%'}} /> +<col style={{width: '32%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of threads used by the post-call transcriber. This must be in the range [1, numCPUs].</p><p>The default is 2. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>transcribernumthread</code></li><li>Environment variable: <code>MM_CALLS_TRANSCRIBER_NUM_THREADS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - The call transcriber threads setting will affect the performance of the job service. Refer to the [Calls deployment guide](/administration-guide/configure/calls-deployment-guide) documentation for more information. This setting is available starting in plugin version 0.26.2. + +</Note> + +### Enable live captions + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables live captioning of calls.</li><li><strong>false</strong>: <strong>(Default)</strong> Live captions functionality is disabled.</li></ul><p>Live captions are generated from the call participants' audio tracks and the resulting captions can be optionally displayed on the call clients by selecting the <strong>[cc]</strong> option.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enablelivecaptions</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_LIVE_CAPTIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- The ability to enable live call captions in Mattermost calls is currently in [Beta](/administration-guide/manage/feature-labels#beta). - This server-side configuration setting is available starting in plugin version 0.26.2. - Live captions require [call recordings](/administration-guide/configure/plugins-configuration-settings#enable-call-recordings) and [call transcriptions](/administration-guide/configure/plugins-configuration-settings#enable-call-transcriptions) to be enabled. + +</Note> + +### Live captions: Model size + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The speech-to-text model size to use for live captions. While heavier models can produce more accurate results, live captioning requires the transcriber to process up to ten seconds of audio within two seconds. Therefore a maximum of size <code>base</code> is recommended. Available options are: <em>Tiny</em>, <em>Base</em> and <em>Small</em>.</p><p>The default is <strong>Tiny</strong>. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>livecaptionsmodelsize</code></li><li>Environment variable: <code>MM_CALLS_LIVE_CAPTIONS_MODEL_SIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This setting is available starting in plugin version 0.26.2. The model size setting will affect the performance of the job service. Refer to the [performance and scalability recommendations](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md) documentation for more information. + +</Note> + +### Live captions: Number of transcribers used per call + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '71%'}} /> +<col style={{width: '28%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of separate live captions transcribers for each call. Each transcribes one audio stream at a time. The product of LiveCaptionsNumTranscribers * LiveCaptionsNumThreadsPerTranscriber must be in the range [1, numCPUs].</p><p>The default is 1. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>livecaptionsnumtranscribers</code></li><li>Environment variable: <code>MM_CALLS_LIVE_CAPTIONS_NUM_TRANSCRIBERS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This setting is available starting in plugin version 0.26.2. The live captions number of transcribers setting will affect the performance of the job service. Refer to the [performance and scalability recommendations](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md) documentation for more information. + +</Note> + +### Live captions: Number of threads per transcriber + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of threads per live-captions transcriber. The product of <code>LiveCaptionsNumTranscribers</code> * <code>LiveCaptionsNumThreadsPerTranscriber</code> must be in the range [1, numCPUs].</p><p>The default is 2. This is a required value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>livecaptionsnumthreadspertranscriber</code></li><li>Environment variable: <code>MM_CALLS_LIVE_CAPTIONS_NUM_THREADS_PER_TRANSCRIBER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This setting is available starting in plugin version 0.26.2. The live captions number of threads per transcriber setting will affect the performance of the job service. Refer to the [performance and scalability recommendations](https://github.com/mattermost/calls-offloader/blob/master/docs/performance.md) documentation for more information + +</Note> + +### Live captions language + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The language passed to the live captions transcriber. Should be a 2-letter ISO 639 Set 1 language code, e.g. 'en'.</p><p>If blank, the lange will be set to 'en' (English) as default.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>livecaptionslanguage</code></li><li>Environment variable: <code>MM_CALLS_LIVE_CAPTIONS_LANGUAGE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable only to self-hosted deployments. + +</Note> + +### (Experimental) Enable IPv6 + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: The RTC service will work in dual-stack mode, listening for IPv6 connections and generating candidates in addition to IPv4 ones.</li><li><strong>false</strong>: <strong>(Default)</strong> The RTC service will only listen for IPv4 connections.</li></ul><p>Changing this setting requires a plugin restart to take effect.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enableipv6</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_IPV6</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable only to self-hosted deployments. - This setting is available starting in plugin version 0.17, and is only applicable when not running calls through the standalone `rtcd` service. + +</Note> + +### Enable call ringing + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Ringing functionality is enabled. Direct and group message participants receive a desktop app alert and a ringing notification when a call starts.</li><li><strong>false</strong>: <strong>(Default</strong>) Ringing functionality is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enableringing</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_RINGING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +The ability to enable call ringing in Mattermost calls is in [Beta](/administration-guide/manage/feature-labels#beta). + +</Note> + +### Enable AV1 (Experimental) + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the ability to use the AV1 codec to encode screen sharing tracks. Can result in improved screen sharing quality via clients that support AV1 encoding.</li><li><strong>false</strong>: <strong>(Default</strong>) AV1 codec is disabled for screen sharing tracks.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enableAV1</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_AV1</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Avoid enabling both this experimental configuration setting and the [Enable simulcast for screen sharing](#enable-simulcast-for-screen-sharing-experimental) experimental configuration setting at the same time. + +</Note> + +### Enable DC signaling (Experimental) + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Clients will use WebRTC data channels for signaling of media tracks (i.e., voice, screen). This can result in a more efficient and less race-prone process, especially in case of poor network connections.</li><li><strong>false</strong>: <strong>(Default</strong>) Clients will use WebSockets for signaling media tracks.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Calls</strong></li><li><code>config.json</code> setting: <code>PluginSettings</code> > <code>Plugins</code> > <code>com.mattermost.calls</code> > <code>enabledcsignaling</code></li><li>Environment variable: <code>MM_CALLS_ENABLE_DC_SIGNALING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Version v0.18.0 or higher of the [RTCD service](/administration-guide/configure/calls-deployment-guide) is required for this functionality to work when hosting calls through the dedicated WebRTC service. +- Use caution when enabling this experimental configuration setting since it determines how the system handles part of the setup for WebRTC-based calls. Enabling this configuration setting may make the call setup a bit faster or more reliable in certain situations. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## AI Agents + +<Note> + +Mattermost Agents is formerly known as Mattermost Copilot. + +</Note> + +Access the following Mattermost Agents configuration settings in the System Console by going to **Plugins \> Agents**. + +### Enable plugin + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the Agents plugin on your Mattermost workspace.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the Agents plugin.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Agents</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Display name + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The bot's display name in Mattermost used to distinguish the bot from other bots in the system.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Agent username + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The bot's username that can be used to @mention the bot in a channel.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Agent avatar + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Upload an image to use as the agent's avatar in Mattermost.</p><p>Image upload interface.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Service + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Select the LLM service provider to use for AI assistance.</p><p>Available options: <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, <strong>Azure</strong>, <strong>Anthropic</strong>, and <strong>Ask Sage</strong>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Username + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The username used to authenticate with the <strong>Ask Sage</strong> LLM service.</p><p>String input required.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Password + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The password used to authenticate with the <strong>Ask Sage</strong> LLM service.</p><p>String input required. This value is encrypted when stored.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### API URL + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The endpoint that Mattermost will use to communicate with the LLM's API. Required for <strong>OpenAI Compatible</strong> and <strong>Azure</strong> LLM services.</p><p>String input (URL format).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### API key + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The key used to authenticate requests to the LLM's API. Required for <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, and <strong>Anthropic</strong> LLM services.</p><p>String input. This value is encrypted when stored.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Organization ID + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Ensures that requests are billed and processed under the correct organization, where applicable. Supported for <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, and <strong>Azure</strong> LLM services.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Send user ID + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Includes unique user identifiers in API requests to the LLM for analytics, personalization, and auditing purposes.</li><li><strong>false</strong>: <strong>(Default)</strong> Does not include user identifiers.</li></ul><p>Review LLM data privacy policies before enabling this setting.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +We recommend reviewing LLM data privacy policies to confirm whether transmitting user information is acceptable and secure within your organization's regulatory framework. Do not enable when you need to conform to strict privacy regulations (e.g., GDPR) that limit sharing user-identifiable data with external services. + +</Note> + +### Default model + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The specific LLM that will be used to process queries if no other model is explicitly selected. Supported for all LLM services.</p><p>String input (model name).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Input token limit + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of tokens (chunks of text, including words, punctuation, or special characters) that the selected LLM can process in a single prompt or request.</p><p>Numerical value. Directly impacts the size of user queries that can be handled.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Output token limit + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of tokens (chunks of text, including words, punctuation, or special characters) that the LLM can generate in its response to a query.</p><p>Numerical value. Must be greater than 0 for <strong>Anthropic</strong> LLM services.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Streaming timeout + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Determines how long the system will wait for a response from the LLM when using streaming (real-time) output mode. Supported for <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, and <strong>Azure</strong> LLM services.</p><p>Numerical value (in seconds). If the LLM takes longer than the configured timeout, the connection is terminated.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Streaming allows LLMs to display the response gradually as it's being generated, creating a smoother and more interactive experience for users. + +</Note> + +### Custom instructions + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Preset specific contextual or behavioral guidance for the LLM. Helps tailor the model's responses to align with your organization's needs, tone, or expectations. Supported for all LLM services.</p><p>Text input. Instructions that the model will implicitly follow for every interaction, providing consistency and adaptability.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Custom instructions can include behavioral guidance, tone preferences, contextual functions, and organizational preferences. This ensures responses adhere to your organization's language and tone guidelines and aligns the model's behavior with specific roles or purposes. + +</Note> + +### Enable vision + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the LLM to process and generate responses that incorporate image-related input or output. Supported for <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, <strong>Azure</strong>, and <strong>Anthropic</strong> LLM services.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables vision capabilities.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This feature is in [Beta](/administration-guide/manage/feature-labels#beta). When enabled, the LLM can interact with prompts that include image-related input, such as image analysis, visual-related assistance, and visual outputs, where supported. + +</Note> + +### Enable tools + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the LLM to leverage additional tools or plugins to enhance its capabilities. Supported for <strong>OpenAI</strong>, <strong>OpenAI Compatible</strong>, <strong>Azure</strong>, and <strong>Anthropic</strong> LLM services.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables tool capabilities.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +When enabled, advanced features beyond basic query processing allow the LLM to perform specialized tasks like retrieving data, integrating with external APIs, or performing computations, where supported. + +</Note> + +### Channel access + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Determines whether the bot can consume the contents of a given channel and provide answers only from content available in the channel. Supported for all LLM services.</p><p>Available options: <strong>Allow for all channels</strong>, <strong>Allow for selected channels</strong>, <strong>Block selected channels</strong>, and <strong>Block all channels</strong>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### User access + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Determines whether users who chat with this bot can get private assistance about content across all channels the user has access to. Supported for all LLM services.</p><p>Available options: <strong>Allow for all users</strong>, <strong>Allow for selected users</strong>, and <strong>Block selected users</strong>.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Add an AI Bot</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Default agent + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Select the default bot to use for AI functions when multiple agents are configured. Based on defined agents.</td> +<td><ul><li>System Config path: <strong>Plugins > Agents > AI Functions</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Allowed upstream hostnames + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Comma-separated list of hostnames that LLMs are allowed to contact when using tools. Supports wildcards like <code>*.mydomain.com</code>.</p><p>Example: <code>mattermost.atlassian.net</code> to allow JIRA tool use.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > AI Functions</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Enable LLM trace + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables tracing of LLM requests and outputs full conversation data to the logs. Supported for all LLM services.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables LLM request tracing.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Debug</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Use this setting for debugging purposes only. When enabled, it may log sensitive conversation data. + +</Note> + +### Enable embedding search + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>Composite</strong>: Enables experimental embedding search capabilities for semantic search across Mattermost content using pgvector and OpenAI-compatible endpoints.</li><li><strong>Disabled</strong>: <strong>(Default)</strong> Disables embedding search capabilities.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Embedding search requires an Enterprise license and is available as an [experimental](/administration-guide/manage/feature-labels#experimental) feature. You must also enable the `pgvector` extension in your PostgreSQL database. Performance may vary with large datasets. + +</Note> + +### Embedding provider type + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td>Select the provider for generating embeddings for semantic search. Available options: <strong>OpenAI</strong> and <strong>OpenAI Compatible</strong>.</td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### API Key + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The API key used to authenticate requests to the embedding provider's API. Required for <strong>OpenAI Compatible</strong> embedding providers.</p><p>String input. This value is encrypted when stored.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Model + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The specific embedding model to use for generating vector representations of content. Must be compatible with the selected embedding provider.</p><p>String input (model name).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### API URL + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The endpoint URL for the <strong>OpenAI-compatible</strong> embedding API.</p><p>Required string input (URL format).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Dimensions + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The dimensionality of the embedding vectors, which must match the chosen embedding model. Common values include 1536 for OpenAI text-embedding-ada-002 and 3072 for text-embedding-3-large.</p><p>Numerical input. Common values are 768, 1024, or 1536, depending on the model.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Chunking strategy + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The method used to split content into smaller chunks for embedding generation. Available options: <strong>Sentences</strong>, <strong>Paragraphs</strong>, <strong>Fixed Size</strong>.</p><p>Choose based on your content type and search requirements.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Chunk size + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum size of each content chunk in characters. Recommended range is 512-1024 characters. The optimal value varies by chunking strategy.</p><p>Numerical input.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Chunk overlap + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of tokens that consecutive chunks share for better context continuity. Recommended range is 20-50 characters for <strong>Fixed Size</strong> chunking.</p><p>Numerical input.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Minimum chunk size ratio + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The minimum ratio for chunk size validation to ensure sentence and paragraph chunks meet size requirements. Used to filter out chunks that are too small releative to the configured chunk size.</p><p>Numerical input (decimal ratio).</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Reindex all posts + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Select <strong>Reindex Posts</strong> to trigger a complete reindexing of all posts for embedding search. Use this control to rebuild the search index when changing embeddingproviders, models, or chunking configurations.</p><p>Monitor indexing progress during the reindexing process.</p></td> +<td><ul><li>System Config path: <strong>Plugins > Agents > Embedding Search</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## GitLab + +See the [Connect GitLab to Mattermost](/integrations-guide/gitlab) product documentation for details. + +------------------------------------------------------------------------------------------------------------------------ + +## GitHub + +See the [Connect GitHub to Mattermost](/integrations-guide/github) product documentation for details. + +------------------------------------------------------------------------------------------------------------------------ + +## Jira + +See the [Connect Jira to Mattermost](/integrations-guide/jira) product documentation for available [Mattermost configuration options](/integrations-guide/jira#mattermost-configuration). + +------------------------------------------------------------------------------------------------------------------------ + +## Legal hold + +<PlanAvailability slug="ent-plus" /> + +See the [Legal holds](/administration-guide/comply/legal-hold) product documentation for details. + +------------------------------------------------------------------------------------------------------------------------ + +## Microsoft Calendar Integration + +See the [Connect Microsoft Calendar Integration to Mattermost](/integrations-guide/microsoft-calendar) product documentation for available [Mattermost configuration options](/integrations-guide/microsoft-calendar#enable-and-configure-the-microsoft-calendar-integration-in-mattermost). + +------------------------------------------------------------------------------------------------------------------------ + +## Microsoft Teams Meetings + +See the [Connect Microsoft Teams Meetings to Mattermost](/integrations-guide/microsoft-teams-meetings) product documentation for available [Mattermost configuration options](/integrations-guide/microsoft-teams-meetings#enable-and-configure-the-microsoft-teams-meetings-integration-in-mattermost). + +------------------------------------------------------------------------------------------------------------------------ + +## MS Teams + +Mattermost for Microsoft Teams enables you to break through siloes in a mixed Mattermost and Teams environment by forwarding real-time chat notifications from Teams to Mattermost. + +<Tip> + +Download our [Mattermost for Microsoft Teams datasheet](https://mattermost.com/mattermost-for-microsoft-teams-datasheet/) to learn how Mattermost helps your organization get more from your Microsoft tools. + +</Tip> + +Access the following configuration settings in the System Console by going to **Plugins \> MS Teams**. + +### Enable plugin + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable the Mattermost for Microsoft Teams plugin for all Mattermost teams.</p><ul><li><strong>true</strong>: Enables MS Teams plugin on your Mattermost workspace.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the MS Teams plugin.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Use the [Enabled Teams](#enabled-teams) configuration option to specify which Mattermost teams synchronize direct and group messages with Microsoft Teams chats. + +</Note> + +### Tenant ID + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td>Specify the Microsoft Teams Tenant ID from the Azure portal.</td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Client ID + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td>Specify the Microsoft Teams Client ID of your registered OAuth app in the Azure portal.</td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Client secret + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify the client secret of your registered OAuth app in Azure portal.</p><p>Alpha-numeric value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### At rest encryption key + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Regenerate a new encryption secret. This encryption secret will be used to encrypt and decrypt the OAuth token.</p><p>Alpha-numeric value.</p></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Select **Regenerate** to generate a new key. + +</Note> + +### Webhook secret + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td>Generate the webhook secret that Microsoft Teams will use to send messages to Mattermost.</td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Select **Regenerate** to generate a new key. + +</Note> + +### Use the evaluation API pay model + +<table> +<colgroup> +<col style={{width: '58%'}} /> +<col style={{width: '41%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable this only for testing purposes. You need the pay model to be able to support enough message notifications to work in a real world scenario.</p><ul><li><strong>true</strong>: Enables the evaluation API pay model.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the evaluation API pay model.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Sync notifications + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Notify connected users in Mattermost on receipt of a chat or group chat from Microsoft Teams.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Sync notifications of chat messages for any connected user that enables the feature.</li><li><strong>false</strong>: Do not sync notifications.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Maximum size of attachments to support complete one time download + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify the maximum file size, in mebibytes (MiB), of attachments that can be loaded into memory. Attachment files larger than this value will be streamed from Microsoft Teams to Mattermost.</p><p>Numerical value. Default is <strong>20</strong> MiB.</p></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Buffer size for streaming files + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify the buffer size, in mebibytes (MiB), for streaming attachment files from Microsoft Teams to Mattermost.</p><p>Numerical value. Default is <strong>20</strong> MiB.</p></td> +<td><ul><li>System Config path: <strong>Plugins > MS Teams</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Performance metrics + +<PlanAvailability slug="entry-ent" /> + +See the [Monitor performance metrics](/administration-guide/scale/collect-performance-metrics) product documentation for available [Mattermost configuration options](/administration-guide/scale/collect-performance-metrics#mattermost-configuration). + +------------------------------------------------------------------------------------------------------------------------ + +## Collaborative playbooks + +Use collaborative playbooks in Mattermost to provide structure, monitoring and automation for repeatable, team-based processes integrated with the Mattermost platform. + +Access the following configuration settings in the System Console by going to **Plugins \> Collaborative playbooks**. + +### Enable plugin + +<table> +<colgroup> +<col style={{width: '61%'}} /> +<col style={{width: '38%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables collaborative Playbooks on your Mattermost workspace.</li><li><strong>false</strong>: Disables collaborative Playbooks on your Mattermost workspace.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Collaborative playbooks</strong></li><li><code>config.json</code> setting:</li><li>Environment variable:</li></ul></td> +</tr> +</tbody> +</table> + +### Enabled teams + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td>Enable collaborative playbooks for all Mattermost teams, or for only selected teams.</td> +<td><ul><li>System Config path: <strong>Plugins > Collaborative playbooks</strong></li><li><code>config.json</code> setting:</li><li>Environment variable:</li></ul></td> +</tr> +</tbody> +</table> + +### Enable experimental features + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables experimental playbooks features on your Mattermost workspace.</li><li><strong>false</strong>: Disables experimental playbooks features on your Mattermost workspace.</li></ul></td> +<td><ul><li>System Config path: <strong>Plugins > Collaborative playbooks</strong></li><li><code>config.json</code> setting:</li><li>Environment variable:</li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## ServiceNow + +See the [Connect ServiceNow to Mattermost](/integrations-guide/servicenow) product documentation for available [Mattermost configuration options](/integrations-guide/servicenow#mattermost-configuration). + +------------------------------------------------------------------------------------------------------------------------ + +## Zoom + +See the [Connect Zoom to Mattermost](/integrations-guide/zoom) product documentation for available [Mattermost configuration options](/integrations-guide/zoom#mattermost-configuration). + +------------------------------------------------------------------------------------------------------------------------ + +## config.json-only settings + +The following self-hosted deployment settings are only configurable in the `config.json` file and are not available in the System Console. + +### Signature public key files + +This setting isn't available in the System Console and can only be set in `config.json`. + +In addition to the Mattermost plugin signing key built into the server, each public key specified here is trusted to validate plugin signatures. + +<Important> + +From Mattermost v10.11, pre-packaged plugins require signature validation on startup. Distributions that bundle custom pre-packaged plugins **must** configure this setting with their custom public keys to ensure proper validation of their signed plugins. Use `PluginSettings.SignaturePublicKeyFiles` to define custom plugin signing keys. + +When bundling custom plugins: + +- Drop both the plugin files and their corresponding `.sig` signature files into the `prepackaged_plugins` directory. +- Add your custom public key using this configuration setting to validate the signatures. + +</Important> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"SignaturePublicKeyFiles": {}</code> with string array input consisting of contents that are relative or absolute paths to signature files.</td> +</tr> +</tbody> +</table> + +### Chimera OAuth proxy URL + +This setting isn't available in the System Console and can only be set in `config.json`. + +Specify the [Chimera](https://github.com/mattermost/chimera) URL used by Mattermost plugins to connect with pre-created OAuth applications. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ChimeraOAuthProxyUrl": {}</code> with string input.</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/push-notification-server-configuration-settings.mdx b/docs/main/administration-guide/configure/push-notification-server-configuration-settings.mdx new file mode 100644 index 000000000000..9ad3ae38ee9a --- /dev/null +++ b/docs/main/administration-guide/configure/push-notification-server-configuration-settings.mdx @@ -0,0 +1,125 @@ +--- +title: "Enable push notifications" +draft: true +--- +With self-hosted deployments, you can configure mobile push notifications for Mattermost by going to **System Console \> Environment \> Push Notification Server**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable Mattermost push notifications.</p><ul><li><strong>Do not send push notifications</strong>: Mobile push notifications are disabled.</li><li><strong>Use HPNS connection with uptime SLA to send notifications to iOS and Android apps</strong>: <strong>(Default)</strong> Use Mattermost's hosted push notification service.</li><li><strong>Use TPNS connection to send notifications to iOS and Android apps</strong>: Use Mattermost's test push notification service.</li><li><strong>Manually enter Push Notification Service location</strong>: When building your own custom mobile apps, you must host your own mobile push proxy service, and specify that URL in the <strong>Push Notification Server</strong> field.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Push Notification Server</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SendPushNotifications</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SENDPUSHNOTIFICATIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +## Hosted Push Notifications Service (HPNS) + +Mattermost Enterprise, Professional, and Cloud customers can use Mattermost's Hosted Push Notification Service (HPNS). The HPNS offers: + +- Access to a publicly-hosted Mattermost Push Notification Service (MPNS) [available on GitHub.](https://github.com/mattermost/mattermost-push-proxy) +- An explicit [privacy policy](https://mattermost.com/data-processing-addendum/) for the contents of unencrypted messages. +- Encrypted TLS connections: + - Between HPNS and Apple Push Notification Services + - Between HPNS and Google’s Firebase Cloud Messaging Service + - HPNS and your Mattermost Server +- Production-level uptime expectations. +- Out-of-box configuration for new servers means nothing is required to enable HPNS for new deployments. HPNS can be [enabled for existing deployments](#enable-hpns-for-existing-deployments). + +<Note> + +\- The HPNS only works with pre-built apps Mattermost deploys through the [Apple App Store](https://www.apple.com/app-store/) and [Google Play Store](https://play.google.com/store/games?hl=en). If you build your own mobile apps, you must also [host your own Mattermost push proxy server](#host-your-own-push-proxy-service). - You must ensure that the push proxy can be reached on the correct port. For HPNS, it's port 443 from the Mattermost server. - Mattermost doesn't store any notification data. Any data being stored is at the server level only, such as the `device_id`, since the HPNS needs to know which device the notification must be sent to. + +</Note> + +## Test Push Notifications Service (TPNS) + +Non-commercial self-hosted customers can use Mattermost's free, basic Test Push Notifications Service (TPNS). + +<Note> + +\- The TPNS isn’t recommended for use in production environments, and doesn’t offer production-level update service level agreements (SLAs). - The TPNS isn't available for Mattermost Cloud deployments. - The TPNS only works with the pre-built mobile apps that Mattermost deploys through the [Apple App Store](https://www.apple.com/app-store/) and [Google Play Store](https://play.google.com/store/games?hl=en). If you have built your own mobile apps, you must also [host your own Mattermost push proxy service](#host-your-own-push-proxy-service). - You must ensure that the push proxy can be reached on the correct port. For TPNS, it's port 80 from the Mattermost server. - If you don't need or want Mattermost to send mobile push notifications, disabling this configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Processing Load: Generating and sending push notifications requires processing power and resources. By disabling them, the server can allocate those resources to other tasks. +- Decreased Network Traffic: Push notifications involve network communication. Disabling them reduces the amount of data being transferred, which can enhance overall network performance. +- Lower Database Load: Each push notification may involve reading from and writing to the database. Reducing these operations decreases the load on the database, improving response times for other queries. +- Faster Response Times: With fewer tasks to handle related to notifications, the system can respond faster to other requests from users, leading to a better user experience. +- Simplified Error Handling: Push notification services can sometimes fail or have latency issues, requiring additional error handling. Disabling these notifications simplifies the system's operations. +- However, disabling push notifications can negatively impact user experience, communication efficiency, and overall productivity. It’s important to balance performance improvements with the needs of your organization and users. + +</Note> + +## ID-only push notifications + +<PlanAvailability slug="entry-ent" /> + +Admins can enable mobile notifications to be fully private to protect a Mattermost customer against breaches in iOS and Android notification infrastructure by limiting the data sent to Apple and Google through a Mattermost configuration setting. + +The standard way to send notifications to iOS and Android applications requires sending clear text messages to Apple or Google so they can be forwarded to a user’s phone and displayed on iOS or Android. While Apple or Google assure the data is not collected or stored, should the organizations be breached or coerced, all standard mobile notifications on the platform could be compromised. + +To avoid this risk, Mattermost can be configured to replace mobile notification text with message ID numbers that pass no information to Apple of Google. When received by the Mattermost mobile application on a user’s phone, the message IDs are used to privately communicate with their Mattermost server and to retrieve mobile notification messages over an encrypted channel. This means that, at no time, is the message text visible to Apple or Google’s message relay system. The contents of the message also won't reach Mattermost. + +<Note> + +Because of the extra steps to retrieve the notifications messages under Mattermost’s private mobility capability with ID-only push notifications, end users may experience a slight delay before the mobile notification is fully displayed compared to sending clear text through Apple and Google’s platform. + +</Note> + +See our [configuration settings](/administration-guide/configure/site-configuration-settings#push-notification-contents) documentation to learn more about the ID-only push notifications configuration setting. See our [Mobile Apps FAQ documentation](/deployment-guide/mobile/mobile-faq#how-can-i-use-id-only-push-notifications-to-protect-notification-content-from-being-exposed-to-third-party-services) for details on using ID-only push notifications for data privacy. + +# Push notification server location + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The physical location of the Mattermost Hosted Push Notification Service (HPNS) server.</p> +<p>Select from <strong>US</strong> <strong>(Default)</strong> or <strong>Germany</strong> to automatically populate the <strong>Push Notification Server</strong> field server URL.</p></td> +<td><ul> +<li>System Config path: <strong>Environment > Push Notification Server</strong></li> +<li><code>config.json</code> setting: <code>EmailSettings</code> > <code>PushNotificationServer</code></li> +<li>Environment variable: <code>MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER</code></li> +</ul></td> +</tr> +</tbody> +</table> + +# Maximum notifications per channel + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum total number of users in a channel before @all, @here, and @channel no longer send desktop, email, or mobile push notifications to maximize performance.</p> +<p>Numerical input. Default is <strong>1000</strong>.</p></td> +<td><ul> +<li>System Config path: <strong>Environment > Push Notification Server</strong></li> +<li><code>config.json</code> setting: <code>TeamSettings</code> > <code>MaxNotificationsPerChannel</code> > <code>1000</code></li> +<li>Environment variable: <code>MM_EMAILSETTINGS_MAXNOTIFICATIONSPERCHANNEL</code></li> +</ul></td> +</tr> +</tbody> +</table> + +<Note> + +- We recommend increasing this value a little at a time, monitoring system health by tracking [performance monitoring metrics](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring), and only increasing this value if large channels have restricted permissions controlling who can post to the channel, such as a [read-only channel](/administration-guide/onboard/advanced-permissions#read-only-channels). +- Reducing this configuration setting value to **10** in larger deployments may improve server performance in the following areas: + - **Reduced Load on Notification System**: Each notification generates a certain amount of computational and network load. By limiting the number of notifications per channel, the system processes fewer notifications, thereby reducing the load on servers. + - **Database Efficiency**: Notifications are typically stored in a database. Fewer notifications mean less frequent database writes and reads, leading to quicker database operations and reduced latency. + - **Minimized Client Processing**: Users' clients (e.g., desktop and mobile apps) have to fetch and process notifications. With fewer notifications, clients can operate more efficiently, reducing memory and CPU usage on users' devices. + - **Improved User Experience**: An overload of notifications can lead to performance lags and a cluttered experience for users. Limiting the number ensures that users receive only the most important notifications, which can enhance usability and response times. + - **Network Bandwidth**: High numbers of notifications can consume a lot of bandwidth, particularly if they are being sent to many users. Fewer notifications can lead to lower overall network usage and potentially faster delivery of critical messages. + - **Server Load Balancing**: By reducing the number of notifications, the workload can be more evenly distributed across the servers, leading to better load balancing and preventing any single server from becoming a bottleneck. + +</Note> diff --git a/docs/main/administration-guide/configure/rate-limiting-configuration-settings.mdx b/docs/main/administration-guide/configure/rate-limiting-configuration-settings.mdx new file mode 100644 index 000000000000..3318c2ff58e4 --- /dev/null +++ b/docs/main/administration-guide/configure/rate-limiting-configuration-settings.mdx @@ -0,0 +1,116 @@ +--- +title: "Enable rate limiting" +draft: true +--- +With self-hosted deployments, rate limiting prevents your Mattermost server from being overloaded with too many requests, and decreases the risk and impact of third-party applications or malicious attacks on your server. + +Configure rate limiting settings by going to **System Console \> Environment \> Rate Limiting**, or by editing the `config.json` file as described in the following tables. Changes to configuration settings in this section require a server restart before taking effect. + +<Important> + +Mattermost rate limiting configuration settings are intended for small deployments of Mattermost up to a few hundred users, and is not intended for larger, Enterprise-scale deployments. + +</Important> + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable rate limiting to throttle APIs to a specified number of requests per second.</p><ul><li><strong>true</strong>: APIs are throttled at the rate specified by the <a href="#maximum-queries-per-second">Maximum queries per second</a> configuration setting.</li><li><strong>false</strong>: <strong>(Default)</strong> API access isn’t throttled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +# Maximum queries per second + +<table> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '53%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Throttle the API at this number of requests per second when <a href="#enable-rate-limiting">rate limiting</a> is enabled.</p><p>Numerical input. Default is <strong>10</strong>.</p><p>Increase this value to accept more requests each second, and decrease this value to allow fewer requests.</p></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>PerSec</code> > <code>10</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_PERSEC</code></li></ul></td> +</tr> +</tbody> +</table> + +# Maximum burst size + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of requests allowed beyond the per second query limit when <a href="#enable-rate-limiting">rate limiting</a> is enabled.</p><p>Numerical input. Default is <strong>100</strong>.</p><p>Increase this value to allow for more concurrent requests to be handled, and decrease this value to limit this capacity.</p></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>MaxBurst</code> > <code>100</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_MAXBURST</code></li></ul></td> +</tr> +</tbody> +</table> + +# Memory store size + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of user sessions connected to the system as determined by vary rate limit settings when <a href="#enable-rate-limiting">rate limiting</a> is enabled.</p><p>Numerical input. Default is <strong>10000</strong>. Typically set to the number of users in the system.</p><p>We recommend setting this value to the expected number of users. A higher value may result in underutilized resources, and a lower value may result in user sessions/tokens expiring too frequently.</p></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>MemoryStoreSize</code> > <code>10000</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_MEMORYSTORESIZE</code></li></ul></td> +</tr> +</tbody> +</table> + +# Vary rate limit by remote address + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to rate limit API access by IP address when <a href="#enable-rate-limiting">rate limiting</a> is enabled.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Rate limit API access by IP address. Recommended when using a proxy.</li><li><strong>false</strong>: Rate limiting does not vary by IP address.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>VaryByRemoteAddr</code> > <code>true</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_VARYBYREMOTEADDR</code></li></ul></td> +</tr> +</tbody> +</table> + +# Vary rate limit by user + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to rate limit API access by authentication token or not when <a href="#enable-rate-limiting">rate limiting</a> is enabled.</p><ul><li><strong>true</strong>: Rate limit API access by user authentication token. Recommended when using a proxy.</li><li><strong>false</strong>: <strong>(Default)</strong> Rate limiting does not vary by user authentication token.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>VaryByUser</code> > <code>false</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_VARYBYUSER</code></li></ul></td> +</tr> +</tbody> +</table> + +# Vary rate limit by HTTP header + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Configure Mattermost to vary rate limiting API access by the HTTP header field specified. Recommended when you’re using a proxy.</p><ul><li>When configuring NGINX, set this to <strong>X-Real-IP</strong>.</li><li>When configuring AmazonELB, set this to <strong>X-Forwarded-For</strong>.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Rate Limiting</strong></li><li><code>config.json</code> setting: <code>RateLimitSettings</code> > <code>VaryByHeader</code> > <code>""</code></li><li>Environment variable: <code>MM_RATELIMITSETTINGS_VARYBYHEADER</code></li></ul></td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/reporting-configuration-settings.mdx b/docs/main/administration-guide/configure/reporting-configuration-settings.mdx new file mode 100644 index 000000000000..91579938fad9 --- /dev/null +++ b/docs/main/administration-guide/configure/reporting-configuration-settings.mdx @@ -0,0 +1,125 @@ +--- +title: "Reporting configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +View the following statistics for your overall deployment and specific teams, as well as access server logs, in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Reporting**: + +- [Site statistics](#site-statistics) +- [Team statistics](#team-statistics) +- [Server logs](#server-logs) +- [Statistics configuration settings](#statistics-configuration-settings) + +------------------------------------------------------------------------------------------------------------------------ + +## Site statistics + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td>View statistics on a wide variety of activities in Mattermost, including: users, seats, teams, channels, posts, calls, sessions, commands, webhooks, websocket and database connections, and collaborative playbooks.</td> +<td><ul> +<li>System Config path: <strong>Reporting > Site Statistics</strong></li> +<li><code>config.json setting</code>: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Bots, deactivated users, and synthetic users in [Microsoft Teams integrations](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams) and [connected workspaces](/administration-guide/onboard/connected-workspaces) users aren't counted towards the total number of activated users. +- **Single-channel Guests** shows the number of active guest accounts that belong to exactly one channel. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. Single-channel guests are counted separately from the primary paid seat count and are free up to a 1:1 ratio with licensed seats. When this count exceeds the allowance, the statistic is highlighted as a warning for system admins. +- Guests in multiple channels continue to count as paid active users. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation for details. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Team statistics + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td>View statistics per team on number of activated users, number of public and private channels, total post count, and count of paid users (self-hosted only).</td> +<td><ul> +<li>System Config path: <strong>Reporting > Team Statistics</strong></li> +<li><code>config.json</code> setting: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +</tbody> +</table> + +<Note> + +Bots, deactivated users, and synthetic users in [Microsoft Teams integrations](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams) and [connected workspaces](/administration-guide/onboard/connected-workspaces) users aren't counted towards the total number of active users. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Server logs + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>View logging of server-side events.</p> +<p>Reload data, download the <code>mattermost.log</code> file locally, and view full log event details for any log entry.</p></td> +<td><ul> +<li>System Config path: <strong>Reporting > Server Logs</strong></li> +<li><code>config.json</code> setting: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting is applicable to self-hosted deployments only. +- From Mattermost v10.9, you can toggle between JSON and plain text server logs in the System Console when console log output is configured as [JSON](/administration-guide/configure/environment-configuration-settings#output-console-logs-as-json) by specifying the log format as **JSON** or **Plain text**. This option is located in the top right corner of the page **Server logs** page. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Statistics configuration settings + +The following self-hosted deployment configuration setting controls statistics collection behavior. This setting is not available in the System Console and can only be set in the `config.json` file. + +### Maximum users for statistics + +This setting is used to maximize performance for large Enterprise deployments and isn't available in the System Console and can only be set in `config.json`. + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the maximum number of users on the server before statistics for total messages, total hashtag messages, total file messages, messages per day, and activated users with messages per day are disabled.</p> +<p>Numerical input. Default is <strong>2500</strong> users.</p></td> +<td><ul> +<li>System Config path: N/A</li> +<li><code>config.json</code> setting: <code>"AnalyticsSettings.MaxUsersForStatistics": 2500</code></li> +<li>Environment variable: N/A</li> +</ul></td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/self-hosted-account-settings.mdx b/docs/main/administration-guide/configure/self-hosted-account-settings.mdx new file mode 100644 index 000000000000..052b0ead3bf3 --- /dev/null +++ b/docs/main/administration-guide/configure/self-hosted-account-settings.mdx @@ -0,0 +1,26 @@ +--- +title: "Self-hosted workspace edition and license settings" +--- +<PlanAvailability slug="all-commercial" /> + +Start a trial or manage your self-hosted deployment by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **About \> Edition and License**. + +## Start a trial + +You can start a trial of [Mattermost Enterprise](/product-overview/editions-and-offerings#mattermost-enterprise-edition) for free for 30 days. Select **Start trial** and fill out the form to begin. + +<Note> + +Once you've started a trial, you can't start another one with the same Mattermost instance. If you need more time to evaluate Mattermost Enterprise, contact a [Mattermost Expert](https://mattermost.com/contact-sales/). + +</Note> + +## Manage your self-hosted deployment + +You can also review and manage the following aspects of your self-hosted deployment: + +- View the [edition](/product-overview/editions-and-offerings) of your Mattermost self-hosted deployment. +- Manage your [product subscription](/product-overview/self-hosted-subscriptions). +- [Upload a new license](/administration-guide/manage/admin/installing-license-key). +- Remove a license to [downgrade the server](/administration-guide/upgrade/downgrading-mattermost-server). +- Talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) for assistance. diff --git a/docs/main/administration-guide/configure/site-configuration-settings.mdx b/docs/main/administration-guide/configure/site-configuration-settings.mdx new file mode 100644 index 000000000000..41886e42094a --- /dev/null +++ b/docs/main/administration-guide/configure/site-configuration-settings.mdx @@ -0,0 +1,2140 @@ +--- +title: "Site configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Review and manage the following site configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **Site Configuration**: + +- [Customization](#customization) +- [Localization](#localization) +- [Auto-translation](#autotranslation) +- [Users and Teams](#users-and-teams) +- [Notifications](#notifications) +- [System-wide notifications](#system-wide-notifications) +- [Emoji](#emoji) +- [Posts](#posts) +- [File Sharing and Downloads](#file-sharing-and-downloads) +- [Public Links](#public-links) +- [Notices](#notices) +- [Connected Workspaces](#connected-workspaces) + +<Tip> + +System admins managing a self-hosted Mattermost deployment can edit the `config.json` file as described in the following tables. Each configuration value below includes a JSON path to access the value programmatically in the `config.json` file using a JSON-aware tool. For example, the `SiteName` value is under `TeamSettings`. + +- If using a tool such as [jq](https://stedolan.github.io/jq/), you'd enter: `cat config/config.json | jq '.TeamSettings.SiteName'` +- When working with the `config.json` file manually, look for an object such as `TeamSettings`, then within that object, find the key `SiteName`. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Customization + +Access the following configuration settings in the System Console by going to **Site Configuration \> Customization**. + +### Site name + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Name of the site shown in login screens and user interface.</p><p>String input. Maximum 30 characters. Default is <code>Mattermost</code></p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>SiteName</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_SITENAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Site description + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Text displayed above the login form. When not specified, the phrase "Log in" is displayed.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>CustomDescriptionText</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_CUSTOMDESCRIPTIONTEXT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable custom branding + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the display of a custom image and text on the login page</li><li><strong>false</strong>: <strong>(Default)</strong> Custom branding is disabled</li></ul><p>See also the <a href="#custom-brand-image">custom brand image</a> and <a href="#custom-brand-text">custom brand text</a> configuration settings for more branding options.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableCustomBrand</code> > <code>false</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLECUSTOMBRAND</code></li></ul></td> +</tr> +</tbody> +</table> + +### Custom brand image + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>A JPG image for display on the login page. The image <strong>must</strong> be uploaded through the System Console. There is no <code>config.json</code> setting. The file should be <strong>smaller than 2 MB</strong>.</p><p><a href="#enable-custom-branding">Enable custom branding</a> must be set to <strong>true</strong> to display the image.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: N/A</li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Custom brand text + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>Text that will be shown below the <strong>Custom brand image</strong> on the login page. | - System Config path: <strong>Site Configuration > Customization</strong> | You can format this text using the same <a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fformat-messages">Markdown formatting</a> | - <code>config.json</code> setting: <code>TeamSettings</code> > <code>CustomBrandText</code> as in Mattermost messages. | - Environment variable: <code>MM_TEAMSETTINGS_CUSTOMBRANDTEXT</code> | | | String input. Maximum 500 characters. <a href="#enable-custom-branding">Enable custom branding</a> | | must be set to <strong>true</strong> to display the text. | |</td> +</tr> +</tbody> +</table> + +### Enable Ask Community link + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><blockquote><ul><li><strong>true</strong>: <strong>(Default)</strong> A link to the <a href="https://mattermost.com/community/">Mattermost Community</a> appears as <strong>Ask the community</strong> under the <strong>Help</strong> menu in the channel header.</li><li><strong>false</strong>: The link does not appear.</li></ul><p>The link does not display on mobile apps.</p></blockquote></td> +<td><blockquote><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>EnableAskCommunityLink</code> > <code>true</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_ENABLEASKCOMMUNITYLINK</code></li></ul></blockquote></td> +</tr> +</tbody> +</table> + +### Help link + +<table> +<colgroup> +<col style={{width: '70%'}} /> +<col style={{width: '29%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for the Help link on the login and sign up pages, as well as the <strong>Help Resources</strong> link under the <strong>Help</strong> menu in the channel header.</p><p>String input. Default is <code>https://about.mattermost.com/default-help/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>HelpLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_HELPLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +If this value is empty, the Help link is hidden on the login and sign up pages. However, the **Help Resources** link remains available under the **Help** menu. + +</Note> + +### Terms of Use link + +<table> +<colgroup> +<col style={{width: '85%'}} /> +<col style={{width: '14%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for the Terms of Use of a self-hosted site. A link to the terms appears at the bottom of the sign-up and login pages.</p><p>The default URL links to a <a href="https://mattermost.com/terms-of-use/">Terms of Use</a> page hosted on <code>mattermost.com</code>. This includes the Mattermost Acceptable Use Policy explaining the terms under which Mattermost software is provided to end users. If you change the default link to add your own terms, the new terms <strong>must include a link</strong> to the default terms so end users are aware of the Mattermost Acceptable Use Policy.</p><p>String input. Default is <code>https://about.mattermost.com/default-terms/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>TermsOfServiceLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_TERMSOFSERVICELINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- Customers with a Mattermost subscription may replace or override the Acceptable Use Policy with their own acceptable use or conduct policies, based on contractual terms with Mattermost, so long as your own terms either incorporate the Acceptable Use Policy or include equivalent terms. If you change the default link to add your own terms for using the service you provide, your new terms must include a [link to the default terms](https://mattermost.com/terms-of-use/#acceptable-use-policy) so end users are aware of the Mattermost Acceptable Use Policy for Mattermost software. - This setting is applicable to self-hosted deployments only and doesn't change the **Terms of Use** link in the **About Mattermost** window. + +</Note> + +### Privacy Policy link + +<table> +<colgroup> +<col style={{width: '72%'}} /> +<col style={{width: '27%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for the Privacy Policy of a self-hosted site. A link to the policy appears at the bottom of the sign-up and login pages. If this field is empty, the link does not appear.</p><p>String input. Default is <code>https://about.mattermost.com/default-privacy-policy/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>PrivacyPolicyLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_PRIVACYPOLICYLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable to self-hosted deployments only and doesn't change the **Privacy Policy** link in the **About Mattermost** window. + +</Note> + +### About link + +<table> +<colgroup> +<col style={{width: '77%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for a page containing general information about a self-hosted site. A link to the About page appears at the bottom of the sign-up and login pages. If this field is empty the link does not appear.</p><p>String input. Default is <code>https://about.mattermost.com/default-about/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>AboutLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_ABOUTLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Forgot Password custom link + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>When the <strong>Forgot Password</strong> link is enabled on the Mattermost login page, users are taken to a custom URL to recover or change their password.</p><p>Leave this field blank to use Mattermost's Password Reset workflow.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Forgot password custom link</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>ForgetPasswordLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_FORGETPASSWORDLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This configuration setting applies to all Mattermost clients, including web, desktop app, and mobile app. You can control whether the **Forgot Password** link is visible or hidden in clients by going to **Authentication \> Password \> Enable Forgot Password Link**. See the [configuration](/administration-guide/configure/authentication-configuration-settings#enable-forgot-password-link) documentation for details. + +</Note> + +### Report a Problem + +With self-hosted deployments, you can specify how the **Report a Problem** option behaves in the Mattermost app via the **Help** menu: + +- **Default link**: Uses the default Mattermost URL to report a problem. Customers with a Mattermost subscription are directed to the [Mattermost Support Portal](https://support.mattermost.com/hc/en-us/requests/new). Community deployments are directed to [create a new issue on the Mattermost GitHub repository](https://github.com/mattermost/mattermost/issues/new). +- **Email address**: Enables you to [enter an email address](/administration-guide/configure/site-configuration-settings#report-a-problem-email-address) that users will be prompted to send a message to when they choose **Report a Problem** in Mattermost. +- **Custom link**: Enables you to [enter a URL](/administration-guide/configure/site-configuration-settings#report-a-problem-link) that users will be directed to when they choose **Report a Problem** in Mattermost. +- **Hide link**: Removes the **Report a Problem** option from Mattermost. + +### Report a Problem link + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for the <strong>Report a Problem</strong> link in the channel header <strong>Help</strong> menu. If this field is empty the link does not appear.</p><p>String input. Default is <code>https://mattermost.com/pl/report-a-bug</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>ReportAProblemLink</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_REPORTAPROBLEMLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Report a Problem email address + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the email address for the <strong>Report a Problem</strong> link in the channel header <strong>Help</strong> menu.</p><p>String input. Cannot be left blank.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>ReportAProblemMail</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_REPORTAPROBLMEMAIL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Allow mobile app log downloads + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable users to download mobile app logs for troubleshooting. When the <strong>Report a Problem</strong> link is shown, mobile logs can be downloaded as part of the reporting flow.</p><ul><li><strong>true</strong> (<strong>Default</strong>): Users can download mobile app logs.</li><li><strong>false</strong> Users can't download mobile app logs.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>AllowDownloadLogs</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_ALLOWDOWNLOADLOGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Mattermost apps download page link + +<table> +<colgroup> +<col style={{width: '63%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL for the Download Apps link in the <strong>Product</strong> menu. If this field is empty, the link does not appear.</p><p>If you have an Enterprise App Store, set the link to the appropriate download page for your Mattermost apps.</p><p>String input. Default is <code>https://mattermost.com/pl/download-apps</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>AppDownloadLink</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_APPDOWNLOADLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Android app download link + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL to download the Mattermost Android app. Users who access the Mattermost site on a mobile browser will be prompted to download the app through this link. If this field is empty, the prompt does not appear.</p><p>If you have an Enterprise App Store, link to your Android app.</p><p>String input. Default is <code>https://mattermost.com/pl/android-app/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>AndroidAppDownloadLink</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_ANDROIDAPPDOWNLOADLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### iOS app download link + +<table> +<colgroup> +<col style={{width: '74%'}} /> +<col style={{width: '25%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This field sets the URL to download the Mattermost iOS app. Users who access the site on a mobile browser will be prompted to download the app through this link. If this field is empty, the prompt does not appear.</p><p>If you use an Enterprise App Store, link to your iOS app.</p><p>String input. Default is <code>https://mattermost.com/pl/ios-app/</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>NativeAppSettings</code> > <code>IosAppDownloadLink</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_IOSAPPDOWNLOADLINK</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting is applicable to self-hosted deployments only. + +</Note> + +### Enable desktop app landing page + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Prompts users to use the desktop app.</li><li><strong>false</strong>: Doesn't prompt users to use the desktop app.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Customization</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableDesktopLandingPage</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEDESKTOPLANDINGPAGE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Minimum desktop app version + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>Specify the minimum version of the Mattermost Desktop App required to connect to this server | - System Config path: <strong>Site Configuration > Customization</strong> | (e.g., <code>5.10.0</code>). Users connecting with a Desktop App version below this minimum are shown | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>MinimumDesktopAppVersion</code> | an update required screen and cannot use the application until they update. | - Environment variable: <code>MM_SERVICESETTINGS_MINIMUMDESKTOPAPPVERSION</code> | | | The update screen includes a download link configured via the | | <a href="mm-ref:configure%2Fsite-configuration-settings%3Amattermost%20apps%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20download%20page%20link">Mattermost apps download page link</a> setting. | | | Must be a valid semantic version (e.g., <code>5.0.0</code>). Leave blank to allow all Desktop App | | versions to connect. | | | | String input. Default is empty (no minimum enforced). | |</td> +</tr> +</tbody> +</table> + +### App custom URL schemes + +This setting isn't available in the System Console and can only be set in `config.json`. + +Define valid custom URL schemes for redirect links provided by custom-built mobile Mattermost apps. This ensures users are redirected to the custom-built mobile app and not Mattermost's mobile client. + +When configured, after OAuth or SAML user authentication is complete, custom URL schemes sent by mobile clients are validated to ensure they don't include default schemes such as `http` or `https`. Mobile users are then redirected back to the mobile app using the custom scheme URL provided by the mobile client. We recommend that you update your mobile client values as well with valid custom URL schemes. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"NativeAppSettings.AppCustomURLSchemes"</code> with an array of strings as input separated by spaces.</td> +</tr> +<tr> +<td><p>For example:</p><ul><li><code>MM_NativeAppSettings_AppCustomURLSchemes = mmauth:// mmauthbeta://</code></li><li>Via mmctl: <code>mmctl config set NativeAppSettings.AppCustomURLSchemes "mmauth://" "mmauthbeta://"</code></li></ul></td> +</tr> +</tbody> +</table> + +### Mobile external browser + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>From Mattermost v10.2 and Mobile v2.2.1, this setting configures the mobile app to use an external mobile browser to perform SSO authentication.</p><ul><li><strong>true</strong>: The mobile app uses the default internal mobile browser to perform SSO authentication.</li><li><strong>false</strong>: <strong>(Default)</strong> The mobile app uses an external mobile browser to perform SSO authentication.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>NativeAppSettings.MobileExternalBrowser</code></li><li>Environment variable: <code>MM_NATIVEAPPSETTINGS_MOBILEEXTERNALBROWSER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting is applicable to self-hosted deployments only. +- We recommend enabling this configuration setting when there are issues with the mobile app SSO redirect flow. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Localization + +Access the following configuration settings in the System Console by going to **Site Configuration \> Localization**. Changes to configuration settings in this section require a server restart before taking effect. + +### Default server language + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The default language for system messages and logs.</p><p>Options: <code>"bg"</code>, <code>"de"</code>, <code>"en"</code>, <code>"en-AU"</code>, <code>"es"</code>, <code>"fa"</code>, <code>"fr"</code>, <code>"hu"</code>, <code>"it"</code>, <code>"ja"</code>, <code>"ko"</code>, <code>"nl"</code>, <code>"pl"</code>, <code>"pt-br"</code>, <code>"ro"</code>, <code>"ru"</code>, <code>"sv"</code>, <code>"tr"</code>, <code>"uk"</code>, <code>"vi"</code>, <code>"zh-Hans"</code>, and <code>"zh-Hant"</code>.</p><p>Default is <code>"en"</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>LocalizationSettings</code> > <code>DefaultServerLocale</code></li><li>Environment variable: <code>MM_LOCALIZATIONSETTINGS_DEFAULTSERVERLOCALE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Changing this configuration setting changes the default server language for users who haven't set a language preference via **Settings**. Mattermost applies the user's language preference when specified. + +</Note> + +### Default client language + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The default language for new users and pages where the user isn't logged in.</p><p>Options: <code>"bg"</code>, <code>"de"</code>, <code>"en"</code>, <code>"en-AU"</code>, <code>"es"</code>, <code>"fa"</code>, <code>"fr"</code>, <code>"hu"</code>, <code>"it"</code>, <code>"ja"</code>, <code>"ko"</code>, <code>"nl"</code>, <code>"pl"</code>, <code>"pt-br"</code>, <code>"ro"</code>, <code>"ru"</code>, <code>"sv"</code>, <code>"tr"</code>, <code>"uk"</code>, <code>"vi"</code>, <code>"zh-Hans"</code>, and <code>"zh-Hant"</code>.</p><p>Default is <code>"en"</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>LocalizationSettings</code> > <code>DefaultClientLocale</code></li><li>Environment variable: <code>MM_LOCALIZATIONSETTINGS_DEFAULTCLIENTLOCALE</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Changing this configuration setting changes the default client language for users who haven't set a language preference via **Settings**. Mattermost applies the user's language preference when specified. + +</Note> + +### Available languages + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Sets the list of languages users see under <strong>Settings > Display > Language</strong>. If this field is left blank, users see all supported languages. Newly supported languages are added automatically. If this field is not blank, it must contain the <strong>Default client language</strong>, in addition to any other languages. For example, to limit the language choices to US English and Español (es), the string would be <code>"en,es"</code>.</p><p>Options: <code>"bg"</code>, <code>"de"</code>, <code>"en"</code>, <code>"en-AU"</code>, <code>"es"</code>, <code>"fa"</code>, <code>"fr"</code>, <code>"hu"</code>, <code>"it"</code>, <code>"ja"</code>, <code>"ko"</code>, <code>"nl"</code>, <code>"pl"</code>, <code>"pt-br"</code>, <code>"ro"</code>, <code>"ru"</code>, <code>"sv"</code>, <code>"tr"</code>, <code>"uk"</code>, <code>"vi"</code>, <code>"zh-Hans"</code>, and <code>"zh-Hant"</code>.</p><p>Default is <code>"en"</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>LocalizationSettings</code> > <code>AvailableLocales</code></li><li>Environment variable: <code>MM_LOCALIZATIONSETTINGS_AVAILABLELOCALES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable experimental locales + +Enable work in progress languages in Mattermost to review translations and identify translation gaps. + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Work in progress languages are available in Mattermost in addition to officially supported languages.</li><li><strong>false</strong>: <strong>(Default)</strong> Only officially supported languages are available in Mattermost.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>LocalizationSettings</code> > <code>EnableExperimentalLocales</code> > <code>false</code></li><li>Environment variable: <code>MM_LOCALIZATIONETTINGS_ENABLEEXPERIMENTALLOCALES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Cloud system admins can request this configuration setting to be enabled for their instance by contacting their Mattermost Account Manager. +- Work in progress languages may be incomplete. Strings missing translations display in US English. +- Currently, only web and desktop app product strings are impacted by this configuration setting. Server and mobile product strings aren't impacted by this setting. +- See the [language](/end-user-guide/preferences/manage-your-display-options#language) documentation for details on selecting a language preference in Mattermost. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Auto-translation + +<PlanAvailability slug="ent-adv" /> + +Access the following configuration settings in the System Console by going to **Site Configuration \> Localization**. These settings configure automatic translation of channel messages. See the [Auto-translation setup guide](/administration-guide/manage/admin/autotranslation) for deployment details. + +### Enable auto-translation + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable automatic translation of channel messages.</p><ul><li><strong>true</strong>: Autotranslation is available and can be enabled per channel.</li><li><strong>false</strong>: <strong>(Default)</strong> Autotranslation is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>Enable</code> > <code>false</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_ENABLE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Translation provider + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The translation provider to use for autotranslation.</p><ul><li><code>libretranslate</code>: Use a self-hosted LibreTranslate server for translations.</li><li><code>agents</code>: Use the Mattermost Agents plugin with an LLM backend for translations.</li></ul><p>Default is <code>""</code> (no provider selected).</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>Provider</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_PROVIDER</code></li></ul></td> +</tr> +</tbody> +</table> + +### LibreTranslate URL + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The URL of the LibreTranslate server used for translations. The Mattermost server must be able to reach this URL.</p><p>String value.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>LibreTranslate</code> > <code>URL</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_LIBRETRANSLATE_URL</code></li></ul></td> +</tr> +</tbody> +</table> + +### LibreTranslate API key + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The API key for authenticated access to the LibreTranslate server. Leave blank if the LibreTranslate server doesn't require authentication.</p><p>String value.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>LibreTranslate</code> > <code>APIKey</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_LIBRETRANSLATE_APIKEY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Agents LLM service ID + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The service ID of the LLM configured in the Mattermost Agents plugin to use for translations. Configure LLM services in the Agents plugin settings.</p><p>String value.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>Agents</code> > <code>LLMServiceID</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_AGENTS_LLMSERVICEID</code></li></ul></td> +</tr> +</tbody> +</table> + +### Languages allowed + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The languages that all messages in autotranslation-enabled channels are translated into. Every message is translated into each language in this list, regardless of who is in the channel. Specify languages as an array of language codes.</p><p>Default is <code>["en"]</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>TargetLanguages</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_TARGETLANGUAGES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Translation timeout + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum time in milliseconds to wait for a translation to complete. If a translation exceeds this timeout, it is skipped.</p><p>Numerical value. Default is <strong>5000</strong> (5 seconds).</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>TimeoutMs</code> > <code>5000</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_TIMEOUTMS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Restrict autotranslation in direct and group messages + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '59%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Restrict autotranslation from being enabled in direct and group messages.</p><ul><li><strong>true</strong>: Autotranslation can't be enabled in direct or group messages.</li><li><strong>false</strong>: <strong>(Default)</strong> Autotranslation can be enabled in direct and group messages.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Localization</strong></li><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>RestrictDMAndGM</code> > <code>false</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_RESTRICTDMANDGM</code></li></ul></td> +</tr> +</tbody> +</table> + +### Translation workers + +<table> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '57%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of concurrent translation workers per node. Higher values increase translation throughput but use more resources. This setting is not available in the System Console and can only be set via <code>mmctl</code>, <code>config.json</code>, or environment variable.</p><p>Numerical value. Default is <strong>6</strong>.</p></td> +<td><ul><li><code>config.json</code> setting: <code>AutoTranslationSettings</code> > <code>Workers</code> > <code>6</code></li><li>Environment variable: <code>MM_AUTOTRANSLATIONSETTINGS_WORKERS</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Users and teams + +Access the following configuration settings in the System Console by going to **Site Configuration \> Users and Teams**. + +### Max users per team + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>The <strong>Max users per team</strong> is the maximum total number of users per team, | - System Config path: <strong>Site Configuration > Users and Teams</strong> | including activated and deactivated users. | - <code>config.json</code> setting: <code>TeamSettings</code> > <code>MaxUsersPerTeam</code> > <code>50</code> | | - Environment variable: <code>MM_TEAMSETTINGS_MAXUSERSPERTEAM</code> | In Mattermost, a team of people should be a small organization with a | | specific goal. In the physical world, a team could sit around a single | | table. The default maximum (50) should be enough for most teams, but | | with appropriate <a href="https://docs.mattermost.com/install/ | |software-hardware-requirements.html">hardware</a>, this limit can be increased to | | thousands of users. | | | | <a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fcollaborate-within-channels">Channels</a> | are another way of organizing communications within teams on various topics. | | | | Numerical input. Default is <strong>50</strong> self-hosted deployments, and <strong>10000</strong> | | for Cloud deployments. | |</td> +</tr> +</tbody> +</table> + +### Max channels per team + +<table> +<colgroup> +<col style={{width: '51%'}} /> +<col style={{width: '48%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of channels per team, including both active and archived channels.</p><p>Numerical input. Default is <strong>2000</strong> for self-hosted deployments, and <strong>10000</strong> for Cloud deployments.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>MaxChannelsPerTeam</code> > <code>2000</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_MAXCHANNELSPERTEAM</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable join/leave messages by default + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify the default configuration of system messages displayed when users join or leave channels.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Join/Leave messages are displayed.</li><li><strong>false</strong>: Join/Leave messages are hidden.</li></ul><p>Users can override this default by going to <strong>Settings > Advanced > Enable Join/Leave Messages</strong>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableJoinLeaveMessageByDefault</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLEJOINLEAVEMESSAGEBYDEFAULT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable users to open direct message channels with + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>This setting determines whether a user can open a direct message channel with anyone on the Mattermost server or only to members of the same team. This setting only affects the options presented in the user interface. It does not affect permissions on the backend server. | - System Config path: <strong>Site Configuration > Users and Teams</strong> |</dt><dd><div class="line-block">- <code>config.json</code> setting: <code>TeamSettings</code> > <code>RestrictDirectMessage</code>|</div></dd><dt>- <strong>Any user on the Mattermost server</strong>: <strong>(Default)</strong> Users can send a direct message to any user through the <strong>Direct Messages > More</strong> menu. <code>config.json</code> setting: <code>"any"</code> | - Environment variable: <code>MM_TEAMSETTINGS_RESTRICTDIRECTMESSAGE</code> |</dt><dd><div class="line-block">                                                                       |</div></dd></dl><ul><li><strong>Any member of the team</strong>: The <strong>Direct Messages > More</strong> menu only allows direct messages to users on the same team. Pressing <a href="mm-kbd:">Ctrl</a> <a href="mm-kbd:">K</a> on Windows or Linux, or <a href="mm-kbd:">⌘</a> <a href="mm-kbd:">K</a> on Mac, only lists other users on the team currently being viewed. A user who is a member of multiple teams can only send direct messages to the team that is being viewed. However, the user can receive messages from other teams, regardless of the team currently being viewed. <code>config.json</code> setting: <code>"team"</code> |</li></ul></td> +</tr> +</tbody> +</table> + +### Teammate name display + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td>This setting determines how names appear in posts and under the <strong>Direct Messages</strong> list. | - System Config path: <strong>Site Configuration > Users and Teams</strong> | Users can change this setting in their interface under <strong>Settings > Display > | - ``config.json`` setting: ``TeamSettings`` > ``TeammateNameDisplay`` > ``username`` | Teammate Name Display</strong>, unless this setting is locked by a system admin | - Environment variable: <code>MM_TEAMSETTINGS_TEAMMATENAMEDISPLAY</code> | via the <strong>Lock teammate name display for all users</strong> configuration setting. | | | | - <strong>Show username</strong>: <strong>(Default for self-hosted deployments)</strong> Displays usernames. | | <code>config.json</code> option: <code>"username"</code>. | | - <strong>Show nickname if one exists...</strong>: Displays the user's nickname. If the user doesn't have a | | nickname, their full name is displayed. If the user doesn't have a full name, their username | | is displayed. <code>config.json</code> option: <code>"nickname_full_name"</code>. | | - <strong>Show first and last name</strong>: <strong>(Default for Cloud deployments)</strong> Displays user's full name. | | If the user doesn't have a full name, their username is displayed. Recommended when using | | <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fsso-saml">SAML</a> or | <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fad-ldap">LDAP</a> if first name and last name | attributes are configured. <code>config.json</code> option: <code>"full_name"</code>. | |</td> +</tr> +</tbody> +</table> + +### Lock teammate name display for all users + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>This setting controls whether users can change settings under <strong>Settings > Display > Teammate Name Display</strong>.</p><ul><li><strong>true</strong>: Users <strong>cannot</strong> change the Teammate Name Display.</li><li><strong>false</strong>: <strong>(Default)</strong> Users can change the Teammate Name Display setting.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>LockTeammateNameDisplay</code> > <code>false</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_LOCKTEAMMATENAMEDISPLAY</code></li></ul></td> +</tr> +</tbody> +</table> + +### Allow users to view archived channels + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows users to access the content of archived channels of which they were a member.</li><li><strong>false</strong>: Users are unable to access content in archived channels.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>ExperimentalViewArchivedChannels</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_EXPERIMENTALVIEWARCHIVEDCHANNELS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- From Mattermost v11, this configuration setting is always enabled and no longer configurable. Users can always access archived channels where they are members. - Cloud admins can't modify this configuration setting. + +</Note> + +### Show email address + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> All users can see the email addresses of every other user.</li><li><strong>false</strong>: Hides email addresses in the client user interface, except from system admins and the System Roles with read/write access to Compliance, Billing, or User Management (users/teams/channels/groups etc).</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and teams</strong></li><li><code>config.json</code> setting: <code>PrivacySettings</code> > <code>ShowEmailAddress</code> > <code>true</code></li><li>Environment variable: <code>MM_PRIVACYSETTINGS_SHOWEMAILADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Show full name + +<table> +<colgroup> +<col style={{width: '59%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Full names are visible to all users in the client user interface.</li><li><strong>false</strong>: Hides full names from all users, except system admins. Username is shown in place of the full name.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>PrivacySettings</code> > <code>ShowFullName</code> > <code>true</code></li><li>Environment variable: <code>MM_PRIVACYSETTINGS_SHOWFULLNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable anonymous team and channel URLs + +<PlanAvailability slug="ent-adv" /> + +<table> +<colgroup> +<col style={{width: '59%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>From Mattermost v11.6.0, when enabled, team and channel URLs are anonymized, meaning the URL no longer contains the team or channel name. This prevents team and channel names from being identified through web addresses.</p><p>When this setting is enabled, the team and channel creation workflows no longer include a step for users to define a URL; teams and channels are created with an automatically generated anonymous URL. This applies only to newly created teams and channels; existing teams and channels are not affected.</p><ul><li><strong>true</strong>: Team and channel URLs are anonymized.</li><li><strong>false</strong>: Team and channel URLs include the team or channel name.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>PrivacySettings</code> > <code>UseAnonymousURLs</code></li><li>Environment variable: <code>MM_PRIVACYSETTINGS_USEANONYMOUSURLS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable custom user statuses + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users can set status messages and emojis that are visible to all users.</li><li><strong>false</strong>: Users cannot set custom statuses.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableCustomUserStatuses</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLECUSTOMUSERSTATUSES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable last active time + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users can see when deactivated users were last active on a user's profile and in direct message channel headers.</li><li><strong>false</strong>: Users can't see when deactivated users were last online.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableLastActiveTime</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLELASTACTIVETIME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable custom user groups + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users with appropriate permissions can create custom user groups, and users can @mention custom user groups in Mattermost conversations.</li><li><strong>false</strong>: Custom user groups cannot be created.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableCustomGroups</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLECUSTOMGROUPS</code></li></ul></td> +</tr> +</tbody> +</table> + +### User statistics update time + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Set the server time for updating the user post statistics, including each user's total message count, and the timestamp of each user's most recently sent message.</p><p>Must be a 24-hour time stamp in the form <code>HH:MM</code> based on the local time of the server. Default is <strong>00:00</strong>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Users and Teams</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>RefreshPostStatsRunTime</code> > <code>00:00</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_REFRESHPOSTSTATSRUNTIME</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Notifications + +Access the following configuration settings in the System Console by going to **Site Configuration \> Notifications**. + +### Show @channel, @all, or @here confirmation dialog + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '39%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Requires users to confirm when posting @channel, @all, @here, or group mentions in channels with more than 5 members.</li><li><strong>false</strong>: No confirmation is required.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>TeamSettings</code> > <code>EnableConfirmNotificationsToChannel</code> > <code>true</code></li><li>Environment variable: <code>MM_TEAMSETTINGS_ENABLECONFIRMNOTIFICATIONSTOCHANNEL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable email notifications + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables automatic email notifications for posts.</li><li><strong>false</strong>: Disables notifications. A developer may choose this option to speed development by skipping email setup (see also the <strong>Enable preview mode banner</strong> setting).</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>SendEmailNotifications</code> > <code>ture</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_SENDEMAILNOTIFICATIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- Cloud admins can't modify this configuration setting. - If this setting is **false**, and the SMTP server is set up, account-related emails (such as authentication messages) will be sent regardless of this setting. - Email invitations and account deactivation emails aren't affected by this setting. - If you don't plan on [configuring Mattermost for email](/administration-guide/configure/smtp-email), disabling this configuration setting in larger deployments may improve server performance in the following areas, particularly in high-traffic environments where performance is a key concern: + +- **Reduced Server Load**: Generating and sending emails requires processing power and resources. By disabling email notifications, you reduce the load on the server, which can be reallocated to other tasks. +- **Decreased I/O Operations**: Sending emails involves input/output (I/O) operations, such as writing to logs and databases, and handling communication with the email server. Reducing these I/O operations can improve overall system efficiency. +- **Lowered Network Traffic**: Each email sent contributes to network traffic. Disabling email notifications decreases the amount of data being transmitted, which can lead to better performance, especially in environments with limited bandwidth. +- **Faster Response Times**: With fewer background tasks (like sending emails) to handle, the application can potentially respond to user requests more quickly, improving perceived performance. +- **Resource Allocation**: Resources like CPU cycles, memory, and network bandwidth that would have been used for sending emails can be used elsewhere, possibly improving the performance of other critical components of the system. +- However, disabling email notifications can negatively impact user experience, communication efficiency, and overall productivity. It's important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable preview mode banner + +<table> +<colgroup> +<col style={{width: '66%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> When <strong>Send email notifications</strong> is <strong>false</strong>, users see the Preview Mode banner. This banner alerts users that email notifications are disabled.</li><li><strong>false</strong>: Preview Mode banner does not appear.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnablePreviewModeBanner</code> > <code>true</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLEPREVIEWMODEBANNER</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Enable email batching + +<table> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '50%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Multiple email notifications for mentions and direct messages over a given time period are batched into a single email.</li><li><strong>false</strong>: <strong>(Default)</strong> Email notifications are sent for each mention or direct message.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EnableEmailBatching</code> > <code>false</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_ENABLEEMAILBATCHING</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- Cloud admins can't modify this configuration setting. +- The [Site Url](/administration-guide/configure/environment-configuration-settings#site-url) and [SMTP Email Server](/administration-guide/configure/environment-configuration-settings#smtp-server) must be configured to allow email batching. +- Regardless of how this setting is configured, users can [disable email-based notifications altogether](/end-user-guide/preferences/manage-your-notifications#email-notifications). +- When email batching is enabled, users can [customize how often to receive batched notifications](/end-user-guide/preferences/manage-your-notifications#email-notifications). The default frequency is 15 minutes. +- Email batching in [High Availability Mode](/administration-guide/configure/environment-configuration-settings#enable-high-availability-mode) is planned, but not yet supported. + +</Note> + +### Email notification contents + +<PlanAvailability slug="ent-plus" /> + +<table> +<colgroup> +<col style={{width: '77%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>Send full message contents</strong>: <strong>(Default)</strong> Email notifications include the full message contents, along with the name of the sender and the channel. <code>config.json</code> setting: <code>"full"</code></li><li><strong>Send generic description with only sender name</strong>: Only the name of the sender and team name are included in email notifications. Use this option if Mattermost contains confidential information and policy dictates it cannot be stored in email. <code>config.json</code> setting: <code>"generic"</code></li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>EmailNotificationContentsType</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_EMAILNOTIFICATIONCONTENTSTYPE</code></li></ul></td> +</tr> +</tbody> +</table> + +### Notification display name + +<table> +<colgroup> +<col style={{width: '60%'}} /> +<col style={{width: '39%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Display name for email notifications sent from the Mattermost system.</p><p>String input. No default setting. This field is required when changing settings in the System Console.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>FeedbackName</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_FEEDBACKNAME</code></li></ul></td> +</tr> +</tbody> +</table> + +### Notification from address + +<table> +<colgroup> +<col style={{width: '63%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Email address for notification emails from the Mattermost system. This address should be monitored by a system admin.</p><p>String input. Default is <code>test@example.com</code>. This field is required when changing settings in the System Console.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>FeedbackEmail</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_FEEDBACKEMAIL</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Cloud admins can't modify this configuration setting. + +</Note> + +### Support email address + +<table> +<colgroup> +<col style={{width: '80%'}} /> +<col style={{width: '19%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Sets a user support (or feedback) email address that is displayed on email notifications and during the Getting Started tutorial. This address should be monitored by a system admin. If no value is set, email notifications will not contain a way for users to request assistance.</p><p>String input. Default is <code>feedback@mattermost.com</code>. This field is required when changing settings in the System Console.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>SupportSettings</code> > <code>SupportEmail</code></li><li>Environment variable: <code>MM_SUPPORTSETTINGS_SUPPORTEMAIL</code></li></ul></td> +</tr> +</tbody> +</table> + +### Notification reply-to address + +<table> +<colgroup> +<col style={{width: '69%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Email address used in the reply-to header when sending notification emails from the Mattermost system. This address should be monitored by a system admin.</p><p>String input. Default is <code>test@example.com</code>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>ReplyToAddress</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_REPLYTOADDRESS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Notification footer mailing address + +<table> +<colgroup> +<col style={{width: '65%'}} /> +<col style={{width: '34%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Optional setting to include the organization's name and mailing address in the footer of email notifications. If not set, nothing will appear.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>FeedbackOrganization</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_FEEDBACKORGANIZATION</code></li></ul></td> +</tr> +</tbody> +</table> + +### Push notification contents + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><p><strong>Generic description with only sender name</strong>: Push notifications include the sender's name, but not the channel name or message contents. <code>config.json</code> setting: <code>"generic_no_channel"</code></p></li><li><p><strong>Generic description with sender and channel names</strong>: <strong>(Default)</strong> Push notifications include the name of the sender and channel, but not the message contents. <code>config.json</code> setting: <code>"generic"</code></p></li><li><p><strong>Full message content sent in the notification payload</strong>: Includes the message contents in the push notification payload, which may be sent through <a href="https://developer.apple.com/documentation/usernotifications">Apple's Push Notification service</a> or <a href="https://firebase.google.com/docs/cloud-messaging">Google's Firebase Cloud Messaging</a> . We <strong>highly recommended</strong> this option only be used with an <code>https</code> protocol to encrypt the connection and protect confidential information. <code>config.json</code> setting: <code>"full"</code></p></li><li><p><strong>Full message content fetched from the server on receipt</strong> (<em>Available in Mattermost Enterprise</em>): The notification payload contains no message content. Instead it contains a unique message ID used to fetch message content from the Mattermost server when a push notification is received via a <a href="https://developer.apple.com/documentation/usernotifications/modifying-content-in-newly-delivered-notifications">notification service app extension</a> on iOS or <a href="https://developer.android.com/develop/ui/views/notifications/expanded">an expandable notification pattern</a> on Android.</p><p>If the server cannot be reached, a generic push notification is displayed without message content or sender name. For customers who wrap the Mattermost mobile application in a secure container, the container must fetch the message contents using the unique message ID when push notifications are received.</p><p>If the container is unable to execute the fetch, the push notification contents cannot be received by the customer's mobile application without passing the message contents through Apple's or Google's notification service. <code>config.json</code> setting: <code>"id_loaded"</code></p></li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Notifications</strong></li><li><code>config.json</code> setting: <code>EmailSettings</code> > <code>PushNotificationContents</code></li><li>Environment variable: <code>MM_EMAILSETTINGS_PUSHNOTIFICATIONCONTENTS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable notification monitoring + +<table> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '67%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable notification metrics data collection.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Mattermost notification data collection is enabled for client-side web and desktop app users.</li><li><strong>false</strong>: Mattermost notification data collection is disabled.</li></ul></td> +<td><ul><li>System Config path: <strong>Environment > Performance Monitoring</strong></li><li><code>config.json</code> setting: <code>MetricsSettings</code> > <code>EnableNotificationMetrics</code> > <code>true</code></li><li>Environment variable: <code>MM_METRICSSETTINGS_ENABLENOTIFICATIONMETRICS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +See the [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring#getting-started) documentation to learn more about Mattermost Notification Health metrics. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## System-wide notifications + +<PlanAvailability slug="all-commercial" /> + +Access the following configuration settings in the System Console by going to **Site Configuration \> System-wide notifications**. + +### Enable system-wide notifications + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '36%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enable system-wide notifications to display at the top of the Mattermost interface for all users across all teams.</li><li><strong>false</strong>: <strong>(Default)</strong> Disable system-wide notifications.</li></ul></td> +<td colspan="2"><ul><li>System Config path: <strong>Site Configuration > System-wide notifications</strong></li><li><code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>SystemWideNotifications</code> > <code>false</code></li><li>Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_SYSTEMWIDENOTIFICATIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Banner text + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '42%'}} /> +<col style={{width: '24%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The text of the system-wide notification, when enabled.</p><p>String input.</p></td> +<td colspan="2"><ul><li>System Config path: <strong>Site Configuration > System-wide notifications</strong></li><li><code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>BannerText</code></li><li>Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_BANNERTEXT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Banner color + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The background color of system-wide notifications.</p><p>String input of a CSS color value.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > System-wide notifications</strong></li><li><code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>BannerColor</code> > <code>"#f2a93b"</code></li><li>Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_BANNERCOLOR</code></li></ul></td> +</tr> +</tbody> +</table> + +### Banner text color + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The color of the text in system-wide notifications.</p><p>String input of a CSS color value.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > System-wide notifications</strong></li><li><code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>BannerTextColor</code> > <code>"#333333"</code></li><li>Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_BANNERTEXTCOLOR</code></li></ul></td> +</tr> +</tbody> +</table> + +### Allow banner dismissal + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '54%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users can dismiss the system-wide notification. It will re-appear the next time the user logs in, and when the text is updated by an admin, or when an admin disables system-wide notifications and reenables them.</li><li><strong>false</strong>: Users cannot dismiss the banner.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > System-wide notifications</strong></li><li><code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>AllowBannerDismissal</code> > <code>true</code></li><li>Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_ALLOWBANNERDISMISSAL</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Emoji + +Access the following configuration settings in the System Console by going to **Site Configuration \> Emoji**. + +### Enable emoji picker + +<table> +<colgroup> +<col style={{width: '55%'}} /> +<col style={{width: '44%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables an emoji picker when composing messages and for message reactions.</li><li><strong>false</strong>: Disables the emoji picker in message composition and reactions.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Emoji</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableEmojiPicker</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEEMOJIPICKER</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable custom emoji + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows users to add up to 6000 emojis through a <strong>Custom Emoji</strong> option in the emoji picker. Emojis can be GIF, PNG, or JPG files up to 512 KB in size.</li><li><strong>false</strong>: Disables custom emojis.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Emoji</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableCustomEmoji</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLECUSTOMEMOJI</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +While Mattermost supports up to 6000 custom emojis, an increase in custom emojis can slow your server's performance. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Posts + +Access the following configuration settings in the System Console by going to **Site Configuration \> Posts**. + +### Automatically follow threads + +<table> +<colgroup> +<col style={{width: '54%'}} /> +<col style={{width: '45%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables automatic following for all threads that a user starts, or in which the user participates or is mentioned. A <strong>Threads</strong> table in the database tracks threads and thread participants. A <strong>ThreadMembership</strong> table tracks followed threads for each user and whether the thread is read or unread.</li><li><strong>false</strong>: Disables automatic following of threads.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>ThreadAutoFollow</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_THREADAUTOFOLLOW</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +\- This setting is applicable to self-hosted deployments only. - This setting **must** be enabled for [threaded discussions](/end-user-guide/collaborate/organize-conversations) to function. - Enabling this setting does not automatically follow threads based on previous user actions. For example, threads a user participated in prior to enabling this setting won't be automatically followed, unless the user adds a new comment or is mentioned in the thread. + +</Note> + +### Threaded discussions + +<Important> + +Customers upgrading from a legacy Mattermost release prior to v7.0 must review the [administrator's guide to enabling threaded discussions](https://support.mattermost.com/hc/en-us/articles/6880701948564-Administrator-s-guide-to-enabling-Collapsed-Reply-Threads) (formerly known as Collapsed Reply Threads) prior to enabling this functionality. + +</Important> + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><dl><dt>- <strong>Always On</strong>: <strong>(Default)</strong> Enables <a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Forganize-conversations">threaded discussions | - System Config path: **Site Configuration > Posts** |</a> | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>CollapsedThreads</code></dt><dd><p>on the server and for all users. This is the recommended configuration for optimal user experience | - Environment variable: <code>MM_SERVICESETTINGS_COLLAPSEDTHREADS</code> | and to ensure consistency in how users read and respond to threaded conversations. | | <code>config.json</code> setting: <code>"always_on"</code> | |</p></dd></dl><ul><li><strong>Default On</strong>: Enables threaded discussions on the server and for all users. | |</li><li><strong>Default Off</strong>: Enables threaded discussions on the server but <strong>not</strong> for users. | |</li><li><strong>Disabled</strong>: Users cannot enable threaded discussions. <code>config.json</code> setting: <code>"disabled"</code> | |</li></ul></td> +</tr> +</tbody> +</table> + +### Message priority + +<Tip> + +[Mattermost Enterprise or Professional](https://mattermost.com/pricing) customers can additionally request message acknowledgements to track that specific, time-sensitive messages have been seen and actioned. See the [message priority](/end-user-guide/collaborate/message-priority) documentation to learn more. + +</Tip> + +<table> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables message priority for all users which enables them to set a visual indiciator for important or urgent root messages.</li><li><strong>false</strong>: Disables the ability to set message priority and request acknowledgements.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>PostPriority</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_POSTPRIORITY</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas, particularly in environments where performance and responsiveness are critical: + +- Simplified Processing: When post priority is enabled, the system has to manage and prioritize posts based on their designated priority levels. This adds additional processing overhead as the system must evaluate and sort posts accordingly. By disabling this feature, all posts are treated equally, which simplifies the processing logic and reduces the computational load. +- Reduced Latency: With post priority enabled, there might be delays introduced while the system determines the priority of each post and processes them in the correct order. Disabling post priority can lead to more consistent and potentially quicker handling of posts because the system processes them on a first-come, first-served basis. +- Lower Resource Utilization: Managing post priorities can consume additional system resources such as CPU and memory. Disabling this feature can free up these resources, allowing the system to allocate them to other tasks, thereby improving overall performance. +- Improved Scalability: In a high-traffic environment, the complexity of managing post priorities can become more pronounced. Disabling this feature simplifies the system's operations, making it easier to scale as the number of users and posts increases. + +</Note> + +### Persistent notifications + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users can trigger repeating notifications to mentioned recipients of urgent messages.</li><li><strong>false</strong>: Disables the ability to send repeating notifications.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>AllowPersistentNotifications</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ALLOWPERSISTENTNOTIFICATIONS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum number of recipients for persistent notifications + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of recipients users may send persistent notifications to.</p><p>Numerical input. Default is <strong>5</strong>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>PersistentNotificationMaxRecipients</code> > <code>5</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_PERSISTENTNOTIFICATIONMAXRECIPIENTS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Frequency of persistent notifications + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of minutes between repeated notifications for urgent messages sent with persistent notifications.</p><p>Numerical input. Default is <strong>5</strong>. Minimum is <strong>2</strong>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>PersistentNotificationIntervalMinutes</code> > <code>5</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_PERSISTENTNOTIFICATIONINTERVALMINUTES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Total number of persistent notifications per post + +<table> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of times users may receive persistent notifications.</p><p>Numerical input. Default is <strong>6</strong>.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>PersistentNotificationMaxCount</code> > <code>6</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_PERSISTENTNOTIFICATIONMAXCOUNT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable burn-on-read messages + +<PlanAvailability slug="entry-adv" /> + +[Burn-on-read messages](/end-user-guide/collaborate/send-messages#send-burn-on-read-messages) have irreversible behavior: + +- Once a recipient reveals a burn-on-read message, it can't be hidden again. +- Once a burn-on-read message expires or is burned, it is permanently deleted and can't be recovered. +- Recipients can't reply to, edit, or thread burn-on-read messages. + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable burn-on-read messages.</p><ul><li><strong>false</strong>: <strong>(Default)</strong> The option to send a burn-on-read message isn't available.</li><li><strong>true</strong>: Users can send burn-on-read messages in channels, direct messages, and group messages.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableBurnOnRead</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLEBURNONREAD</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this feature prevents users from sending new burn-on-read messages. Once disabled, users can interact with existing burn-on-read messages. + +</Note> + +### Burn-on-read duration + +<PlanAvailability slug="entry-adv" /> + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Sets the countdown duration for burn-on-read messages once they are revealed. After a recipient reveals a burn-on-read message, the message is deleted for that user after the specified duration. This setting applies to all burn-on-read messages.</p><p>Numerical input in seconds. Default is <strong>600</strong> seconds (10 minutes).</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>BurnOnReadDurationSeconds</code> > <code>600</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_BURNONREADDURATIONSECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum time to live for burn-on-read messages + +<PlanAvailability slug="entry-adv" /> + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Sets the maximum duration that burn-on-read messages can exist after they are sent. The message is deleted after the specified duration, even if it hasn't been revealed by all recipients.</p><p>Numerical input in seconds. Default is <strong>604800</strong> seconds (7 days).</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>BurnOnReadMaximumTimeToLiveSeconds</code> > <code>604800</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_BURNONREADMAXIMUMTIMETOLIVESECONDS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable website link previews + +<Important> + +The server must be connected to the internet to generate previews. This connection can be established through a [firewall or outbound proxy](/deployment-guide/server/preparations#outbound-proxy-configuration) if necessary. + +</Important> + +<table> +<colgroup> +<col style={{width: '73%'}} /> +<col style={{width: '26%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: The server generates a preview of the first website, image, or YouTube video linked in a message. Users can disable website previews, but not image or YouTube previews, under <strong>Settings > Display > Website Link Previews</strong>.</li><li><strong>false</strong>: <strong>(Default)</strong> All previews are disabled and the server does not request metadata for any links contained in messages.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableLinkPreviews</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLELINKPREVIEWS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas: + +- Reduced Network Requests: When link previews are enabled, the system needs to fetch metadata (such as title, description, or image) from the linked webpage. This requires additional network requests, which can slow down the system. +- Lower Server Load: Creating link previews involves parsing the content of the linked pages. If many users are sharing links, the server will have to perform numerous network requests and process a lot of additional data, increasing the load on the server. +- Less Data Processing: Every link shared needs to be processed to extract the necessary preview information. This processing consumes CPU and memory resources, which can otherwise be reserved for other tasks. +- Decreased Client-Side Rendering Time: On the client side, rendering link previews (adding text, images, and layouts) takes time and resources. Disabling link previews means that clients do not need to render these elements, leading to faster message display. +- Saved Bandwidth: Link previews often include images and other data from the linked content. By disabling them, you save the bandwidth that would be used to download these additional resources. +- However, disabling link previews can negatively impact user experience, communication efficiency, and overall productivity. It's important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Disable link previews for specific domains + +<table> +<colgroup> +<col style={{width: '57%'}} /> +<col style={{width: '42%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Use this setting to disable previews of links for specific domains.</p><p>String input of a comma-separated list of domains, for example: <code>"mattermost.com, images.example.com"</code></p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>RestrictLinkPreviews</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_RESTRICTLINKPREVIEWS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable message link previews + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> <a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fshare-links">Share links to Mattermost messages</a> | - System Config path: <strong>Site Configuration > Posts</strong> will generate a preview for any users that have access to the original message. | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnablePermalinkPreviews</code> > <code>true</code> |</li><li><strong>false</strong>: Share links do not generate a preview. | - Environment variable: <code>MM_SERVICESETTINGS_ENABLEPERMALINKPREVIEWS</code> |</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Disabling this configuration setting in larger deployments may improve server performance in the following areas, particularly in environments with high message throughput or limited resources: + +- Reduced Server Load: When permalink previews are enabled, the server has to generate preview summaries for each shared link. This generates additional requests to fetch metadata and may involve parsing web pages, which increases the processing load on the server. +- Less Data Transfer: Permalink previews include additional metadata such as images, titles, and descriptions. Disabling previews reduces the amount of data that needs to be transferred, which can decrease bandwidth usage and improve message load times, particularly for channels with a high volume of links. +- Faster Message Rendering: On the client-side, rendering messages with multimedia previews takes more time compared to plain text messages. Disabling previews can reduce rendering complexity and improve client performance, especially on devices with limited resources. +- Network Latency: Fetching metadata for link previews may introduce network latency, as the server must reach out to external resources. Disabling this can eliminate these delays, ensuring faster message processing and display. +- Simplified Message Handling: In the absence of previews, messages are simpler and less resource-intensive to store, retrieve, and display. This can contribute to overall improved system responsiveness and efficiency. +- However, disabling permalink previews can negatively impact user experience, communication efficiency, and overall productivity. It's important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Enable SVGs + +<table> +<colgroup> +<col style={{width: '50%'}} /> +<col style={{width: '49%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables previews of SVG files attached to messages.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables previews of SVG files.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableSVGs</code> > <code>false</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLESVGS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Warning> + +Enabling SVGs is not recommended in environments where not all users are trusted. + +</Warning> + +### Enable LaTeX code block rendering + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables rendering of <a href="mm-ref:end-user-guide%2Fcollaborate%2Fformat-messages%3Amath%20formulas">LaTeX in code blocks</a>. | - System Config path: <strong>Site Configuration > Posts</strong></li><li><dl><dt><strong>false</strong>: <strong>(Default)</strong> Disables rendering in blocks. Instead, LaTeX code is highlighted. | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableLatex</code> > <code>false</code>|</dt><dd><div class="line-block">- Environment variable: <code>MM_SERVICESETTINGS_ENABLELATEX</code> |</div></dd></dl></li></ul></td> +</tr> +</tbody> +</table> + +<Warning> + +Enabling LaTeX rendering is not recommended in environments where not all users are trusted. + +</Warning> + +### Enable inline LaTeX rendering + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables rendering of | - System Config path: <strong>Site Configuration > Posts</strong> | <a href="mm-ref:end-user-guide%2Fcollaborate%2Fformat-messages%3Amath%20formulas">LaTeX in message text</a>. | - <code>config.json</code> setting: <code>ServiceSettings</code> > <code>EnableInlineLatex</code> > <code>false</code></li><li><strong>false</strong>: <strong>(Default)</strong> Disables inline rendering of LaTeX. Instead, LaTeX in message text is highlighted. | - Environment variable: <code>MM_SERVICESETTINGS_ENABLEINLINELATEX</code> | LaTeX can also be rendered in a code block, if that feature is enabled. See <strong>Enable LaTeX code block rendering</strong>. | |</li></ul></td> +</tr> +</tbody> +</table> + +<Warning> + +Enabling LaTeX rendering isn't recommended in environments where not all users are trusted. + +</Warning> + +### Custom URL schemes + +<table> +<colgroup> +<col style={{width: '71%'}} /> +<col style={{width: '28%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>A list of URL schemes that will automatically create a link in message text, for example: <code>["git", "smtp"]</code>. These schemes always create links: <code>http</code>, <code>https</code>, <code>ftp</code>, <code>tel</code>, and <code>mailto</code>.</p><p><code>config.json</code> setting: an array of strings</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>DisplaySettings</code> > <code>CustomURLSchemes</code> > <code>[]</code></li><li>Environment variable: <code>MM_DISPLAYSETTINGS_CUSTOMURLSCHEMES</code></li></ul></td> +</tr> +</tbody> +</table> + +### Maximum Markdown nodes + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The maximum number of Markdown elements (such as emojis, links, or table cells), that can be included in a single piece of text in a message.</p><p>Numerical input. Default is <strong>0</strong> which applies a Mattermost-specified limit.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>DisplaySettings</code> > <code>MaxMarkdownNodes</code> > <code>0</code></li><li>Environment variable: <code>MM_DISPLAYSETTINGS_MAXMARKDOWNNODES</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This limit applies to all Mattermost clients, including web, desktop app, and mobile app. + +</Note> + +### Google API key + +<table> +<colgroup> +<col style={{width: '77%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>If a key is provided in this setting, Mattermost displays titles of embedded YouTube videos and detects if a video is no longer available. Setting a key should also prevent Google from throttling access to embedded videos that receive a high number of views.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>GoogleDeveloperKey</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_GOOGLEDEVELOPERKEY</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +- This setting is applicable to self-hosted deployments only. +- This key is used in client-side Javascript, and must have the YouTube Data API added as a service. + +</Note> + +### Enable server syncing of message drafts + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Enable or disable the ability to synchronize draft messages across all supported Mattermost clients.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Message drafts are saved on the server and may be accessed from different clients. Users may still disable server synchronization of draft messages by going to <strong>Settings > Advanced Settings</strong>.</li><li><strong>false</strong>: Draft messages are stored locally on each device.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>AllowSyncedDrafts</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ALLOWSYNCEDDRAFTS</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +While drafts can be very useful for maintaining work continuity, especially in collaborative environments, disabling draft synchronization across devices can lead to noticeable performance improvements by reducing the computational and data management overhead as follows: + +- Reduced Data Synchronization: When drafts are enabled and synchronized across devices, the system needs to handle those data synchronization operations which can consume significant bandwidth and computing resources. Disabling draft syncing reduces the load on servers and networks. +- Lower Storage Usage: Storing drafts requires additional database operations and storage space. Each draft is an extra piece of data that needs to be saved, managed, and retrieved. Without drafts, the system has fewer records to keep, which can streamline database operations. +- Decreased Client Processing: On the client side, draft management involves monitoring changes, saving drafts periodically, and handling conflict resolution if multiple drafts are edited from different devices. Disabling drafts reduces these client-side processes, thus freeing up memory and CPU resources. +- Simplified Architecture: Maintaining synced drafts often requires complex backend logic to ensure consistency and avoid data conflicts. Simplifying this architecture by removing draft syncing can lead to more efficient and faster backend operations. +- Improved User Experience: Users may experience faster load times and reduced latency without the overhead of draft syncing. This can be particularly noticeable in environments with limited or variable internet connectivity. +- However, disabling draft synchronization can negatively impact user experience, communication efficiency, and overall productivity. It's important to balance performance improvements with the needs of your organization and users. + +</Note> + +### Unique emoji reaction limit + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Limit the number of unique emoji reactions on each message. Increasing this limit can lead to poor client performance.</p><p>Numerical input. Default is <strong>50</strong>. Maximum is 500.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Posts</strong></li><li><code>config.json</code> setting: <code>ServiceSettings</code> > <code>UniqueEmojiReactionLimitPerPost</code> > <code>50</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_UNIQUEEMOJIREACTIONLIMITPERPOST</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Content flagging + +<PlanAvailability slug="entry-adv" /> + +Access the following configuration settings in the System Console by going to **Site Configuration \> Content Flagging**. + +### Enable content flagging + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Enables the Content Flagging feature.</li><li><strong>false</strong>: <strong>(Default)</strong> Disables the feature.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>EnableContentFlagging</code> > <code>false</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_ENABLECONTENTFLAGGING</code></li></ul></td> +</tr> +</tbody> +</table> + +### Notification settings + +<table> +<colgroup> +<col style={{width: '33%'}} /> +<col style={{width: '66%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Default notification recipients for each event:</p><ul><li>Events: flagged, assigned, removed, dismissed</li><li>Recipients: reviewers, author, reporter</li></ul><p>Default mappings include:</p><ul><li>flagged = reviewers</li><li>assigned = reviewers</li><li>removed = reviewers, author, reporter</li><li>dismissed = reviewers, reporter</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>NotificationSettings</code> > <code>EventTargetMapping</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Additional settings + +<table> +<colgroup> +<col style={{width: '35%'}} /> +<col style={{width: '64%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Specify the reasons for flagging.</p><p>Default reasons include:</p><ul><li>Inappropriate content</li><li>Sensitive data</li><li>Security concern</li><li>Harassment or abuse</li><li>Spam or phishing</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>AdditionalSettings</code> > <code>Reasons</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Require reporters to add comment + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Reporters must add a comment when flagging.</li><li><strong>false</strong>: Reporters aren't required to add a comment.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>AdditionalSettings</code> > <code>ReporterCommentRequired</code> > <code>true</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_ADDITIONALSETTINGS_REPORTERCOMMENTREQUIRED</code></li></ul></td> +</tr> +</tbody> +</table> + +### Require reviewers to add comment + +<table> +<colgroup> +<col style={{width: '36%'}} /> +<col style={{width: '63%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Reviewers must add a comment when reviewing flagged content.</li><li><strong>false</strong>: Reviewers aren't required to add a comment.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>AdditionalSettings</code> > <code>ReviewerCommentRequired</code> > <code>true</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_ADDITIONALSETTINGS_REVIEWERCOMMENTREQUIRED</code></li></ul></td> +</tr> +</tbody> +</table> + +### Hide message from channel while it is being reviewed + +<table> +<colgroup> +<col style={{width: '37%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Hide flagged content from the channel while under review.</li><li><strong>false</strong>: Keep flagged content visible while under review.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>AdditionalSettings</code> > <code>HideFlaggedContent</code> > <code>true</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_ADDITIONALSETTINGS_HIDEFLAGGEDCONTENT</code></li></ul></td> +</tr> +</tbody> +</table> + +### Same reviewers for all teams + +<table> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '67%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Use the same set of reviewers across all teams.</li><li><strong>false</strong>: Reviewers can be managed per team.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>ReviewerSettings</code> > <code>CommonReviewers</code> > <code>true</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_REVIEWERSETTINGS_COMMONREVIEWERS</code></li></ul></td> +</tr> +</tbody> +</table> + +### System administrators as reviewers + +<table> +<colgroup> +<col style={{width: '31%'}} /> +<col style={{width: '68%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Include system administrators as reviewers.</li><li><strong>false</strong>: <strong>(Default)</strong> System administrators are not included by default.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>ReviewerSettings</code> > <code>SystemAdminsAsReviewers</code> > <code>false</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_REVIEWERSETTINGS_SYSTEMADMINSASREVIEWERS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Team administrators as reviewers + +<PlanAvailability slug="entry-ent" /> + +<table> +<colgroup> +<col style={{width: '32%'}} /> +<col style={{width: '68%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Include team administrators as reviewers for their respective teams.</li><li><strong>false</strong>: Team administrators aren't included as reviewers.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > Content Flagging</strong></li><li><code>config.json</code> setting: <code>ContentFlaggingSettings</code> > <code>ReviewerSettings</code> > <code>TeamAdminsAsReviewers</code> > <code>true</code></li><li>Environment variable: <code>MM_CONTENTFLAGGINGSETTINGS_REVIEWERSETTINGS_TEAMADMINSASREVIEWERS</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## File sharing and downloads + +Access the following configuration settings in the System Console by going to **Site Configuration \> File Sharing and Downloads**. + +### Allow file sharing + +<table> +<colgroup> +<col style={{width: '64%'}} /> +<col style={{width: '35%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows users to attach files to messages.</li><li><strong>false</strong>: Prevents users from attaching files (including images) to a message. This affects users on all clients and devices, including mobile apps.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > File Sharing and Downloads</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>EnableFileAttachments</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_ENABLEFILEATTACHMENTS</code></li></ul></td> +</tr> +</tbody> +</table> + +### Allow file uploads on mobile + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Allows users to attach files to messages from mobile apps.</li><li><strong>false</strong>: Prevents users from attaching files (including images) to messages from mobile apps.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > File Sharing and Downloads</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>EnableMobileUpload</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_ENABLEMOBILEUPLOAD</code></li></ul></td> +</tr> +</tbody> +</table> + +### Allow file downloads on mobile + +<table> +<colgroup> +<col style={{width: '56%'}} /> +<col style={{width: '43%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables file downloads on mobile apps.</li><li><strong>false</strong>: Disables file downloads on mobile apps. Users can still download files from a mobile web browser.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > File sharing and downloads</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>EnableMobileDownload</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_ENABLEMOBILEDOWNLOAD</code></li></ul></td> +</tr> +</tbody> +</table> + +### Enable secure file preview on mobile + +<PlanAvailability slug="ent-adv" /> + +This setting improves an organization's mobile security posture by restricting file access while still allowing essential file viewing capabilities. + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Prevents file downloads, previews, and sharing for most file types, | - System Config path: <strong>Site Configuration > File sharing and downloads</strong> | even when the | - <code>config.json</code> setting: <code>FileSettings</code> > <code>MobileEnableSecureFilePreview</code> > <code>false</code> | <a href="mm-ref:administration-guide%2Fconfigure%2Fsite-configuration-settings%3Aallow%20file%20downloads%20on%20mobile">Allow file downloads on mobile</a> | - Environment variable: <code>MM_FILESETTINGS_MOBILEENABLESECUREFILEPREVIEW</code> configuration setting is enabled. Allows in-app previews for PDFs, | | videos, and images only. Files are stored temporarily in the app's cache and cannot be exported or shared. | |</li><li><strong>false</strong>: <strong>(Default)</strong> Secure file preview mode is disabled. | |</li></ul></td> +</tr> +</tbody> +</table> + +### Allow PDF link navigation on mobile + +<PlanAvailability slug="ent-adv" /> + +<table> +<colgroup> +<col style={{width: '44%'}} /> +<col style={{width: '55%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Enables tapping links inside PDFs when Secure File Preview Mode is active. Links will open in the device browser or supported app.</li><li><strong>false</strong>: Disables link navigation in PDFs when Secure File Preview Mode is active.</li></ul></td> +<td><ul><li>System Config path: <strong>Site Configuration > File sharing and downloads</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>MobileAllowPdfLinkNavigation</code> > <code>true</code></li><li>Environment variable: <code>MM_FILESETTINGS_MOBILEALLOWPDFLINKNAVIGATION</code></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +This setting has no effect when the [Secure file preview on mobile](/administration-guide/configure/site-configuration-settings#enable-secure-file-preview-on-mobile) configuration setting is disabled. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## Public Links + +With self-hosted deployments, you can access the following configuration settings in the System Console by going to **Site Configuration \> Public Links**. + +### Enable public file links + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Allows users to create <a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fshare-files-in-messages">public links</a> to files attached to Mattermost messages. | - System Config path: <strong>Site Configuration > Public Links</strong></li><li><dl><dt><strong>false</strong>: <strong>(Default)</strong> Prevents users from creating public links to files and disables all previously created links. | - <code>config.json</code> setting: <code>FileSettings</code> > <code>EnablePublicLink</code> > <code>false</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_FILESETTINGS_ENABLEPUBLICLINK</code> |</div></dd></dl></li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +When set to **false**, anyone who tries to visit a previously created public link will receive an error message. If the setting is returned to **true**, previously created links will be accessible, unless the **Public link salt** has been regenerated. + +</Note> + +### Public link salt + +<table> +<colgroup> +<col style={{width: '80%'}} /> +<col style={{width: '19%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>32-character salt added to the URL of public file links. Changing this setting will <strong>invalidate</strong> all previously generated links. The salt is randomly generated when Mattermost is installed, and can be regenerated by selecting <strong>Regenerate</strong> in the System Console.</p><p>String input.</p></td> +<td><ul><li>System Config path: <strong>Site Configuration > Public Links</strong></li><li><code>config.json</code> setting: <code>FileSettings</code> > <code>PublicLinkSalt</code></li><li>Environment variable: <code>MM_FILESETTINGS_PUBLICLINKSALT</code></li></ul></td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Notices + +Access the following configuration settings in the System Console by going to **Site Configuration \> Notices**. + +### Enable admin notices + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> System admins will receive <a href="mm-doc:%2Fadministration-guide%2Fmanage%2Fin-product-notices">in-product notices</a> about server upgrades and administration features. | - System Config path: <strong>Site Configuration > Notices</strong> - | - <code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>AdminNoticesEnabled</code> > <code>true</code> |</li><li><strong>false</strong>: System admins will not receive specific notices. Admins will still receive notices for all users (see <strong>Enable end user notices</strong>) | - Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_ADMINNOTICESENABLED</code> |</li></ul></td> +</tr> +</tbody> +</table> + +### Enable end user notices + +<table> +<colgroup> +<col style={{width: '100%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> All users receive <a href="mm-doc:%2Fadministration-guide%2Fmanage%2Fin-product-notices">in-product notices</a> about client upgrades and end user features. | - System Config path: <strong>Site Configuration > Notices</strong></li><li><dl><dt><strong>false</strong>: Users will not receive in-product notices. | - <code>config.json</code> setting: <code>AnnouncementSettings</code> > <code>UserNoticesEnabled</code> > <code>true</code> |</dt><dd><div class="line-block">- Environment variable: <code>MM_ANNOUNCEMENTSETTINGS_USERNOTICESENABLED</code> |</div></dd></dl></li></ul></td> +</tr> +</tbody> +</table> + +## Connected workspaces + +<PlanAvailability slug="entry-ent" /> + +The following settings aren't available in the System Console and can only be set in `config.json`. + +When connected workspaces are enabled, system admins can [create and manage connected workspaces](/administration-guide/onboard/connected-workspaces) in the System Console by going to **Site Configuration \> Connected Workspaces**. + +### Enable connected workspaces + +Enable the ability to establish secure connections between Mattermost instances, and invite secured connections to shared channels where users can participate as they would in any public and private channel. + +Connected workspaces requires Mattermost Enterprise servers running v10.2 or later. + +By default, both configuration settings are disabled and must be enabled in order to share channels with secure connections. Enabling connected workspace functionality requires a server restart. + +This feature's two `config.json` settings include: + +- `ConnectedWorkspacesSettings.EnableRemoteClusterService: false` with options `true` and `false`. +- `ConnectedWorkspacesSettings.EnableSharedChannels: false` with options `true` and `false`. + +<Note> + +- Neither setting is available in the System Console and can only be set in `config.json` under `ConnectedWorkspacesSettings`. +- System admins for Cloud deployments can submit a request to have these required configuration settings enabled for their Cloud deployment instance. +- Following an upgrade to Mattermost v10.2 or later, existing configuration values for shared channels, including `EnableSharedChannels` and `EnableRemoteClusterService` are automatically converted to connected workspace configuration settings in the `config.json` file. The [deprecated shared channels experimental settings](/administration-guide/configure/deprecated-configuration-settings#shared-channels-settings) remain in the `config.json` file to support backwards compatibility. + +</Note> + +### Disable shared channel status sync + +Disable member status and availability synchronization between connected workspaces. + +<table> +<colgroup> +<col style={{width: '52%'}} /> +<col style={{width: '47%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: Channel as well as member status and availability isn't synchronized.</li><li><strong>false</strong>: <strong>(Default)</strong> Channel as well as channel member status and availability is synchronized at regular intervals.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ConnectedWorkspacesSettings</code> > <code>DisableSharedChannelsStatusSync</code> > <code>false</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +### Default maximum posts per sync + +<table> +<colgroup> +<col style={{width: '43%'}} /> +<col style={{width: '56%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Define the default maximum number of mesages to synchronize at a time.</p><p>Default is <strong>50</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ConnectedWorkspacesSettings</code> > <code>DefaultMaxPostsPerSync</code> > <code>50</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +### Sync users on connection open + +Automatically synchronize users when a new connection between workspaces is established. This ensures that remote users are immediately discoverable for direct and group messages without requiring them to post in a shared channel first. + +<table> +<colgroup> +<col style={{width: '53%'}} /> +<col style={{width: '46%'}} /> +</colgroup> +<tbody> +<tr> +<td><ul><li><strong>true</strong>: <strong>(Default)</strong> Users are automatically synchronized when a new connection is established.</li><li><strong>false</strong>: Users are not automatically synchronized when a new connection is established.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ConnectedWorkspacesSettings</code> > <code>SyncUsersOnConnectionOpen</code> > <code>true</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +### Global user sync batch size + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of users to sync in each batch when performing global user synchronization between connected workspaces.</p><p>Default is <strong>100</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ConnectedWorkspacesSettings</code> > <code>GlobalUserSyncBatchSize</code> > <code>100</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +### Member sync batch size + +<table> +<colgroup> +<col style={{width: '41%'}} /> +<col style={{width: '58%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>The number of channel members to sync in each batch when synchronizing channel membership between connected workspaces.</p><p>Default is <strong>100</strong>.</p></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ConnectedWorkspacesSettings</code> > <code>MemberSyncBatchSize</code> > <code>100</code></li><li>Environment variable: N/A</li></ul></td> +</tr> +</tbody> +</table> + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +------------------------------------------------------------------------------------------------------------------------ + +## config.json-only settings + +The following self-hosted deployment settings are only configurable in the `config.json` file and are not available in the System Console. + +### Cross-team search + +<table> +<colgroup> +<col style={{width: '38%'}} /> +<col style={{width: '61%'}} /> +</colgroup> +<tbody> +<tr> +<td><p>Disable the ability to search across all teams or a specific team.</p><ul><li><strong>true</strong>: <strong>(Default)</strong> Cross-team search is enabled. Searches can be performed against all channels the user is a member of across all teams, a specific team, or the current team.</li><li><strong>false</strong>: Cross-team search is disabled. Searches are performed on all channels the user is member of within the current team only.</li></ul></td> +<td><ul><li>System Config path: N/A</li><li><code>config.json</code> setting: <code>ServiceSettings.EnableCrossTeamSearch</code> > <code>true</code></li><li>Environment variable: <code>MM_SERVICESETTINGS_ENABLECROSSTEAMSEARCH</code></li></ul></td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/configure/smtp-email.mdx b/docs/main/administration-guide/configure/smtp-email.mdx new file mode 100644 index 000000000000..16600a421844 --- /dev/null +++ b/docs/main/administration-guide/configure/smtp-email.mdx @@ -0,0 +1,171 @@ +--- +title: "SMTP email setup" +--- +<PlanAvailability slug="all-commercial" /> + +In a production environment, Mattermost requires SMTP email enabled for email notifications and password resets when using [email-based authentication](/administration-guide/configure/authentication-configuration-settings#enable-sign-in-with-email). + +## Set up an SMTP email service + +Any SMTP email service can be used. You need a copy of the following information: `Server Name`, `Port`, `SMTP Username`, and `SMTP Password`. + +<Tip> + +If you don't have an SMTP service you can set one up with [Amazon Simple Email Service (SES)](https://aws.amazon.com/ses/): + +1. Go to [Amazon SES console](https://console.aws.amazon.com/ses) then **SMTP Settings \> Create My SMTP Credentials**. +2. Copy the `Server Name`, `Port`, `SMTP Username`, and `SMTP Password` values. You'll need these values to configure Mattermost. +3. From the `Domains` menu, set up and verify a new domain, then enable `Generate DKIM Settings` for the domain. We recommend you set up [Sender Policy Framework](https://en.wikipedia.org/wiki/Sender_Policy_Framework) (SPF) and/or [Domain Keys Identified Mail](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) (DKIM) for your email domain. +4. Choose a sender address like `mattermost@domain.com` and select `Send a Test Email` to verify setup is working correctly. + +Alternatively, you can use one of the [services listed below](#sample-smtp-settings), or can set up local `sendmail` by setting **Server Name** `127.0.0.1` with **Port** `25`. + +If deploying Mattermost using [Docker](/deployment-guide/server/deploy-containers), the standard docker `172.16.0.0/12` IP range isn't used. Specify the IP range `192.168.0.0/24` to the email service to avoid relay access errors. If using postfix, under `/etc/postfix/main.cf`, specify `mynetworks = 192.168.0.0/24`. This may vary depending on how Mattermost is deployed. Ensure that **Port 25** is open if a firewall is present. + +</Tip> + +<Note> + +[Outlook365 no longer supports Basic Auth](https://support.microsoft.com/en-us/office/pop-imap-and-smtp-settings-for-outlook-com-d088b986-291d-42b8-9564-9c414e2aa040) which is required by Mattermost. We recommend using an alternate Email service like AWS SES (Simple Email Service). + +</Note> + +## Configure SMTP settings + +1. In Mattermost go to **System Console \> Authentication \> Email**, and set **Allow Sign Up With Email** to **true**. +2. In the System Console, go to **Notifications \> Email** and configure Mattermost for your SMTP service. See the [SMTP configuration](/administration-guide/configure/environment-configuration-settings#smtp) documentation for details. + +> - Set **Send Email Notifications** to **true**. +> - Set the **Notification Display Name** for the account sending notifications. +> - Set **Notification Email Address** for the email address used to send notifications. +> - Enter the **SMTP Username**, **SMTP Password**, **SMTP Server**, and **SMTP Port** you copied from initial setup. +> - We recommend setting **Connection Security**: to **TLS (Recommended)** to encrypt communication between Mattermost and your SMTP service. + +<Note> + +`SMTPPort` and related port settings use string format (e.g., `"465"`) for compatibility with the `host:port` binding format, which requires string concatenation. + +</Note> + +3. Select **Save**. +4. Under **Connection Security**, select **Test Connection**. Mattermost will confirm whether a connection to the SMTP service is successful by sending you an email. If the test fails, Mattermost will provide details about why it failed in the System Console. See the [check Mattermost logs](#troubleshooting-using-logs) section below for details. + +## Sample SMTP settings + +<div class="tab"> + +Amazon SES + +- Set **SMTP Username** to **\[YOUR_SMTP_USERNAME\]** +- Set **SMTP Password** to **\[YOUR_SMTP_PASSWORD\]** +- Set **SMTP Server** to **email-smtp.us-east-1.amazonaws.com** +- Set **SMTP Port** to **465** +- Set **Connection Security** to **TLS** + +</div> + +<div class="tab"> + +Postfix + +Make sure Postfix is installed on the same machine as Mattermost. + +- Set **SMTP Username** to **(empty)** +- Set **SMTP Password** to **(empty)** +- Set **SMTP Server** to **localhost** +- Set **SMTP Port** to **25** +- Set **Connection Security** to **(empty)** + +</div> + +<div class="tab"> + +Gmail + +- Set **SMTP Username** to **your_email@gmail.com** +- Set **SMTP Password** to **your_password** +- Set **SMTP Server** to **smtp.gmail.com** +- Set **SMTP Port** to **587** +- Set **Connection Security** to **STARTTLS** + +<Warning> + +Additional configuration is required in Google to allow SMTP email to relay through their servers. See [SMTP relay: Route outgoing non-Gmail messages through Google](https://support.google.com/a/answer/2956491?hl=en) for the required steps. + +</Warning> + +</div> + +<div class="tab"> + +Hotmail + +- Set **SMTP Username** to **your_email@hotmail.com** +- Set **SMTP Password** to **your_password** +- Set **SMTP Server** to **smtp-mail.outlook.com** +- Set **SMTP Port** to **587** +- Set **Connection Security** to **STARTTLS** + +</div> + +<div class="tab"> + +Office365/Outlook + +- Set **SMTP Username** to **your_email@hotmail.com** +- Set **SMTP Password** to **your_password** +- Set **SMTP Server Name** to **smtp.office365.com** +- Set **SMTP Port** to **587** +- Set **Connection Security** to **STARTTLS** + +</div> + +## Troubleshooting SMTP + +### TLS/STARTTLS requirements + +If you fill in **SMTP Username** and **SMTP Password** then you must set **Connection Security** to **TLS** or to **STARTTLS** + +### Troubleshooting using logs + +If you have issues with your SMTP install, from your Mattermost team site go to **System Console \> Logs** to look for error messages related to your setup. You can do a search for the error code to narrow down the issue. Sometimes ISPs require nuanced setups for SMTP and error codes can hint at how to make the proper adjustments. + +For example, if **System Console \> Logs** displays the following error, search for `554 5.7.1 error` and `Client host rejected: Access denied`. + +``` text +Connection unsuccessful: Failed to add to email address - 554 5.7.1 <unknown[IP-ADDRESS]>: Client host rejected: Access denied +``` + +### Checking your Notifications settings + +If an SMTP connection test in the System Console for a self-hosted Mattermost deployment fails with the message `Connection unsuccessful: Failed to set the to address: 550 5.7.27 [test@example.com](mailto:test@example.com)`, go to **System Console \> Site Configuration \> Notifications** to verify that notification settings are configured correctly, including **Notification Display Name**, **Notification From Address**, **Support Email Address**, and **Notification Reply-To Address**. Cloud administrators can't manage **Notification From Address** or **Notification Reply-To Address**. + +### Checking your SMTP server is reachable + +- Attempt to Telnet to the email service to make sure the server is reachable. For additional information, visit [https://learn.microsoft.com/en-us/exchange/mail-flow/test-smtp-with-telnet?view=exchserver-2019](https://learn.microsoft.com/en-us/exchange/mail-flow/test-smtp-with-telnet?view=exchserver-2019). If you're using an earlier version than Exchange Server 2019, select your version from the left-hand navigation menu. + +- You must run the following commands from the same machine or virtual instance where `mattermost/bin/mattermost` is located. + +- Telnet to the email server with `telnet mail.example.com 25`. If the command works you should see something like: + + ``` text + Trying 24.121.12.143... + Connected to mail.example.com. + 220 mail.example.com NO UCE ESMTP + ``` + + Then type something like `HELO <your mail server domain>`. If the command works you should see something like: + + ``` text + 250-mail.example.com NO UCE + 250-STARTTLS + 250-PIPELINING + 250 8BITMIME + ``` + +<Note> + +- Telnet isn't included in official Mattermost Docker images, so you either need to use `ping` on those, or install Telnet yourself either directly or by modifying the Dockerfile. +- For further assistance, review the [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) for previously reported errors, or [join the Mattermost user community for troubleshooting help](https://mattermost.com/community/). + +</Note> diff --git a/docs/main/administration-guide/configure/system-attributes.mdx b/docs/main/administration-guide/configure/system-attributes.mdx new file mode 100644 index 000000000000..55e843f2d038 --- /dev/null +++ b/docs/main/administration-guide/configure/system-attributes.mdx @@ -0,0 +1,14 @@ +--- +title: "System Attributes" +--- +<PlanAvailability slug="ent-plus" /> + +System attributes configuration settings provide system admins with centralized control over key user account properties. + +Review and manage the following system attributes configuration options in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **System Attributes**. + +You can define, manage, and enforce specific attributes, including: + +- **Custom attributes for user profiles**: Display details such as job titles, departments, or other metadata, on user profiles that align with your organizational structures and workflows. Learn more about [managing custom user profile attributes](/administration-guide/manage/admin/user-attributes). API responses for custom profile attributes return default visibility and sort order when those values are missing. +- **Granular access controls based on user attributes**: Ensure users have access to only the resources and functionality relevant to their roles, bolstering security and compliance across the organization. Learn more about [managing access based on user attributes](/administration-guide/manage/admin/attribute-based-access-control). +- **Control user-managed attributes in attribute-based access control (ABAC)**: From Mattermost v10.11 (Enterprise Edition Advanced), user-managed attributes are excluded from ABAC rules by default to prevent unauthorized access. System admins can enable them with a configuration setting. Learn more about enabling user-managed attributes in ABAC rules in the [User Attributes documentation](/administration-guide/manage/admin/user-attributes#before-you-begin). diff --git a/docs/main/administration-guide/configure/user-management-configuration-settings.mdx b/docs/main/administration-guide/configure/user-management-configuration-settings.mdx new file mode 100644 index 000000000000..6dabe9391ab0 --- /dev/null +++ b/docs/main/administration-guide/configure/user-management-configuration-settings.mdx @@ -0,0 +1,666 @@ +--- +title: "User management configuration settings" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Review and manage the following in the System Console by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu, selecting **System Console**, and then selecting **User Management**: + +- [Users](#users) +- [Groups](#groups) +- [Teams](#teams) +- [Channels](#channels) +- [Permissions](#permissions) +- [System roles](#system-roles) + +------------------------------------------------------------------------------------------------------------------------ + +## Users + +Mattermost system admins can provision and manage user accounts, team membership, roles and permissions, and update user email addresses, usernames, and authentication data. + +### Provision users + +Getting people set up with a Mattermost account is typically something that system admins do when deploying and configuring the Mattermost deployment. A Mattermost admin can [provision Mattermost users](/administration-guide/onboard/user-provisioning-workflows) using one or more of the following methods: + +- [Enable account creation](/administration-guide/configure/authentication-configuration-settings#enable-account-creation). +- Use [mmctl user create](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-create) or Mattermost [APIs](https://api.mattermost.com/#tag/users) to create user accounts. +- [Migrate user accounts](/administration-guide/onboard/migrating-to-mattermost#migration-guide) from other collaboration systems and [bulk load](/administration-guide/onboard/bulk-loading-data) that user data into Mattermost. +- Connect an authentication service to assist with user provisioning, such as [AD/LDAP authentication](/administration-guide/onboard/ad-ldap) or [SAML authentication](/administration-guide/onboard/sso-saml). + +### Review user data + +From Mattermost v9.6, you can review the following user data in the System Console: + +- **Email**: The user's email address. +- **Member since**: The number of days since the user joined the Mattermost server. +- **Last login**: The date of the user's last successful login to the server. +- **Last activity**: The total number of days since the user was last active on the server, which is typically based on the [user's availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability). +- **Last post**: The total number of days since the user's last sent message on the server. +- **Days active**: (PostgreSQL only) The total number of days in which the user has sent a message in Mattermost. +- **Messages posted**: (PostgreSQL only) The total number of messages the user has sent on the server. + +From Mattermost v11.0, you can also review the following authentication data for each user: + +- **Authentication Method**: Shows how users authenticate with the Mattermost server, including external authentication system details such as LDAP Distinguished Name (DN), SAML NameID, OAuth ID, or other external authentication identifiers. This information helps system administrators troubleshoot authentication issues and correlate Mattermost users with their external authentication systems. + +By default, you see all columns of data and data for all time. + +- Show or hide data all data columns exccept **User details** and **Actions**, as preferred. +- Filter results to the last 30 days, the previous month, and the last 6 months for **Last post**, **Days active**, and **Messages posted** user data. + +### Find users + +Find a user using the System Console. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Search for specific users by entering a partial or full username, user ID, first name, last name, or email address in the **Search** field and pressing <kbd>Enter</kbd>. + +![Find a Mattermost user using the System Console.](/images/find-users.png) + +### Filter user searches + +Filter System Console user searches to narrow down results based on the team membership, role, and user status. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select **Filters** located to the right of the **Search users** field to access available filter options. +3. Select **Apply** to filter user search results. + +![Filter the user list based on team membership, role, and user status using the System Console.](/images/user-search-filters.png) + +### Identify a user's ID + +Users can be specified in Mattermost by username or user ID. Usernames automatically resolve when a match is detected. Identify a user's ID using the System Console, the Mattermost API, or mmctl. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select a **User** to review their ID in the User Configuration page. + +![Find the User ID under User Management using the System Console.](/images/user-id.png) + +Alternatively, identify a user's ID using the Mattermost API or mmctl: + +- Using the Mattermost API, make an HTTP GET request to the following endpoint: `https://your-mattermost-url/api/v4/users/username/username_here`. Replace `your-mattermost-url` with the URL of your Mattermost instance and `username_here` with the username you are looking for. The API response contains a JSON object that includes the user's ID among other details. +- Using mmctl, in a terminal window, use the following command to list all users and their IDs: `mmctl user list` to return a list of user IDs. + +### Export user data + +From Mattermost v9.6, Mattermost Enterprise and Professional customers can export user data as a CSV report. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. [Filter](#filter-user-searches) the user data as needed. +3. Select **Export** located in the top right corner of the System Console interface, and then select **Export data**. You'll receive the report in CSV format as a direct message in Mattermost. + +### Deactivate users + +To delete a user from your Mattermost deployment, you can deactivate the user's account. Deactivated users have an deactivated status, are logged out of Mattermost as soon as they are deactivated, and deactivated users can no longer log back in. You can manage the user's role, password, and email address while a user's account is deactivated. + +<Note> + +- From Mattermost v10.10, when a user account is deactivated, the account's [availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability) is automatically set to offline. +- LDAP-managed users must be deactivated through LDAP, and can't be deactivated using the System Console or the API. + +</Note> + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select a **User** that you wish to activate or deactivate. +3. If the selected user is currently active, you can find the **Deactivate** button in the **User Configuration** page. +4. Select **Deactivate**, and confirm the deactivation. You can re-activate a deactivated user by selecting **Activate**. + +![Deactivate a user in Mattermost using the System Console.](/images/deactivate-user.png) + +<Tip> + +Re-activate a deactivated user by selecting **Activate**. + +</Tip> + +#### What happens to deactivated user integrations? + +If you deactivate a Mattermost user who has integrations tied to their user account, consider the following consequences and recommendations based on the integration type: + +- **Slash commands** will continue to work after user deactivation. Consider deleting the existing slash command and creating a new slash command associated with a different user account to decouple sensitive token data from the deactivated user account. Alternatively, consider regenerating the token of the existing slash command. Check that the deactivated user doesn't have access to the slash command **Request URL** which is the callback URL to receive the HTTP POST or GET event request when the slash command is run. +- **Outgoing webhooks** will continue to work after user deactivation. Consider regenerating the webhook token and check that the deactivated user no longer has access to the callback URLs, as having access would result in the deactivating user receiving the outgoing webhooks. +- **Incoming webhooks** will continue to work after user deactivation. Because the [URL produced](https://developers.mattermost.com/integrate/webhooks/incoming/#create-an-incoming-webhook) includes `xxx-generatedkey-xxx`, anyone who has the URL can post messages to the Mattermost instance. We recommend removing the incoming webhook and creating a new one associated with a different user account. +- **Bot accounts** won't continue to work after user deactivation when the [disable bot accounts when owner is deactivated](/administration-guide/configure/integrations-configuration-settings#disable-bot-accounts-when-owner-is-deactivated) is enabled. This configuration setting is enabled by default. +- **OAuth apps** won't continue to work after user deactivation, and associated tokens are deleted. Manual action is needed to keep these integrations running. + +### Manage user attributes + +From Mattermost v11.1, you can can view and update user attribute values for individual users directly from the System Console. This capability provides a centralized way to manage user profile attributes without requiring users to update their own profiles or using [mmctl user attribute commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-cpa). + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select a **User** to open their User Configuration page. +3. Scroll to the **User Attributes** section to view and edit the user's attribute values. +4. Update attribute values as needed and save your changes. + +<Note> + +- User attributes must be created first through **System Console \> Site Configuration \> System Attributes \> User Attributes** before they can be edited in individual user profiles. See the [User attributes](/administration-guide/manage/admin/user-attributes) documentation for details on creating and configuring attributes. +- Users can edit their own attributes if that attribute is configured as [user-editable](/administration-guide/manage/admin/user-attributes#admin-managed-vs-user-editable-attributes). + +</Note> + +### Delete users + +From Mattermost v10.11, when using email/password for authentication, you can enable users to permanently delete their own accounts, or you can delete user accounts as a system administrator. + +#### Enable account deletion + +Define the URL for a **Delete Account Link** that users can access by going to their profile and selecting **Security \> Delete Your Account**. Leave this field blank to hide the abiltiy for users to delete their account. + +<table style={{width: '90%'}}> +<colgroup> +<col style={{width: '90%'}} /> +</colgroup> +<tbody> +<tr> +<td>This feature's <code>config.json</code> setting is <code>"ServiceSettings.DeleteAccountLink": ""</code> with string input.</td> +</tr> +</tbody> +</table> + +When a user deletes their account, deleted accounts cannot be reactivated, and the user is automatically removed from all teams and channels. + +#### What data is removed? + +When an account is permanently deleted, the following data is permanently removed: + +- User profile information (name, email, username) +- User preferences and settings +- User authentication credentials +- Direct message channel memberships +- Team and channel memberships +- User session data +- All posts and replies authored by the deleted user +- File uploads and attachments shared in channels by the user +- All webhooks, slash commands and OAuth apps created by the user + +#### What data is retained? + +After account deletion, audit logs referencing the user's actions, channel and team membership are retained. + +### Manage user's roles + +Apply roles to users using the System Console. The current available roles are **System admin** and **Member**. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Under **Actions**, select **Manage roles**. +3. Specify whether the user has the role of **System admin** or **Member**, and then select **Save**. + +![Manage a user's Mattermost role using the System Console.](/images/manage-roles.png) + +### Manage user's teams + +Add or remove users from teams using the System Console. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user you want to manage. +3. You can include the user in one new team or a group of teams. Select **Add Team**, select one or more teams, and then select **Add**. + +![Add a user to a Mattermost team using the System Console.](/images/add-user-to-team.png) + +4. To remove the user from a specific team, select **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> next to the team name, and select **Remove from team**. + +![Remove a user from a Mattermost team using the System Console.](/images/remove-user-from-team.png) + +<Tip> + +You can also remove the user from a specific team from the **Actions** column on the **Users** page. Select **Manage Teams**, and then select **Remove from Team** for applicable teams. + +</Tip> + +### Manage user's settings + +<PlanAvailability slug="ent-plus" /> + +From Mattermost v9.11, system admins can help end users customize their Mattermost notifications by editing the user's [notification settings](/end-user-guide/preferences/manage-your-notifications) on the user's behalf within the System Console. Users can view, modify, and override their own settings at any time. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user you want to manage. +3. Select **Manage User Settings**. +4. In **Admin Mode**, modify the user's settings as needed. Saved changes take effect immediately in the user's account. + +### Reset login attempts + +If a user, whose account details are synchronized with AD/LDAP, can't access their Mattermost account due to too many failed login attempts, you can reset the number of failed login attempts for their user account in the System Console. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Under **Actions**, select **Reset login attempts**. + +<Note> + +To adjust the maximum login attempts allowed for all users, go to **System Console \> Authentication \> AD/LDAP \> Maximum Login Attempts**. Lowering this [configuration setting](/administration-guide/configure/authentication-configuration-settings#maximum-login-attempts) value below the maximum threshhold allowed on your AD/LDAP server will ensure that your users won’t get locked out of AD/LDAP due to failed login attempts in Mattermost. + +</Note> + +### Update user's email + +Update the emails of users using the System Console. + +<Note> + +From Mattermost v10.9, email addresses enclosed in angle brackets (e.g., `[billy@example.com](mailto:billy@example.com)`) will be rejected. To avoid issues, ensure all user emails comply with the plain address format (e.g., `billy@example.com`). In addition, we strongly recommend taking proactive steps to audit and update Mattermost user data to align with this product change, as impacted users may face issues accessing Mattermost or managing their user profile. You can update these user emails manually using [mmctl user email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-email). + +</Note> + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user, and enter a new email in the **Email** field. +3. Select **Save**. + +![Update the email of a Mattermost user using the System Console.](/images/user-email-update.png) + +<Tip> + +You can also update the email from the **Actions** column on the **Users** page. Select **Update email**, enter the new email for the user, and then select **Save**. + +</Tip> + +### Update user's username + +From Mattermost 11.6: Update the username of a user using the System Console. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user, and enter a new username in the **Username** field. +3. Select **Save**. + +### Update user's authentication data + +From Mattermost 11.6: System admins can view and update the authentication data (AuthData) for a user directly in the System Console. AuthData is the external identifier associated with the user's authentication method, such as an LDAP Distinguished Name (DN), SAML NameID, or OAuth ID. Updating this field is useful when a user's external authentication identifier changes, for example after an identity provider migration. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user to open their User Configuration page. +3. In the **Authentication** section, view or update the user's authentication data value. +4. Select **Save**. + +### Reset user's password + +Reset a user's password using the System Console. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user from the list, and then select **Reset Password**. +3. Enter a new password and select **Reset**. + +![In System Console, Reset the password of a User under User Management.](/images/user-password-reset.png) + +You can also reset the password using the **Actions** column for the specific user on the **Users** page. Select **Reset password** from the **Actions** column dropdown, enter the new password in the pop-up dialog box and select **Reset**. + +### Revoke a user's session + +Revoke the user sessions in case of an emergency to secure the user account using the System Console. This logs the user out of all devices. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Under the **Actions** column for the specific user, select **Remove sessions**. +3. Select **Revoke** to remove all sessions for that user. + +![Revoke the sessions of a user using the System Console.](/images/revoke-user-session.png) + +### Review user profile details + +View user profile details using the System Console. Gather information including the user's ID, username, email, authentication method, and team memberships. + +1. Go to **System Console \> User Management \> Users** to access all user accounts. +2. Select the user from the list, and browse user details. + +![Review user details using the System Console](/images/user-profile-details.png) + +------------------------------------------------------------------------------------------------------------------------ + +## Groups + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '46%'}} /> +<col style={{width: '45%'}} /> +<col style={{width: '7%'}} /> +</colgroup> +<tbody> +<tr> +<td>Manage default teams and channels by linking AD/LDAP groups to Mattermost groups.</td> +<td><ul> +<li>System Config path: <strong>User Management > Groups</strong></li> +<li><code>config.json setting</code>: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +<td></td> +</tr> +<tr> +<td colspan="3">See the <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fad-ldap-groups-synchronization">AD/LDAP groups</a> documentation for details. |</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Teams + +### Find Teams + +You can find existing teams in your Mattermost instance using the System Console. + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Enter the team name in the **Search** box. + +![Find a Mattermost team using the System Console.](/images/find-teams.png) + +<Tip> + +From Mattermost v9.6, you can search for specific teams by entering a partial or full team name in the **Search** field and pressing <kbd>Enter</kbd>. + +</Tip> + +### Filter team searches + +Filter your team search to narrow down results based on the team management type (anyone can join, invite only, or group sync). + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select **Filters** located to the right of the **Search** field to access available filter options. +3. Choose any filter and select **Apply** to filter team search results. + +![Filter the teams based on team membership types using the System Console.](/images/team-search-filters.png) + +### Review team configuration + +View team configuration details using the System Console. Gather information including the team name, team description, team management options, groups, and members. + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. + +![Review team configuration details using the System Console](/images/team-configuration-details.png) + +### Manage team membership + +Admins can directly add or remove member from the team and customize how members are added to the team using the System Console. + +#### Add members + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Members** section, select **Add Members**. +4. Select an user or available bot from the list or try using the **Search** to find a specific one. +5. Select **Add** to add the user or bot. +6. Select **Save**. + +![Add a member to the team using the System Console.](/images/add-members-to-a-team.png) + +#### Remove members + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Members** section, select **Remove** for the user or bot that you want to remove. +4. Select **Save**. + +![Remove a member from the team using the System Console.](/images/remove-members-from-a-team.png) + +#### Sync group members + +When enabled, adding and removing users from groups will add or remove them from this team. The only way of inviting members to this team is by adding the groups they belong to. See the [Synchronize teams and channels](/administration-guide/onboard/ad-ldap-groups-synchronization#synchronize-teams-and-channels) documentation for further details. + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Team Management** section, enable the **Sync Group Members** option. +4. Select **Save**. + +![Enable Sync Group Members for a team using the System Console.](/images/sync-group-members-in-a-team.png) + +#### Anyone can join this team + +This team can be discovered allowing anyone with an account to join this team. + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Team Management** section, enable the **Anyone can join this team** option. +4. Select **Save**. + +![Enable Anyone can join this team option for a team using the System Console.](/images/anyone-can-join-a-team.png) + +#### Only specific email domains can join this team + +Users can only join the team if their email matches one of the specified domains. + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Team Management** section, enable the **Only specific email domains can join this team** option and add the specific domains. +4. Select **Save**. + +![Enable Only specific email domains can join this team option for a team using the System Console.](/images/specific-email-domains-can-join-a-team.png) + +### Synchronize team members + +Admins can choose between inviting members to a team manually or synchronizing members automatically from AD/LDAP groups. See the [using AD/LDAP synchronized groups](/administration-guide/onboard/ad-ldap-groups-synchronization#synchronize-ad-ldap-groups-to-mattermost) documentation for details on managing team or private channel membership. + +### Archive the team + +1. Go to **System Console \> User Management \> Teams** to access all available teams. +2. Select the team from the list to view its configuration page. +3. In the **Team Profile** section, select **Archive Team**. +4. Select **Save**. + +![Archive a team using the System Console.](/images/archive-a-team.png) + +------------------------------------------------------------------------------------------------------------------------ + +## Channels + +### Find Channels + +Find existing channels in your Mattermost instance using the System Console. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Enter the channel name in the **Search** box. + +![Find a Mattermost channel using the System Console.](/images/find-channels.png) + +### Filter channel searches + +Filter your channel search to narrow down results based on the channel type (as public, private or archived), channel management type (group sync or manual invites) or based on the team the channel belongs to. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select **Filters** located to the right of the **Search** field to access available filter options. +3. Choose any filter and select **Apply** to filter channel search results. + +![Filter the channels based on channel type, channel membership types or they team that they belong to using the System Console.](/images/channel-search-filters.png) + +### Review channel configuration + +View channel configuration details using the System Console. Gather information including the channel profile, advanced access controls, channel management options, groups, and members. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select a channel from the list to review its channel configuration details. + +![Review channel configuration details using the System Console](/images/channel-configuration-details.png) + +### Advanced Access Control + +Manage the Management actions available to channel members and guests. + +#### Create Posts + +The ability for members and guests to create posts in the channel. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select a channel from the list to view its configuration page. +3. In the **Create Posts** section under the **Advanced Access Control** tab, select the option for **Guests**, **Members**, or both to enable those users to post messages in the channel. +4. Select **Save**. + +![Add Members and Guests to post to the channel using the System Console.](/images/allow-create-posts-for-a-channel.png) + +#### Post Reactions + +The ability for members and guests to react with emojis on messages in the channel. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select a channel from the list to view its configuration page. +3. In the **Post Reactions** section under the **Advanced Access Control** tab, select the option for **Guests**, **Members**, or both to enable those users to react with emojis on messages posted to the channel. +4. Select **Save**. + +![Add Members and Guests to post reactions to the channel using the System Console.](/images/allow-post-reactions-for-a-channel.png) + +#### Manage Members + +The ability for members to add and remove people from the channels. Guests can't add or remove people from channels. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select a channel from the list to view its configuration page. +3. In the **Manage Members** section under the **Advanced Access Control** tab, select **Members** to enable those users to manage members for the channel. +4. Select **Save**. + +![Allow Members to add or remove people from the channel using the System Console.](/images/allow-manage-members-for-a-channel.png) + +#### Channel Mentions + +The ability for members and guests to use channel mentions, including **@all**, **@here**, and **@channel**, in the channel. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Channel Mentions** section under the **Advanced Access Control** tab, select the option for **Guests**, **Members**, or both to enable those users to use channel mentions. +4. Select **Save**. + +![Add Members and Guests to use mentions in a channel using the System Console.](/images/allow-mentions-for-a-channel.png) + +<Tip> + +**Guests** and **Members** can't use channel mentions without the ability to **Create Posts**. To enable this permission, these users must have been granted **Create Posts** permission first. + +</Tip> + +#### Manage Bookmarks + +The ability for members to add, delete, and sort bookmarks. Guests can't add, remove, or sort bookmarks for the channel. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Manage Bookmarks** section under the **Advanced Access Control** tab, select **Members** to enable those users to add, sort, or remove bookmarks for the channel. +4. Select **Save**. + +![Allow Members to manage bookmarks for the channel using the System Console.](/images/allow-manage-bookmarks-for-a-channel.png) + +<Tip> + +The ability to manage bookmarks for the channel is available for **Members** only. **Guests** can't add, remove or sort bookmarks for the channel. + +</Tip> + +### Channel Management + +Choose between inviting members manually or sychronizing members automatically from groups. + +#### Sync Group Members + +When enabled, adding and removing users from groups will add or remove them from this team. The only way of inviting members to this team is by adding the groups they belong to. See the [Synchronize teams and channels](/administration-guide/onboard/ad-ldap-groups-synchronization#synchronize-teams-and-channels) documentation for further details. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Channel Management** tab, enable the **Sync Group Members** option. +4. Select **Save**. + +![Enable Sync Group Members for a channel using the System Console.](/images/sync-group-members-in-a-channel.png) + +#### Public channel or private channel + +Public channels are discoverable and any user can join. Private channels require invitations to join. + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Public channel or private channel** section under the **Channel Management** tab, toggle between **Public** or **Private** to change channel visibility. +4. Select **Save**. + +![Set the channel visibility to either Public or Private using the System Console.](/images/set-a-channel-to-public-or-private.png) + +<Tip> + +When Group Sync is enabled, private channels can't be converted to public channels. + +</Tip> + +### Members + +Choose between inviting members manually or synchronizing members automatically from groups. + +#### Add members + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Members** section, select **Add Members**. +4. Use the **Search** box to find a specific user or group to add to the channel. +5. Select **Add** to add the user or group as a **Member**. +6. Select **Save**. + +![Add a member to the channel using the System Console.](/images/add-members-to-a-channel.png) + +#### Remove members + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Members** section, select **Remove** for the user that you want to remove. +4. Select **Save**. + +![Remove a member from the channel using the System Console.](/images/remove-members-from-a-channel.png) + +### Archive a channel + +1. Go to **System Console \> User Management \> Channels** to access all available channels. +2. Select the channel from the list to view its configuration page. +3. In the **Channel Profile** section, select **Archive Channel**. +4. Select **Save**. + +![Archive a channel using the System Console.](/images/archive-a-channel.png) + +<Tip> + +Channels can be deleted with all content, including posts in the database, using the [mmctl channel delete](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-delete) tool. + +</Tip> + +------------------------------------------------------------------------------------------------------------------------ + +## Permissions + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '48%'}} /> +<col style={{width: '43%'}} /> +<col style={{width: '6%'}} /> +</colgroup> +<tbody> +<tr> +<td>Restrict actions in Mattermost to authorized users only.</td> +<td><ul> +<li>System Config path: <strong>User Management > Permissions</strong></li> +<li><code>config.json setting</code>: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +<td></td> +</tr> +<tr> +<td colspan="3">See <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fadvanced-permissions">advanced permissions</a> documentation for details</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## System roles + +<PlanAvailability slug="pro-plus" /> + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '49%'}} /> +<col style={{width: '42%'}} /> +<col style={{width: '6%'}} /> +</colgroup> +<tbody> +<tr> +<td>Restrict System Console access to authorized users only.</td> +<td><ul> +<li>System Config path: <strong>User Management > System Roles</strong></li> +<li><code>config.json setting</code>: N/A</li> +<li>Environment variable: N/A</li> +</ul></td> +<td></td> +</tr> +<tr> +<td colspan="3">See the <a href="mm-doc:%2Fadministration-guide%2Fonboard%2Fdelegated-granular-administration">delegated granular administration</a> documentation for details |</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/manage/admin/abac-channel-access-rules.mdx b/docs/main/administration-guide/manage/admin/abac-channel-access-rules.mdx new file mode 100644 index 000000000000..3303066c9221 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/abac-channel-access-rules.mdx @@ -0,0 +1,227 @@ +--- +title: "Channel-specific access rules" +--- +<PlanAvailability slug="entry-adv" /> + +Channel and Team Admins can self-manage access controls for their private channels directly through the Channel Settings modal, without requiring System Admin intervention. For organization-wide policies created by System Admins, see [System-wide attribute-based access policies](/administration-guide/manage/admin/abac-system-wide-policies). + +Each ABAC channel access policy has an explicit active state that determines whether the policy will automatically add users who meet the policy's criteria but are not yet channel members. When a policy is applied to a channel, the policy's rules are always enforced to remove members who no longer meet the required attribute rules, regardless of the active state. + +With channel access rules, Channel and Team Admins can: + +- Create channel-specific access rules using a simple interface. +- Rules are **additive** to any system policies (both must be satisfied). +- Automatic member synchronization with immediate feedback. +- Self-exclusion prevention to avoid locking yourself out. + +## Prerequisites + +- [Attribute-Based Access Control (ABAC)](/administration-guide/manage/admin/attribute-based-access-control) must be enabled by a System Admin in **System Console \> System Attributes \> Attribute-Based Access**. +- You need Channel Admin permissions and the `manage_channel_access_rules` permission. +- Channel access rules are available only for private channels. + +### Access Channel Settings + +1. In a private channel where you have Channel Admin permissions, select the channel name at the top of the center pane. +2. Select **Channel Settings** from the dropdown menu. +3. Navigate to the **Access Control** tab. This tab is only visible for private channels when you have the appropriate permissions and ABAC is enabled system-wide. + +<Tip> + +You can also assign ABAC rules to a channel directly from a channel's details page in the System Console under **Channel Management** by enabling the **Enable attribute-based channel access** option. Under **Access policy**, select **Link to a policy** to select an existing policy. + +</Tip> + +## Configure access rules + +Channel access rules use the same simple interface as system policies, allowing you to create attribute-based conditions without complex syntax. + +1. In the **Access Control** tab, you'll see any inherited system policies at the top in a blue information banner (if applicable). +2. Use the **Add attribute** button to create new access conditions: + - **Select attribute**: Choose from available user attributes + - **Choose operator**: Select how the attribute should match: + - **Is**: Exact match with specified value + - **Is not**: Must not match specified value + - **In**: Must match any of multiple specified values + - **Contains**: Attribute value must contain specified text + - **Set values**: Enter the required attribute values +3. Add multiple conditions as needed. All conditions are combined with logical AND (all must be satisfied). +4. Select **Test access rules** to preview which users would be granted access based on your current rules. + +### Auto-sync membership + +The **Auto-add members based on access rules** toggle controls automatic membership management. This setting ensures that channel membership stays consistently aligned with the defined attribute rules, similar to how LDAP group channels work: + +- **Enabled**: Users matching the rules are automatically added to the channel. If users temporarily lose attributes and later regain them, they will be automatically re-added +- **Disabled**: Rules act as a gate (preventing unauthorized joins) but don't automatically add qualifying users + +<Important> + +- Auto-add/auto-sync is checked on a per-channel policy basis, not inherited from parent system-wide policies. +- If a system policy has auto-sync enabled, Channel and Team Admins cannot disable it at the channel level. +- If a system policy has auto-sync disabled, Channel and Team Admins can choose to enable it for their channel. +- When no rules are configured, this toggle is automatically disabled. +- Regardless of the auto-sync setting, users who no longer meet required attribute rules are always removed during synchronization. + +</Important> + +### Validation and safety + +Before saving changes, Mattermost validates your rules to prevent common issues: + +- **Required fields**: All attribute selections and values must be completed +- **Self-exclusion prevention**: You cannot create rules that would remove yourself from the channel +- **Conflict detection**: Rules that create impossible conditions are identified + +When you save changes that affect membership, a confirmation dialog shows you: + +- How many users will be added or removed +- Option to view the specific users affected +- Confirmation required before applying changes + +## Policy inheritance + +Channel-level (child) ABAC policies now behave independently and consistently, even when parent system-wide policies exist. Each policy maintains its own active state and configuration. + +When both [system policies](/administration-guide/manage/admin/abac-system-wide-policies) and channel rules are configured: + +1. **System policies** are displayed in a blue banner at the top (read-only) +2. **Channel rules** are managed in the access rules section below +3. **Users must satisfy BOTH** system policies and channel rules to access the channel +4. Channel rules **add restrictions** but cannot weaken system policies +5. **Auto-add behavior** is determined by the individual channel policy, not inherited from parent system-wide policies. System-wide policies can pass down their rules, but auto-add/auto-sync is evaluated per channel. + +## Use cases and recommendations + +**Ideal use cases for channel access rules:** + +- **Project-specific channels**: Restrict access to team members working on specific projects +- **Clearance-based discussions**: Ensure only users with appropriate security clearance can participate +- **Department communications**: Limit channel access to specific organizational units +- **Temporary access**: Create rules for short-term project teams or contractor access + +**Best practices:** + +- **Start simple**: Begin with basic attribute conditions before adding complexity +- **Test before saving**: Always use the "Test access rules" feature to verify your intended scope +- **Document changes**: Consider posting a message in the channel when access rules change +- **Regular review**: Periodically review rules to ensure they remain appropriate +- **Coordinate with IT**: Work with System Admins for complex organizational policies + +**When to use system policies vs. channel rules:** + +- **System policies**: Use for organization-wide standards, compliance requirements, or policies affecting multiple channels +- **Channel rules**: Use for channel-specific restrictions, project-based access, or when you need immediate control without IT involvement + +## End-user experience + +When channels have attribute-based access controls applied, users will see clear indicators and experience specific behaviors designed to maintain security while providing transparency. + +### Visual indicators + +**Channel Members panel:** + +- Information banner at the top explains that attribute-based access is enabled. +- Displays required attribute values as tags (e.g., "Engineering", "Confidential"). +- Tooltip on hover shows the attribute name for each value. + +**Add Members modal:** + +- Similar information banner and attribute value display. +- Users who don't match the access criteria won't appear in search results. +- Only eligible users can be selected and added to the channel. + +### Functional restrictions + +When ABAC is enabled for a channel: + +- **Search limitations**: Users who don't match access criteria don't appear in member search results. +- **Invitation restrictions**: Only users meeting attribute requirements can be added to the channel. +- **Guest user exclusions**: Private channels with ABAC policies cannot have guest users invited. +- **Automatic removal**: Users who lose required attributes are automatically removed during the next synchronization. + +<Note> + +These restrictions apply across all Mattermost clients, including web, desktop, and mobile, to ensure consistent security enforcement. + +</Note> + +## Troubleshooting and FAQs + +Common questions about attribute-based access control implementation and usage. + +### Permission and access + +#### Why can't I see the Access Control tab in Channel Settings? + +The **Access Control** tab is only visible when all of these conditions are met: + +- You have Channel Admin role or higher for the channel +- The channel is a private channel (not public, group message, or direct message) +- ABAC is enabled system-wide by a System Admin in **System Console \> System Attributes \> Attribute-Based Access** +- Your user role includes the `manage_channel_access_rules` permission + +#### Can Channel and Team Admins override system policies? + +No. Channel rules are always **additive** to system policies. Users must satisfy both system policies AND channel rules to access the channel. Channel and Team Admins cannot weaken or override restrictions set by System Admins. + +#### What happens if I create rules that would exclude myself? + +Mattermost prevents this with self-exclusion validation. If your rules would remove you from the channel, you'll see an error message and cannot save the changes until you adjust the rules or reset them. + +### Rule configuration + +#### Can I use advanced CEL expressions in Channel Settings? + +No. Channel Settings only supports Basic Mode with simple attribute conditions. For complex expressions with nested logic or mixed operators, System Admins need to create policies in the System Console. + +#### How do I remove all access rules from a channel? + +Delete all attribute conditions from the access rules table. When no rules are configured and no system policies are applied, the channel returns to standard access behavior. + +#### Why is the auto-sync toggle disabled? + +The auto-sync toggle is automatically disabled when: + +- No access rules are configured +- A system policy with auto-sync enabled is applied (Channel and Team Admins cannot disable it) +- There are validation errors in the current rules +- The channel's access control policy is not in an active state + +<Note> + +**Troubleshooting auto-sync issues**: If auto-sync functionality (automatic adding/re-adding of members) is not working as expected, verify that the channel's access control policy is in an active state. An inactive policy will prevent automatic member additions from occurring. Note that enforcement of rules (removal of members who no longer meet requirements) happens regardless of the policy's active state. + +</Note> + +### Synchronization and membership + +#### How quickly are membership changes applied? + +When you save access rules, membership sync job is created and changes are applied as soon as the job is completed. Additionally, Mattermost runs synchronization jobs every 30 minutes to handle attribute changes from external systems (LDAP, SAML). + +#### Will users be notified when they're removed from a channel? + +Yes, users receive standard Mattermost notifications when they're removed from channels due to access rule changes, similar to manual removals. + +#### Can I see who was added or removed during synchronization? + +Yes, the confirmation modal before saving shows exactly which users will be affected. System Admins can also view detailed synchronization logs in the System Console. + +### Attribute and data questions + +#### Which user attributes can I use in access rules? + +You can use any user attributes either synchronized via LDAP/SAML or manually configured by System Admins in **System Console \> System Attributes \> User Attributes**. + +#### What happens if a user attribute changes? + +During the next synchronization (every 30 minutes), users who no longer match the access rules will be removed from the channel, and new users who now match will be added (if auto-sync is enabled). + +#### Do guest users work with ABAC channels? + +No. Private channels with attribute-based access control cannot have guest users. This ensures strict adherence to access control policies based on organizational attributes. + +#### Can group-sync channels use ABAC? + +No. Channels configured with group synchronization cannot use attribute-based access control. Group-sync and ABAC are mutually exclusive features - you must choose one method of access control per channel. diff --git a/docs/main/administration-guide/manage/admin/abac-system-wide-policies.mdx b/docs/main/administration-guide/manage/admin/abac-system-wide-policies.mdx new file mode 100644 index 000000000000..91423628647e --- /dev/null +++ b/docs/main/administration-guide/manage/admin/abac-system-wide-policies.mdx @@ -0,0 +1,111 @@ +--- +title: "System-wide attribute-based access policies" +--- +<PlanAvailability slug="entry-adv" /> + +Use this guide to create and manage organization-wide attribute-based access policies in the System Console. For channel-level rules managed by Channel Admins, see [Channel-specific access rules](/administration-guide/manage/admin/abac-channel-access-rules). + +## Prerequisites + +- [Attribute-based access controls (ABAC)](/administration-guide/manage/admin/attribute-based-access-control) require defined user attributes. First [configure user attributes](/administration-guide/manage/admin/user-attributes) in the System Console. +- Then go to **System Console \> System Attributes \> Attribute-Based Access** to enable attribute-based access controls for your Mattermost instance. This functionality requires a Mattermost Enterprise Advanced license. + +From Mattermost v10.11, user-managed attributes are excluded from attribute-based access control (ABAC) rules by default for security reasons. This prevents access control policies from being circumvented by users editing their own profile attributes. To include user-managed attributes in ABAC rules, a system admin must explicitly enable the `EnableUserManagedAttributes` configuration setting. See the [user attribute](/administration-guide/manage/admin/user-attributes#before-you-begin) documentation for details on enabling this feature. This configuration setting is available only in Enterprise Edition Advanced and is disabled by default. + +## Define access control policies + +You can add multiple rules to a single policy, and each rule can include multiple attribute values. + +1. In the System Console, go to **System Attributes \> Attribute-Based Access** and select **Add Policy**. + +2. Enter a unique policy name. + +3. Choose whether to automatically add users who match your configured attribute values as new members. Automatic synchronization is disabled by default. + + - **True**: Automatically maintains channel membership according to the defined rules as user attributes change. + - **False** (**Default**): Only removes members and restricts adding them to the channel if they don’t match defined rules. Users are not automatically added. + + Regardless of whether this configuration setting, users who no longer match the configured attribute values in the future will be removed from the channel after the next channel synchronization. + +4. Define the attribute-based access rules to restrict channel membership. + + <div class="tab"> + + Simple Mode + + Simple Mode is ideal for simple and straightforward access control scenarios. Each row is a single condition that must be met for a user to comply with the policy. Simple Mode only supports simple conditions without nested logic or mixed logical operators. All rules are combined with a logical AND operator `&&`. + + 1. Select **Add attribute** and select the attribute you want to use for access control. + + 2. Specify how you want the attribute to match the user profile. You can choose from the following options: + + > - **Is**: The attribute must be an exact match of the value. + > - **Is not**: The attribute must not contain specified value. + > - **In**: The attribute must match at least one value. + > - **Starts with**: The attribute value must start with the specified value. + > - **Ends with**: The attribute value must end with the specified value. + > - **Contains**: The attribute value must exist somewhere with the specified value. + + 3. Specify the attribute values that users must have to be granted access to the channel. + + </div> + + <div class="tab"> + + Advanced Mode + + Advanced Mode is ideal for complex access control scenarios that require CEL syntax to combine multiple conditions with logical operators that support rules like `user.<attribute> == <value>`, using `&&` / `||` (and/or) for multiple conditions, and `()` to group conditions. The CEL Expression Editor provides real-time syntax validation and feedback, as well as context-aware autocomplete for attributes, operators, and attribute values. + + You can also start defining rules in Simple Mode and then switch to Advanced Mode to refine the rules further as needed. However, you'll be blocked from switching from Advanced back to Simple Mode if one of the following are true: + + - Mixed logical operators are used between conditions. + - Nested logic/grouping (parentheses) are present. + - Unsupported operators or expressions are detected. + + The syntax structure is `user.<attribute> <operator> <value>`. + + As you type, autocompletes show available attributes. As you select attributes, autocomplete suggests appropriate CEL operators. After selecting an operator, when attribute values are pre-defined, autocomplete suggests values to choose from. Mattermost will explicitly indicate issues such as missing operators, incorrect syntax, or incomplete conditions. + + Select the **Validate syntax** bar to check the syntax of your rule. If the syntax is valid, the bar will turn green and display a message indicating that the syntax is valid. If there are any issues, the bar will turn red and display an error message. + + </div> + +### Test rules + +Select **Test access rule** to test the rule against your user base to return how many users would be granted access to the channel based on the current rule. Test your rules to ensure the intended scope and avoid unexpected access changes. + +### Manage rules + +You can apply changes to existing rules or remove rules at any time using either Simple Mode or Advanced Mode. Select **Save** to save your changes. + +### Assign policies to private channels + +Specify the private channel that your access control policy applies to by selecting **Add channels** to search for and select the channels you want. You can assign the policy to multiple channels at once, or you can [assign it to individual channels](#define-access-controls-per-channel) later. Select **Save** to save your changes. + +<Note> + +Private channels with attribute-based access control policies can't have guest users invited to them. Only users who match the defined attribute criteria can be added to ABAC-controlled channels, ensuring strict adherence to access control policies. + +</Note> + +### Delete policies + +To delete a policy, select the **Delete** button next to the policy you want to remove. You can only delete policies that are not currently assigned to any channels. If a policy is assigned to channels, you must first remove it from those channels before you can delete it. + +## Define access controls per channel + +You can assign an existing access control policy to a private channels for more granular control over channel membership. This is useful when you need to apply different rules for different channels. + +1. In the System Console, go to **User Management \> Channels** to select the private channel you want to configure, and select **Edit**. +2. In the **Channel Management** section, enable the **Enable attribute-based channel access** option. +3. Under **Access policy**, select **Link to a policy** to select an existing policy. + +<Tip> + +You can also assign ABAC rules to a channel directly from a channel's details page in the System Console under **Channel Management** by enabling the **Enable attribute-based channel access** option. Under **Access policy**, select **Link to a policy** to select an existing policy. + +</Tip> + +### Remove channel policies + +Disable the policy for the channel by selecting **Remove Policy**. You can then link the channel to a different policy if preferred. diff --git a/docs/main/administration-guide/manage/admin/attribute-based-access-control.mdx b/docs/main/administration-guide/manage/admin/attribute-based-access-control.mdx new file mode 100644 index 000000000000..b8416a33467b --- /dev/null +++ b/docs/main/administration-guide/manage/admin/attribute-based-access-control.mdx @@ -0,0 +1,36 @@ +--- +title: "Attribute-Based Access Control" +--- +<PlanAvailability slug="entry-adv" /> + +From Mattermost v10.9, system admins in large or complex organizations who require Zero Trust Security when handling with sensitive information can prevent unauthorized access through attribute-based access controls. + +Enforcing strict access controls based on user attributes eliminates manual role adjustment processes that can lead to security risks, inefficiencies, or inappropriate access, while maintaining security and compliance by ensuring that only authorized users can access specific Mattermost channels. + +Attribute-based access control (ABAC) provides 2 levels of control: + +- **System-wide policies** (managed by System Admins): Centralized policies that can be applied across multiple channels in the System Console. See [System-wide attribute-based access policies](/administration-guide/manage/admin/abac-system-wide-policies). +- **Channel-specific rules** (managed by Channel Admins): Self-service access rules that Channel Admins can configure directly in Channel Settings for individual channels. See [Channel-specific access rules](/administration-guide/manage/admin/abac-channel-access-rules). + +## Before you begin + +Attribute-based access controls require defined user attributes that are either synchronized from an external system (such as LDAP or SAML) or manually configured and enabled on your Mattermost server. You'll need to [configure user attributes](/administration-guide/manage/admin/user-attributes) in the System Console first before creating access policies. + +Each attribute becomes a user profile option users can populate, unless you disable the **Editable by Users** option, available from Mattermost v11. Admin-managed attributes can be used in addition to the LDAP/SAML synchronized attributes for attribute-based access control rules. + +Once user attributes are defined, go to **System Console \> System Attributes \> Attribute-Based Access** to enable attribute-based access controls for your Mattermost instance. This functionality requires a Mattermost Enterprise Advanced license. + +From Mattermost v10.11, user-managed attributes are excluded from attribute-based access control (ABAC) rules by default for security reasons. This prevents access control policies from being circumvented by users editing their own profile attributes. To include user-managed attributes in ABAC rules, a system admin must explicitly enable the `EnableUserManagedAttributes` configuration setting. See the [user attribute](/administration-guide/manage/admin/user-attributes#before-you-begin) documentation for details on enabling this feature. This configuration setting is available only in Enterprise Edition Advanced and is disabled by default. + +## Configure access policies + +Once enabled, you have multiple ways to configure access policies in Mattermost: + +**System Admins can:** + +- Create [system-wide access policies](/administration-guide/manage/admin/abac-system-wide-policies) that can be assigned across multiple channels in the System Console. +- Assign [individual channel policies](/administration-guide/manage/admin/abac-system-wide-policies#define-access-controls-per-channel) to specific channels in the System Console. + +**Channel Admins can:** + +- Configure [channel-specific access rules](/administration-guide/manage/admin/abac-channel-access-rules) directly in Channel Settings without requiring a system admin. diff --git a/docs/main/administration-guide/manage/admin/autotranslation.mdx b/docs/main/administration-guide/manage/admin/autotranslation.mdx new file mode 100644 index 000000000000..673341e5ba5a --- /dev/null +++ b/docs/main/administration-guide/manage/admin/autotranslation.mdx @@ -0,0 +1,219 @@ +--- +title: "Set up Auto-translation (Beta)" +--- +<PlanAvailability slug="ent-adv" /> + +From Mattermost v11.5, auto-translation automatically translates channel messages into each user's preferred display language. This enables multilingual teams to collaborate without language barriers. + +Auto-translation uses an asynchronous queue-based architecture. When a message is posted in a channel with auto-translation enabled, the message is queued for translation into every configured target language. Translated messages replace the original display for users whose display language matches a target language, and they can view the original text at any time by selecting the translation icon on the message. + +Two translation provider options are available: + +- **LibreTranslate**: A self-hosted, open-source machine translation engine. +- **Agents**: Uses the [Mattermost Agents plugin](/administration-guide/configure/agents-admin-guide) with a configured LLM backend. + +## Before you begin + +- A Mattermost **Enterprise Advanced** license is required. +- Choose a translation provider and ensure its infrastructure is available: + - **LibreTranslate**: A running LibreTranslate server reachable from the Mattermost server. + - **Agents**: The [Mattermost Agents plugin](/administration-guide/configure/agents-admin-guide) installed and configured with at least one LLM service. + +## Set up Auto-translation + +### Configure a translation provider + +Choose one of the following translation providers and follow the setup instructions for your choice. + +#### Set up LibreTranslate + +[LibreTranslate](https://libretranslate.com/) is a self-hosted, open-source machine translation engine. See the [LibreTranslate installation guide](https://docs.libretranslate.com/guides/installation/) for deployment instructions. + +Once your LibreTranslate server is running: + +1. Go to **System Console \> Site Configuration \> Localization**. +2. Set **Translation provider** to `libretranslate`. +3. Enter the [LibreTranslate URL](/administration-guide/configure/site-configuration-settings#libretranslate-url) (for example, `http://libretranslate.internal:5000`). +4. If your LibreTranslate instance requires authentication, enter the [LibreTranslate API key](/administration-guide/configure/site-configuration-settings#libretranslate-api-key). +5. Select **Save**. + +<Important> + +The Mattermost server must be able to reach the LibreTranslate URL over the network. Ensure firewall rules and DNS resolution allow connectivity between the Mattermost server and the LibreTranslate instance. + +</Important> + +#### Set up the Agents provider + +The Agents provider uses the Mattermost Agents plugin to translate messages via a configured LLM service. + +Prerequisites: + +- The [Mattermost Agents plugin](/administration-guide/configure/agents-admin-guide) is installed and enabled. +- At least one LLM service is configured in the Agents plugin. + +To configure: + +1. Go to **System Console \> Site Configuration \> Localization**. +2. Set **Translation provider** to `agents`. +3. Enter the [Agents LLM service ID](/administration-guide/configure/site-configuration-settings#agents-llm-service-id) matching the LLM service configured in the Agents plugin. +4. Select **Save**. + +<Tip> + +**Choosing between LibreTranslate and Agents**: LibreTranslate is a lightweight, self-hosted translation engine. The Agents provider uses an LLM backend and generally produces more accurate translations, especially for languages such as Japanese, Korean, and Chinese where contextual understanding improves quality. Consider your translation quality needs and existing infrastructure when choosing. + +**Choosing an LLM for the Agents provider**: Smaller, faster models are recommended for auto-translation. Translation is a well-defined task that doesn't benefit from the extended reasoning capabilities of larger models — larger models may actually overthink the task, adding unnecessary latency without improving quality. A model like `gpt-3.5-turbo` provides accurate translations with lower latency. + +</Tip> + +### Enable auto-translation + +1. Go to **System Console \> Site Configuration \> Localization**. +2. Set [Enable autotranslation](/administration-guide/configure/site-configuration-settings#enable-autotranslation) to **True**. +3. Select a [Translation provider](/administration-guide/configure/site-configuration-settings#translation-provider) (`libretranslate` or `agents`). +4. Configure [Languages allowed](/administration-guide/configure/site-configuration-settings#languages-allowed) — every message in auto-translation-enabled channels is translated into each language in this list. +5. Select **Save**. + +Use the [Restrict autotranslation in direct and group messages](/administration-guide/configure/site-configuration-settings#restrict-autotranslation-in-direct-and-group-messages) setting to control whether auto-translation can be enabled in direct and group messages. + +See the [auto-translation configuration reference](/administration-guide/configure/site-configuration-settings#autotranslation) for all available settings. + +### Enable auto-translation in a channel + +Auto-translation is managed on a per-channel basis and is disabled by default for all channels. System admins and channel admins can enable or disable auto-translation for individual channels. + +- When auto-translation is enabled or disabled in a channel, a system post notifies channel members of the change. + +<Note> + +Enabling auto-translation in a channel only translates new messages going forward. Existing message history is not retroactively translated. + +</Note> + +## Tune worker performance + +For most deployments the default worker settings are sufficient. If your deployment has a high message volume, many configured target languages, or you observe growing translation queue depth, you may need to increase the worker count. This section explains how to calculate and monitor the right values. + +### How the translation queue works + +When a message is posted in a channel with auto-translation enabled, it's added to a per-node translation queue. A worker picks up the post and translates it sequentially into each configured target language. Each completed language translation triggers a websocket broadcast to the channel so users see translations arrive in real time. + +In a high availability deployment, each node runs its own pool of workers and processes its own queue independently. + +### Calculate your worker count + +Use the following formula to estimate how many workers each node needs: + +``` text +required_workers = ceil( + (posts_per_sec × pct_autotranslated × num_languages × avg_provider_latency_ms / 1000) + / num_app_nodes + × 1.2 +) +``` + +Where: + +- **posts_per_sec** — average message rate across the server. +- **pct_autotranslated** — fraction of posts in auto-translation-enabled channels (0.0–1.0). +- **num_languages** — number of configured target languages. +- **avg_provider_latency_ms** — mean response time from the translation provider in milliseconds. +- **num_app_nodes** — number of Mattermost application nodes. +- **1.2** — headroom factor (20%) to absorb traffic bursts. + +The following table shows results from load tests with 6,500 concurrent users, 2 app nodes, ~5 posts/sec, and ~2 s mean provider latency. The provider latency distribution used in testing was realistic, with buckets ranging from 500 ms to 10 s weighted toward the 500 ms–1.5 s range, producing a ~2 s mean. + +<table> +<colgroup> +<col style={{width: '30%'}} /> +<col style={{width: '30%'}} /> +<col style={{width: '40%'}} /> +</colgroup> +<thead> +<tr> +<th>Target languages</th> +<th>% autotranslated</th> +<th>Workers per node</th> +</tr> +</thead> +<tbody> +<tr> +<td>7</td> +<td>100%</td> +<td>38</td> +</tr> +<tr> +<td>6</td> +<td>100%</td> +<td>32</td> +</tr> +<tr> +<td>3</td> +<td>75%</td> +<td>8</td> +</tr> +</tbody> +</table> + +<Note> + +In the 6-language test the formula yields 33, but workers were capped at 32 due to the configured maximum. Adjust the [Translation workers](/administration-guide/configure/site-configuration-settings#translation-workers) setting to match your calculated value. + +</Note> + +### Scaling considerations + +- **Target languages are the biggest multiplier.** Each additional language increases both worker time per post and the number of websocket broadcasts per post. Reducing the number of target languages is the most effective way to reduce load. +- **Websocket traffic scales with languages.** Each target language produces one channel-wide websocket broadcast per translated post. Under high load, the main symptom of saturation is websocket disconnects caused by per-connection send queues filling up. +- **Provider latency shapes traffic patterns.** Lower latency means translations complete in quicker bursts, concentrating websocket traffic. Higher latency spreads events over time. Monitor provider response times and factor them into your capacity planning. + +### Monitor with Prometheus + +Mattermost exposes the following Prometheus metrics for auto-translation: + +- `mattermost_autotranslation_queue_depth_total` *(Gauge)* — current tasks waiting in the queue. A steadily rising value means workers can't keep up with incoming posts. + +- `mattermost_autotranslation_provider_call_duration_seconds` *(Histogram; labels: provider, result)* — translation provider latency. This is the `avg_provider_latency_ms` value used in the formula above. Calculate the average with the following PromQL query: + + ``` promql + rate(mattermost_autotranslation_provider_call_duration_seconds_sum{result="success"}[10m]) + / + rate(mattermost_autotranslation_provider_call_duration_seconds_count{result="success"}[10m]) + ``` + +- `mattermost_autotranslation_worker_task_duration_seconds` *(Histogram)* — total time for a worker to process one post across all target languages. + +### Configuration reference + +- [Translation workers](/administration-guide/configure/site-configuration-settings#translation-workers): The number of concurrent workers per node. Default is **6**. Increase this value for high-traffic deployments or decrease it to reduce resource consumption. +- [Translation timeout](/administration-guide/configure/site-configuration-settings#translation-timeout): The maximum time in milliseconds for a single translation request. Default is **5000** ms (5 seconds). Increase this value if your translation provider is experiencing timeouts due to network latency or high load. + +You can also update the worker count from the command line using mmctl: + +``` shell +mmctl config set AutoTranslationSettings.Workers <number> +``` + +## Frequently asked questions + +### Why aren't messages being translated? + +- Verify auto-translation is enabled globally in **System Console \> Site Configuration \> Localization**. +- Verify auto-translation is enabled for the specific channel. +- Confirm a translation provider is selected and properly configured. +- Check that the Mattermost server can reach the translation provider (LibreTranslate URL or Agents plugin). +- Review Mattermost server logs for translation errors. + +### What happens when the translation provider is unavailable? + +Messages are still posted normally. Translations that fail due to provider downtime are skipped, and users see the original untranslated message. When the provider recovers, new messages are translated as expected. + +### What languages are supported? + +Supported languages depend on the translation provider: + +- **LibreTranslate**: Supports the languages available in your LibreTranslate deployment. See the [LibreTranslate language list](https://libretranslate.com/languages) for details. +- **Agents**: Language support depends on the capabilities of the configured LLM. Most modern LLMs support a wide range of languages. + +Configure the [Languages allowed](/administration-guide/configure/site-configuration-settings#languages-allowed) setting to specify which languages all messages are translated into. diff --git a/docs/main/administration-guide/manage/admin/content-flagging.mdx b/docs/main/administration-guide/manage/admin/content-flagging.mdx new file mode 100644 index 000000000000..e56bfe3b1b8e --- /dev/null +++ b/docs/main/administration-guide/manage/admin/content-flagging.mdx @@ -0,0 +1,113 @@ +--- +title: "Data Spillage Handling" +--- +<PlanAvailability slug="entry-adv" /> + +Data Spillage Handling helps prevent accidental data spillage and helps system administrators respond quickly to potential leaks without disrupting collaboration. Enabling this feature empowers Mattermost users to report messages that may contain sensitive, regulated, or inappropriate information, and enables designated content reviewers to assess and take appropriate action by removing or dismissing quarantined messages. + +By making every team member a first line of defense against sensitive-data exposure, Data Spillage Handling strengthens mission-critical, secure deployments and supports compliance with organizational and regulatory data-handling standards. + +## Before you begin + +You must be a System Admin in Mattermost. You need to identify who will be content reviewers for quarantined messages, and you need to decide whether quarantined messages should be hidden from users in Mattermost while under review. + +## Enable + +Data Spillage Handling isn't enabled by default. To enable Data Spillage Handling: + +1. Go to **System Console \> Site Configuration \> Data Spillage Handling**. +2. Set **Enable Data Spillage Handling** to **True**. + +Alternatively, you can configure Data Spillage Handling via the [config.json file or through environment variables](/administration-guide/configure/site-configuration-settings#content-flagging). + +## Configure + +1. Under **Content Reviewers**, define who should review quarantined content: + + - **Same reviewers for all teams**: Set to **True** to apply one global reviewer list across all teams, or **False** to configure reviewers per team. + - **Reviewers**: Start typing to search for users to assign as content reviewers. + + <div class="important"> + + <div class="title"> + + Important + + </div> + + Choose reviewers carefully. Assigning reviewer roles grants access to potentially sensitive information and may expose data from private channels. + + - A global reviewer can view quarantined messages from all teams and channels, including private channels they’re not a member of. + - Team-specific reviewers can view quarantined messages from their assigned teams, including private channels within those teams they’re not members of. + + </div> + + - **Additional reviewers**: Optionally include: + - **System Administrators**: System admins receive quarantined messages for all teams they are part of. + - **Team Administrators**: Team admins receive quarantined messages for their respective teams. + +2. Under **Notification Settings**, specify who receives updates at each stage of the quarantine workflow when content is quarantined or reviewed: + + - **Notify when content is quarantined**: Reviewer(s), Author. + - **Notify when a reviewer is assigned**: Reviewer(s). + - **Notify when content is removed**: Reviewer(s), Author, Reporter. + - **Notify on dismissal**: Reviewer(s), Author, Reporter. + + All notifications are sent via the **Data Spillage Bot** as direct messages. + +3. Under **Additional Settings**, configure how the quarantine workflow behaves: + + - **Reasons for quarantine**: Define the preset categories that appear in the quarantine dialog for users (for example: **Classification mismatch**, **Need-to-know violation**, **Personally identifiable information (PII) exposure**, **Operational security (OPSEC) concern**, **Controlled Unclassified Information (CUI) violation**). + - **Require reporters to add comment**: Set to **True** to require users to add a short explanation when quarantining a message. + - **Require reviewers to add comment**: Set to **True** to require reviewers to add a comment when resolving a quarantine. + - **Hide message from channel while it is being reviewed**: Set to **True** to automatically hide quarantined messages from the channel until reviews are complete. If a root post is quarantined, the entire thread is hidden. + +<Tip> + +We recommend enabling **Hide message from channel while it is being reviewed** and require comments from both reporters and reviewers to maintain transparency, accountability, and an auditable record of actions. + +</Tip> + +## Monitor quarantined messages + +When [a user quarantines a message](/end-user-guide/collaborate/flag-messages), the **Data Spillage Bot** sends a direct message to all content reviewers. + +Direct messages from the **Data Spillage Bot** is a centralized moderation queue, where reviewers can view, assign, and act on quarantined messages without leaving Mattermost. Reviewers can use it to monitor potential data spills, coordinate response, and maintain an auditable record of review activity. + +Each quarantined message appears as a card-formatted message that includes: + +- **Quarantined by**: The user who reported the message. +- **Status**: The current state of the review. All quarantined content starts in **Pending** status. +- **Reason**: The reason selected by the reporter (for example, **Classification mismatch**, **Need-to-know violation**). +- **Message preview**: A snippet of the quarantined message, including the author, timestamp, and original channel. +- **Reviewer**: The user currently assigned to review the message (initially **Unassigned**). +- **Channel**: The name of the channel where the message was originally posted. +- **Team**: The team context for the quarantined message. +- **Comment**: Any reporter-provided context. +- **Post ID**: The system identifier for the original message for auditing purposes. + +Reviewers can select **View details** to take action as follows: + +- Assign a **Reviewer** responsible for reviewing the quarantined message. +- **Remove message**: Permanently delete the quarantined message from its original channel for all users. The status of the quarantined message changes to **Removed**. +- **Keep message**: Dismiss the quarantine and restore the message if it was hidden. The status of the quarantined message changes to **Retained**. +- **Add a comment**: Record the reason for the decision when required. + +Once an action is taken, the **Status** field updates automatically. The **Data Spillage Bot** sends follow-up notifications to the reporter, author, and other reviewers based on how Data Spillage Handling is configured. + +### Deleted messages + +When a reviewer permanently removes a quarantined message, the message and all associated data are deleted from the database and can't be recovered, including: + +- Message content and properties: The text of the message and any associated post properties. +- File metadata: Information about files attached to the message (e.g., file names, IDs, and links to storage). +- File metadata from edit history: Information about files attached to earlier versions of the message. +- Edit history: All previous versions of the message and their timestamps. +- Uploaded files: The actual files stored in Mattermost’s file storage (local, S3, etc.). +- Priority data: Any message priority or importance settings. +- Acknowledgements: Records of users who acknowledged the message. +- Reminders: Any reminders created for the message. + +## Best practice recommendations + +Before rolling out Data Spillage Handling organization-wide, we recommend communicating that the feature protects both users and the organization from accidental data spillage. Start with a pilot team to validate reviewer notifications and workflows, integrate the process with existing data-handling or incident-response playbooks, and require reporter and reviewer comments to ensure every decision is transparent and auditable. diff --git a/docs/main/administration-guide/manage/admin/customize-branding.mdx b/docs/main/administration-guide/manage/admin/customize-branding.mdx new file mode 100644 index 000000000000..fc386b139f11 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/customize-branding.mdx @@ -0,0 +1,8 @@ +--- +title: "Customize branding" +--- +Whether you’re customizing the appearance of your workspace, utilizing branding tools, or managing code signing for custom builds, this section of documentation has you covered and provides everything you need to customize the branding of Mattermost to align with your organization’s identity. Use the navigation below to access detailed instructions for each customization option. + +- [Customize Mattermost](/administration-guide/configure/customize-mattermost) - Learn how to customize the Mattermost server. +- [Custom branding tools](/administration-guide/configure/custom-branding-tools) - Learn about custom branding tools for Mattermost. +- [Code signing custom builds](/administration-guide/manage/code-signing-custom-builds) - Learn about code signing custom builds of Mattermost. diff --git a/docs/main/administration-guide/manage/admin/error-codes.mdx b/docs/main/administration-guide/manage/admin/error-codes.mdx new file mode 100644 index 000000000000..a39ee4ae7760 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/error-codes.mdx @@ -0,0 +1,36 @@ +--- +title: "Mattermost error codes" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost is designed to deploy in private networks which may be disconnected or “air-gapped” from the internet. In these deployments, links to Mattermost’s online documentation may be unavailable. + +Therefore, Mattermost error codes are provided to enable administrators to use internet connected machines to look up error messages and resolutions in online resources, including Mattermost documentation and user forums, as well as providing Mattermost support teams a concise way to identify issues. + +Mattermost error codes are used in logs, administrative tools, as well as on-screen messages to concisely identify issues and connect them with additional resources. + +In advanced deployments, error codes can be overwritten by administrators to reference internal documentation and guides. + +## ERROR_SAFETY_LIMITS_EXCEEDED + +A safety limits exceeded error (`ERROR_SAFETY_LIMITS_EXCEEDED`) displays in the [free version of Mattermost](/product-overview/editions-and-offerings#mattermost-team-edition), and certain functionality may be limited, when usage grossly exceeds the recommended limit for users in a safe deployment, including more than 250 users are registered on the server. + +250 users represents a “high upper limit” for deployments that are approximately 5 times the recommended size, which is far beyond the intended design of the product. + +The free version of Mattermost is intended for approximately 50 users. If your Mattermost materially exceeds this recommended size, system admins should seek to either [purchase a commercial license](https://mattermost.com/pricing/), or apply for a [non-profit subscription](/product-overview/non-profit-subscriptions) license. Alternatively, admins can [deactivate users](/administration-guide/configure/user-management-configuration-settings#deactivate-users) until the user count falls below the high upper limit. + +## ERROR_LICENSED_USERS_LIMIT_EXCEEDED + +A licensed user limit exceeded error (`ERROR_LICENSED_USERS_LIMIT_EXCEEDED`) displays when attempting to create or activate users on a licensed Mattermost server where the user count would exceed the maximum number of users allowed by the license. + +This error occurs when: + +- Creating new users would exceed the license user limit. +- Activating deactivated users would exceed the license user limit. + +To resolve this error, system administrators can: + +- [Deactivate users](/administration-guide/configure/user-management-configuration-settings#deactivate-users) to reduce the active user count below the license limit. +- Contact [Mattermost Sales](https://mattermost.com/contact-sales/) to request an updated license that increases the number of licensed users. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/manage/admin/generating-support-packet.mdx b/docs/main/administration-guide/manage/admin/generating-support-packet.mdx new file mode 100644 index 000000000000..d420ea698b1f --- /dev/null +++ b/docs/main/administration-guide/manage/admin/generating-support-packet.mdx @@ -0,0 +1,395 @@ +--- +title: "Generate a Support Packet" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +The Support Packet is used to help customers diagnose and troubleshoot issues. Use the System Console or the [mmctl system supportpacket](/administration-guide/manage/mmctl-command-line-tool#mmctl-system-supportpacket) command to generate a zip file that includes configuration information, logs, plugin details, and data on external dependencies across all nodes in a high-availability cluster. Confidential data, such as passwords, are automatically stripped. + +## Generate + +<Important> + +- Before generating a Support Packet, go to **System Console \> Environment \> Logging** and ensure **Output logs to file** is set to **true**, and set **File Log Level** to **DEBUG** +- From Mattermost v11.4, support packet generation is recorded in the audit log (when [audit logging is enabled and configured](/administration-guide/manage/logging#audit-logging)). The audit event includes the username, timestamp, success/failure status, whether logs were included, plugin packets requested, and the output filename. This audit trail helps track access to potentially sensitive log data for compliance purposes. + +</Important> + +<div class="tab"> + +Web/Desktop + +1. Go to the System Console, and select **Commercial Support** from the System Console menu. + + ![Example of available System Console menu options.](/images/system-console-commercial-support.png) + +2. Select **Download Support Packet**. A zip file is downloaded to the local machine. You'll be notified if any packet files are unavailable during packet generation. See the `warning.txt` file for details. + +</div> + +<div class="tab"> + +mmctl + +Run the [mmctl system supportpacket](/administration-guide/manage/mmctl-command-line-tool#mmctl-system-supportpacket) command to generate and download a Support Packet to share with Mattermost Support. + +``` sh +go run ./cmd/mmctl system supportpacket +``` + +``` text +Downloading Support Packet +Downloaded Support Packet to mattermost_support_packet_.zip +``` + +</div> + +## Santitize confidential data + +Please sanitize any confidential data you wish to exclude before sharing the packet with Mattermost. + +When present, the following information is automatically santized during packet generation: `LdapSettings.BindPassword`, `FileSettings.PublicLinkSalt`, `FileSettings.AmazonS3SecretAccessKey`, `EmailSettings.SMTPPassword`, `GitLabSettings.Secret`, `GoogleSettings.Secret`, `Office365Settings.Secret`, `OpenIdSettings.Secret`, `SqlSettings.DataSource`, `SqlSettings.AtRestEncryptKey`, `ElasticsearchSettings.Password`, `All SqlSettings.DataSourceReplicas`, `All SqlSettings.DataSourceSearchReplicas`, `MessageExportSettings.GlobalRelaySettings.SmtpPassword`, `ServiceSettings.SplitKey`, `FileSettings.ExportAmazonS3SecretAccessKey`, `ElasticsearchSettings.ClientKey`, `ServiceSettings.GoogleDeveloperKey`, and `ServiceSettings.GiphySdkKey` (from Mattermost v11.6.0). + +<Important> + +Plugins may not be sanitized during packet generation. + +- From Mattermost v10.1, plugins can mark their configuration as hidden. If a plugin marks its configuration as hidden, the configuration is sanitized during packet generation. +- Otherwise, ensure you sanitize any additional confidential details in the `plugin.json` file before sharing it with Mattermost. Replace details with example strings that contain the same special characters if possible, as special characters are common causes of configuration errors. + +</Important> + +## Share the packet with Mattermost + +Add the generated Support Packet to a [standard support request](https://support.mattermost.com/hc/en-us/requests/new), or share with with the Mattermost team you're working with. + +<Important> + +Disable debug logging once you've generated the Support Packet. Debug logging can cause log files to expand substantially, and may adversely impact server performance. We recommend enabling it temporarily, or in development environments, but not production enviornments. + +</Important> + +## Contents of a Support Packet + +The contents of a Mattermost Support Packet can differ by server version. Select the tab that corresponds to your Mattermost version to see the files included in the Support Packet. + +<div class="tab" parse-titles=""> + +v11.0 and later + +### Cluster-wide files + +The following cluster-wide files are located in the root directory of the Support Packet: + +- [metadata.yaml](#metadata) +- `plugins.json` (all active and inactive plugins) +- `sanitized_config.json` (sanitized copy of the Mattermost configuration) +- `stats.yaml` (Mattermost usage statistics) +- `jobs.yaml` (last runs of important jobs) +- `diagnostics.yaml` (system and plugin diagnostics) +- `permissions.yaml` (role and scheme information) +- `postgres_schema_dump.sql` (PostgreSQL database schema information including tables, indexes, constraints, and other metadata to assist with database configuration diagnosis) +- `warning.txt` (present when issues are encountered during packet generation) +- `tsdb_dump.tar.gz` (present when the Metrics plugin is installed and the **Performance metrics** option is selected when generating the Support Packet) + +### Node-specific files + +The following node-specific files are located in node subdirectories: + +- `<node-id>/mattermost.log` (Mattermost logs for each node) +- `<node-id>/audit.log` (Mattermost audit logs for each node) +- `<node-id>/ldap.log` (AD/LDAP logs for each node) +- `<node-id>/notifications.log` (notifications logs for each node) +- `<node-id>/cpu.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/heap.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/goroutines` ([Go performance metrics](#go-performance-metrics) for each node) + +### Diagnostics highlights + +The Support Packet `diagnostics.yaml` file includes system and plugin diagnostics to support troubleshooting and configuration validation. + +### Plugin diagnostic data + +The following additional plugin diagnostic data is available when the plugin is enabled and operational: + +- GitHub: `/github/diagnostics.yaml` +- GitLab: `/com.github.manland.mattermost-plugin-gitlab/diagnostics.yaml` +- Jira: `/jira/diagnostics.yaml` +- Calls: `/com.mattermost.calls/diagnostics.yaml` +- Boards: `/focalboard/diagnostics.yaml` +- Playbooks: `/playbooks/diagnostics.yaml` +- MSCalendar: `/com.mattermost.mscalendar/diagnostics.yaml` +- Google Calendar: `/com.mattermost.gcal/diagnostics.yaml` + +</div> + +<div class="tab"> + +v10.11 + +From v10.11, Support Packets include PostgreSQL database schema dump information that provides comprehensive metadata to help diagnose database configuration issues, performance problems, collation mismatches, and other database-related issues. + +**Cluster-wide files (root directory):** + +- [metadata.yaml](#metadata) +- `plugins.json` (all active and inactive plugins) +- `sanitized_config.json` (sanitized copy of the Mattermost configuration) +- `stats.yaml` (Mattermost usage statistics) +- `jobs.yaml` (last runs of important jobs) +- `diagnostics.yaml` (core plugin diagnostics data) +- `permissions.yaml` (role & scheme information) +- `postgres_schema_dump.sql` (PostgreSQL database schema information including tables, indexes, constraints, and other database metadata to assist with database configuration diagnosis) +- `warning.txt` (present when issues are encountered during packet generation) +- `tsdb_dump.tar.gz` (present when the Metrics plugin is installed and the **Performance metrics** option is selected when generating the Support Packet) + +**Cluster-specific files (in node subdirectories):** + +- `<node-id>/mattermost.log` (Mattermost logs for each node) +- `<node-id>/audit.log` (Mattermost audit logs for each node) +- `<node-id>/ldap.log` (AD/LDAP logs for each node) +- `<node-id>/notifications.log` (notifications logs for each node) +- `<node-id>/cpu.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/heap.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/goroutines` ([Go performance metrics](#go-performance-metrics) for each node) + +The following additional plugin diagnostic data is included in the generated Support Packet when the plugin is enabled and operational: + +- GitHub: `/github/diagnostics.yaml` +- GitLab: `/com.github.manland.mattermost-plugin-gitlab/diagnostics.yaml` +- Jira: `/jira/diagnostics.yaml` +- Calls: `/com.mattermost.calls/diagnostics.yaml` +- Boards: `/focalboard/diagnostics.yaml` +- Playbooks: `/playbooks/diagnostics.yaml` +- MSCalendar: `/com.mattermost.mscalendar/diagnostics.yaml` +- Google Calendar: `/com.mattermost.gcal/diagnostics.yaml` + +</div> + +<div class="tab"> + +v10.10 + +From Mattermost v10.10, Support Packets from [high availability](/administration-guide/scale/high-availability-cluster-based-deployment) deployments organize cluster-specific files (such as log files) in subdirectories named after each cluster node, while cluster-wide files remain in the root directory. + +Support packet file organization has been improved to make it easier to identify cluster-wide versus cluster-specific files: + +- **Cluster-wide files** (identical across all nodes in a [high-availability cluster](/administration-guide/scale/high-availability-cluster-based-deployment)) remain in the root directory of the support packet. +- **Cluster-specific files** (unique per node) are now organized in subdirectories named after each cluster node. + +**Cluster-wide files (root directory):** + +- [metadata.yaml](#metadata) +- `plugins.json` (all active and inactive plugins) +- `sanitized_config.json` (sanitized copy of the Mattermost configuration) +- `stats.yaml` (Mattermost usage statistics) +- `jobs.yaml` (last runs of important jobs) +- `diagnostics.yaml` (core plugin diagnostics data) +- `permissions.yaml` (role & scheme information) +- `warning.txt` (present when issues are encountered during packet generation) +- `tsdb_dump.tar.gz` (present when the Metrics plugin is installed and the **Performance metrics** option is selected when generating the Support Packet) + +**Cluster-specific files (in node subdirectories):** + +- `<node-id>/mattermost.log` (Mattermost logs for each node) +- `<node-id>/audit.log` (Mattermost audit logs for each node) +- `<node-id>/ldap.log` (AD/LDAP logs for each node) +- `<node-id>/notifications.log` (notifications logs for each node) +- `<node-id>/cpu.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/heap.prof` ([Go performance metrics](#go-performance-metrics) for each node) +- `<node-id>/goroutines` ([Go performance metrics](#go-performance-metrics) for each node) + +The following additional plugin diagnostic data is included in the generated support packet when the plugin is enabled and operational: + +- GitHub: `/github/diagnostics.yaml` +- GitLab: `/com.github.manland.mattermost-plugin-gitlab/diagnostics.yaml` +- Jira: `/jira/diagnostics.yaml` +- Calls: `/com.mattermost.calls/diagnostics.yaml` +- Boards: `/focalboard/diagnostics.yaml` +- Playbooks: `/playbooks/diagnostics.yaml` +- MSCalendar: `/com.mattermost.mscalendar/diagnostics.yaml` +- Google Calendar: `/com.mattermost.gcal/diagnostics.yaml` + +</div> + +<div class="tab"> + +v10.5 to v10.9 + +Prior to v10.10, each node in the cluster of a high availability deployment has its own `mattermost.log` file and advanced logging files included directly in the Support Packet. + +From v10.5, the following Support Packet data has changed: + +- The `support_packet.yaml` file has been removed and split into `diagnostics.yaml` and `stats.yaml` files. +- All fields in `diagnostics.yaml` have been moved into their own objects for improved readability. +- Field names are normalized. +- New data includes server statistics, logs, permissions, and extended job list details. +- Mattermost-supported plugin diagnostic data is included where applicable. + +The contents of a support packet include: + +- [metadata.yaml](#metadata) +- `mattermost.log` (Mattermost logs) +- `audit.log` (Mattermost audit logs) +- `ldap.log` (AD/LDAP logs) +- `notifications.log` (notifications logs) +- `plugins.json` (all active and inactive plugins) +- `sanitized_config.json` (sanitized copy of the Mattermost configuration) +- `stats.yaml` (Mattermost usage statistics) +- `jobs.yaml` (last runs of important jobs) +- `diagnostics.yaml` (core plugin diagnostics data) +- `permissions.yaml` (role & scheme information) +- [Go performance metrics](#go-performance-metrics), including: `cpu.prof`, `heap.prof`, and `goroutines` +- `warning.txt` (present when issues are encountered during packet generation) +- `tsdb_dump.tar.gz` (present when the Metrics plugin is installed and the **Performance metrics** option is selected when generating the Support Packet) + +The following additional plugin diagnostic data is included in the generated support packet when the plugin is enabled and operational: + +- GitHub: `/github/diagnostics.yaml` +- GitLab: `/com.github.manland.mattermost-plugin-gitlab/diagnostics.yaml` +- Jira: `/jira/diagnostics.yaml` +- Calls: `/com.mattermost.calls/diagnostics.yaml` +- Boards: `/focalboard/diagnostics.yaml` +- Playbooks: `/playbooks/diagnostics.yaml` +- MSCalendar: `/com.mattermost.mscalendar/diagnostics.yaml` +- Google Calendar: `/com.mattermost.gcal/diagnostics.yaml` + +</div> + +<div class="tab"> + +Prior to v10.5 + +From Mattermost v10.4, a new `diagnostics.yaml` file includes Mattermost Calls diagostics data, including plugin version, calls and active session counts, as well as average duration and participant counts. + +- [metadata.yaml](#metadata) +- `mattermost.log` +- `plugins.json` +- `sanitized_config.json` +- `support_packet.yaml` +- `diagnostics.yaml` (core plugin diagnostics data) +- [Go performance metrics](#go-performance-metrics), including: `cpu.prof`, `heap.prof`, and `goroutines` +- `warning.txt` (present when issues are encountered during packet generation) + +</div> + +<Note> + +- LDAP groups are not included during Support Packet generation. Only `LDAP Version` and `LDAP Vendor` are included when present. These values are included in the `support_packet.yaml` file. +- From Mattermost v9.11, `LDAP Vendor` errors are included in the Support Packet. If fetching the LDAP Vendor name fails, the Support Packet generation includes the error in `warning.txt`. If no LDAP Vendor name is found, the Support Packet lists them as `unknown`. + +</Note> + +## Metadata + +From Mattermost v9.11, generated Support Packets include a `metadata.yaml` file that contains the following information. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '12%'}} /> +<col style={{width: '12%'}} /> +<col style={{width: '59%'}} /> +<col style={{width: '14%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Field name</strong></th> +<th><strong>Required/Optional</strong></th> +<th><strong>Description</strong></th> +<th><blockquote> +<p><strong>Example</strong></p> +</blockquote></th> +</tr> +</thead> +<tbody> +<tr> +<td>version</td> +<td>Required</td> +<td>Version of the schema that the current metadata file is compatible with. Current version is 1.</td> +<td>1</td> +</tr> +<tr> +<td>type</td> +<td>Required</td> +<td>The type of the packet. Each type of Support Packet can be mapped to a specific component generating the Support Packet.</td> +<td>mattermost</td> +</tr> +<tr> +<td>generated_at</td> +<td>Required</td> +<td>The date and time the packet was created. Value is in epoch (ms).</td> +<td>1707473288731</td> +</tr> +<tr> +<td>server_version</td> +<td>Required</td> +<td>Version of the server that the Support Packet was generated at. Semver is expected.</td> +<td>9.1.1</td> +</tr> +<tr> +<td>server_id</td> +<td>Required</td> +<td>Unique identifier of the server. Expected to be 26 characters or longer.</td> +<td>9qpiszyjr3g8bxda35abcd1234</td> +</tr> +<tr> +<td>license_id</td> +<td>Optional</td> +<td>Unique identifier of the current server's license. Expected to be 26 characters or longer. This field is empty when there's no license.</td> +<td>abcdejisd67yigqhmkz4ho1234</td> +</tr> +<tr> +<td>customer_id</td> +<td>Optional</td> +<td>The id of the customer, as defined in the license file. Expected to be 26 characters or longer. Empty when there's no license.</td> +<td>a1b2c3d4qbbr5cpkbpbmef123h</td> +</tr> +<tr> +<td>extras</td> +<td>Optional</td> +<td>Key/value of any additional information, specific to the plugin/component that generated the file. Can be useful for identifying the contents of the data. Consider adding plugin (or component) versions in order to set expectation regarding the contents of this object.</td> +<td></td> +</tr> +<tr> +<td>extras.plugin_id</td> +<td>Required for plugins</td> +<td>The ID of the plugin.</td> +<td></td> +</tr> +<tr> +<td>extras.plugin_version</td> +<td>Required for plugins</td> +<td>The version of the plugin.</td> +<td></td> +</tr> +</tbody> +</table> + +For example: + +``` yaml +version: 1 +type: support-packet +generated_at: 1622569200 +server_version: 9.1.1 +server_id: 8fqk9rti13fmpxdd5934a3xsxh +license_id: 3g3pqn8in3brzjkozcn1kdidgr +customer_id: 74cmws7gf3ykpj31car7zahsny +extras: + plugin_version: 0.1.0 +``` + +## Go performance metrics + +The Support Packet contains 3 go runtime profiling files: + +- `cpu.prof` contains a 5-second CPU profile +- `heap.prof` contains a heap profile +- `goroutines` contains a dump of all the running go routines + +These files can be read using [pprof](https://golang.google.cn/cmd/pprof/). + +Use `go tool pprof -web X` to open a visualization of the profile in your browser, replacing `X` with the profile's file name. + +## Load metric + +From Mattermost v10.10, the **Load Metric** field under **Product Menu \> About Mattermost** displays monthly active users relative to the total number of licensed users. This value gives Mattermost support teams a contextual reference point for understanding deployment active usage for troubleshooting and guidance. It isn’t a comprehensive performance monitoring tool or health indicator, but serves as a supplementary data point when traditional diagnostic methods aren’t available. diff --git a/docs/main/administration-guide/manage/admin/installing-license-key.mdx b/docs/main/administration-guide/manage/admin/installing-license-key.mdx new file mode 100644 index 000000000000..8d6468ec7552 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/installing-license-key.mdx @@ -0,0 +1,67 @@ +--- +title: "Install a license key" +--- +<PlanAvailability slug="all-commercial" /> + +You can use the System Console or the mmctl tools to add or change a Mattermost license key. + +<div class="tab"> + +Use System Console + +1. Go go **System Console \> About \> Edition and License**. +2. Upload your license key file. + +Once the key is uploaded and installed, the details of your license are displayed. + +</div> + +<div class="tab"> + +Use mmctl + +Use the [mmctl license upload](/administration-guide/manage/mmctl-command-line-tool#mmctl-license-upload) command to upload a new license or replace an existing license file with a new one. When complete, restart the Mattermost server. If you're running in a [High Availability](/administration-guide/scale/high-availability-cluster-based-deployment) environment, the new license file must be updated to every node. + +``` sh +mmctl license upload [license] [flags] +``` + +</div> + +<Note> + +- From Mattermost v10.11, the option to add a license is disabled when the license is set using an [environment variable](/administration-guide/configure/environment-configuration-settings#license-file-location). +- Enterprise customers with the Premier Support add-on can request a staging license for testing. +- Removing a Mattermost Enterprise or Professional license key won't remove the configuration for Enterprise settings; however, these features won't function until an Enterprise or Professional license key is applied. +- When you're using [High Availability](/administration-guide/scale/high-availability-cluster-based-deployment), it's critical to ensure that all servers in the cluster have same Enterprise license properly installed to prevent multi-node clusters from failing. An Enterprise license is required for High Availability to work. +- When you apply an Enterprise license key to a server previously licensed for Professional, Professional features retain their configuration settings in Enterprise. +- When you apply a Professional license to a server previously licensed for Enterprise, Enterprise features retain their configuration but will no longer be accessible for use. + +</Note> + +## Change an existing license key + +You don't need to wait for your current license key to expire before replacing it with a new license from Mattermost. The server only checks for seat count and license end date, not the start date, so you can apply a new license as soon as you receive it. However, ensure your new license is for a seat count that's greater than or equal to your current total number of Mattermost users. + +<Tip> + +To review license usage before uploading a new key, go to **System Console \> Reporting \> Site Statistics**. The **Total Activated Users** field shows the primary paid seat count used for license validation. Review **Single-channel Guests** separately because guests in exactly one channel are tracked outside the primary paid seat count, are free up to a 1:1 ratio with licensed seats, and generate warnings instead of hard enforcement when that allowance is exceeded. + +</Tip> + +Follow these steps to change your license key: + +1. Go to **System Console \> About \> Edition and License**. +2. From Mattermost v6.7, simply upload your new license key file. + +<Note> + +If you're running a Mattermost release older than v6.7, select **Remove Enterprise License and Downgrade Server** to clear the license from the server and refresh the System Console first before uploading the new key. + +</Note> + +## License key storage + +Once you've uploaded your license key to your Mattermost server, it's stored in your SQL database at `mattermost.Licenses`. You can check what keys are on your server by running `select * from mattermost.Licenses;`. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/manage/admin/migration.mdx b/docs/main/administration-guide/manage/admin/migration.mdx new file mode 100644 index 000000000000..547ad92c7c1b --- /dev/null +++ b/docs/main/administration-guide/manage/admin/migration.mdx @@ -0,0 +1,14 @@ +--- +title: "Migration" +--- +This Mattermost Migration Guide is organized into sections based on migration scenarios and tools to help you transition smoothly to Mattermost or optimize your current setup. + +Whether you’re migrating from another platform, upgrading your database, or using bulk tools for data management, this guide provides the resources and instructions you need for a successful migration. Use the navigation below to explore detailed guidance tailored to your migration needs. + +- [Migrate from MySQL to PostgreSQL](/deployment-guide/postgres-migration) - Learn how to migrate from MySQL to PostgreSQL. +- [Server migration guide](/administration-guide/onboard/migrating-to-mattermost) - Learn about about migrating to Mattermost. +- [Migrate from Slack](/administration-guide/onboard/migrate-from-slack) - Learn how to migrate from Slack to Mattermost. +- [Migrate from Gitlab Omnibus](/administration-guide/onboard/migrate-gitlab-omnibus) - Learn how to migrate from GitLab Omnibus to a standalone Mattermost installation. +- [Bulk export tool](/administration-guide/manage/bulk-export-tool) - Learn about the bulk export tool for Mattermost. +- [Bulk loading tool](/administration-guide/onboard/bulk-loading-data) - Learn about the bulk loading tool for Mattermost. +- [Migration announcement email template](/administration-guide/onboard/migration-announcement-email) - Use this email template to notify your users that you've migrated to Mattermost. diff --git a/docs/main/administration-guide/manage/admin/monitoring-and-performance.mdx b/docs/main/administration-guide/manage/admin/monitoring-and-performance.mdx new file mode 100644 index 000000000000..c2159ee3621a --- /dev/null +++ b/docs/main/administration-guide/manage/admin/monitoring-and-performance.mdx @@ -0,0 +1,24 @@ +--- +title: "Monitoring and performance" +--- +This Monitoring and Performance Guide is organized into sections to help you effectively monitor, optimize, and manage the performance of your Mattermost installation. + +From collecting performance metrics and deploying monitoring tools to configuring health checks and managing notifications, this guide offers comprehensive resources to ensure your Mattermost workspace operates at peak efficiency. Use the navigation below to explore detailed instructions and best practices. + +- [Optimize your Mattermost workspace](/administration-guide/configure/optimize-your-workspace) - Learn about optimizing your Mattermost workspace. +- [Collect performance metrics](/administration-guide/scale/collect-performance-metrics) - Learn about collecting performance metrics for Mattermost. +- [Deploy Prometheus and Grafana for performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) - Learn how to deploy Prometheus and Grafana for performance monitoring. +- [Performance monitoring metrics](/administration-guide/scale/performance-monitoring-metrics) - Learn about performance monitoring metrics for Mattermost. +- [Deploy Grafana Loki for centralized logging](/administration-guide/scale/deploy-grafana-loki-for-centralized-logging) - Learn how to deploy Grafana Loki for centralized logging. +- [Push notification health targets](/administration-guide/scale/push-notification-health-targets) - Learn about push notification health targets for Mattermost. +- [Performance alerting guide](/administration-guide/scale/performance-alerting) - Learn about performance alerting for Mattermost. +- [Ensuring releases perform at scale](/administration-guide/scale/ensuring-releases-perform-at-scale) - Learn how to ensure releases perform at scale for Mattermost. +- [Manage user surveys](/administration-guide/configure/manage-user-surveys) - Learn about managing user surveys for Mattermost. +- [User satisfaction surveys](/administration-guide/manage/user-satisfaction-surveys) - Learn how to send user satisfaction surveys for Mattermost. +- [Notify admin](/administration-guide/upgrade/notify-admin) - Learn how to notify admins for Mattermost. +- [System-wide notifications](/administration-guide/manage/system-wide-notifications) - Learn about system-wide notifications for Mattermost. +- [Statistics](/administration-guide/manage/statistics) - Learn about Mattermost statistics . +- [In-product notices](/administration-guide/manage/in-product-notices) - Learn how to use in-product notices for Mattermost. +- [Health checks](/administration-guide/manage/request-server-health-check) - Learn about health checks for Mattermost. +- [Health check probes](/administration-guide/manage/configure-health-check-probes) - Learn how to set up health check probes for Mattermost. +- [Product limits](/administration-guide/manage/product-limits) - Learn about product limits for Mattermost. diff --git a/docs/main/administration-guide/manage/admin/self-hosted-billing.mdx b/docs/main/administration-guide/manage/admin/self-hosted-billing.mdx new file mode 100644 index 000000000000..463c2afb4107 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/self-hosted-billing.mdx @@ -0,0 +1,14 @@ +--- +title: "Self-hosted billing" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost commercial plans are offered as an annual subscription service. With your purchase you're provided with a license key. Depending on which version of Mattermost you're on, you may have to download and apply this license manually via the System Console. + +When you upgrade to commercial plan, the number of user seats you need has to be equal to or greater than your current number of activated users (formerly called active users). + +You can add new users to your deployment at any time. Every quarter, during the true-up review (section 3.5 License True-up Review of Software License Agreement, also referenced in docs), we check the license license seat count relative to number of activated users. If there's a difference, we'll provide you with a new invoice which is payable immediately. + +Please see the [self-hosted subscriptions documentation](/product-overview/self-hosted-subscriptions#buy-a-subscription) for more detailed information. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/manage/admin/server-configuration.mdx b/docs/main/administration-guide/manage/admin/server-configuration.mdx new file mode 100644 index 000000000000..87493caa50f8 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/server-configuration.mdx @@ -0,0 +1,22 @@ +--- +title: "Server configuration" +--- +This Server Configuration Guide is organized into sections to provide you with the tools and knowledge necessary to configure your Mattermost server for improved efficiency, scalability, and functionality. + +Whether you’re setting up email notifications, optimizing search capabilities, enabling high availability, or configuring telemetry, this guide covers all aspects of server setup and management. Use the navigation below to access detailed instructions for each topic. + +- [Store configuration in your database](/administration-guide/configure/configuration-in-your-database) - Learn how to store configuration information in your Mattermost database rather than as a JSON file. +- [Server configuration options](/administration-guide/configure/configuration-settings) - Learn about server configuration options for Mattermost. +- [Set up attribute-based access controls](/administration-guide/manage/admin/attribute-based-access-control) - Learn how to set up attribute-based access controls for your Mattermost instance for Zero Trust Security. +- [Set up Mattermost Agents](/administration-guide/configure/agents-admin-guide) - Learn how to enable AI-powered Agents for your Mattermost instance. +- [Set up auto-translation](/administration-guide/manage/admin/autotranslation) - Learn how to enable and configure automatic message translation for your Mattermost instance. +- [Install Mattermost Boards](/administration-guide/configure/install-boards) - Learn how to install and configure the Boards plugin for your Mattermost instance. +- [Manage custom user attributes](/administration-guide/manage/admin/user-attributes) - Learn how to manage custom user attributes in user profiles in Mattermost. +- [Environment variables](/administration-guide/configure/environment-variables) - Learn how to use environment variables for Mattermost configuration. +- [Customize the server](/administration-guide/manage/admin/customize-branding) - Learn about customizing branding for Mattermost server. +- [SMTP email setup](/administration-guide/configure/smtp-email) - Learn how to set up SMTP email for Mattermost. +- [Email templates](/administration-guide/configure/email-templates) - Learn about customizing email templates for Mattermost. +- [Chinese, Japanese, and Korean search](/administration-guide/configure/enabling-chinese-japanese-korean-search) - Learn about enabling Chinese, Japanese, and Korean search for Mattermost. +- [SSL client certificate setup](/administration-guide/onboard/ssl-client-certificate) - Learn how to set up SSL client certificates for Mattermost. +- [Connected workspaces](/administration-guide/onboard/connected-workspaces) - Learn how to connect Mattermost workspaces. +- [Telemetry](/administration-guide/manage/telemetry) - Learn about Mattermost telemetry and data collection. diff --git a/docs/main/administration-guide/manage/admin/server-maintenance.mdx b/docs/main/administration-guide/manage/admin/server-maintenance.mdx new file mode 100644 index 000000000000..eaafc2de050d --- /dev/null +++ b/docs/main/administration-guide/manage/admin/server-maintenance.mdx @@ -0,0 +1,17 @@ +--- +title: "Server maintenance" +--- +This Server Maintenance Guide is organized into sections that provide the tools and knowledge needed to maintain your Mattermost server effectively, ensuring optimal security, scalability, and reliability. + +Whether you’re installing a license key, performing backups, upgrading the server, or using administrative tools like mmctl and the CLI, this guide offers comprehensive instructions to help you manage your server with confidence. Use the navigation below to access detailed information on each topic. + +- [Install a license key](/administration-guide/manage/admin/installing-license-key) - Learn how to install a license key for Mattermost. +- [Generate a support packet](/administration-guide/manage/admin/generating-support-packet) - Learn how to generate a support packet for Mattermost. +- [Backup and disaster recovery](/deployment-guide/backup-disaster-recovery) - Learn about backup and disaster recovery for Mattermost. +- [Upgrade Mattermost server](/administration-guide/upgrade-mattermost) - Learn how to upgrading Mattermost server. +- [Secure Mattermost](/security-guide/secure-mattermost) - Learn about securing Mattermost server. +- [Mattermost error codes](/administration-guide/manage/admin/error-codes) - Learn about Mattermost error codes and troubleshooting. +- [Logging](/administration-guide/manage/logging) - Learn how to customize logging options based on business practices and needs. +- [mmctl](/administration-guide/manage/mmctl-command-line-tool) - Learn about the mmctl command line tool for Mattermost. +- [CLI](/administration-guide/manage/command-line-tools) - Learn about command line tools for Mattermost. +- [Feature labels](/administration-guide/manage/feature-labels) - Learn about Mattermost feature labels and their meanings. diff --git a/docs/main/administration-guide/manage/admin/user-attributes.mdx b/docs/main/administration-guide/manage/admin/user-attributes.mdx new file mode 100644 index 000000000000..205a1caa6843 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/user-attributes.mdx @@ -0,0 +1,161 @@ +--- +title: "User attributes" +--- +<PlanAvailability slug="ent-plus" /> + +From Mattermost v10.8, ensure your teams always have the critical information they need to collaborate effectively by defining and managing organization-specific user profile attributes as system attributes that you can synchronize with your AD/LDAP or SAML identity provider. + +System attributes enable you to customize user profile attributes to match your organization's unique needs and streamline collaboration while keeping user data centralized and consistent. + +From Mattermost v11, you have enhanced control over these user attributes through admin-managed vs user-editable settings. By default, attributes are admin-managed for security, but you can explicitly allow user editing for specific attributes that don't impact access control or sensitive organizational data. These user attributes supplement existing user details visible from the user's profile picture. + +![Mobile examples of a user profile with custom user attributes added as system attributes.](/images/cpa-properties.png) + +## Before you begin + +If you plan to synchronize system properties with your AD/LDAP or SAML identity provider, ensure AD/LDAP or SAML synchronization is already enabled and configured. See the [AD/LDAP groups](/administration-guide/onboard/ad-ldap-groups-synchronization) product documentation or [SAML 2.0](/administration-guide/configure/authentication-configuration-settings#saml-2-0) configuration settings documentation for details. + +<div class="tab"> + +Mattermost v11 or later + +From Mattermost v11, user attributes have enhanced admin controls with a security-first approach. All attributes are admin-managed by default, providing better security and governance. System administrators can explicitly enable user editing for specific attributes through the System Console interface. + +If your organization uses [attribute-based access control (ABAC)](/administration-guide/manage/admin/attribute-based-access-control), which requires an Enterprise Edition Advanced license, attributes used in access control policies should remain admin-managed for security reasons. You can enable user-managed attributes for ABAC by setting `EnableUserManagedAttributes` in `config.json`, or via an environment variable as noted below, but this should be done with caution: + +- `config.json` setting: `".AccessControlSettings.EnableUserManagedAttributes: false",` with options `true` and `false`. +- Environment variable: `MM_ACCESSCONTROLSETTINGS_ENABLEUSERMANAGEDATTRIBUTES` + +This configuration setting isn't managed using the System Console, and is disabled by default to ensure that access control policies remain secure and can't be circumvented by users modifying their own profile attributes. Learn more about [admin-managed versus user-editable attributes](#admin-managed-vs-user-editable-attributes). + +Additionally, from mobile app v2.31.0, user attributes are fully supported on mobile devices. Mobile users can both view and manage profile attributes (if allowed by admin settings) directly from the mobile app. Mobile attribute support requires the same server-side configuration, and no additional mobile-specific setup is required. + +</div> + +<div class="tab"> + +Mattermost v10.11 or later + +From Mattermost v10.11, user-managed attributes are excluded from ABAC rules for security reasons. If your organization uses ABAC (which requires Enterprise Edition Advanced), a system admin can explicitly enable user-managed attributes for ABAC by setting `EnableUserManagedAttributes` in `config.json` or via an environment variable as noted below. This configuration setting isn't managed using the System Console, and is disabled by default to ensure that access control policies remain secure and can't be circumvented by users modifying their own profile attributes. + +- `config.json` setting: `".AccessControlSettings.EnableUserManagedAttributes: false",` with options `true` and `false`. +- Environment variable: `MM_ACCESSCONTROLSETTINGS_ENABLEUSERMANAGEDATTRIBUTES` + +Additionally, from mobile app v2.31.0, user attributes are fully supported on mobile devices. Mobile users can both view and manage profile attributes directly from the mobile app. Mobile attribute support requires the same server-side configuration, and no additional mobile-specific setup is required. + +</div> + +<div class="tab"> + +Mattermost v10.9 or later + +From Mattermost Enterprise v10.9, the ability to create and manage system properties as a Mattermost system admin requires no manual setup. + +</div> + +<div class="tab"> + +Mattermost v10.8 + +You'll need Mattermost Enterprise v10.8 or later, and be a Mattermost system admin to enable the system properties feature flag, `MM_FEATUREFLAGS_CUSTOMPROFILEATTRIBUTES` to create and manage system properties. See the Mattermost developer documentation for details on [enabling feature flags in a self-hosted deployment](https://developers.mattermost.com/contribute/more-info/server/feature-flags/#self-hosted-and-local-development). Mattermost Cloud customers can request this feature flag be enabled by contacting their Mattermost Account Manager or by [creating a support ticket](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=11184911962004) request. + +</div> + +## Admin-managed vs user-editable attributes + +From Mattermost v11, system administrators have enhanced control over user attributes through admin-managed vs user-editable settings. This distinction provides better security and governance for organizational profile data. + +**Admin-managed attributes** (default behavior): + +- Controlled exclusively by system administrators +- Users cannot edit these values in their profiles +- Recommended for security-sensitive information like roles, clearance levels, or organizational identifiers +- Ideal for attributes used in ABAC (Attribute-Based Access Control) policies +- Values can only be updated by admins or through identity provider synchronization + +**User-editable attributes**: + +- Users can update these values in their own profiles +- System administrators can still modify these attributes +- Appropriate for non-sensitive information like personal preferences, skills, or contact details +- Should not be used for attributes that impact security access controls + +<Note> + +For security reasons, attributes used in ABAC policies are admin-managed by default and cannot be edited by users unless explicitly enabled by a system administrator through the **Allow user editing** option. + +</Note> + +**Best practices:** + +- Keep attributes that affect access control or contain sensitive organizational data as admin-managed +- Only enable user editing for attributes that don't impact security policies +- Regularly review user-editable attributes to ensure they remain appropriate for user management +- Consider your organization's data governance requirements when determining attribute editability + +## Add attributes + +You can define and manage up to 20 system attributes using the System Console. Each attribute becomes a user profile option users can populate, unless you disable the **Editable by Users** option, available from Mattermost v11. Once you reach the maximum of 20 attributes, you can't create new attributes until you [delete attributes](#manage-attributes) you no longer need. + +<Note> + +When you disable the **Editable by Users** option for an attribute, only admins can set its value using [mmctl cpa](/administration-guide/manage/mmctl-command-line-tool#mmctl-cpa) commands. + +</Note> + +1. In the System Console, go to **Site Configuration \> System Attributes \> User Attributes** and select **Add Attribute**. + +2. Enter the following details: + + > - **Attribute name**: Enter a unique name for the attribute. Attribute names can be up to 40 characters long. + > - **Type**: Specify the type of attribute as one of the following: + > - **Text** for text-based profile attributes. + > - **Phone** for phone number-based profile attributes. + > - **URL** for web site address-based profile attributes. + > - **Select** for a list of profile attribute values users can choose from. Specify each value followed by pressing **TAB** or **ENTER**. Values can be up to 64 characters long, and users can choose a single value. + > - **Multi-select** for a list of profile attribute values users can select from. Specify each value followed by pressing **TAB** or **ENTER**. Values can be up to 64 characters long, and users can choose multiple values. + +3. Specify the attribute's visibility as one of the following: + +> - **Always show**: The attribute is always visible in user profiles. +> - **Hide when empty**: The attribute is only visible in user profiles when it has a value. +> - **Always hide**: The attribute is never visible in user profiles. + +<Note> + +If an attribute is created or updated without explicit visibility or sort order (for example via API or automation), Mattermost returns default values in responses even if those attributes weren't stored. Visibility defaults to the server's default visibility, and sort order defaults to `0`. + +</Note> + +4. Configure user editing permissions (Mattermost v11 or later) by enabling or disabling the **Editable by users** option. +5. Save your changes. + +<Tip> + +Duplicate existing attributes by selecting **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> and selecting **Duplicate attribute**. This creates a new attribute with the same name and type as the original attribute. You can then edit the new attribute to change its name, type, and visibility as needed. + +</Tip> + +## Manage attributes + +- **Modify**: Select the attribute fields to make inline changes to the attribute's name, type, or values. Select **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> to change a attribute's visibility. +- **Order**: Control the order you want attributes to appear in user profiles by dragging and dropping them in the list. +- **Delete**: Delete attributes you no longer need or want by selecting **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> and selecting **Delete property**. + +<Note> + +When updating custom profile attributes via API or automation, the `attrs` object replaces existing attribute settings rather than merging. If you send only visibility, the sort order resets to `0` unless you include `sort_order` in the same request. If a patch fails, the API may return the error string "Unable to patch Custom Profile Attribute field". + +</Note> + +- **User Edit Permissions**: From Mattermost v11, all user attributes are admin-managed by default for enhanced security. To allow user editing for specific attributes, administrators can enable this through the **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> menu and selecting **Allow user editing**. This should only be enabled for attributes that do not impact security access controls or organizational policies. Attributes used in ABAC policies should remain admin-managed unless there's a specific business need and the security implications are fully understood. +- **Edit User Attribute Values**: From Mattermost v11.1, you can view and update custom profile attribute values for individual users through the System Console. See the [Manage user attributes](/administration-guide/configure/user-management-configuration-settings#manage-user-attributes) documentation for details. + +In cases where multiple system admins manage system attributes, refresh your web browser instance to see real-time updates to system attributes made by other admins. + +## Sync attributes with your identity provider + +1. Synchronize a attribute with AD/LDAP or SAML by selecting **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> and selecting **Link attribute to AD/LDAP** or **Link attribute to SAML**. Mattermost takes you directly to the **AD/LDAP** or **SAML 2.0** configuration settings page in the System Console where you can map the attributes you want to synchronize. +2. Scroll to the **User attributes sync** section to specify the attribute used to populate the attribute in user profiles. +3. Specify the attribute mapping for the attribute by entering the attribute name in the system attribute's **Attribute** field. The attribute name must match the attribute name in your identity provider. +4. Save your changes. diff --git a/docs/main/administration-guide/manage/admin/user-management.mdx b/docs/main/administration-guide/manage/admin/user-management.mdx new file mode 100644 index 000000000000..c394f23371e4 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/user-management.mdx @@ -0,0 +1,11 @@ +--- +title: "User management" +--- +Welcome to the Mattermost User Management Guide. This User Management Guide is organized into sections to help you manage users, permissions, and roles effectively in your Mattermost workspace. + +Whether you’re configuring team and channel settings, managing guest accounts, or leveraging advanced permissions infrastructure, this guide provides the resources and instructions necessary to tailor user management to your organization’s needs. Use the navigation below to explore detailed guidance for each area. + +- [Permissions](/administration-guide/onboard/advanced-permissions) - Learn about permissions in Mattermost. +- [Manage team and channel configuration](/administration-guide/manage/team-channel-members) - Learn about managing team and channel configuration in Mattermost. +- [Advanced permissions infrastructure](/administration-guide/onboard/advanced-permissions-backend-infrastructure) - Learn about advanced permissions infrastructure in Mattermost. +- [Guest accounts](/administration-guide/onboard/guest-accounts) - Learn about guest accounts in Mattermost. diff --git a/docs/main/administration-guide/manage/admin/user-provisioning.mdx b/docs/main/administration-guide/manage/admin/user-provisioning.mdx new file mode 100644 index 000000000000..c2d92153a668 --- /dev/null +++ b/docs/main/administration-guide/manage/admin/user-provisioning.mdx @@ -0,0 +1,12 @@ +--- +title: "User provisioning" +--- +- [Corporate directory integrations](/product-overview/corporate-directory-integration) - Mattermost integrates with all major account providers via Active Directory, SAML, and OAuth. +- [Provisioning workflows](/administration-guide/onboard/user-provisioning-workflows) - Learn about provisioning workflows in Mattermost. +- [AD/LDAP setup](/administration-guide/onboard/ad-ldap) - Learn how to set up AD/LDAP in Mattermost. +- [AD/LDAP manage team or private channel membership](/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups) - Learn how to manage team or private channel membership using AD/LDAP sync groups in Mattermost. +- [GitLab SSO](/administration-guide/onboard/sso-gitlab) - Learn how to use GitLab SSO in Mattermost. +- [OpenID Connect SSO](/administration-guide/onboard/sso-openidconnect) - Learn how to use about OpenID Connect SSO in Mattermost. +- [Google SSO](/administration-guide/onboard/sso-google) - Learn how to use Google SSO in Mattermost. +- [Entra ID SSO](/administration-guide/onboard/sso-entraid) - Learn how to use Entra ID SSO in Mattermost. +- [Convert OAuth 2.0 providers to OpenID](/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect) - Learn how to convert OAuth 2.0 providers to OpenID in Mattermost. diff --git a/docs/main/administration-guide/manage/bulk-export-tool.mdx b/docs/main/administration-guide/manage/bulk-export-tool.mdx new file mode 100644 index 000000000000..c82b235bade0 --- /dev/null +++ b/docs/main/administration-guide/manage/bulk-export-tool.mdx @@ -0,0 +1,677 @@ +--- +title: "Bulk export tool" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Moving data from one Mattermost instance into another begins with exporting data to a [JSONL](https://jsonlines.org) file using the [bulk loading feature](/administration-guide/onboard/bulk-loading-data). This tool is useful if you have created a server for a proof of concept, have created another server for production use, and now want to retain the history from the proof of concept instance. + +You can export the following data types: + +- Teams +- Channels (public, private, and direct) +- Messages (regular, non-reply, and direct messages) +- Threaded discussions and message replies +- Message reactions +- Users +- Users' preferences, including pinned and saved messages +- Users' team memberships +- Users' channel memberships +- Users' notification preferences +- Custom emoji +- Direct message and group message channels, including read/unread status +- Roles +- Permissions schemes +- Bot users + +<Note> + +Configuration for data types such as exporting specific areas of the server, exporting additional types of posts, file attachments, webhooks, and bot messages is not yet supported. Deleted objects are also not yet supported. + +For requests to add additional attributes or objects to our exporter, please add a feature request on our [feature idea forum](https://portal.productboard.com/mattermost/33-what-matters-to-you). + +</Note> + +## Bulk export data + +<div class="tab"> + +Use mmctl + +1. Create a full export file including attachments by running the [mmctl export create -- attachments](/administration-guide/manage/mmctl-command-line-tool#mmctl-export-create) command. See the [Mattermost data migration](/administration-guide/manage/cloud-data-export#create-the-export) documentation for details. +2. While the job is running, you can check its status by running the [mmctl export job show](/administration-guide/manage/mmctl-command-line-tool#mmctl-export-job-show) command. +3. When the export job status is successful: + +> 1. Identify the name of the completed export file by running the [mmctl export list](/administration-guide/manage/mmctl-command-line-tool#mmctl-export-list) command. +> 2. Download the export file to your local machine by running the [mmctl export download](/administration-guide/manage/mmctl-command-line-tool#mmctl-export-download) command. + +</div> + +<div class="tab"> + +Use CLI + +<Note> + +From Mattermost v6.0, this command has been deprecated in favor of [mmctl export commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-export) as the supported way to export data out of Mattermost. + +</Note> + +The export command runs in the [CLI](/administration-guide/manage/command-line-tools). It has permissions to access all information in the Mattermost database. + +To run the export command: + +1. Navigate to the directory where the Mattermost server is installed. On a default install of Mattermost, the directory is `/opt/mattermost`. + +2. Run the following command to extract data from all teams on the server. Note that you can change the file name and specify an absolute or relative path to dictate where the file is exported: + + `sudo -u mattermost bin/mattermost export bulk file.json --all-teams` + + `sudo -u mattermost bin/mattermost export bulk /home/user/bulk_data.json --all-teams` + +3. Retrieve your file from the location you specified. + +</div> + +All Mattermost bulk export data files will begin with a `Version` object as the first line of the file. This indicates the version of the Mattermost bulk import file format with which the exported data is compatible. + +## Version object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>The string "version"</td> + </tr> + <tr class="row-odd"> + <td valign="middle">version</td> + <td valign="middle">number</td> + <td>The number 1.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">info</td> + <td valign="middle">object</td> + <td>Optional VersionInfo object</td> + </tr> +</table> + +## VersionInfo object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">generator</td> + <td valign="middle">string</td> + <td>The name of the tool this export was generated with. Well known tools are:<br /> <kbd>"mattermost-server"</kbd> for the Mattermost Server.<br /> <kbd>"mmetl"</kbd> for the Slack export converter "mmetl".</td> + </tr> + <tr class="row-odd"> + <td valign="middle">version</td> + <td valign="middle">string</td> + <td>The version of the tool this export was generated with. This may contain multiple pieces of version info, separated by spaces. The first one should be a semantic version.<br /> <kbd>"7.6.0 (29bb1e53ef5a439c73065f47de2972f9bbcb09a4, enterprise: true)"</kbd> is an example of such a version string.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">created</td> + <td valign="middle">string</td> + <td>The timestamp of the file creation. This should be formatted as an RFC 3339 timestamp. The nanosecond part is optional.<br /> <kbd>"2022-11-22T16:40:51.019582328+01:00"</kbd></td> + </tr> + <tr class="row-odd"> + <td valign="middle">additional</td> + <td valign="middle">any</td> + <td>Any additional information the generator wants to include into the file header. May be omitted. Be aware that the size of each line is limited to a few MiB.</td> + </tr> +</table> + +## Team object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The team name.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the team.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>The type of team. Will have one of the following values:<br /> <kbd>"O"</kbd> for an open team<br /> <kbd>"I"</kbd> for an invite-only team.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">description</td> + <td valign="middle">string</td> + <td>The team description.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">allow_open_invite</td> + <td valign="middle">bool</td> + <td>Whether to allow open invitations. Will have one of the following values:<br /> <kbd>"true"</kbd><br /> <kbd>"false"</kbd></td> + </tr> + <tr class="row-odd"> + <td valign="middle">scheme</td> + <td valign="middle">string</td> + <td>The name of the permissions scheme that applies to this team.</td> + </tr> +</table> + +## Channel object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">team</td> + <td valign="middle">string</td> + <td>The name of the team this channel belongs to.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the channel.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the channel.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>The type of channel. Will have one the following values:<br /> <kbd>"O"</kbd> for a public channel.<br /> <kbd>"P"</kbd> for a private channel.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">header</td> + <td valign="middle">string</td> + <td>The channel header.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">purpose</td> + <td valign="middle">string</td> + <td>The channel purpose.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">scheme</td> + <td valign="middle">string</td> + <td>The name of the permissions scheme that applies to this team.</td> + </tr> +</table> + +## User object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">username</td> + <td valign="middle">string</td> + <td>The user’s username. This is the unique identifier for the user.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email</td> + <td valign="middle">string</td> + <td>The user’s email address.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">auth_service</td> + <td valign="middle">string</td> + <td>The authentication service used for this user account. This field will be absent for user/password authentication.<br /> <kbd>"gitlab"</kbd> - GitLab authentication.<br /> <kbd>"ldap"</kbd> - LDAP authentication (Enterprise and Professional)<br /> <kbd>"saml"</kbd> - Generic SAML based authentication (Enterprise)<br /> <kbd>"google"</kbd> - Google OAuth authentication (Enterprise)<br /> <kbd>"entra id"</kbd> - Microsoft Entra ID OAuth Authentication (Enterprise)</td> + </tr> + <tr class="row-odd"> + <td valign="middle">auth_data</td> + <td valign="middle">string</td> + <td>The authentication data if <kbd>auth_service</kbd> is used. The value depends on the <kbd>auth_service</kbd> that is specified.<br /> The data comes from the following fields for the respective auth_services:<br /> <kbd>"gitlab"</kbd> - The value of the Id attribute provided in the GitLab auth data.<br /> <kbd>"ldap"</kbd> - The value of the LDAP attribute specified as the "ID Attribute" in the Mattermost LDAP configuration.<br /> <kbd>"saml"</kbd> - The value of the SAML email address attribute.<br /> <kbd>"google"</kbd> - The value of the OAuth Id attribute.<br /> <kbd>"office365"</kbd> - The value of the OAuth Id attribute.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">nickname</td> + <td valign="middle">string</td> + <td>The user’s nickname.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">first_name</td> + <td valign="middle">string</td> + <td>The user’s first name.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">last_name</td> + <td valign="middle">string</td> + <td>The user’s last name.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">position</td> + <td valign="middle">string</td> + <td>The user’s position.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The user’s roles. </td> + </tr> + <tr class="row-odd"> + <td valign="middle">locale</td> + <td valign="middle">string</td> + <td>The user’s localization configuration.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">use_markdown_preview</td> + <td valign="middle">bool</td> + <td><kbd>"true"</kbd> if the user has enabled markdown preview in the message input box.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">use_formatting</td> + <td valign="middle">bool</td> + <td><kbd>"true"</kbd> if the user has enabled post formatting for links, emoji, text styles, and line breaks.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">show_unread_section</td> + <td valign="middle">string</td> + <td><kbd>"true"</kbd> if the user has enabled showing unread messages at top of channel sidebar.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">theme</td> + <td valign="middle">string</td> + <td>The user’s theme. Formatted as a Mattermost theme string.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">military_time</td> + <td valign="middle">string</td> + <td><kbd>"true"</kbd> if the user has enabled a 24-hour clock. <kbd>"false"</kbd> if using a 12-hour clock.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">collapse_previews</td> + <td valign="middle">string</td> + <td><kbd>"true"</kbd> if user collapses link preview by default. <kbd>"false"</kbd> if user expands link previews by default.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message_display</td> + <td valign="middle">string</td> + <td>The style the user prefers for displayed messages. Options are <kbd>"clean"</kbd> if the user uses the standard style or <kbd>"compact"</kbd> if the user uses compact style.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel_display_mode</td> + <td valign="middle">string</td> + <td><kbd>"full"</kbd> if the users displays channel messages at the full width of the screen or <kbd>"centered"</kbd> if the user uses a fixed width, centered block.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">tutorial_step</td> + <td valign="middle">string</td> + <td><kbd>"1"</kbd>, <kbd>"2"</kbd>, or <kbd>"3"</kbd> indicates which specified tutorial step to start with for the user. <kbd>"999"</kbd> skips the tutorial.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email_interval</td> + <td valign="middle">string</td> + <td>Email batching interval to use during bulk import. </td> + </tr> + <tr class="row-odd"> + <td valign="middle">delete_at</td> + <td valign="middle">int64</td> + <td>Timestamp of when the user was deactivated.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">teams</td> + <td valign="middle">array</td> + <td>The teams which the user is member of. Is an array of <b>UserTeamMembership</b> objects.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">notify_props</td> + <td valign="middle">object</td> + <td>The user’s notify preferences, as defined by the <b>UserNotifyProps</b> object.</td> + </tr> +</table> + +## UserNotifyProps object + +This object is a member of the User object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop</td> + <td valign="middle">string</td> + <td>Preference for sending desktop notifications. Will be one of the following values:<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop_sound</td> + <td valign="middle">string</td> + <td>Preference for whether desktop notification sound is played. Will be one of the following values:<br /> <kbd>"true"</kbd> - Sound is played.<br /> <kbd>"false"</kbd> - Sound is not played.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email</td> + <td valign="middle">string</td> + <td>Preference for email notifications. Will be one of the following values:<br /> <kbd>"true"</kbd> - Email notifications are sent immediately.<br /> <kbd>"false"</kbd> - Email notifications are not sent.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile</td> + <td valign="middle">string</td> + <td>Preference for sending mobile push notifications. Will be one of the following values:<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile_push_status</td> + <td valign="middle">string</td> + <td>Preference for when push notifications are triggered. Will be one of the following values:<br /> <kbd>"online"</kbd> - When online, away or offline.<br /> <kbd>"away"</kbd> - When away or offline.<br /> <kbd>"offline"</kbd> - When offline.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel</td> + <td valign="middle">string</td> + <td>Preference for whether @all, @channel, and @here trigger mentions. Will be one of the following values:<br /> <kbd>"true"</kbd> - Mentions are triggered.<br /> <kbd>"false"</kbd> - Mentions are not triggered.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">comments</td> + <td valign="middle">string</td> + <td>Preference for reply mention notifications. Will be one of the following values:<br /> <kbd>"any"</kbd> - Trigger notifications on messages in reply threads that the user starts or participates in.<br /> <kbd>"root"</kbd> - Trigger notifications on messages in threads that the user starts.<br /> <kbd>"never"</kbd> - Do not trigger notifications on messages in reply threads unless the user is mentioned.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mention_keys</td> + <td valign="middle">string</td> + <td>Preference for custom non-case sensitive words that trigger mentions. Words are separated by commas.</td> + </tr> +</table> + +## UserTeamMembership object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the team this user is a member of.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The roles the user has within this team. </td> + </tr> + <tr class="row-odd"> + <td valign="middle">theme</td> + <td valign="middle">string</td> + <td>The user’s theme for this team. Formatted as a Mattermost theme string.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channels</td> + <td valign="middle">array</td> + <td>The channels within this team that the user is a member of. Listed as an array of <b>UserChannelMembership</b> objects.</td> + </tr> +</table> + +## UserChannelMembership object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the channel in the parent team that this user is a member of.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The roles the user has within this channel. </td> + </tr> + <tr class="row-odd"> + <td valign="middle">notify_props</td> + <td valign="middle">object</td> + <td>The notify preferences for this user in this channel as defined by the <b>ChannelNotifyProps</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">favorite</td> + <td valign="middle">boolean</td> + <td>Whether the channel is marked as a favorite for this user. Will be one of the following values:<br /> <kbd>"true"</kbd> - Yes.<br /> <kbd>"false"</kbd> - No.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mention_count</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>ChannelMentionCount</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mention_count_root</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>ChannelMentionCountRoot</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">urgent_mention_count</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>UrgendMentionCount</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">msg_count</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>MsgCount</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">msg_count_root</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>MsgCountRoot</b> object.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">last_viewed_at</td> + <td valign="middle">int64</td> + <td>The mention preferences for this user in this channel as defined by the <b>LastViewedAt</b> object.</td> + </tr> +</table> + +### ChannelNotifyProps object + +This object is a member of the ChannelMembership object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop</td> + <td valign="middle">string</td> + <td>Preference for sending desktop notifications. Will be one of the following values:<br /> <kbd>"default"</kbd> - Global default.<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile</td> + <td valign="middle">string</td> + <td>Preference for sending mobile notifications. Will be one of the following values:<br /> <kbd>"default"</kbd> - Global default.<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mark_unread</td> + <td valign="middle">string</td> + <td>Preference for marking channel as unread. Will be one of the following values:<br /> <kbd>"all"</kbd> - For all unread messages.<br /> <kbd>"mention"</kbd> - Only for mentions.</td> + </tr> +</table> + +## Post object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">team</td> + <td valign="middle">string</td> + <td>The name of the team that this post is in.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel</td> + <td valign="middle">string</td> + <td>The name of the channel that this post is in.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this post.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the post contains.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">props</td> + <td valign="middle">object</td> + <td>The props for a post. Contains additional formatting information used by integrations and bot posts. For a more detailed explanation see the <a href="https://docs.mattermost.com/developer/message-attachments.html">message attachments documentation</a>.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the post, in milliseconds since the Unix epoch.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">reactions</td> + <td valign="middle">array</td> + <td>The emoji reactions to this post. Will be an array of Reaction objects.</td> + </tr> +</table> + +## Reply object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this reply.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the reply contains.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the reply, in milliseconds since the Unix epoch.</td> + </tr> +</table> + +## Reaction object + +This object is a member of the Post object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this reply.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">emoji_name</td> + <td valign="middle">string</td> + <td>The emoji of the reaction.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the reply, in milliseconds since the Unix epoch.</td> + </tr> +</table> + +## Emoji object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The emoji name.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">image</td> + <td valign="middle">string</td> + <td>The path (either absolute or relative to the current working directory) to the image file for this emoji.</td> + </tr> +</table> + +## DirectChannel object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">members</td> + <td valign="middle">array</td> + <td>List of channel members.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">favorited_by</td> + <td valign="middle">array</td> + <td>List of channel members who have favorited the direct channel.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">header</td> + <td valign="middle">string</td> + <td>The channel header.</td> + </tr> +</table> + +## DirectPost object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this post.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the post contains.</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the post, in milliseconds since the Unix epoch.</td> + </tr> +</table> diff --git a/docs/main/administration-guide/manage/cloud-byok.mdx b/docs/main/administration-guide/manage/cloud-byok.mdx new file mode 100644 index 000000000000..4d55c781af61 --- /dev/null +++ b/docs/main/administration-guide/manage/cloud-byok.mdx @@ -0,0 +1,76 @@ +--- +title: "Cloud Dedicated Bring Your Own Key" +--- +Bring Your Own Key (BYOK) provides Enterprise Cloud customers with autonomy over their encryption key life cycle. BYOK supports encryption at rest with custom KMS keys that the enterprise provides and maintains. + +**BYOK requires a subscription to Mattermost Cloud Enterprise Dedicated**, which offers enhanced data security and compliance by ensuring that enterprises have full control over their data encryption processes. + +In Mattermost Cloud Enterprise Dedicated, you can use KMS keys in 2 ways: + +- One KMS key for all services; or, + +- Per-service KMS keys (EBS, RDS, S3) + - Keys do not need to be unique to each service. + - All services must be encrypted at rest. + - Selective enablement of this feature can be supported. + - In cases where a global database is needed, we recommend providing 2 KMS keys (1 per region). + +## Configure BYOK + +1. Enterprise customer provides their AWS KMS ARN to the Mattermost Infrastructure SRE team. +2. Enterprise customer adds the following blocks to their KMS Policy for the AWS KMS ARN provided: + +``` json +{ + "Sid": "Allow use of the key", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::<MATTERMOST_AWS_ACCOUNT_ID>:user/mattermost-cloud-<environment>-provisioning-<VPC_ID>" + }, + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + "Resource": "<CUSTOM_CUSTOMER_KMS_ID>" +}, +{ + "Sid": "Allow use of the key role nodes", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::<MATTERMOST_AWS_ACCOUNT_ID>:role/nodes.<CLUSTER_ID>-kops.k8s.local" + }, + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + "Resource": "<CUSTOM_CUSTOMER_KMS_ID>" +}, +``` + +3. The Mattermost Infrastructure SRE team updates the kops cluster and S3, RDS resources after the KMS policy is updated on the customer's end. + +Alternatively, the Enterprise customer can provide an external key (non-KMS) to the Mattermost Infrastructure SRE team that Mattermost maintains on behalf of the customer. This path offers less control to customers but simplifies the setup process. + +### Requirements + +- Customers must own their AWS Account. (In the alternative path mentioned above this is delegated to Mattermost.) +- Customers oversee the maintenance life cycle of their custom KMS key. +- A valid AWS KMS ARN for encrypting storage and databases should be provided to the Infrastructure SRE team. +- The customer should incorporate the provided policy blocks from the Infrastructure SRE team into their KMS key policy. + +### Considerations + +- Changing the AWS KMS key in the database necessitates downtime due to AWS Aurora's encryption [limitations.](https://repost.aws/knowledge-center/update-encryption-key-rds) +- Proper communication is essential for setting expectations and scheduling changes. + +## Conclusion + +If you are a large enterprise with compliance requirements, or are working in highly-regulated industries, using Mattermost Cloud Dedicated with BYOK ensures full data control. + +For any further assistance or queries, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) diff --git a/docs/main/administration-guide/manage/cloud-data-export.mdx b/docs/main/administration-guide/manage/cloud-data-export.mdx new file mode 100644 index 000000000000..81e471863a2c --- /dev/null +++ b/docs/main/administration-guide/manage/cloud-data-export.mdx @@ -0,0 +1,378 @@ +--- +title: "Mattermost workspace migration" +draft: true +--- +This document outlines the process for migrating an existing Mattermost instance [from self-hosted to Cloud](#migrate-from-self-hosted-to-cloud), and [from Cloud to self-hosted](#migrate-from-cloud-to-self-hosted). + +<Note> + +Migrating an existing Mattermost instance to another using the same deployment method follows the same process that's documented below, regardless as to whether the source or destination of the migration is in the Cloud or self-hosted. **These steps will work for both Cloud and self-hosted Mattermost instances**. + +</Note> + +## Migrate from self-hosted to Cloud + +When you migrate from self-hosted to Cloud, you'll need to open a ticket with the Mattermost Support team so they can assist you with the process. The information below describes the migration process. Before you get started, visit our [Support site](https://support.mattermost.com/hc/en-us/requests/new) to open a ticket. + +<Important> + +- This migration process is only available to customers using paid Mattermost editions. +- We recommend reviewing the knowledge base article on [migrating from self-hosted to Cloud](https://support.mattermost.com/hc/en-us/articles/4412503667604-Migrating-from-Self-hosted-Mattermost-Instance-to-Cloud-Mattermost-Instance) before starting a migration to familiarize yourself with key considerations, required prerequisites, and our guidance on testing your export. + +</Important> + +Before you begin your migration, take note of the following information before you begin: + +**User Authentication** + +If you are using the email login method, users will need to reset their passwords after the migration has been completed. Other authentication methods, such as LDAP and GitLab SSO, required changes to your infrastructure allowing the specific authentication method to function in Mattermost cloud. + +**Plugins** + +If you’re using plugins that aren’t listed on the Marketplace, they won’t be included in the export and you won’t have access to them going forward. See the list of supported plugins by visiting the [integrations overview](/integrations-guide/integrations-guide-index#plugins) documentation. + +**Data** + +The migration only includes data from Channels. No Playbooks data is exported. + +### Migration process + +**Export from your self-hosted instance** + +Use your administrator credentials to log into your self-hosted Mattermost server. Once you're logged in, run: + +``` +mmctl export create --attachments +``` + +This creates a full export of the server, and includes attached files. If you don’t want to export attached files, leave out `--attachments`. + +This process can take some time, so `mmctl` will return immediately, and the job will run in the background until the export is fully created. If successful, the command will immediately output a job ID, like this: + +``` +Export process job successfully created, ID: yfrr9ku5i7fjubeshs1ksrknzc +``` + +While the job is running, its status can be checked using the ID that was provided when it was created, and when it's done the output will look similar to this: + +``` +mmctl export job show yfrr9ku5i7fjubeshs1ksrknzc +ID: yfrr9ku5i7fjubeshs1ksrknzc +Status: success +Created: 2021-11-03 10:44:13 -0500 CDT +Started: 2021-11-03 10:44:23 -0500 CDT +``` + +The completed file will be downloaded to your desktop as a `.zip` file. + +<Note> + +Do not rename the file as the file name is referenced in log files, which are used by the Support team to validate the exported file. + +</Note> + +The Support team will provide you with S3 credentials so you can upload the exported file. Once you’ve uploaded the file, please contact the Support team and let them know. + +### Create a new workspace on the Mattermost Cloud + +In the meantime, you can log into Mattermost Cloud with your Mattermost credentials and create a Cloud workspace. + +<Note> + +Do not create any users in your Mattermost Cloud instance as the migration process performs this task for you. + +</Note> + +### Importing your data into your Mattermost Cloud instance + +Once the export upload to the provided S3 bucket is complete and you’ve shared your Mattermost Cloud instance name/URL, Support can begin the import step. + +Depending on the size of the export this process can take some time. Support will contact you as soon as the import is complete. During this time it is highly recommended you do not use your Mattermost Cloud instance. + +### Start using your Mattermost Cloud instance + +When the export is complete, you can log into your Cloud instance and can invite your users to log in. + +<Note> + +We recommend that you keep your self-hosted Mattermost server until you’ve been using your Cloud instance for a while and all is verified as is as expected. + +</Note> + +## Migrate from Cloud to self-hosted + +You can migrate your Cloud workspace data to a self-hosted deployment at any time. + +### How does the process work? + +Before you export and migrate your data, you must [install Mattermost](/deployment-guide/deployment-guide-index) on the server you’ll be using to run Mattermost. The migration is done using the mmctl CLI tool, which is a remote CLI tool for Mattermost that's installed locally and uses the Mattermost API. `mmctl` is pre-installed. + +The [mmctl usage notes](/administration-guide/manage/mmctl-command-line-tool#mmctl-usage-notes) provide some additional context and information which you can reference before and during the process. + +You'll be using the [mmctl export](/administration-guide/manage/mmctl-command-line-tool#mmctl-export) commands to export your Cloud data for channels, messages, users, etc. The export file is downloaded to a location specified in the export commands. Once the export is complete, you'll import the data into your self-hosted instance. + +Alternatively, you can export the data to an Amazon S3 cloud storage location in cases where an export is quite large and challenging to download from the Mattermost server. See the [create the export](#create-the-export) section below for details. + +<Note> + +Prior to migrating your data from Cloud, please ensure you have the appropriate permissions within your organization to carry out the data export which may contain sensitive information. Mattermost is not liable for any actions taken after the data export. + +Moreover, the export process doesn’t include integrations or any custom data. Other aspects of your instance, such as specific security settings and requirements, are also not included. For assistance with migrating additional data and settings, see our support options: [https://mattermost.com/support/](https://mattermost.com/support/). + +</Note> + +Once `mmctl` is authenticated, you can generate the export from the source instance. + +## Authenticate + +Authentication is done with either Mattermost login credentials or an authentication token. First, use your administrator credentials to log into the instance with mmctl, replacing <code>example-source-domain.com</code> with the network address of the source instance: + +``` +mmctl auth login https://yourdomain.cloud.mattermost.com +``` + +You'll be prompted for a username (use your admin user), password, and for a connection name. The connection name can be anything you want, and it's used to identify this set of credentials in the future, for your convenience. Then you will be able to start the export process. + +## Create the export + +<Important> + +If your Mattermost Cloud deployment includes plugins that aren't listed on the Cloud Marketplace, those plugins won't be included in the export, and you won't have access to those plugins going forward. See the [integrations](/integrations-guide/integrations-guide-index#plugins) documentation for a list of Cloud-supported integrations. + +</Important> + +Once you're logged in, run the following `mmctl` command: + +``` +mmctl export create +``` + +Running this command creates a full export of the server, including attached files. Append `--no-attachments` if you do not wish to export attached files from your instance, and append `--with-archived-channels` to include archived channels in the export file. This process can take some time, so `mmctl` will return immediately, and the job will run in the background on the Mattermost instance until the export is fully created. If successful, the command will immediately output a job ID, like this: + +``` +Export process job successfully created, ID: yfrr9ku5i7fjubeshs1ksrknzc +``` + +While the job is running, its status can be checked using the ID that was provided when it was created, and when it's done the output will look similar to this: + +``` +mmctl export job show yfrr9ku5i7fjubeshs1ksrknzc +ID: yfrr9ku5i7fjubeshs1ksrknzc +Status: success +Created: 2021-11-03 10:44:13 -0500 CDT +Started: 2021-11-03 10:44:23 -0500 CDT +``` + +Once the status is `success`, download the export onto your local machine. First, discover the name of the completed export file with `mmctl export list`: + +``` +mmctl export list +r3kcj8yuwbramdt714doafi3oo_export.zip +``` + +This will show all of the exports on the server, so be sure to download the latest one and to delete it when you're done to save storage. Generate a link to download the file with a command like the following, but with the filename of the export on your server: + +``` +mmctl export generate-presigned-url r3kcj8yuwbramdt714doafi3oo_export.zip +``` + +<Tip> + +- As an alternative to this last step, from your Mattermost Cloud web instance, you can retrieve the file download link to the export by using the Mattermost slash command `/exportlink [job-id|zip file|latest]`. Use the `latest` option to automatically pull the latest export available, or specify the download link by `job-id` or `zip file`. +- Mattermost v8.1.0-RC1 is required to use the `mmctl export generate-presigned-url` command on a self-hosted Mattermost instance. Access the [Mattermost Enterprise v8.1.0-RC1 binary](https://releases.mattermost.com/8.1.0-rc1/mattermost-enterprise-8.1.0-rc1-linux-amd64.tar.gz) or the [Mattermost Team Edition v8.1.0-RC1 binary](https://releases.mattermost.com/8.1.0-rc1/mattermost-team-8.1.0-rc1-linux-amd64.tar.gz). + +</Tip> + +## Upload the export to the new server + +Finally, it's time to take our export from the source server and use it as an import into the destination server. Before proceeding, review and modify the following self-hosted Mattermost configuration settings, where applicable, to ensure a smooth and successful import. + +<table style={{width: '100%'}}> +<colgroup> +<col style={{width: '39%'}} /> +<col style={{width: '51%'}} /> +<col style={{width: '8%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Mattermost configuration setting</strong></td> +<td><strong>Large file import recommendation</strong></td> +<td></td> +</tr> +<tr> +<td colspan="3"><a href="mm-ref:administration-guide%2Fconfigure%2Fsite-configuration-settings%3Amax%20users%20per%20team">Maximum Users Per Team | Increase this value to a number that **exceeds** the maximum number of users, per team, in the import file. |</a> |</td> +</tr> +<tr> +<td colspan="3"><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Amaximum%20file%20size">Maximum File Size | Temporarily increase this value to be **larger** than the size of the import file. |</a> | Following a successful import, we strongly recommend reverting this value to a reasonable limit for daily expected usage. |</td> +</tr> +<tr> +<td colspan="3"><dl> +<dt><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Awrite%20timeout">Write Timeout | Temporarily adjust this value based on import file speed and network path to enable the file to upload without timeouts. |</a> | Start with a value of <strong>3600</strong> and adjust if needed. |</dt> +<dd> +<div class="line-block">Following a successful import, we strongly recommend reverting this setting to its initial or previous value. |</div> +</dd> +</dl></td> +</tr> +<tr> +<td colspan="3"><dl> +<dt><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Aread%20timeout">Read Timeout | Temporarily adjust this value based on import file speed and network path to enable the file to upload without timeouts. |</a> | Start with a value of <strong>3600</strong> and adjust if needed. |</dt> +<dd> +<div class="line-block">Following a successful import, we strongly recommend reverting this setting to its initial or previous value. |</div> +</dd> +</dl></td> +</tr> +<tr> +<td colspan="3"><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Aamazon%20s3%20request%20timeout">Amazon S3 Request Timeout | If using cloud-based file storage, adjust this value to ensure your storage requests don't time out too soon. |</a> |</td> +</tr> +</tbody> +</table> + +Next, log into the destination server using `mmctl` the same way you logged into the source server: + +``` +mmctl auth login https://localinstance.company.com +``` + +Use the following command to upload the export to the destination server. The speed of the upload may vary based on connection speed. When the upload is complete the command will return with the ID of the import: + +``` +mmctl import upload r3kcj8yuwbramdt714doafi3oo_export.zip +Upload session successfully created, ID: cfuq6q9kkjrqfgnph1pew3db4e +Import file successfully uploaded, name: xrzs9wrzufntbfcxpy39mdq9hy +``` + +## Complete the import into the new server + +``` +mmctl import list available +cfuq6q9kkjrqfgnph1pew3db4e_r3kcj8yuwbramdt714doafi3oo_export.zip +``` + +Run the import job to process to import the export file into the server. The speed of this process may vary based on connection speed. First, start the import process: + +``` +mmctl import process cfuq6q9kkjrqfgnph1pew3db4e_r3kcj8yuwbramdt714doafi3oo_export.zip +``` + +Once you've marked the file for processing, you can check the status of the job using `mmctl import job list`: + +``` +mmctl --local import job list +ID: f93jxu1hzty79enwa1xy6f1tbr +Status: pending +Created: 2021-10-28 13:32:55 +0200 CEST +``` + +When the job is complete, the `success` status is displayed: + +``` +mmctl --local import job list +ID: f93jxu1hzty79enwa1xy6f1tbr +Status: success +Created: 2021-10-28 13:32:55 +0200 CEST +Started: 2021-10-28 13:33:05 +0200 CEST +``` + +Then extract the export file to use it by running the following mmctl command: + +``` +mmctl extract run [flags]. +``` + +Once your migration is complete and you’ve imported your data into your self-hosted instance we recommend that you take a few days to validate your data and ensure everything is working as expected before taking down your Cloud instance. + +<Note> + +If you are using email/password authentication, your users must reset their passwords. + +</Note> + +If you encounter any issues or problems, [contact our support team](https://mattermost.com/support/), or visit the [Mattermost Help Center](https://support.mattermost.com/). + +## Migrate from self-hosted to Cloud + +When you migrate from self-hosted to Cloud, you'll need to open a ticket with the Mattermost Support team so they can assist you with the process. The information below describes the migration process. Before you get started, visit our [Support site](https://support.mattermost.com/hc/en-us/requests/new) to open a ticket. + +<Note> + +This migration process is only available to customers using paid Mattermost editions. + +</Note> + +Before you begin your migration, take note of the following information before you begin: + +**User Authentication** + +If you are using the email login method, users will need to reset their passwords after the migration has been completed. Other authentication methods, such as LDAP and GitLab SSO, required changes to your infrastructure allowing the specific authentication method to function in Mattermost cloud. + +**Plugins** + +If you’re using plugins that aren’t listed on the Marketplace, they won’t be included in the export and you won’t have access to them going forward. You can view the list of plugins [in the Support knowledgebase](https://support.mattermost.com/hc/en-us/articles/5346624843924-Mattermost-Plugin-Marketplace-List-as-of-November-12th-2024). + +**Data** + +The migration only includes channel data. No collaborative playbooks data is exported. + +### Migration process + +**Export from your self-hosted instance** + +Use your administrator credentials to log into your self-hosted Mattermost server. Once you're logged in, run: + +``` +mmctl export create --attachments +``` + +This creates a full export of the server, and includes attached files. If you don’t want to export attached files, leave out `--attachments`. + +This process can take some time, so `mmctl` will return immediately, and the job will run in the background until the export is fully created. If successful, the command will immediately output a job ID, like this: + +``` +Export process job successfully created, ID: yfrr9ku5i7fjubeshs1ksrknzc +``` + +While the job is running, its status can be checked using the ID that was provided when it was created, and when it's done the output will look similar to this: + +``` +mmctl export job show yfrr9ku5i7fjubeshs1ksrknzc +ID: yfrr9ku5i7fjubeshs1ksrknzc +Status: success +Created: 2021-11-03 10:44:13 -0500 CDT +Started: 2021-11-03 10:44:23 -0500 CDT +``` + +The completed file will be downloaded to your desktop as a `.zip` file. + +<Note> + +Do not rename the file as the file name is referenced in log files, which are used by the Support team to validate the exported file. + +</Note> + +The Support team will provide you with S3 credentials so you can upload the exported file. Once you’ve uploaded the file, please [contact our support team](https://mattermost.com/support/) and let them know. + +### Create a new workspace on the Mattermost Cloud + +In the meantime, you can log into Mattermost Cloud with your Mattermost credentials and create a Cloud workspace. + +<Note> + +Do not create any users in your Mattermost Cloud instance as the migration process performs this task for you. + +</Note> + +### Importing your data into your Mattermost Cloud instance + +Once the export upload to the provided S3 bucket is complete and you’ve shared your Mattermost Cloud instance name/URL, Support can begin the import step. + +Depending on the size of the export this process can take some time. Support will contact you as soon as the import is complete. During this time it is highly recommended you do not use your Mattermost Cloud instance. + +### Start using your Mattermost Cloud instance + +When the export is complete, you can log into your Cloud instance and can invite your users to log in. + +<Note> + +We recommend that you keep your self-hosted Mattermost server until you’ve been using your Cloud instance for a while and all is verified as is as expected. + +</Note> diff --git a/docs/main/administration-guide/manage/cloud-data-residency.mdx b/docs/main/administration-guide/manage/cloud-data-residency.mdx new file mode 100644 index 000000000000..7d9538718b7a --- /dev/null +++ b/docs/main/administration-guide/manage/cloud-data-residency.mdx @@ -0,0 +1,15 @@ +--- +title: "Mattermost Cloud data residency" +--- +Mattermost Cloud resides in the `aws-us-east-1` region, located in Virginia, United States. The following customer data will be stored at rest in this data center when using Mattermost Cloud: + +- Channels, messages, replies, and channel membership information +- Collaborative playbooks and event runs +- User accounts and profiles +- Files (e.g., images, docs, etc.) uploaded to the Mattermost Service +- Plugin, app- or bot-generated messages and files +- Data used to measure user count, usage, and revenue +- Data used for analytics and to measure quality of service, e.g., sanitized logs +- IDs generated by Mattermost on behalf of the customer + +If you require your data to reside in an area outside of the United States, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/), or consider [deploying one of our self-hosted options](https://mattermost.com/download/) that provides full control of your data. You may also work with [one of our partners](https://mattermost.com/partners) for deploying and hosting your Mattermost server. diff --git a/docs/main/administration-guide/manage/cloud-ip-filtering.mdx b/docs/main/administration-guide/manage/cloud-ip-filtering.mdx new file mode 100644 index 000000000000..f5d40b69ebac --- /dev/null +++ b/docs/main/administration-guide/manage/cloud-ip-filtering.mdx @@ -0,0 +1,84 @@ +--- +title: "Cloud IP Filtering" +--- +IP filtering is a powerful security feature that allows system admins to control access to their workspace by defining approved IP ranges. Only users within these specified IP ranges can access the workspace, ensuring enhanced security for your workspace. + +**IP filtering requires a subscription to Mattermost Cloud Enterprise.** + +## Configure IP filtering + +1. **Log in as system admin**: As a system admin, access the System Console of your workspace by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> menu and selecting **System Console**. + +2. **Go to Site Configuration**: Go to the **Site Configuration** section. + +3. **Access IP Filtering Settings**: Under **Site Configuration**, select **IP Filtering** to access the IP Filtering settings. + + ![An example of the System Console interface where admins can configure IP filtering.](/images/system-console-ip-filtering.png) + +## About CIDR notation + +CIDR (Classless Inter-Domain Routing) notation is used to specify a range of IP addresses. It consists of an IP address followed by a forward slash and a number indicating the network's prefix length. For example: + +- `192.168.0.0/24` represents the IP range from `192.168.0.0` to `192.168.0.255`. +- The `/24` signifies that the first 24 bits are the network address, leaving 8 bits for host addresses. + +<Tip> + +For a more in-depth explanation of CIDR notation, refer to [this article](https://aws.amazon.com/what-is/cidr/). + +</Tip> + +## Configure IP filters + +### Enable/disable IP filtering + +System admins have the option to enable or disable IP filtering: + +- **Enable:** To activate IP filtering, ensure at least one IP range is added to the whitelist. +- **Disable:** Temporarily disable IP filtering by removing all IP ranges from the whitelist, or by flipping the global IP Filtering toggle in the System Console. + +![An example of enabling and disabling Mattermost IP filtering in the System Console.](/images/enable-disable-ip-filtering.gif) + +### Add an IP range + +To add an IP range to the whitelist, follow these steps: + +1. Select the **Add Filter** button within the IP Filtering settings page in the System Console. +2. Enter the IP range using CIDR notation. For example, `192.168.1.0/24`. +3. Provide a descriptive name or label for the IP range to ease identification in the future. +4. Save the changes. + +![An example of adding an IP filter range for a Mattermost Cloud deployment.](/images/add-ip-filter-range.png) + +<Note> + +The System Console will restrict you from saving changes if the IP address you are accessing your workspace on is not within the ranges you have specified at the time you save your changes. + +![An example of the Mattermost System Console blocking changes to IP filtering.](/images/ip-address-not-in-filters.png) + +</Note> + +### Edit or remove an existing IP range + +To edit or remove an existing IP range from the whitelist: + +1. Locate the IP range you want to modify within the **IP Filtering** settings. +2. Hover over the rule you'd like to edit or delete, and select the respective edit or delete option beside the IP range. +3. Make necessary changes or confirm the removal of the IP range. +4. Save your changes by selecting **Save**. + +### Unable to access your workspace? + +If you are unable to access your workspace due to previously set IP filters, and you need to regain access to your workspace, [contact our support team](https://mattermost.com/support/). + +<Note> + +Going through this process will disable **all** existing rules applied to your workspace. This means that any IP address will now be able to access it. + +</Note> + +## Conclusion + +By configuring IP filters using CIDR notation, system admins can effectively manage access to the workspace, enhancing security by allowing access only from specified IP ranges. + +For any further assistance or queries, [contact our support team](https://mattermost.com/support/). diff --git a/docs/main/administration-guide/manage/code-signing-custom-builds.mdx b/docs/main/administration-guide/manage/code-signing-custom-builds.mdx new file mode 100644 index 000000000000..14c78a9e283a --- /dev/null +++ b/docs/main/administration-guide/manage/code-signing-custom-builds.mdx @@ -0,0 +1,135 @@ +--- +title: "Code signing custom builds" +--- +<PlanAvailability slug="all-commercial" /> + +Code signing is an essential process for ensuring the authenticity and integrity of your custom `Mattermost` builds. This guide provides steps on how to code sign a build using your own certificates for Windows, Mac, and Linux. + +<Important> + +Make sure to follow each operating system's guidelines and best practices for signing applications. + +</Important> + +## Prerequisites + +<div class="tab"> + +Windows + +1. **Code Signing Certificate**: Obtain a certificate from a Certificate Authority (CA) or use a self-signed certificate if suitable. +2. **SignTool**: Available as part of the Windows SDK. + +</div> + +<div class="tab"> + +Linux + +1. **GPG Key**: Create a GPG key if you don't have one. +2. **GnuPG**: Install [GnuPG](https://gnupg.org/howtos/card-howto/en/ch02.html) if not already installed. + +</div> + +<div class="tab"> + +Mac + +1. **Developer ID Application Certificate**: Obtain from Apple. It requires an Apple Developer account. +2. **Xcode**: Ensure [Xcode](https://developer.apple.com/xcode/) is installed. + +</div> + +## Process + +<div class="tab"> + +Windows + +1. **Install SignTool**: Install the Windows SDK to access the `SignTool` utility. + +2. **Obtain a Code Signing Certificate**: Purchase or create a certificate (`.pfx` file) via a CA. + +3. **Import the Certificate**: Open the `.pfx` file and import it into the Windows Certificate Store. + +4. **Sign the Executable** + + - Open the command prompt as Administrator. + - Use `SignTool` to sign your executable: + + ``` sh + signtool sign /v /s "My" /sha1 <cert hash> /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 <path-to-your-executable> + ``` + +</div> + +<div class="tab"> + +Linux + +1. **Create or Import Your GPG Key**: If you don't have a GPG key, create one: + + ``` sh + gpg --full-generate-key + ``` + + Alternatively, import an existing GPG key, if you have one: + + ``` sh + gpg --import /path/to/your-key.asc + ``` + +2. **Sign the Package**: Use `dpkg-sig` to sign a Debian package: + + ``` sh + dpkg-sig --sign builder your-package.deb + ``` + + Use `rpmsign` to sign an RPM package: + + ``` sh + rpmsign --addsign your-package.rpm + ``` + +3. **Verify the Signature**: Verify the signature of a `.deb` package: + + ``` sh + dpkg-sig --verify your-package.deb + ``` + + Verify the signature of an `.rpm` package: + + ``` sh + rpm --checksig your-package.rpm + ``` + +</div> + +<div class="tab"> + +Mac + +1. **Obtain a Code Signing Certificate**: Create a `Developer ID Application` certificate in your Apple Developer account and download it. + +2. **Import the Certificate**: Double-click the certificate to import it into the Keychain. + +3. **Sign the Application**: Use the `codesign` tool from Xcode to sign your application: + + ``` sh + codesign --deep --force --verify --verbose --sign "Developer ID Application: Your Name (TeamID)" /path/to/your.app + ``` + +4. \[Optional\] **Verify the Signature**: Verify the signature to ensure everything is correctly signed: + + ``` sh + spctl --assess --verbose=4 /path/to/your.app + codesign -dv --verbose=4 /path/to/your.app + ``` + +</div> + +## Summary + +- **Windows**: Use `SignTool` from the Windows SDK with your imported code signing certificate. +- **Mac**: Use `codesign` and `spctl` tools from Xcode with your Apple Developer ID certificate. +- **Linux**: Use `GnuPG` to create/sign with your GPG key, `dpkg-sig` for `.deb` packages, and `rpmsign` for `.rpm` packages. diff --git a/docs/main/administration-guide/manage/command-line-tools.mdx b/docs/main/administration-guide/manage/command-line-tools.mdx new file mode 100644 index 000000000000..83ce9a9ec45b --- /dev/null +++ b/docs/main/administration-guide/manage/command-line-tools.mdx @@ -0,0 +1,408 @@ +--- +title: "Command line tools" +--- +<PlanAvailability slug="all-commercial" /> + +In self-managed deployments, a `mattermost` command is available for configuring the system from the directory where the Mattermost server is installed. For an overview of the Mattermost command line interface (CLI), [read this article](https://medium.com/@santosjs/plugging-in-to-the-mattermost-cli-8cdcef2bd1f6) from Santos. + +<Important> + +From Mattermost v6.0, the majority of these CLI commands have been replaced with equivalents available using the [mmctl command line tool](/administration-guide/manage/mmctl-command-line-tool). However, [mattermost import](/administration-guide/manage/command-line-tools#mattermost-import) commands, [mattermost export](/administration-guide/manage/command-line-tools#mattermost-export) commands, and related subcommands, remain available and fully supported from Mattermost v6.0. + +</Important> + +These `mattermost` commands include the following functionality: + +**Compliance Export** + +- Export data +- Schedule an export job + +**Database** + +- Initialize the database, execute migrations, and load custom defaults +- Migrate the database schema for unapplied migrations +- Reset the database to its initial state +- Return the most recently applied version number +- Roll back database migrations + +**Server Operations** + +- Start the Mattermost job server +- Run the Mattermost server +- Display Mattermost version information + +## Use the CLI + +<div class="tab"> + +Via Mattermost + +To run the CLI commands, you must be in the Mattermost root directory. On a default installation of Mattermost, the root directory is `/opt/mattermost`. If you followed our standard [installation process](/deployment-guide/deployment-guide-index), you must run the commands as the user `mattermost`. The name of the executable is `mattermost`, and it can be found in the `/opt/mattermost/bin` directory. + +For example, to get the Mattermost version on a default installation of Mattermost: + +``` sh +cd /opt/mattermost/ +sudo -u mattermost bin/mattermost version +``` + +<Note> + +- Ensure you run the Mattermost binary as the `mattermost` user. Running it as `root` user (for example) may cause complications with permissions as the binary initiates plugins and accesses various files when running CLI commands. Running the server as `root` may result in ownership of the plugins and files to be overwritten as well as other potential permissions errors. + +- When running CLI commands on a Mattermost installation that has the configuration stored in the database, you might need to pass the database connection string as: + + ``` sh + bin/mattermost --config="postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable\u0026connect_timeout=10" + ``` + +</Note> + +</div> + +<div class="tab"> + +Via GitLab Omnibus + +On GitLab Omnibus, you must be in the following directory when you run CLI commands: `/opt/gitlab/embedded/service/mattermost`. Also, you must run the commands as the user *mattermost* and specify the location of the configuration file. The executable is `/opt/gitlab/embedded/bin/mattermost`. + +For example, to get the Mattermost version on GitLab Omnibus: + +``` sh +cd /opt/gitlab/embedded/service/mattermost +sudo /opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/mattermost/env -P -U mattermost:mattermost -u mattermost:mattermost /opt/gitlab/embedded/bin/mattermost version +``` + +<Note> + +The example commands on this documentation page are for a default installation of Mattermost. You must modify the commands so that they work on GitLab Omnibus. + +</Note> + +</div> + +<div class="tab"> + +Via Docker Install + +On Docker install, the `/mattermost/bin` directory was added to `PATH`, so you can use the CLI directly with the `docker exec` command. Note that the container name may be `mattermostdocker_app_1` if you installed Mattermost with `docker-compose.yml`. + +For example, to get the Mattermost version on a Docker Install: + +``` sh +docker exec -it <your-mattermost-container-name> mattermost version +``` + +</div> + +<div class="tab"> + +Via Docker Preview + +The Docker Install tab details and command references below also apply to the [Mattermost docker preview image](https://github.com/mattermost/mattermost-docker-preview). + +</div> + +<Note> + +\- The CLI is run in a single node which bypasses the mechanisms that a [High Availability environment](/administration-guide/scale/high-availability-cluster-based-deployment) uses to perform actions across all nodes in the cluster. As a result, when running [CLI commands](/administration-guide/manage/command-line-tools) in a High Availability environment, tasks that change configuration settings require a server restart. - Parameters in CLI commands are order-specific. - If special characters (`!`, `|`, `(`, `)`, `\`, `'`, or `"`) are used, the entire argument needs to be surrounded by single quotes, or the individual characters need to be escaped out. + +</Note> + +## mattermost CLI commands + +Description +Commands for configuring and managing your Mattermost instance and users. + +Options +``` text +-c, --config {string} Configuration file to use. (default "config.json") +--disableconfigwatch {boolean} When true, the config.json file will not be reloaded automatically when another process changes it (default "false") +``` + +Child Commands +- [mattermost db](#mattermost-db) - Database commands +- [mattermost export](#mattermost-export) - Compliance export commands +- [mattermost help](#mattermost-help) - Generate full documentation for the CLI +- [mattermost import](#mattermost-import) - Legacy import command +- [mattermost jobserver](#mattermost-jobserver) - Start the Mattermost job server +- [mattermost server](#mattermost-server) - Run the Mattermost server +- [mattermost version](#mattermost-version) - Display version information + +## mattermost db + +Description +Commands related to the database + +Child Commands +- [mattermost db downgrade](#mattermost-db-downgrade) - Roll back database migrations. Requires either an update plan to roll back to, or comma-separated version numbers to be rolled back. +- [mattermost db init](#mattermost-db-init) - Initialize the database, execute migrations, and load custom defaults +- [mattermost db migrate](/administration-guide/manage/command-line-tools#mattermost-db-migrate) - Migrate the database schema for unapplied migrations +- [mattermost db reset](#mattermost-db-reset) - Reset the database to its initial state +- [mattermost db version](#mattermost-db-version) - Return the most recently applied version number + +Options +``` text +-h, --help help for db +-c, --config string Configuration file to use +``` + +### mattermost db downgrade + +Description +Rolls back database migrations. Requires either an update plan to roll back to, or comma-separated version numbers to be rolled back. + +Format +``` sh +mattermost db downgrade +``` + +Example +``` sh +mattermost db downgrade 99,100,101 +``` + +Options +``` text +--<plan-file> string Runs the rollback migrations defined in the plan file. +``` + +### mattermost db init + +Description +Initializes the database for a given data source name (DSN), executes migrations, and loads custom defaults when specified. + +Format +``` sh +mattermost db init +``` + +Examples +Use the `config` flag to pass the DSN: + +``` sh +mattermost db init --config postgres://localhost/mattermost +``` + +Run this command to use the `MM_CONFIG` environment variable: + +``` sh +MM_CONFIG=postgres://localhost/mattermost mattermost db init +``` + +Run this command to set a custom defaults file to be loaded into the database: + +``` sh +MM_CUSTOM_DEFAULTS_PATH=custom.json MM_CONFIG=postgres://localhost/mattermost mattermost db init +``` + +### mattermost db migrate + +Description +Migrates the database schema if there are any unapplied migrations. + +Child Commands +- [mattermost db downgrade](#mattermost-db-downgrade) - Roll back database migrations. + +Format +``` sh +mattermost db migrate +``` + +Example +``` sh +mattermost db migrate +``` + +Options +``` text +--auto-recover bool If the migration plan receives an error during migrations, this command will try to rollback migrations already applied within the plan. Not recommended without reviewing migration plan by combining --save-plan and --dry-run options. +--save-plan bool Saves the plan for the migration into the file store so that it can be used for reviewing the plan or for downgrading. +--dry-run bool Does not apply the migrations, but it validates how the migration would run based on the given conditions. +``` + +### mattermost db reset + +Description +Resets the database to its initial state. Doesn't start the application server. Only starts the store layer and truncates the tables, excluding the `migrations` table. + +Format +``` sh +mattermost db reset +``` + +Example +``` sh +bin/mattermost db reset +``` + +### mattermost db version + +Description +Returns the most recently applied version number. + +Format +``` sh +mattermost db version +``` + +------------------------------------------------------------------------------------------------------------------------ + +## mattermost export + +<PlanAvailability slug="ent-plus" /> + +Description +Commands for exporting data for compliance and for merging multiple Mattermost instances. + +Child Commands +- [mattermost export actiance](#mattermost-export-actiance) - Deprecated from Mattermost v10.5 in favor of [mattermost export schedule](#mattermost-export-schedule). +- [mattermost export csv](#mattermost-export-csv) - Deprecated from Mattermost v10.5. +- [mattermost export global-relay-zip](#mattermost-export-global-relay-zip) - Deprecated from Mattermost v10.5. +- [mattermost export schedule](#mattermost-export-schedule) - Schedule a compliance export job. +- [mattermost export bulk](#mattermost-export-bulk) - Export data to a file compatible with the Mattermost [Bulk Import format](/administration-guide/onboard/bulk-loading-data). Deprecated in favor of [mmctl export commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-export). + +### mattermost export actiance + +From Mattermost v10.5, this command has been deprecated. It will be added to the mmctl command line tool in a future version. Until then, please use [mattermost export schedule](#mattermost-export-schedule). + +### mattermost export csv + +From Mattermost v10.5, this command has been deprecated. It will be added to the mmctl command line tool in a future version. + +### mattermost export global-relay-zip + +From Mattermost v10.5, this command has been deprecated. It will be added to the mmctl command line tool in a future version. + +### mattermost export schedule + +Description +Schedule an export job in a format suitable for importing into a third-party archive system. + +Format +``` sh +mattermost export schedule +``` + +Example +``` sh +bin/mattermost export schedule --exportFrom=1513102632 +``` + +Options +``` text +--exportFrom string Unix timestamp (seconds since epoch, UTC) to export data from. +--timeoutSeconds string Set how long the export should run for before timing out. +``` + +### mattermost export bulk + +From Mattermost v6.0, this command has been deprecated in favor of [mmctl export commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-export) as the supported way to export data out of Mattermost. + +------------------------------------------------------------------------------------------------------------------------ + +## mattermost help + +Description +Generate full documentation in Markdown format for the Mattermost command line tools. + +Format +``` sh +mattermost help {outputdir} +``` + +<div id="command-line-tools-mattermost-jobserver"> + +------------------------------------------------------------------------------------------------------------------------ + +</div> + +## mattermost import + +Description +Import data into Mattermost. + +Child Command +- [mattermost import bulk](#mattermost-import-bulk) - Import a Mattermost Bulk Import File. Deprecated in favor of [mmctl import commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-import). +- [mattermost import slack](#mattermost-import-slack) - Import a team from Slack. + +### mattermost import bulk + +From Mattermost v6.0, this command has been deprecated in favor of [mmctl import commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-import) as the supported way to import data into Mattermost. + +### mattermost import slack + +See the [mmctl import commands](/administration-guide/manage/mmctl-command-line-tool#mmctl-import) documentation as the preferred way to import Slack data into Mattermost. + +Description +Import a team from a Slack export zip file. + +Format +. code-block:: sh + +mattermost import slack {team} {file} + +Example +``` sh +bin/mattermost import slack myteam slack_export.zip +``` + +------------------------------------------------------------------------------------------------------------------------ + +## mattermost jobserver + +Description +Start the Mattermost job server. + +Format +``` sh +mattermost jobserver +``` + +Example +``` sh +bin/mattermost jobserver +``` + +------------------------------------------------------------------------------------------------------------------------ + +## mattermost server + +Description +Runs the Mattermost server. + +Format +``` sh +mattermost server +``` + +------------------------------------------------------------------------------------------------------------------------ + +## mattermost version + +<Note> + +From Mattermost v6.5, this CLI command no longer interacts with the database. The [mattermost db migrate](/administration-guide/manage/command-line-tools#mattermost-db-migrate) CLI command has been introduced to trigger schema migrations. + +</Note> + +Desription +Displays Mattermost version information. + +Format +``` sh +mattermost version +``` + +------------------------------------------------------------------------------------------------------------------------ + +## Troubleshooting + +### Executing a command hangs and doesn't complete + +If you have Bleve search indexing enabled, temporarily disable it in **System Console \> Experimental \> Bleve** and run the command again. You can also optionally use the new [mmctl Command Line Tool](/administration-guide/manage/mmctl-command-line-tool). + +Bleve does not support multiple processes opening and manipulating the same index. Therefore, if the Mattermost server is running, an attempt to run the CLI will lock when trying to open the indeces. + +If you aren't using the Bleve search indexing, feel free to post in our [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to get help. diff --git a/docs/main/administration-guide/manage/configure-health-check-probes.mdx b/docs/main/administration-guide/manage/configure-health-check-probes.mdx new file mode 100644 index 000000000000..b02b4e146be7 --- /dev/null +++ b/docs/main/administration-guide/manage/configure-health-check-probes.mdx @@ -0,0 +1,48 @@ +--- +title: "Configure server health check probes" +--- +<PlanAvailability slug="entry-ent" /> + +This page describes how to configure health check probes for a Mattermost server. + +Before you begin, you should have a running Mattermost server. If you don't, you can [install Mattermost on various distributions](/deployment-guide/deployment-guide-index). + +<Note> + +[Highly available Mattermost cluster support](/administration-guide/scale/high-availability-cluster-based-deployment) requires Mattermost Enterprise. + +</Note> + +You can perform a health check with the following 2 methods: + +- [ping the APIv4 endpoint](#ping-the-apiv4-endpoint) +- [ping the Mattermost server](#ping-the-mattermost-server) + +## Ping the APIv4 endpoint + +You can use the [GET /system/ping APIv4 endpoint](https://api.mattermost.com/#tag/system%2Fpaths%2F~1system~1ping%2Fget) to check for system health. + +A sample request is included below. The endpoint checks if the server is up and healthy based on the configuration setting `GoRoutineHealthThreshold`. + +- If `GoRoutineHealthThreshold` and the number of goroutines on the server exceeds that threshold, the server is considered unhealthy. +- If `GoRoutineHealthThreshold` is not set or the number of goroutines is below the threshold the server is considered healthy. + +This endpoint can also be provided to schedulers like [Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/). + +``` go +import github.com/mattermost/mattermost/tree/master/server/public/model" + +Client := model.NewAPIv4Client("https://your-mattermost-url.com") +Client.Login("email@domain.com", "Password1") + +// GetPing +status, err := Client.GetPing() +``` + +## Ping the Mattermost server + +The [Mattermost Probe](https://github.com/csduarte/mattermost-probe) constantly pings a Mattermost server using a variety of probes. + +These probes can be configured to verify core features, including sending and receiving messages, joining channels, pinging a login page, and searching of users and channels. + +The project is contributed by the Mattermost open source community. Suggestions and contributions for the project are welcome. diff --git a/docs/main/administration-guide/manage/feature-labels.mdx b/docs/main/administration-guide/manage/feature-labels.mdx new file mode 100644 index 000000000000..a3d031e23c45 --- /dev/null +++ b/docs/main/administration-guide/manage/feature-labels.mdx @@ -0,0 +1,22 @@ +--- +title: "Mattermost feature labels" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost’s feature labels serve as indicators of the status, maturity, and support level of each feature, helping users and system administrators navigate product feature adoption with clarity and confidence. Feature labels communicate the stage of development, level of readiness, and potential risks associated with a feature for customers seeking to adopt new value. + +## Experimental + +Feature is an early Proof of Concept (POC) with an unstable codebase, minimal QA covering a small or specific set of use cases, and potential UI issues. Security reviews are incomplete, making it unsuitable for production. Distribution of the solution is limited, and our Cloud environments are typically not eligible to use experimental features. Data loss can occur as data schemas and configurations may change, and minimal documentation is available. Caution is advised as the solution may be discarded if its value is not proven. + +## Beta + +Feature is in active development towards General Availability. Not fully complete, but reviewed by our security team, adoption is suitable for a small set of customers behind a feature flag. Identified bugs are fixed on a best effort basis, and no major breaking changes are anticipated, full testing is in progress, and detailed documentation may not be available. Beta is a transitional stage, meaning the solution is maturing but requires careful consideration in a full production deployment as scale and client availability may vary. [Premier Support](https://mattermost.com/support/) is recommended when using beta features in production environments. + +## General Availability + +Feature has undergone thorough validation and testing and has production-level quality. It is feature-complete, meets quality standards, has successfully passed security reviews, and has detailed product documentation available. General Availability features are suitable for widespread production deployment and adoption, and are eligible for commercial support, as they offer stability and reliability, with no expected changes that could disrupt functionality or scalability. + +## Deprecated + +Feature is officially marked for removal from the product. It is no longer supported or actively maintained by the development team. If the feature is still in use in your deployed version, we recommend users discontinue its use and migrate to alternative functionalities. diff --git a/docs/main/administration-guide/manage/in-product-notices.mdx b/docs/main/administration-guide/manage/in-product-notices.mdx new file mode 100644 index 000000000000..33a5c601b809 --- /dev/null +++ b/docs/main/administration-guide/manage/in-product-notices.mdx @@ -0,0 +1,39 @@ +--- +title: "In-product notices" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost in-product notices keep users and administrators informed of the newest product improvements, features, and releases. + +## Administrator notices + +Administrator notices inform system admins when a new server version is available, when external dependencies are being deprecated, or when server upgrades are recommended due to ending support life cycles. System admins may also receive notices about recommended server configuration options to optimize the user experience of their deployment. + +![An example of an in-product administrator notice announcing that a new server version of Mattermost is available. Admin notices can be disabled.](/images/notices_admin.png) + +System admins can disable end user notices by going to **System Console \> Site Configuration \> Notices**. + +## End user notices + +End user notices are used to inform all users when: + +- New desktop app versions and feature enhancements are available for users. +- Mattermost is gathering user feedback to improve the product and user experience. + +System admins can disable end user notices by going to **System Console \> Site Configuration \> Notices**. + +![An example of an end user in-product notice announcing that a new Mattermost desktop app release is available. End user notices can be disabled.](/images/notices.png) + +## Frequently asked questions (FAQs) + +### Are notices enabled by default? + +Yes. Notices are enabled by default for all Mattermost users. System admins may choose to disable admin or end user notices in **System Console \> Site Configuration \> Notices**. + +### Will I still receive notices if my server is air-gapped? + +No, the Mattermost server requires a connection to the internet to receive notices. + +### How often will users receive notices? + +Notices will be used to raise awareness of new features as part of our monthly release cadence. Users will only receive notices that specifically apply to them. For example, if a user is already running the latest Desktop App version, they will not receive an upgrade notice. diff --git a/docs/main/administration-guide/manage/logging.mdx b/docs/main/administration-guide/manage/logging.mdx new file mode 100644 index 000000000000..c9c3dac2fb0f --- /dev/null +++ b/docs/main/administration-guide/manage/logging.mdx @@ -0,0 +1,1222 @@ +--- +title: "Mattermost logging" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +<Important> + +**From Mattermost v11, notification log settings have been consolidated into the standard console logs and mattermost.log file**. You can no longer disable notification logging without using advanced logging settings, as the main log level setting now controls both server and notification logs. + +You can use the `AdvancedLoggingJSON` configuration with discrete notification log levels: `NotificationError`, `NotificationWarn`, `NotificationInfo`, `NotificationDebug`, and `NotificationTrace` to split notification logs into separate files and reduce troubleshooting noise. See the section below on [advanced logging](#advanced-logging) for details. + +</Important> + +Mattermost provides independent logging systems that can be configured separately with separate log files and rotation policies to meet different operational and compliance needs: + +<table> +<colgroup> +<col style={{width: '45%'}} /> +<col style={{width: '25%'}} /> +<col style={{width: '30%'}} /> +</colgroup> +<thead> +<tr> +<th>Logging Type & Capture</th> +<th>Production Recommendation</th> +<th>Configuration Priority</th> +</tr> +</thead> +<tbody> +<tr> +<td><p><strong>Log Settings</strong></p><p>All general Mattermost server operations, errors, startup/initialization, API calls, and system events. From v11.0, also includes notification subsystem events.</p></td> +<td>Always enabled. Console: INFO, File: INFO</td> +<td><strong>High</strong> - Essential for operations</td> +</tr> +<tr> +<td><p><strong>Audit Log Settings</strong></p><p>Security and compliance events, user actions, API access, authentication events, and administrative changes.</p></td> +<td>Enable if compliance is required</td> +<td><strong>Medium</strong> - Based on regulatory needs</td> +</tr> +<tr> +<td><p><strong>Notification Log Settings</strong> <em>(applicable to v10.12 and earlier releases only)</em></p><p>Notification subsystem events, push notifications, email delivery, mobile notification processing.</p></td> +<td>Enable for notification troubleshooting</td> +<td><strong>Low</strong> - Enable when debugging issues</td> +</tr> +</tbody> +</table> + +By default, all Mattermost plans write logs to both the console and to the `mattermost.log` file in a machine-readable JSON format for log aggregation tools. Mattermost Enterprise and Professional customers can additionally log directly to syslog and TCP socket destination targets. Audit logging is designed to be asynchronous to minimize performance impact. + +System admins can customize the following logging options based on your business practices and needs by going to **System Console \> Environment \> Logging** or by editing the `config.json` file directly. + +<Note> + +From Mattermost v11.3, AdvancedLoggingJSON configuration includes enhanced validation that enforces proper separation between standard and audit log levels: + +- Standard logging configurations reject audit-specific log levels (`audit-api`, `audit-content`, `audit-permissions`, `audit-cli`) +- Audit logging configurations reject standard log levels (`debug`, `info`, `warn`, `error`, `fatal`, `panic`, etc.) +- Configuration validation occurs at startup and when updating settings, preventing invalid log level combinations + +</Note> + +## Console logs + +Console logs feature verbose debug level log messages for general activities that are written to the console using the standard output stream (stdout). You can customize console logs for general activities. + +From Mattermost v11.0, notification logs are automatically included in the main console logs. See the [Logging configuration settings](/administration-guide/configure/environment-configuration-settings#output-logs-to-console) for details. + +## File logs + +File logs feature info level log messages for general activities including errors and information around startup, and initialization and webhook debug messages. The file is stored in `./logs/mattermost.log`, rotated at 100 MB, and archived to a separate file in the same directory. You can customize file logs for general activities. + +From Mattermost v11.0, notification logs are automatically included in the main `mattermost.log` file. See the [Logging configuration settings](/administration-guide/configure/environment-configuration-settings#output-logs-to-file) for details. + +<Tip> + +Download the `mattermost.log` file locally by going to **System Console \> Reporting \> Server Logs**, and selecting **Download Logs**. + +</Tip> + +You can optionally output log records to any combination of [console](#console-target-configuration-options), [local file](#file-target-configuration-options), [syslog](#syslog-target-configuration-options), and [TCP socket](#tcp-target-configuration-options) targets, each featuring additional customization. See [Advanced Logging](#advanced-logging) for details. + +## Define logging output + +Define logging output for general activities in JSON format in the System Console by going to **Environment \> Logging \> Advanced Logging** or by editing the `config.json` file directly. + +You can use the sample JSON below as a starting point. + +<div class="tab"> + +v11 or later + +``` JSON +{ + "console1": { + "type": "console", + "format": "json", + "levels": [ + {"id": 5, "name": "debug", "stacktrace": false}, + {"id": 4, "name": "info", "stacktrace": false, "color": 36}, + {"id": 3, "name": "warn", "stacktrace": false}, + {"id": 2, "name": "error", "stacktrace": true, "color": 31}, + {"id": 1, "name": "fatal", "stacktrace": true, "color": 31}, + {"id": 0, "name": "panic", "stacktrace": true, "color": 31}, + {"id": 10, "name": "stdlog", "stacktrace": false}, + + {"id": 300, "name": "NotificationError", "stacktrace": true, "color": 31}, + {"id": 301, "name": "NotificationWarn", "stacktrace": false}, + {"id": 302, "name": "NotificationInfo", "stacktrace": false, "color": 36}, + {"id": 303, "name": "NotificationDebug", "stacktrace": false}, + {"id": 304, "name": "NotificationTrace", "stacktrace": false} + ], + "options": { + "out": "stdout" + }, + "maxqueuesize": 1000 + }, + "file1": { + "type": "file", + "format": "json", + "levels": [ + {"id": 5, "name": "debug", "stacktrace": false}, + {"id": 4, "name": "info", "stacktrace": false}, + {"id": 3, "name": "warn", "stacktrace": false}, + {"id": 2, "name": "error", "stacktrace": true}, + {"id": 1, "name": "fatal", "stacktrace": true}, + {"id": 0, "name": "panic", "stacktrace": true}, + + {"id": 300, "name": "NotificationError", "stacktrace": true}, + {"id": 301, "name": "NotificationWarn", "stacktrace": false}, + {"id": 302, "name": "NotificationInfo", "stacktrace": false}, + {"id": 303, "name": "NotificationDebug", "stacktrace": false}, + {"id": 304, "name": "NotificationTrace", "stacktrace": false} + ], + "options": { + "filename": "mattermost_logging.log", + "max_size": 100, + "max_age": 1, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + }, + "file2": { + "type": "file", + "format": "json", + "levels": [ + {"id": 2, "name": "error", "stacktrace": true}, + {"id": 1, "name": "fatal", "stacktrace": true}, + {"id": 0, "name": "panic", "stacktrace": true}, + + {"id": 300, "name": "NotificationError", "stacktrace": true}, + {"id": 301, "name": "NotificationWarn", "stacktrace": false} + ], + "options": { + "filename": "mattermost_logging_errors.log", + "max_size": 100, + "max_age": 30, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + } +} +``` + +</div> + +<div class="tab"> + +v10.12 or earlier + +``` JSON +{ + "console1": { + "type": "console", + "format": "json", + "levels": [ + {"id": 5, "name": "debug", "stacktrace": false}, + {"id": 4, "name": "info", "stacktrace": false, "color": 36}, + {"id": 3, "name": "warn", "stacktrace": false}, + {"id": 2, "name": "error", "stacktrace": true, "color": 31}, + {"id": 1, "name": "fatal", "stacktrace": true, "color": 31}, + {"id": 0, "name": "panic", "stacktrace": true, "color": 31}, + {"id": 10, "name": "stdlog", "stacktrace": false} + ], + "options": { + "out": "stdout" + }, + "maxqueuesize": 1000 + }, + "file1": { + "type": "file", + "format": "json", + "levels": [ + {"id": 5, "name": "debug", "stacktrace": false}, + {"id": 4, "name": "info", "stacktrace": false}, + {"id": 3, "name": "warn", "stacktrace": false}, + {"id": 2, "name": "error", "stacktrace": true}, + {"id": 1, "name": "fatal", "stacktrace": true}, + {"id": 0, "name": "panic", "stacktrace": true} + ], + "options": { + "filename": "mattermost_logging.log", + "max_size": 100, + "max_age": 1, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + }, + "file2": { + "type": "file", + "format": "json", + "levels": [ + {"id": 2, "name": "error", "stacktrace": true}, + {"id": 1, "name": "fatal", "stacktrace": true}, + {"id": 0, "name": "panic", "stacktrace": true} + ], + "options": { + "filename": "mattermost_logging_errors.log", + "max_size": 100, + "max_age": 30, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + } +} +``` + +</div> + +------------------------------------------------------------------------------------------------------------------------ + +## Audit logging + +<PlanAvailability slug="ent-plus" /> + +By default, Mattermost doesn't write audit logs locally to a file on the server, and the ability to enable audit logging in Mattermost is currently in [Beta](/administration-guide/manage/feature-labels#beta). + +You can enable and customize advanced audit logging in Mattermost to record activities and events performed within Mattermost, such as user access to the Mattermost REST API or mmctl. Audit logs are recorded asynchronously to reduce latency to the caller, and are stored separately from general logging. During short spans of inability to write to targets, the audit records buffer in memory with a configurable maximum record cap. Based on typical audit record volumes, it could take many minutes to fill the buffer. After that, the records are dropped, and the record drop event is logged. + +<Note> + +From Mattermost v7.2, audit logging is a breaking change from previous releases in cases where customers looking to parse previous audit logs with the new format. The format and content of an audit log record has changed to become standardized for all events using a [standard JSON schema](/administration-guide/comply/embedded-json-audit-log-schema). Existing tools which ingest or parse audit log records may need to be modified. + +From Mattermost v9.3, you can enable and customize advanced logging for AD/LDAP events separately from other logging. + +</Note> + +<div class="tab"> + +Self-Hosted Deployments + +Go to **System Console \> Compliance \> Audit Logging** to customize audit logging. You can use the sample JSON below as a starting point. + +You can customize console logs for [general](/administration-guide/configure/environment-configuration-settings#log-settings) activities. From v11.0, [notification](/administration-guide/configure/environment-configuration-settings#notification-logging) logs are automatically included unless advanced logging is configured. + +Additionally, you can also output audit log records to any combination of [console](#console-target-configuration-options), [local file](#file-target-configuration-options), [syslog](#syslog-target-configuration-options), and [TCP socket](#tcp-target-configuration-options) targets, each featuring additional customization. See [Advanced Logging](#advanced-logging) below for details. + +</div> + +<div class="tab"> + +Cloud Deployments + +From Mattermost v10.11, go to **System Console \> Compliance \> Audit Logging** to customize audit logging. You can use the sample JSON below as a starting point. Prior to Mattermost v10.11, customize audit logging by going to **System Console \> Experimental \> Features \> Audit Logging**. + +<Note> + +- From Mattermost v10.11, Cloud deployments include certificate-based audit logging capabilities not available within self-hosted deployments. + +- Cloud-based deployments use the following self-hosted audit logging default values: + + > - FileEnabled: false + > - FileMaxSizeMB: 100 + > - FileMaxAgeDays: 0 (no limit) + > - FileMaxBackups: 0 (retain all) + > - FileCompress: false + > - FileMaxQueueSize: 1000 + +- Cloud deployments can't configure local file-based audit logging, and all file-related settings are hidden. + +</Note> + +</div> + +------------------------------------------------------------------------------------------------------------------------ + +## Log path restrictions + +From Mattermost v11.4, log file paths are validated to ensure they remain within a designated logging root directory. This security enhancement prevents log files from being written to or read from unauthorized locations on the file system. + +### Configure the logging root directory + +From Mattermost v11.4, use the `MM_LOG_PATH` environment variable to define the root directory for all log files: + +``` sh +export MM_LOG_PATH=/var/log/mattermost +``` + +If `MM_LOG_PATH` isn't set, Mattermost uses the default `logs` directory relative to the Mattermost binary location. + +### Log path validation + +All log file paths configured via the following settings are validated: + +- `LogSettings.FileLocation` - main [server log file location](/administration-guide/configure/environment-configuration-settings#file-log-directory) +- `LogSettings.AdvancedLoggingJSON` - all [file targets in advanced logging configuration](/administration-guide/configure/environment-configuration-settings#output-logs-to-multiple-targets) +- `ExperimentalAuditSettings.AdvancedLoggingJSON` - all [file targets in audit logging configuration](/administration-guide/configure/environment-configuration-settings#output-audit-logs-to-multiple-targets) + +**How validation works**: + +1. Paths are resolved to absolute paths +2. Symlinks are resolved to their actual locations +3. The resolved path is validated against the logging root directory +4. Paths outside the root directory generate error logs and are excluded from downloads + +**Validation occurs**: + +- When accessing log files via **System Console \> Reporting \> Server Logs** +- When generating support packets +- During configuration changes (warnings are logged for invalid paths) + +When a log file path is outside the allowed root directory, Mattermost logs an error and excludes the file from support packet downloads: `"Blocked attempt to read log file outside allowed root"`. The error message includes the file path, configuration section, and validation failure details. + +### Configuration requirements + +**If using default logging**: No action required. Logs are stored in the default `logs` directory. + +**If using custom log paths**: Ensure all log file paths in `AdvancedLoggingJSON` point to locations within your logging root directory. + +**Valid configuration example**: + +``` sh +export MM_LOG_PATH=/var/log/mattermost +``` + +In `config.json`: + +``` JSON +{ + "file1": { + "type": "file", + "format": "json", + "levels": [ + {"id": 2, "name": "error", "stacktrace": true} + ], + "options": { + "filename": "/var/log/mattermost/errors.log", + "max_size": 100, + "max_age": 7, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + } +} +``` + +This configuration is valid because `/var/log/mattermost/errors.log` is within the `/var/log/mattermost` root. + +**Invalid configuration example**: + +If `MM_LOG_PATH=/var/log/mattermost`, this configuration fails: + +``` JSON +{ + "file1": { + "type": "file", + "options": { + "filename": "/tmp/logs/app.log" + } + } +} +``` + +This fails because `/tmp/logs/app.log` is outside the `/var/log/mattermost` root directory. + +See the [troubleshooting](/deployment-guide/server/troubleshooting#log-files-not-accessible) documentation for troubleshooting steps if logs aren't appearing in the System Console or support packets due to log path issues. + +------------------------------------------------------------------------------------------------------------------------ + +## Advanced logging + +<PlanAvailability slug="entry-ent" /> + +System admins can output log and audit records for general and audit activities to any combination of [console](#console-target-configuration-options), [local file](#file-target-configuration-options), [syslog](#syslog-target-configuration-options), and [TCP socket](#tcp-target-configuration-options) targets. + +<Tip> + +- From Mattermost v11.0, notification activities are included in general logs by default, but can be separated using the new discrete notification log levels. Each output target features additional configuration options you can customize for your Mattermost deployment. +- From Mattermost v9.11, system admins can configure advanced logging JSON options using the `mmctl config set` command. See the [mmctl config set](/administration-guide/manage/mmctl-command-line-tool#mmctl-config-set) documentation for an example slash command. +- From Mattermost v9.3, system admins can configure advanced logging options in the System Console using multi-line JSON by going to **Environment \> Logging**. +- Alternatively, admins can configure advanced logging within the `AdvancedLoggingJSON` section of the `config.json` file using multi-line JSON or escaped JSON as a string. +- Mattermost Team Edition customers can output audit log records to the console or a file. + +</Tip> + +Advanced logging options can be configured to: + +- Enable trace logging for AD/LDAP to troubleshoot authentication issues. +- Capture errors and panics in a separate, monitored file that triggers alerts. +- Capture production debug and error logs in a separate file with log file rotation to reproduce issues, while enforcing a cap on the amount of disk space the debug logs are allowed to use. +- Audit every API endpoint accessed during a user workflow. + +### Define advanced log output + +<div class="tab" parse-titles=""> + +Multi-line JSON + +In the example below, file output is written to `./logs/audit.log` in plain text and includes all audit log levels & events. Older logs are kept for 1 day, and up to a total of 10 backup log files are kept at a time. Logs are rotated using gzip when the maximum size of the log file reaches 500 MB. A maximum of 1000 audit records can be queued/buffered while writing to the file. + +#### v11 or later + +``` JSON +"AdvancedLoggingJSON": { + "file_1": { + "type": "file", + "format": "plain", + "format_options": { + "disable_level": false + }, + "levels": [ + { "id": 100, "name": "audit-api" }, + { "id": 101, "name": "audit-content" }, + { "id": 102, "name": "audit-permissions" }, + { "id": 103, "name": "audit-cli" } + ], + "options": { + "compress": true, + "filename": "./logs/audit.log", + "max_age": 1, + "max_backups": 10, + "max_size": 500 + }, + "maxqueuesize": 1000 + }, + "file_notifications": { + "type": "file", + "format": "json", + "levels": [ + { "id": 300, "name": "NotificationError" }, + { "id": 301, "name": "NotificationWarn" }, + { "id": 302, "name": "NotificationInfo" }, + { "id": 303, "name": "NotificationDebug" }, + { "id": 304, "name": "NotificationTrace" } + ], + "options": { + "compress": true, + "filename": "./logs/notifications.log", + "max_age": 7, + "max_backups": 5, + "max_size": 200 + }, + "maxqueuesize": 1000 + } +} +``` + +#### v10.12 or earlier + +``` JSON +"AdvancedLoggingJSON": { + "file_1": { + "type": "file", + "format": "plain", + "format_options": { + "disable_level": false + }, + "levels": [ + { "id": 100, "name": "audit-api" }, + { "id": 101, "name": "audit-content" }, + { "id": 102, "name": "audit-permissions" }, + { "id": 103, "name": "audit-cli" } + ], + "options": { + "compress": true, + "filename": "./logs/audit.log", + "max_age": 1, + "max_backups": 10, + "max_size": 500 + }, + "maxqueuesize": 1000 + } +} +``` + +</div> + +<div class="tab" parse-titles=""> + +Filespec + +Advanced logging configuration can be pointed to a filespec to another configuration file, rather than multi-line JSON, to keep the config.json file tidy: + +``` JSON +"AdvancedLoggingJSON": "/path/to/audit_log_config.json" +``` + +The separate configuration file includes the multi-line JSON instead. + +In the example below, the first output is written to the console in plain text and includes all audit log levels, events, and command outputs. A pipe `|` delimiter is placed between fields. + +A second output is written to `./logs/audit.log` in plain text in a machine-readable JSON format and includes all audit log levels, events, and command outputs. Older logs are kept for 1 day, and up to a total of 10 backup log files are kept at a time. Logs are rotated using GZIP when the maximum size of the log file reaches 500 MB. A maximum of 1000 audit records can be queued/buffered while writing to the file. + +Contents of `audit_log_config.json` file: + +#### v11 or later + +``` JSON +{ + "sample-console": { + "type": "console", + "format": "plain", + "format_options": { + "delim": " | " + }, + "levels": [ + {"id": 100, "name": "audit-api"}, + {"id": 101, "name": "audit-content"}, + {"id": 102, "name": "audit-permissions"}, + {"id": 103, "name": "audit-cli"} + ], + "options": { + "out": "stdout" + }, + "maxqueuesize": 1000 + }, + "sample-file": { + "type": "file", + "format": "json", + "levels": [ + {"id": 100, "name": "audit-api"}, + {"id": 101, "name": "audit-content"}, + {"id": 102, "name": "audit-permissions"}, + {"id": 103, "name": "audit-cli"} + ], + "options": { + "filename": "./logs/audit.log", + "max_size": 500, + "max_age": 1, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + }, + "notifications-file": { + "type": "file", + "format": "json", + "levels": [ + {"id": 300, "name": "NotificationError"}, + {"id": 301, "name": "NotificationWarn"}, + {"id": 302, "name": "NotificationInfo"}, + {"id": 303, "name": "NotificationDebug"}, + {"id": 304, "name": "NotificationTrace"} + ], + "options": { + "filename": "./logs/notifications.log", + "max_size": 200, + "max_age": 7, + "max_backups": 5, + "compress": true + }, + "maxqueuesize": 1000 + } +} +``` + +#### v10.12 or earlier + +``` JSON +{ + "sample-console": { + "type": "console", + "format": "plain", + "format_options": { + "delim": " | " + }, + "levels": [ + {"id": 100, "name": "audit-api"}, + {"id": 101, "name": "audit-content"}, + {"id": 102, "name": "audit-permissions"}, + {"id": 103, "name": "audit-cli"} + ], + "options": { + "out": "stdout" + }, + "maxqueuesize": 1000 + }, + "sample-file": { + "type": "file", + "format": "json", + "levels": [ + {"id": 100, "name": "audit-api"}, + {"id": 101, "name": "audit-content"}, + {"id": 102, "name": "audit-permissions"}, + {"id": 103, "name": "audit-cli"} + ], + "options": { + "filename": "./logs/audit.log", + "max_size": 500, + "max_age": 1, + "max_backups": 10, + "compress": true + }, + "maxqueuesize": 1000 + } +} +``` + +</div> + +### Specify destination targets + +Log records can be sent to any combination of [console](#console-target-configuration-options), [local file](#file-target-configuration-options), [syslog](#syslog-target-configuration-options), and [TCP socket](#tcp-target-configuration-options) targets. Log targets have been chosen based on support for the vast majority of log aggregators and other log analysis tools, without needing additional software installed. + +System admins can define multiple log targets to: + +- Mirror log output to files and log aggregators for redundancy. +- Log certain entries to specific destinations. For example, all `audit-content` records can be routed to a different destination than the other levels. +- Admins can also temporarily disable log targets by setting its `type` to `none`. + +### Configure format preferences + +System admins can control log formatting per target by configuring the `format_options` section. + +#### Plain log format configuration options + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '13%'}} /> +<col style={{width: '6%'}} /> +<col style={{width: '78%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>disable_timestamp</td> +<td>bool</td> +<td>Disables output of the timestamp. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_level</td> +<td>bool</td> +<td>Disables output of the level name. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_msg</td> +<td>bool</td> +<td>Disables output of the message text. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_fields</td> +<td>bool</td> +<td>Disables output of all fields. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disables_stacktrace</td> +<td>bool</td> +<td>Disables output of stack traces. Default is <code>false</code>.</td> +</tr> +<tr> +<td>enable_caller</td> +<td>string</td> +<td>Enables output of the file and line number that emitted a log record. Default is <code>false</code>.</td> +</tr> +<tr> +<td>delim</td> +<td>string</td> +<td>Delimiter placed between fields. Default is single space.</td> +</tr> +<tr> +<td>min_level_len</td> +<td>number</td> +<td>Minimum level name length. When level names are less than the minimum, level names are padded with spaces. Default is <code>0</code>.</td> +</tr> +<tr> +<td>min_msg_len</td> +<td>number</td> +<td>Minimum message length. When message text is less than the minimum, message text is padded with spaces. Default is <code>0</code>.</td> +</tr> +<tr> +<td>timestamp_format</td> +<td>string</td> +<td>Format for timestamps. Default is <a href="https://www.rfc-editor.org/rfc/rfc3339">RFC3339</a>.</td> +</tr> +<tr> +<td>line_end</td> +<td>string</td> +<td>Alternative end of line character(s). Default is <code>n</code>.</td> +</tr> +<tr> +<td>enable_color</td> +<td>bool</td> +<td>Enables color for targets that support color output. Default is <code>false</code>.</td> +</tr> +</tbody> +</table> + +#### JSON log format configuration options + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '17%'}} /> +<col style={{width: '8%'}} /> +<col style={{width: '73%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>disable_timestamp</td> +<td>bool</td> +<td>Disables output of the timestamp. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_level</td> +<td>bool</td> +<td>Disables output of the log level display name. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_msg</td> +<td>bool</td> +<td>Disables output of the message text. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disable_fields</td> +<td>bool</td> +<td>Disables output of all fields. Default is <code>false</code>.</td> +</tr> +<tr> +<td>disables_stacktrace</td> +<td>bool</td> +<td>Disables output of stack traces. Default is <code>false</code>.</td> +</tr> +<tr> +<td>enable_caller</td> +<td>string</td> +<td>Enables output of the file and line number that emitted a log record. Default is <code>false</code>.</td> +</tr> +<tr> +<td>timestamp_format</td> +<td>string</td> +<td>Format for timestamps. Default is <a href="https://www.rfc-editor.org/rfc/rfc3339">RFC3339</a>.</td> +</tr> +</tbody> +</table> + +#### GELF log format configuration options + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '13%'}} /> +<col style={{width: '8%'}} /> +<col style={{width: '77%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>hostname</td> +<td>string</td> +<td>Outputs a custom hostname in log records. If omitted, hostname is taken from the operating system.</td> +</tr> +<tr> +<td>enable_caller</td> +<td>string</td> +<td>Enables output of the file and line number that emitted a log record. Default is <code>false</code>.</td> +</tr> +</tbody> +</table> + +### Configure log levels and events + +<table style={{width: '72%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '9%'}} /> +<col style={{width: '51%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>id</td> +<td>number</td> +<td>Unique identifier of the log level.</td> +</tr> +<tr> +<td>name</td> +<td>string</td> +<td>Name of the log level.</td> +</tr> +<tr> +<td>stacktrace</td> +<td>bool</td> +<td>Outputs a stack trace. Default is <code>false</code>.</td> +</tr> +<tr> +<td>color</td> +<td>number</td> +<td><p>The ANSI color code used to output parts of the log record. Supported values include:</p><ul><li>Black: <code>30</code></li><li>Red: <code>31</code></li><li>Green: <code>32</code></li><li>Yellow: <code>33</code></li><li>Blue: <code>34</code></li><li>Magenta: <code>35</code></li><li>Cyan: <code>36</code></li><li>White: <code>37</code></li></ul></td> +</tr> +</tbody> +</table> + +#### Log levels + +The following log levels support audit logs: + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '7%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>ID</strong></td> +<td><strong>Name</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>100</td> +<td><code>audit-api</code></td> +<td>API events</td> +</tr> +<tr> +<td>101</td> +<td><code>audit-content</code></td> +<td>Content changes. This log level can generate considerably more records than the other audit log levels.</td> +</tr> +<tr> +<td>102</td> +<td><code>audit-permissions</code></td> +<td>Permission changes</td> +</tr> +<tr> +<td>103</td> +<td><code>audit-cli</code></td> +<td>CLI operations</td> +</tr> +</tbody> +</table> + +The following log levels support application logs: + +<table style={{width: '88%'}}> +<colgroup> +<col style={{width: '7%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>ID</strong></td> +<td><strong>Name</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>140</td> +<td><code>LDAPError</code></td> +<td>AD/LDAP authentication errors</td> +</tr> +<tr> +<td>141</td> +<td><code>LDAPWarn</code></td> +<td>AD/LDAP authentication warnings</td> +</tr> +<tr> +<td>142</td> +<td><code>LDAPInfo</code></td> +<td>AD/LDAP authentication information logs</td> +</tr> +<tr> +<td>143</td> +<td><code>LDAPDebug</code></td> +<td>AD/LDAP authentication debug logs</td> +</tr> +<tr> +<td>144</td> +<td><code>LDAPTrace</code></td> +<td>AD/LDAP authentication trace logs. Replaces <code>LdapSetings.trace</code> from Mattermost v9.3.</td> +</tr> +</tbody> +</table> + +### Configure target-specific settings + +#### Console target configuration options + +Console targets can be either `stdout` or `stderr`. + +- The standard output stream, `stout`, is typically used for command output that prints the results of a command to the user. +- The standard error stream, `sterr`, is typically used to print any errors that occur when a program is running. + +#### File target configuration options + +File targets support rotation and compression triggered by size and/or duration. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '9%'}} /> +<col style={{width: '7%'}} /> +<col style={{width: '81%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>filename</td> +<td>string</td> +<td>Full path to the output file. From v11.4, should be within the directory specified by <code>MM_LOG_PATH</code>.</td> +</tr> +<tr> +<td>max_size</td> +<td>number</td> +<td>Maximum size, in megabytes (MB), the log file can grow before it gets rotated. Default is <code>100</code> MB.</td> +</tr> +<tr> +<td>max_age</td> +<td>number</td> +<td>Maximum number of days to retain old log files based on the timestamp encoded in the filename. Default is <code>0</code> which disables the removal of old log files.</td> +</tr> +<tr> +<td>max_backups</td> +<td>number</td> +<td>Maximum number of old log files to retain. Default is <code>0</code> which retains all old log files. <strong>Note</strong>: Configuring <code>max_age</code> can result in old log files being deleted regardless of this configuration value.</td> +</tr> +<tr> +<td>compress</td> +<td>bool</td> +<td>Compress rotated log files using <a href="https://www.gnu.org/software/gzip/">gzip</a>. Default is <code>false</code>.</td> +</tr> +</tbody> +</table> + +#### Syslog target configuration options + +<PlanAvailability slug="entry-ent" /> + +Syslog targets support local and remote syslog servers, with or without TLS transport. Syslog target support requires Mattermost Enterprise. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '7%'}} /> +<col style={{width: '7%'}} /> +<col style={{width: '84%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>host</td> +<td>string</td> +<td>IP or domain name of the server receiving the log records.</td> +</tr> +<tr> +<td>port</td> +<td>number</td> +<td>Port number for the server receiving the log records.</td> +</tr> +<tr> +<td>tls</td> +<td>bool</td> +<td>Create a TLS connection to the server receiving the log records. Default is <code>false</code>.</td> +</tr> +<tr> +<td>cert</td> +<td>string</td> +<td>Path to a cert file (.pem) to be used when establishing a TLS connection to the server.</td> +</tr> +<tr> +<td>insecure</td> +<td>bool</td> +<td>Mattermost accepts any certificate presented by the server, and any host name in that certificate. Default is <code>false</code>. <strong>Note</strong>: Should only be used in testing environments, and shouldn’t be used in production environments.</td> +</tr> +<tr> +<td>tag</td> +<td>string</td> +<td>Syslog tag field.</td> +</tr> +</tbody> +</table> + +#### TCP target configuration options + +<PlanAvailability slug="entry-ent" /> + +The TCP socket targets can be configured with an IP address or domain name, port, and optional TLS certificate. TCP socket target support requires Mattermost Enterprise. You can [download a sample JSON file](/samples/sample-logger-config.json) of the configuration to use as a starting point. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '7%'}} /> +<col style={{width: '7%'}} /> +<col style={{width: '84%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>Key</strong></td> +<td><strong>Type</strong></td> +<td><strong>Description</strong></td> +</tr> +<tr> +<td>host</td> +<td>string</td> +<td>IP or domain name of the server receiving the log records.</td> +</tr> +<tr> +<td>port</td> +<td>number</td> +<td>Port number for the server receiving the log records.</td> +</tr> +<tr> +<td>tls</td> +<td>bool</td> +<td>Create a TLS connection to the server receiving the log records. Default is <code>false</code>.</td> +</tr> +<tr> +<td>cert</td> +<td>string</td> +<td>Path to a cert file (.pem) to be used when establishing a TLS connection to the server.</td> +</tr> +<tr> +<td>insecure</td> +<td>bool</td> +<td>Mattermost accepts any certificate presented by the server, and any host name in that certificate. Default is <code>false</code>. <strong>Note</strong>: Should only be used in testing environments, and shouldn’t be used in production environments.</td> +</tr> +</tbody> +</table> + +------------------------------------------------------------------------------------------------------------------------ + +## Cluster job execution debug messages + +<PlanAvailability slug="ent-plus" /> + +From Mattermost v11.4, debug-level log messages are available to help system admins understand cluster job execution behavior in [high availability](/administration-guide/scale/high-availability-cluster-based-deployment) deployments for specific Recurring Tasks. + +These debug messages apply only to the following Recurring Tasks: + +- Scheduled Posts +- Post Reminders +- DND Status Reset + +<Important> + +- These debug messages aren't available for other job types such as Elasticsearch indexing, SAML sync, LDAP sync, data retention, or compliance exports. The absence of these debug messages for other job types doesn't indicate a problem with job execution. +- These messages are only visible when debug logging is enabled. See [How do I enable debug logging?](#how-do-i-enable-debug-logging) for details. +- In a cluster deployment, only the leader node executes these Recurring Tasks. Non-leader nodes skip these specific jobs and log debug messages to indicate this is expected behavior. + +</Important> + +### Debug messages for job startup + +When a non-leader node starts up, it skips initialization for these specific Recurring Tasks and logs one of the following debug messages: + +- `Skipping scheduled posts job startup since this is not the leader node` +- `Skipping unset DND status job startup since this is not the leader node` +- `Skipping post reminder job startup since this is not the leader node` + +These messages indicate normal operation. In a high availability cluster, these Recurring Tasks should only run on the leader node to prevent duplicate execution. + +### Debug messages for leadership changes + +When a node loses leadership status while these Recurring Tasks are running, it cancels the running tasks and logs: + +- `This is no longer leader node. Cancelling the [job name] task` + +Where `[job name]` is one of: `scheduled posts`, `DND status reset`, or `post reminder`. + +This indicates the cluster is performing leader election correctly. The new leader node will take over execution of these Recurring Tasks. + +### Troubleshooting with cluster job debug messages + +If you're investigating why Recurring Tasks (Scheduled Posts, Post Reminders, or DND Status Reset) aren't running on a specific node: + +1. Enable debug logging if not already enabled. +2. Check the logs for the debug messages listed above. +3. If you see these messages, the node is correctly identified as a non-leader and is behaving as expected. +4. These Recurring Tasks will be running on the leader node instead. + +<Note> + +These debug messages only apply to Recurring Tasks. For other job types (Elasticsearch indexing, SAML sync, LDAP sync, data retention, compliance exports), different logging mechanisms apply. The absence of these specific debug messages for other job types is expected and does not indicate a problem. + +</Note> + +For more information about leader election and cluster configuration, see [High Availability cluster-based deployment](/administration-guide/scale/high-availability-cluster-based-deployment). + +------------------------------------------------------------------------------------------------------------------------ + +## Frequently asked questions + +### How do I enable debug logging? + +As a Mattermost system admin, go to **System Console \> Environment \> Logging \> File Log Level**, and set it to **DEBUG**. Then save your changes. + +![A screenshot of the System Console page where Mattermost system admins can enable and disable debug logging.](/images/enable-debug-logging.png) + +Debug logging can cause log files to expand substantially, and may adversely impact server performance. Keep an eye on your server logs, or only enable it temporarily, or in development environments, but not production enviornments. + +### Does Mattermost have an audit log besides the system `auditd`? + +Yes. See the [audit logging](#audit-logging) documentation for details. + +### When syslog is configured as the target, does it contain the IP address of the emitter of the data (i.e., the Mattermost app node)? + +Yes. That is a function of the syslog daemon (receiver). Typically, all the log lines are prefixed with a timestamp and the hostname of the node sending the data. For example, a log line starts with: `Nov 28 10:56:59 tower kernel: [1072437.431123] ....`, where `tower` is the hostname of the server that generated the log line. + +### Once audit logs are enabled, can audit logging track events where an admin disables or modifies the audit log settings? + +Yes, though it depends on how audit logs are configured. Audit log config can be specified via REST API, mmctl, System Console, file on disk, and using environment variables. When changes are made via the REST API or System Console, there is an audit record. However, the Mattermost server can't capture changes to a configuration file or via environment variables. + +### Do server logs show any information about a service or similar stopping/updating when auditing would be disabled? + +Yes. When updating the audit log configuration via REST API, mmctl, or System Console, the last event of the audit log should be about the admin user updating the config of the server, which helps your security team identify which actions took place in the system and by whom. + +### How do I omit incoming webhook details from the logs? + +See [enable-webhook-debugging](/administration-guide/configure/environment-configuration-settings#enable-webhook-debugging) + +### How do I adjust the maximum log field size? + +See [maximum-field-size](/administration-guide/configure/environment-configuration-settings#maximum-field-size) + +### How can I configure Advanced logging via environment variables? + +The `MM_LOGSETTINGS_ADVANCEDLOGGINGJSON` environment variable is used to configure Advanced logging . You can use `jq` to generate the JSON payload, e.g. + +``` sh +export MM_LOGSETTINGS_ADVANCEDLOGGINGJSON=$(jq -n -c '{ + "console1": { + "Type": "console", + "Format": "json", + "Levels": [ + {"ID": 5, "Name": "debug", "Stacktrace": false}, + {"ID": 4, "Name": "info", "Stacktrace": false, "color": 36}, + {"ID": 3, "Name": "warn", "Stacktrace": false}, + {"ID": 2, "Name": "error", "Stacktrace": true, "color": 31}, + {"ID": 1, "Name": "fatal", "Stacktrace": true, "color": 31}, + {"ID": 0, "Name": "panic", "Stacktrace": true, "color": 31}, + {"ID": 10, "Name": "stdlog", "Stacktrace": false} + ], + "Options": { + "Out": "stdout" + }, + "MaxQueueSize": 1000 + } +}') +``` + +### How can I turn on trace logging for LDAP? + +Please use the following JSON configuration as as starting point to enable trace logging for LDAP: + +``` JSON +{ + "ldap-file": { + "type": "file", + "format": "plain", + "levels": [ + { + "id": 144, + "name": "LDAPTrace" + }, + { + "id": 143, + "name": "LDAPDebug" + }, + { + "id": 142, + "name": "LDAPInfo" + }, + { + "id": 141, + "name": "LDAPWarn", + "stacktrace": true + }, + { + "id": 140, + "name": "LDAPError", + "stacktrace": true + } + ], + "options": { + "filename": "./logs/ldap.log", + "max_size": 100, + "max_age": 14, + "max_backups": 3, + "compress": false + }, + "maxqueuesize": 1000 + } +} +``` + +### How do I configure centralized logging for Mattermost? + +Mattermost recommends centralized logging using Grafana Loki and the OpenTelemetry Collector. See the [Deploy Grafana Loki for centralized logging](/administration-guide/scale/deploy-grafana-loki-for-centralized-logging) guide for details on how to set up log aggregation, useful LogQL queries, and Grafana dashboards. diff --git a/docs/main/administration-guide/manage/mmctl-command-line-tool.mdx b/docs/main/administration-guide/manage/mmctl-command-line-tool.mdx new file mode 100644 index 000000000000..18c5908fa25f --- /dev/null +++ b/docs/main/administration-guide/manage/mmctl-command-line-tool.mdx @@ -0,0 +1,8143 @@ +--- +title: "mmctl command line tool" +--- +<PlanAvailability slug="all-commercial" /> + +The mmctl is a CLI tool for the Mattermost server which is installed locally and uses the Mattermost API, but may also be used remotely. Authentication is done with either login credentials or an authentication token. This mmctl tool is included and replaces the [CLI](/administration-guide/manage/command-line-tools). The mmctl can currently be used alongside the Mattermost CLI tool. The Mattermost CLI tool will be deprecated in a future release. + +Being installed locally enables system admins for both self-hosted and Cloud Mattermost instances to run CLI commands even in instances where there's no access to the server (e.g., via SSH). + +This feature was developed to a large extent by community contributions and we'd like to extend our gratitude to the contributors who have worked on this project. We are currently accepting pull requests for Help Wanted issues in the [mattermost-server](https://github.com/mattermost/mattermost/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+Wanted%22+label%3AArea%2Fmmctl) repo. You can learn more about the unit test coverage campaign for mmctl in the [Unit testing mmctl commands](https://mattermost.com/blog/unit-testing-mmctl-commands/) blog post. + +## mmctl usage notes + +- System admins have two ways to run `mmctl` commands: by downloading `mmctl` from the release URLs, which you can find in the [installation instructions](#install-mmctl), or by building it directly, for which you can check the [build instructions](#build-mmctl) below. The source code lives in the [server/cmd/mmctl directory within the mattermost repository](https://github.com/mattermost/mattermost/tree/master/server/cmd/mmctl). +- `mmctl` also comes bundled with the Mattermost distribution, and is located in the `bin` folder of the installation, next to the `CLI`. + - We recommend you add the path to the Mattermost `bin` folder into your `$PATH` environment variable. This ensures that you can run mmctl commands locally regardless of your current directory location. + - If the `bin` directory is not added to the `$PATH` environment variable, each time you use mmctl you must be in the `bin` directory to run mmctl commands, and the commands must be prefixed with `./`. If you're working from a different directory, make sure you specify the full path to mmctl when running mmctl commands. +- Parameters in mmctl commands are order-specific. +- You can use the `--local` flag with mmctl commands to run them without authentication by allowing communicating with the server through a Unix socket. See the [local mode](#local-mode) documentation for activation and usage details. +- If special characters (`!`, `|`, `(`, `)`, `\`, `'`, and `"`) are used, the entire argument needs to be surrounded by single quotes (e.g. `-password 'mypassword!'`, or the individual characters need to be escaped out (e.g. `password mypassword\!`). +- Team name and channel name refer to the handles, not the display names. So in the URL `https://community.mattermost.com/core/channels/town-square` team name would be `core` and channel name would be `town-square`. + +## mmctl commands + +- [mmctl auth](#mmctl-auth) - Authentication Management +- [mmctl bot](#mmctl-bot) - Bot Management +- [mmctl channel](#mmctl-channel) - Channel Management +- [mmctl command](#mmctl-command) - Command Management +- [mmctl cpa](#mmctl-cpa) - Custom Profile Attribute Management +- [mmctl completion](#mmctl-completion) - Generate autocompletion scripts for bash, fish, powershell, and zsh +- [mmctl compliance-export](#mmctl-compliance-export) - Compliance Export Management +- [mmctl config](#mmctl-config) - Configuration Management +- [mmctl docs](#mmctl-docs) - Generate mmctl documentation +- [mmctl export](#mmctl-export) - Exports Management +- [mmctl group](#mmctl-group) - Group Management +- [mmctl group channel](#mmctl-group-channel) - Channel Group Management +- [mmctl group team](#mmctl-group-team) - Team Group Management +- [mmctl group user](#mmctl-group-user) - Custom User Group Management +- [mmctl import](#mmctl-import) - Import Management +- [mmctl extract](#mmctl-extract) - Content Extraction Job Management +- [mmctl integrity](#mmctl-integrity) - (Deprecated) Database Record Integrity +- [mmctl job](#mmctl-job) - Job Management +- [mmctl ldap](#mmctl-ldap) - LDAP Management +- [mmctl license](#mmctl-license) - License Management +- [mmctl logs](#mmctl-logs) - Log Management +- [mmctl oauth](#mmctl-oauth) - OAuth2 application management +- [mmctl permissions](#mmctl-permissions) - Permissions Management +- [mmctl plugin](#mmctl-plugin) - Plugin Management +- [mmctl post](#mmctl-post) - Post Management +- [mmctl roles](#mmctl-roles) - Roles Management +- [mmctl saml](#mmctl-saml) - SAML Management +- [mmctl sampledata](#mmctl-sampledata) - Generate sample data +- [mmctl system](#mmctl-system) - System Management +- [mmctl team](#mmctl-team) - Team Management +- [mmctl team users](#mmctl-team-users) - Team User Management +- [mmctl token](#mmctl-token) - Token Management +- [mmctl user](#mmctl-user) - User Management +- [mmctl user preference](#mmctl-user-preference) - Manage User Preferences +- [mmctl version](#mmctl-version) - Version Management +- [mmctl webhook](#mmctl-webhook) - Webhook Management +- [mmctl websocket](#mmctl-websocket) - Websocket Management + +**Options** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +-h, --help help for mmctl +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## Install mmctl + +The mmctl tool comes bundled with Mattermost package. For customers that want to setup it independently from the package, the following methods are available to install mmctl. + +<div id="install-mmctl-options"> + +<div class="tab"> + +Release package + +If you're using a release page for Linux, macOS, or Windows, we recommend downloading the mmctl builds through their release URL: `https://releases.mattermost.com/mmctl/${MATTERMOST_VERSION}/${PLATFORM}_${ARCHITECTURE}.tar` (for windows, substitute the `.tar` suffix with `.zip`) + +E.g. to download version `v10.7.0` of the mmctl amd64 build for linux, you can run the following: + +``` sh +curl -vfsSL -O https://releases.mattermost.com/mmctl/v10.7.0/linux_amd64.tar +``` + +Supported platforms, and corresponding supported architectures include linux (amd64 and arm64), darwin (amd64 and arm64), windows (amd64 only). + +</div> + +</div> + +<div class="tab"> + +Local git clone + +You can build mmctl from a local Git clone to work directly with the source code, use the latest features, and experiment with custom changes. This workflow is ideal if you need a tailored version of mmctl, want to fix bugs, or test new updates before they’re officially released. + +``` sh +git clone https://github.com/mattermost/mattermost.git +cd mattermost/server +go install ./cmd/mmctl +``` + +</div> + +<div class="tab"> + +Homebrew + +**On Linux or macOS, this isn't an officially supported method** This installation channel is managed by the community. Please refer to the [homebrew/homebrew-core repo](https://github.com/Homebrew/homebrew-core) for reporting issues. + +Use this option on Linux and macOS if you have Homebrew installed. + +``` sh +brew install mmctl +``` + +</div> + +## Build mmctl + +<div id="build-mmctl"> + +The `mmctl` tool uses `go` modules to manage dependencies, so you need to have installed `go` 1.19 or greater on your machine. + +</div> + +After checking out the [mattermost repository](https://github.com/mattermost/mattermost) locally to your machine, from the root directory of the project, you can compile the mmctl binary by running: + +``` sh +make -C server mmctl-build +``` + +## Local mode + +**Local mode is available for self-hosted deployments only.** + +Local mode allows platform administrators with access to the Mattermost server to run mmctl commands against the API without needing to have a user registered. To ensure secure usage of this API, the server exposes a local socket that only a user with access to the server's file system can access. The requests coming from the socket are treated as authorized, so they can reach the handlers without requiring a user session. + +The API that the socket exposes follows the same specification that can be found [in the API documentation](https://api.mattermost.com), so mmctl is able to interact with it without needing any modifications. When a request comes in through the socket, it is flagged as local by the server, and this flag is taken into account when checking for session permissions to correctly authorize the sessions. + +### Activating local mode + +To use local mode, the Mattermost server first needs to [have local mode enabled](/administration-guide/configure/experimental-configuration-settings#enable-local-mode-for-mmctl). When local mode is enabled, a socket is created at `/var/tmp/mattermost_local.socket` by default. + +<Tip> + +When trying to use local mode with mmctl, ensure you're using the same user when running the server and mmctl, or clean up the socket file before switching to a new user. If you encounter an error like `socket file "/var/tmp/mattermost_local.socket" doesn't exists, please check the server configuration for local mode`, this can be resolved by setting this configuration setting to `true`. + +</Tip> + +### Using local mode + +From Mattermost v10.8, when no authentication credentials are found in the authentication configuration, mmctl automatically assumes local mode, eliminating the need to manually append the `--local` flag to the command you want to use. When valid credentials exist, Mattermost will continue to validate them as expected. + +Prior to Mattermost v10.8, you must append `--local` to the command you want to use, or set the environment variable as `MMCTL_LOCAL=true`. + +To use a socket file other than the default, you need to set the environment variable to `MMCTL_LOCAL_SOCKET_PATH`. This file must match the [server configuration setting](/administration-guide/configure/experimental-configuration-settings#enable-local-mode-socket-location). + +## Running mmctl tests + +**Available for self-hosted deployments only.** + +mmctl has two types of tests: unit tests and end to end tests. + +To execute them, you can run the following commands from the mattermost project root directory: + +``` sh +# For the unit tests +make -C server test-mmctl-unit + +# For the end to end tests +make -C server test-mmctl-e2e +``` + +## mmctl auth + +**Description** + +Manage the credentials and authentication methods of remote Mattermost instances. + +> Child Commands +> - [mmctl auth clean](#mmctl-auth-clean) - Clean credentials +> - [mmctl auth current](#mmctl-auth-current) - Display current credentials +> - [mmctl auth delete](#mmctl-auth-delete) - Delete authentication details +> - [mmctl auth list](#mmctl-auth-list) - List registered credentials +> - [mmctl auth login](#mmctl-auth-login) - Log into Mattermost instance +> - [mmctl auth renew](#mmctl-auth-renew) - Renew login credentials +> - [mmctl auth set](#mmctl-auth-set) - Set login credentials + +**Options** + +``` sh +-h, --help help for auth +``` + +### mmctl auth clean + +**Description** + +Clean the credentials associated with a Mattermost instance. + +**Format** + +``` sh +mmctl auth clean [flags] +``` + +**Examples** + +``` sh +mmctl auth clean +``` + +**Options** + +``` sh +-h, --help help for clean +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl auth current + +**Description** + +Show the currently stored user credentials. + +**Format** + +``` sh +mmctl auth current [flags] +``` + +**Examples** + +``` sh +mmctl auth current +``` + +**Options** + +``` sh +-h, --help help for current +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl auth delete + +**Description** + +Delete a named credential. + +**Format** + +``` sh +mmctl auth delete [server name] [flags] +``` + +**Examples** + +``` sh +mmctl auth delete local-server +``` + +**Options** + +``` sh +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl auth list + +**Description** + +Print a list of registered credentials. + +**Format** + +``` sh +mmctl auth list [flags] +``` + +**Examples** + +``` sh +mmctl auth list +``` + +**Options** + +``` sh +-h, --help help for auth list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl auth login + +**Description** + +Log in to an instance and store credentials. You can log in with [a personal access token](https://developers.mattermost.com/integrate/reference/personal-access-token) instead of using username/password. See [access tokens](#access-tokens) for details. + +**Format** + +``` sh +mmctl auth login [instance url] --name [server name] --username [username] --password-file [password-file] [flags] +``` + +**Examples** + +``` sh +mmctl auth login https://mattermost.example.com +mmctl auth login https://mattermost.example.com --name local-server --username sysadmin --password-file mysupersecret.txt +mmctl auth login https://mattermost.example.com --name local-server --username sysadmin --password-file mysupersecret.txt --mfa-token 123456 +mmctl auth login https://mattermost.example.com --name local-server --access-token myaccesstoken +``` + +**Options** + +``` text +-t, --access-token-file string Access token file to be read to use instead of username/password +-h, --help help for login +-m, --mfa-token string MFA token for the credentials +-n, --name string Name for the credentials + --no-activate If present, it won't activate the credentials after login +-f, --password-file string Password file to be read for the credentials +-u, --username string Username for the credentials +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +#### Password + +``` sh +$ mmctl auth login https://community.mattermost.com --name community --username my-username --password-file mysupersecret +``` + +The `login` command can also work interactively, so if you leave any required flag empty, `mmctl` will ask you for it interactively: + +``` sh +$ mmctl auth login https://community.mattermost.com +Connection name: community +Username: my-username +Password File: +``` + +#### MFA + +To log in with MFA, use the `--mfa-token` flag: + +``` sh +$ mmctl auth login https://community.mattermost.com --name community --username my-username --password-file mysupersecret --mfa-token 123456 +``` + +#### Access tokens + +You can generate and use a personal access token to authenticate with a server, instead of using username and password to log in: + +``` sh +$ mmctl auth login https://community.mattermost.com --name community --access-token MY_ACCESS_TOKEN +``` + +Alternatively, you can log in to your Mattermost server with a username and password: + +``` sh +$ mmctl auth login https://my-instance.example.com --name my-instance --username john.doe --password-file mysupersecret +credentials for my-instance: john.doe@https://my-instance.example.com stored +``` + +We can check the currently stored credentials with: + +``` sh +$ mmctl auth list + +| Active | Name | Username | InstanceUrl | +|--------|-------------|----------|---------------------------------| +| * | my-instance | john.doe | https://my-instance.example.com | +``` + +And now we can run commands normally: + +``` sh +$ mmctl user search john.doe +id: qykfw3t933y38k57ubct77iu9c +username: john.doe +nickname: +position: +first_name: John +last_name: Doe +email: john.doe@example.com +auth_service: +auth_data: +``` + +#### Installing shell completions + +mmctl supports shell completions for bash, fish, powershell, and zsh from Mattermost v11. + +To install the shell completions for **bash**, add the following line to your `~/.bashrc` or `~/.profile` file: + +``` sh +source <(mmctl completion bash) +``` + +For **zsh**, add the following line to your `~/.zshrc` file: + +``` sh +source <(mmctl completion zsh) +``` + +For **fish**, add the following line to your fish configuration: + +``` sh +mmctl completion fish | source +``` + +For **powershell**, add the following line to your PowerShell profile: + +``` powershell +mmctl completion powershell | Out-String | Invoke-Expression +``` + +### mmctl auth renew + +**Description** + +Renew the credentials for a given server. + +**Format** + +``` sh +mmctl auth renew [flags] +``` + +**Examples** + +``` sh +mmctl auth renew local-server +``` + +**Options** + +``` sh +-t, --access-token-file string Access token file to be read to use instead of username/password +-h, --help help for renew +-m, --mfa-token string MFA token for the credentials +-f, --password-file string Password file to be read for the credentials +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl auth set + +**Description** + +Set credentials to use in the following commands. + +**Format** + +``` sh +mmctl auth set [server name] [flags] +``` + +**Examples** + +``` sh +mmctl auth set local-server +``` + +**Options** + +``` sh +-h, --help help for set +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +Authenticate to a server (e.g. \>mmctl auth login `https://test.mattermost.com)`, then enter your username and password (and MFA token if MFA is enabled on the account). + +## mmctl bot + +Manage bots. + +> Child Commands +> - [mmctl bot assign](#mmctl-bot-assign) - Assign bot ownership +> - [mmctl bot create](#mmctl-bot-create) - Create a new bot +> - [mmctl bot disable](#mmctl-bot-disable) - Disable a bot +> - [mmctl bot enable](#mmctl-bot-enable) - Enable a bot +> - [mmctl bot list](#mmctl-bot-list) - List all bots +> - [mmctl bot update](#mmctl-bot-update) - Update bot configuration + +**Options** + +``` sh +-h, --help help for bot +``` + +### mmctl bot assign + +**Description** + +Assign the ownership of a bot to another user. + +**Format** + +``` sh +mmctl bot assign [bot-username] [new-owner-username] [flags] +``` + +**Examples** + +``` sh +mmctl bot assign testbot user2 +``` + +**Options** + +``` sh +-h, --help help for assign +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl bot create + +**Description** + +Create a bot. + +**Format** + +``` sh +mmctl bot create [username] [flags] +``` + +**Examples** + +``` sh +mmctl bot create testbot +``` + +**Options** + +``` sh +--description string Optional. The description text for the new bot. +--display-name string Optional. The display name for the new bot. +-h, --help help for create +--with-token Optional. Auto genreate access token for the bot. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl bot disable + +**Description** + +Disable an enabled bot. + +**Format** + +``` sh +mmctl bot disable [username] [flags] +``` + +**Examples** + +``` sh +mmctl bot disable testbot +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl bot enable + +**Description** + +Enable a disabled bot. + +**Format** + +``` sh +mmctl bot enable [username] [flags] +``` + +**Examples** + +``` sh +mmctl bot enable testbot +``` + +**Options** + +``` sh +-h, --help help for enable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl bot list + +**Description** + +List the bot's users. + +**Format** + +``` sh +mmctl bot list [flags] +``` + +**Examples** + +``` sh +mmctl bot list +``` + +**Options** + +``` sh +--all Optional. Show all bots (including deleleted and orphaned) +-h, --help help for list +--orphaned Optional. Only show orphaned bots +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl bot update + +**Description** + +Update bot information. + +**Format** + +``` sh +mmctl bot update [username] [flags] +``` + +**Examples** + +``` sh +mmctl bot update testbot --username newbotusername +``` + +**Options** + +``` sh +--description string Optional. The new description text for the bot +--display-name string Optional. The new display name for the bot +-h, --help help for update +--username string Optional. The new username for the bot +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl channel + +Manage channels. + +> Child Commands +> - [mmctl channel add](#mmctl-channel-add) - (Deprecated) Add a user to a channel +> - [mmctl channel archive](#mmctl-channel-archive) - Archive a channel +> - [mmctl channel create](#mmctl-channel-create) - Create a channel +> - [mmctl channel delete](#mmctl-channel-delete) - Delete a channel +> - [mmctl channel list](#mmctl-channel-list) - List all channels on specified teams +> - [mmctl channel make-private](#mmctl-channel-make-private) - (Deprecated) Set a channel's type to "private" +> - [mmctl channel modify](#mmctl-channel-modify) - Modify a channel's type (private/public) +> - [mmctl channel move](#mmctl-channel-move) - Move channels to the specified team +> - [mmctl channel remove](#mmctl-channel-remove) - (Deprecated) Remove a user from a channel +> - [mmctl channel rename](#mmctl-channel-rename) - Rename a channel +> - [mmctl channel restore](#mmctl-channel-restore) - (Deprecated) Restore a channel from the archive +> - [mmctl channel search](#mmctl-channel-search) - Search a channel by name +> - [mmctl channel unarchive](#mmctl-channel-unarchive) - Unarchive a channel +> - [mmctl channel users](#mmctl-channel-users) - Manage channel users +> - [mmctl channel users add](#mmctl-channel-users-add) - Add a user to a channel +> - [mmctl channel users remove](#mmctl-channel-users-remove) - Remove a user from a channel + +**Options** + +``` sh +-h, --help help for channel +``` + +### mmctl channel archive + +**Description** + +Archive channels along with all related information including posts from the database. Channels can be specified by `[team]:[channel]` (i.e., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel archive [channels] [flags] +``` + +**Examples** + +``` sh +mmctl channel archive myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for archive +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel add + +This command is deprecated in favor of [mmctl channel users add](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-users-add). + +**Description** + +Add a user to a channel. + +**Format** + +``` sh +mmctl channel add [channel] [users] [flags] +``` + +**Examples** + +``` sh +mmctl channel add myteam:mychannel user@example.com username +``` + +**Options** + +``` sh +-h, --help help for add +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel create + +**Description** + +Create a channel. + +**Format** + +``` sh +mmctl channel create [flags] +``` + +**Examples** + +``` sh +mmctl channel create --team myteam --name mynewchannel --display-name "My New Channel" +mmctl channel create --team myteam --name mynewprivatechannel --display-name "My New Private Channel" --private +``` + +**Options** + +``` sh +--display-name string Channel Display Name +--header string Channel header +-h, --help help for create +--name string Channel Name +--private Create a private channel +--purpose string Channel purpose +--team string Team name or ID +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel delete + +**Description** + +Permanently delete channels along with all related information including posts from the database. + +<Note> + +Requires the [Enable API Channel Deletion](/administration-guide/configure/environment-configuration-settings#enable-api-channel-deletion) configuration setting to be set to `true`. If this configuration setting is set to `false`, attempting to delete the channel using mmctl fails. + +</Note> + +**Format** + +``` sh +mmctl channel delete [channels] [flags] +``` + +**Examples** + +``` sh +mmctl channel delete myteam:mychannel +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the channel and a database backup has been performed. +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel list + +**Description** + +List all Public, Private, and archived channels on specified teams. Archived channels are appended with `(archived)`. Private channels the user is a member of, or has access to, are appended with `(private)`. + +**Format** + +``` sh +mmctl channel list [teams] [flags] +``` + +**Examples** + +``` sh +mmctl channel list myteam +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel make-private + +This command is deprecated in favour of [mmctl channel modify](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-modify) and the `--private` flag. + +**Description** + +Set the type of a channel from Public to Private. Channel can be specified by `[team]:[channel]` (e.g., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel make-private [channel] [flags] +``` + +**Examples** + +``` sh +mmctl channel make-private myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for make-private +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel modify + +**Description** + +Change the Public/Private type of a channel. Channel can be specified by `[team]:[channel]` (e.g., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel modify [channel] [flags] +``` + +**Examples** + +``` sh +mmctl channel modify myteam:mychannel --private +mmctl channel modify channelId --public +``` + +**Options** + +``` sh +-h, --help help for modify +--private Convert the channel to a private channel +--public Convert the channel to a public channel +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel move + +**Description** + +Move the provided channels to the specified team. Validate that all users in the channel belong to the target team. Incoming/outgoing webhooks are moved along with the channel. Channels can be specified by `[team]:[channel]` (e.g., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel move [team] [channels] [flags] +``` + +**Examples** + +``` sh +mmctl channel move newteam oldteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for move +--force Remove users that are not members of target team before moving the channel. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel rename + +**Description** + +Rename an existing channel. + +**Format** + +``` sh +mmctl channel rename [channel] [flags] +``` + +**Examples** + +``` sh +mmctl channel rename myteam:oldchannel --name 'new-channel' --display-name 'New Display Name' +mmctl channel rename myteam:oldchannel --name 'new-channel' +mmctl channel rename myteam:oldchannel --display-name 'New Display Name' +``` + +**Options** + +``` sh +--display-name string Channel Display Name +-h, --help help for rename +--name string Channel Name +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel remove + +This command is deprecated in favor of [mmctl channel users remove](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-users-remove). + +**Description** + +Remove a user from a channel. + +**Format** + +``` sh +mmctl channel remove [channel] [users] [flags] +``` + +**Examples** + +``` sh +mmctl channel remove myteam:mychannel user@example.com username +``` + +**Options** + +``` sh +-h, --help help for remove +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel restore + +This command is deprecated in favor of [mmctl channel unarchive](#mmctl-channel-unarchive). Not used in Mattermost Server version v5.26 and later. + +**Description** + +Restore a previously deleted channel. Channels can be specified by `[team]:[channel]` (e.g., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel restore [channels] [flags] +``` + +**Examples** + +``` sh +mmctl channel restore myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for restore +``` + +**Options inherited from parent commands** + +``` sh +--format string the format of the command output [plain, json] (default "plain") +--insecure-sha1-intermediate allows the use of insecure TLS protocols, such as SHA-1 +--local allows communicating with the server through a unix socket +--strict will only run commands if the mmctl version matches the server one +``` + +### mmctl channel search + +**Description** + +Search for channel details by channel name. Channels can be specified by team (e.g., `--team myteam mychannel`), or by team ID. Returns channel name, display name, and channel ID. + +**Format** + +``` sh +mmctl channel search [channel] +mmctl search --team [team] [channel] [flags] +``` + +**Examples** + +``` sh +mmctl channel search mychannel +mmctl channel search --team myteam mychannel +``` + +**Options** + +``` sh +-h, --help help for search +--team string team name or ID +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel unarchive + +**Description** + +Unarchive a previously archived channel. Channels can be specified by `[team]:[channel]` (e.g., `myteam:mychannel`), or by channel ID. + +**Format** + +``` sh +mmctl channel unarchive [channels] [flags] +``` + +**Examples** + +``` sh +mmctl channel unarchive myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for unarchive +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel users + +**Description** + +Manage channel users. + +**Options** + +``` sh +-h, --help help for users +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel users add + +**Description** + +Add users to a channel. + +**Format** + +``` sh +mmctl channel users add [channel] [users] [flags] +``` + +**Examples** + +``` sh +mmctl channel users add myteam:mychannel user@example.com username +``` + +**Options** + +``` sh +-h, --help help for add +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl channel users remove + +**Description** + +Remove users from a channel. + +**Format** + +``` sh +mmctl channel users remove [channel] [users] [flags] +``` + +**Examples** + +``` sh +mmctl channel users remove myteam:mychannel user@example.com username +mmctl channel users remove myteam:mychannel --all-users +``` + +**Options** + +``` sh +--all-users Remove all users from the indicated channel +-h, --help help for remove +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl command + +Manage slash commands. + +> Child Commands +> - [mmctl command archive](#mmctl-command-archive) - Archive a slash command +> - [mmctl command create](#mmctl-command-create) - Create a custom command +> - [mmctl command delete](#mmctl-command-delete) - (Deprecated) Delete a specified slash command +> - [mmctl command list](#mmctl-command-list) - List slash commands on specified teams +> - [mmctl command modify](#mmctl-command-modify) - Modify a slash command +> - [mmctl command move](#mmctl-command-move) - Move a slash command to a different team +> - [mmctl command show](#mmctl-command-show) - Show a custom slash command + +**Options** + +``` sh +-h, --help help for command +``` + +### mmctl command archive + +**Description** + +Archive a slash command. Commands can be specified by command ID. + +**Format** + +``` sh +mmctl command archive [commandID] [flags] +``` + +**Examples** + +``` sh +mmctl command archive commandID +``` + +**Options** + +``` sh +-h, --help help for archive +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl command create + +**Description** + +Create a custom slash command for the specified team. + +**Format** + +``` sh +mmctl command create [team] [flags] +``` + +**Examples** + +``` sh +mmctl command create myteam --title MyCommand --description "My Command Description" --trigger-word mycommand --url http://localhost:8000/my-slash-handler --creator myusername --response-username my-bot-username --icon http://localhost:8000/my-slash-handler-bot-icon.png --autocomplete --post +``` + +**Options** + +``` text +--autocomplete Show Command in autocomplete list +--autocompleteDesc string Short Command Description for autocomplete list +--autocompleteHint string Command Arguments displayed as help in autocomplete list +--creator string Command Creator's Username (required) +--description string Command Description +-h, --help help for create +--icon string Command Icon URL +--post Use POST method for Callback URL +--response-username string Command Response Username +--title string Command Title +--trigger-word string Command Trigger Word (required) +--url string Command Callback URL (required) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl command delete + +This command is deprecated in favor of [mmctl command archive](#mmctl-command-archive). + +**Description** + +Delete a slash command. Commands can be specified by command ID. + +**Format** + +``` sh +mmctl command delete [flags] +``` + +**Examples** + +``` sh +mmctl command delete commandID +``` + +**Options** + +``` sh +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--format string the format of the command output [plain, json] (default "plain") +--insecure-sha1-intermediate allows the use of insecure TLS protocols, such as SHA-1 +--local allows communicating with the server through a unix socket +--strict will only run commands if the mmctl version matches the server one +``` + +### mmctl command list + +**Description** + +List all commands on specified teams. + +**Format** + +``` sh +mmctl command list [teams] [flags] +``` + +**Examples** + +``` sh +mmctl command list myteam +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl command modify + +**Description** + +Modify a slash command. Commands can be specified by command ID. + +**Format** + +``` sh +mmctl command modify [commandID] [flags] +``` + +**Examples** + +``` sh +mmctl command modify commandID --title MyModifiedCommand --description "My Modified Command Description" --trigger-word mycommand --url http://localhost:8000/my-slash-handler --creator myusername --response-username my-bot-username --icon http://localhost:8000/my-slash-handler-bot-icon.png --autocomplete --post +``` + +**Options** + +``` text +--autocomplete Show Command in autocomplete list +--autocompleteDesc string Short Command Description for autocomplete list +--autocompleteHint string Command Arguments displayed as help in autocomplete list +--creator string Command Creator's username, email or id (required) +--description string Command Description +-h, --help help for modify +--icon string Command Icon URL +--post Use POST method for Callback URL +--response-username string Command Response Username +--title string Command Title +--trigger-word string Command Trigger Word (required) +--url string Command Callback URL (required) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl command move + +**Description** + +Move a slash command to a different team. Commands can be specified by command ID. + +**Format** + +``` sh +mmctl command move [team] [commandID] [flags] +``` + +**Examples** + +``` sh +mmctl command move newteam commandID +``` + +**Options** + +``` sh +-h, --help help for move +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl command show + +**Description** + +Show a custom slash command. Commands can be specified by command ID. Returns command ID, team ID, trigger word, display name, and creator username. + +**Format** + +``` sh +mmctl command show [commandID] [flags] +``` + +**Examples** + +``` sh +mmctl command show commandID +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl completion + +Generate autocompletion scripts for `bash`, `fish`, `powershell`, and `zsh`. + +> Child Commands +> - [mmctl completion bash](#mmctl-completion-bash) - Generate the autocompletion script for bash +> - [mmctl completion fish](#mmctl-completion-fish) - Generate the autocompletion script for fish +> - [mmctl completion powershell](#mmctl-completion-powershell) - Generate the autocompletion script for powershell +> - [mmctl completion zsh](#mmctl-completion-zsh) - Generate the autocompletion script for zsh + +**Options** + +``` sh +-h, --help help for completion +``` + +### mmctl completion bash + +**Description** + +Generate the `bash` autocompletion scripts. This script depends on the 'bash-completion' package. If it is not installed already, you can install it via your OS's package manager. + +To load completion, run: + +``` sh +. <(mmctl completion bash) +``` + +To configure your `bash` shell to load completions for each session, add the above line to your `~/.bashrc`. + +To load completion, run: + +``` sh +mmctl completion bash [flags] +``` + +**Options** + +``` sh +-h, --help help for bash +--no-descriptions disable completion descriptions +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl completion fish + +**Description** + +Generate the `fish` autocompletion scripts. + +To load completion, run: + +``` sh +mmctl completion fish | source +``` + +To configure your `fish` shell to load completions for each session, add the above line to your fish configuration. + +**Format** + +``` sh +mmctl completion fish [flags] +``` + +**Options** + +``` sh +-h, --help help for fish +--no-descriptions disable completion descriptions +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl completion powershell + +**Description** + +Generate the `powershell` autocompletion scripts. + +To load completion, run: + +``` powershell +mmctl completion powershell | Out-String | Invoke-Expression +``` + +To configure your `powershell` shell to load completions for each session, add the above line to your PowerShell profile. + +**Format** + +``` powershell +mmctl completion powershell [flags] +``` + +**Options** + +``` sh +-h, --help help for powershell +--no-descriptions disable completion descriptions +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl completion zsh + +**Description** + +Generate the `zsh` autocompletion scripts. + +To load completion, run: + +``` sh +. <(mmctl completion zsh) +``` + +To configure your `zsh` shell to load completions for each session, add the above line to your `~/.zshrc`. + +**Format** + +``` sh +mmctl completion zsh [flags] +``` + +**Options** + +``` sh +-h, --help help for zsh +--no-descriptions disable completion descriptions +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl cpa + +<PlanAvailability slug="ent-adv" /> + +Manage User Attributes for extended user profile information. + +> Child Commands +> - [mmctl cpa field](#mmctl-cpa-field) - Manage CPA fields + +**Options** + +``` sh +-h, --help help for cpa +``` + +### mmctl cpa field + +**Description** + +Manage Custom Profile Attribute fields. + +> Child Commands +> - [mmctl cpa field create](#mmctl-cpa-field-create) - Create a new CPA field +> - [mmctl cpa field delete](#mmctl-cpa-field-delete) - Delete a CPA field +> - [mmctl cpa field edit](#mmctl-cpa-field-edit) - Edit a CPA field +> - [mmctl cpa field list](#mmctl-cpa-field-list) - List CPA fields + +**Options** + +``` sh +-h, --help help for field +``` + +### mmctl cpa field create + +**Description** + +Create a new Custom Profile Attribute field. + +**Format** + +``` sh +mmctl cpa field create [field-name] [flags] +``` + +**Examples** + +``` sh +mmctl cpa field create "Department" --type text +mmctl cpa field create "Location" --type select --options "New York,London,Tokyo" +``` + +**Options** + +``` sh +-h, --help help for create +--type string field type (text, select, number, date) +--options string comma-separated list of options for select fields +--required mark field as required +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl cpa field delete + +**Description** + +Delete an existing Custom Profile Attribute field. + +**Format** + +``` sh +mmctl cpa field delete [field-id] [flags] +``` + +**Examples** + +``` sh +mmctl cpa field delete department-field-001 +mmctl cpa field delete location-field-002 --force +``` + +**Options** + +``` sh +-h, --help help for delete +--force skip confirmation prompt +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl cpa field edit + +**Description** + +Edit an existing Custom Profile Attribute field. + +**Format** + +``` sh +mmctl cpa field edit [field-id] [flags] +``` + +**Examples** + +``` sh +mmctl cpa field edit department-field-001 --name "Department/Division" +mmctl cpa field edit location-field-002 --options "New York,London,Tokyo,Sydney" +``` + +**Options** + +``` sh +-h, --help help for edit +--name string update field name +--type string update field type (text, select, number, date) +--options string update comma-separated list of options for select fields +--required mark field as required +--not-required mark field as not required +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl cpa field list + +**Description** + +List all Custom Profile Attribute fields. + +**Format** + +``` sh +mmctl cpa field list [flags] +``` + +**Examples** + +``` sh +mmctl cpa field list +mmctl cpa field list --json +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl compliance-export + +<PlanAvailability slug="ent-plus" /> + +Manage compliance export jobs for archiving channel data to third-party compliance systems. + +> Child Commands +> - [mmctl compliance-export cancel](#mmctl-compliance-export-cancel) - Cancel a compliance export job +> - [mmctl compliance-export create](#mmctl-compliance-export-create) - Create a new compliance export job +> - [mmctl compliance-export download](#mmctl-compliance-export-download) - Download a compliance export file +> - [mmctl compliance-export list](#mmctl-compliance-export-list) - List compliance export jobs, sorted by creation date descending (newest first) +> - [mmctl compliance-export show](#mmctl-compliance-export-show) - Show compliance export job + +### mmctl compliance-export cancel + +**Description** + +Cancel an ongoing compliance export job. + +**Format** + +``` sh +mmctl compliance-export cancel [complianceExportJobID] [flags] +``` + +**Examples** + +``` sh +mmctl compliance-export cancel o98rj3ur83dp5dppfyk5yk6osy +``` + +**Options** + +``` sh +-h, --help help for cancel +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl compliance-export create + +**Description** + +Create a new compliance export job to archive channel messages, direct messages, file uploads, and posts from plugins, bots, or webhooks. Supported export formats include CSV, Actiance XML, and Global Relay EML for integration with third-party compliance systems. + +> - If `--date` is set, the job will run for one day, from 12am to 12am (minus one millisecond) inclusively. +> - Running a compliance export job from mmctl will NOT affect the next scheduled job's `batch_start_time`. This means that if you run a compliance export job from mmctl, the next scheduled job will run from the `batch_end_time` of the previous scheduled job, as usual. + +**Format** + +``` sh +mmctl compliance-export create [complianceExportType] --date "2025-03-27 -0400" [flags] +``` + +**Example** + +``` sh +mmctl compliance-export create csv --date "2025-03-27 -0400" +``` + +**Options** + +``` sh +--date "YYYY-MM-DD -0000" Run the export for one day, from 12am to 12am (minus one millisecond) inclusively, in the format with timezone offset: ``YYYY-MM-DD -0000``. E.g., ``2024-10-21 -0400`` for Oct 21, 2024 EDT timezone. ``2023-11-01 +0000`` for Nov 01, 2023 UTC. If set, the ``start`` and ``end`` flags will be ignored. +--end 1743134400000 The end timestamp in unix milliseconds. Posts with updateAt <= end will be exported. If set, ``start`` must be set as well. eg, ``1743134400000`` for 2025-03-28 EDT. +-h, --help help for create +--start 1743048000000 The start timestamp in unix milliseconds. Posts with updateAt >= start will be exported. If set, ``end`` must be set as well. eg, ``1743048000000`` for 2025-03-27 EDT. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl compliance-export download + +**Description** + +Download a compliance export file. + +**Format** + +``` sh +mmctl compliance-export download [complianceExportJobID] [output filepath (optional)] [flags] +``` + +**Example** + +``` sh +mmctl compliance-export download o98rj3ur83dp5dppfyk5yk6osy +``` + +**Options** + +``` sh +-h, --help help for list +--num-retries int Number of retries if the download fails (default 5) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl compliance-export list + +**Description** + +Lists all compliance export jobs, sorted by creation date descending (newest first). + +**Format** + +``` sh +mmctl compliance-export list [flags] +``` + +**Options** + +``` sh +-h, --help help for list +--all Fetch all compliance export jobs. --page flag will be ignored if provided +--page int Page number to fetch for the list of compliance export jobs +--per-page int Number of compliance export jobs to be fetched (default 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl compliance-export show + +**Description** + +Show details of a compliance export job. + +**Format** + +``` sh +mmctl compliance-export show [complianceExportJobID] [flags] +``` + +**Examples** + +``` sh +mmctl compliance-export show o98rj3ur83dp5dppfyk5yk6osy +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl config + +Configuration settings. + +> Child Commands +> - [mmctl config edit](#mmctl-config-edit) - Edit the configuration settings +> - [mmctl config export](#mmctl-config-export) - Export the server configuration +> - [mmctl config get](#mmctl-config-get) - Get the value of a configuration setting +> - [mmctl config migrate](#mmctl-config-migrate) - Migrate existing configuration between backends +> - [mmctl config patch](#mmctl-config-patch) - Patch the configuration +> - [mmctl config reload](#mmctl-config-reload) - Reload the server configuration +> - [mmctl config reset](#mmctl-config-reset) - Reset the configuration +> - [mmctl config set](#mmctl-config-set) - Set the value of a configuration +> - [mmctl config show](#mmctl-config-show) - Write the server configuration to STDOUT +> - [mmctl config subpath](#mmctl-config-subpath) - Update client asset loading to use the configured subpath + +**Options** + +``` sh +-h, --help help for config +``` + +### mmctl config edit + +**Description** + +Open the editor defined in the EDITOR environment variable to modify the server's configuration. Once complete, save the file, then upload it to your server. + +**Format** + +``` sh +mmctl config edit [flags] +``` + +**Examples** + +``` sh +mmctl config edit +``` + +**Options** + +``` sh +-h, --help help for edit +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config export + +**Description** + +Use this command to export the server configuration, which can then be imported into another server or environment. Masked values are only exported when the tool is running in [local mode](#local-mode). + +**Format** + +``` sh +mmctl config export [flags] +``` + +**Examples** + +``` sh +mmctl config export --remove-masked --remove-defaults +``` + +**Options** + +``` sh +-h, --help help for export + --remove-defaults remove default values from the exported configuration + --remove-masked remove masked values from the exported configuration (default true) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config get + +**Description** + +Get the value of a configuration setting by its name in dot notation. + +**Format** + +``` sh +mmctl config get [flags] +``` + +**Examples** + +``` sh +mmctl config get SqlSettings.DriverName +``` + +**Options** + +``` sh +-h, --help help for get +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config migrate + +**Description** + +Migrate a file-based configuration to (or from) a database-based configuration. Point the Mattermost server at the target configuration to start using it. This command only migrates the configuration data from one type to another. + +<Note> + +- To change the store type to use the database, a system admin needs to set a `MM_CONFIG` [environment variable](/administration-guide/configure/configuration-in-your-database#create-an-environment-file) and restart the Mattermost server. + +- The `migrate` function requires local mode to be enabled. To do this, add the following line to your Mattermost Environment file: + + > ``` sh + > MM_SERVICESETTINGS_ENABLELOCALMODE=true + > ``` + +</Note> + +**Format** + +``` sh +mmctl config migrate [from_config] [to_config] [flags] +``` + +**Examples** + +``` sh +mmctl config migrate path/to/config.json "postgres://mmuser:mostest@localhost:5432/mattermost_test?sslmode=disable&connect_timeout=10" --local +``` + +**Options** + +``` sh +-h, --help help for migrate +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config patch + +**Description** + +Patch the server configuration with the specified configuration file. + +**Format** + +``` sh +mmctl config patch <config-file> [flags] +``` + +**Examples** + +``` sh +mmctl config patch /path/to/config.json +``` + +**Options** + +``` sh +-h, --help help for reload +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config reload + +**Description** + +Reload the server configuration and apply new settings. + +**Format** + +``` sh +mmctl config reload [flags] +``` + +**Examples** + +``` sh +mmctl config reload +``` + +**Options** + +``` sh +-h, --help help for reload +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config reset + +**Description** + +Reset the value of a configuration setting by its name in dot notation or a setting section. Accepts multiple values for array settings. + +**Format** + +``` sh +mmctl config reset [flags] +``` + +**Examples** + +``` sh +mmctl config reset SqlSettings.DriverName LogSettings +``` + +**Options** + +``` sh +--confirm Confirm you really want to reset all configuration settings to the default value +-h, --help help for reset +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config set + +**Description** + +Set the value of a config setting by its name in dot notation. Accepts multiple values for array settings. + +<Note> + +Mattermost plugin uploads can't be enabled through the API or using mmctl in local mode. + +</Note> + +**Format** + +``` sh +mmctl config set [flags] +``` + +**4 Examples** + +``` sh +mmctl config set SqlSettings.DriverName postgres +mmctl config set SqlSettings.DataSourceReplicas "replica1" "replica2" +mmctl config set PluginSettings.Plugins.com.mattermost.calls.rtcdserviceurl "http://mattermost-rtcd" +mmctl config set LogSettings.AdvancedLoggingJSON '{"console1":{"Type":"console","Format":"json","Levels":[{"ID":5,"Name":"debug","Stacktrace":false},{"ID":4,"Name":"info","Stacktrace":false,"color":36},{"ID":3,"Name":"warn","Stacktrace":false},{"ID":2,"Name":"error","Stacktrace":true,"color":31},{"ID":1,"Name":"fatal","Stacktrace":true,"color":31},{"ID":0,"Name":"panic","Stacktrace":true,"color":31},{"ID":10,"Name":"stdlog","Stacktrace":false}],"Options":{"Out":"stdout"},"MaxQueueSize":1000}}' +``` + +**Options** + +``` sh +-h, --help help for set +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config show + +**Description** + +Print the server configuration and write to STDOUT in JSON format. + +**Format** + +``` sh +mmctl config show [flags] +``` + +**Examples** + +``` sh +mmctl config show +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl config subpath + +**Description** + +Update the hard-coded production client asset paths to take into account Mattermost running on a subpath. This command needs access to the Mattermost `assets` directory to be able to rewrite the paths. + +**Format** + +``` sh +mmctl config subpath [flags] +``` + +**Examples** + +``` sh +# you can rewrite the assets to use a subpath +mmctl config subpath --assets-dir /opt/mattermost/client --path /mattermost + +# the subpath can have multiple steps +mmctl config subpath --assets-dir /opt/mattermost/client --path /my/custom/subpath + +# or you can fallback to the root path passing / +mmctl config subpath --assets-dir /opt/mattermost/client --path / +``` + +**Options** + +``` sh +-a, --assets-dir string directory of the Mattermost assets in the local filesystem +-h, --help help for subpath +-p, --path string path to update the assets with +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl docs + +**Description** + +Generate mmctl documentation. + +**Format** + +``` sh +mmctl docs [flags] +``` + +**Options** + +``` sh +-d, --directory string The directory where the docs would be generated in. (default "docs") +-h, --help help for docs +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl export + +Manage exports. + +> Child Commands +> - [mmctl export create](#mmctl-export-create) - Create an export file +> - [mmctl export delete](#mmctl-export-delete) - Delete an export file +> - [mmctl export download](#mmctl-export-download) - Download export files +> - [mmctl export generate-presigned-url](#mmctl-export-generate-presigned-url) - Generate a pre-signed URL for an export file +> - [mmctl export job](#mmctl-export-job) - List, show, and cancel export jobs +> - [mmctl export job cancel](#mmctl-export-job-cancel) - Cancel export job +> - [mmctl export job list](#mmctl-export-job-list) - List export jobs +> - [mmctl export job show](#mmctl-export-job-show) - Show export job +> - [mmctl export list](#mmctl-export-list) - List export files + +**Options** + +``` sh +-h, --help help for group +``` + +### mmctl export create + +**Description** + +Create an export file including message attachments. + +**Format** + +``` sh +mmctl export create [flags] +``` + +**Options** + +``` sh +--no-attachments Omit file attachments in the export file. +--include-archived-channels Include archived channels in the export file. +-h, --help help for create +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export delete + +**Description** + +Delete an export file. + +**Format** + +``` sh +mmctl export delete [exportname] [flags] +``` + +**Example** + +``` sh +mmctl export delete export_file.zip +``` + +**Options** + +``` sh +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export download + +**Description** + +Download export files. + +**Format** + +``` sh +mmctl export download [exportname] [filepath] [flags] +``` + +**Example** + +``` sh +# You can indicate the name of the export and its destination path +$ mmctl export download samplename sample_export.zip + +# If you only indicate the name, the path will match it +$ mmctl export download sample_export.zip +``` + +**Options** + +``` sh +-h, --help help for download +--num-retries int Number of retries to resume a download. (Default is 5) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export generate-presigned-url + +**Description** + +Generate a pre-signed URL for an export file in cases where a Mattermost Cloud export is large and challenging to download from the Mattermost server. + +Requires the `EnableExportDirectDownload` feature flag to be set to `true`. + +**Format** + +``` sh +mmctl export generate-presigned-url [exportname] [flags] +``` + +**Options** + +``` sh +-h, --help help for generate-presigned-url +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export job + +**Description** + +List, show, and export jobs. + +**Options** + +``` sh +-h, --help help for job +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export job cancel + +**Description** + +Cancel an export job. + +**Format** + +``` sh +mmctl export job cancel [exportJobID] [flags] +``` + +**Example** + +``` sh +export job cancel o98rj3ur83dp5dppfyk5yk6osy +``` + +**Options** + +``` sh +-h, --help help for download +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export job list + +**Description** + +List export jobs. Export files include the Job ID in the file name. + +**Format** + +``` sh +mmctl export job list [flags] +``` + +**Example** + +``` sh +mmctl export job list +``` + +**Options** + +``` sh +--all Fetch all export jobs. ``--page`` flag will be ignored if provided +-h, --help help for list +--page int Page number to fetch for the list of export jobs +--per-page int Number of export jobs to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export job show + +**Description** + +Show export job. + +**Format** + +``` sh +mmctl export job show [exportJobID] [flags] +``` + +**Example** + +``` sh +mmctl export job show +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl export list + +**Description** + +List export files. Export files include the job ID in the file name. + +**Format** + +``` sh +mmctl export list [flags] +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl group + +Manage channel and team groups. + +> Child Commands +> - [mmctl group channel](#mmctl-group-channel) - Manage channel groups +> - [mmctl group list-ldap](#mmctl-group-list-ldap) - List LDAP groups +> - [mmctl group team](#mmctl-group-team) - Manage team groups +> - [mmctl group user](#mmctl-group-user) - Manage custom user groups + +## mmctl group channel + +Management of channel groups + +> Child Commands +> - [mmctl group channel disable](#mmctl-group-channel-disable) - Disable group channel constrains +> - [mmctl group channel enable](#mmctl-group-channel-enable) - Enable group channel constrains +> - [mmctl group channel list](#mmctl-group-channel-list) - List channel groups +> - [mmctl group channel status](#mmctl-group-channel-status) - Check group status + +**Options** + +``` sh +-h, --help help for group +``` + +### mmctl group channel disable + +**Description** + +Disable group constrains in the specified channel. + +**Format** + +``` sh +mmctl group channel disable [team]:[channel] [flags] +``` + +**Examples** + +``` sh +mmctl group channel disable myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group channel enable + +**Description** + +Enable group constrains in the specified channel. + +**Format** + +``` sh +mmctl group channel enable [team]:[channel] [flags] +``` + +**Examples** + +``` sh +mmctl group channel enable myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for enable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group channel list + +**Description** + +List the groups associated with a channel. + +**Format** + +``` sh +mmctl group channel list [team]:[channel] [flags] +``` + +**Examples** + +``` sh +mmctl group channel list myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group channel status + +**Description** + +Show the group constrain status for the specified channel. + +**Format** + +``` sh +mmctl group channel status [team]:[channel] [flags] +``` + +**Examples** + +``` sh +mmctl group channel status myteam:mychannel +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group list-ldap + +**Description** + +List LDAP groups. + +**Format** + +``` sh +mmctl group list-ldap [flags] +``` + +**Examples** + +``` sh +mmctl group list-ldap +``` + +**Options** + +``` sh +-h, --help help for list-ldap +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl group team + +Manage team groups. + +> Child Commands +> - [mmctl group team disable](#mmctl-group-team-disable) - Disable group team constrains +> - [mmctl group team enable](#mmctl-group-team-enable) - Enable group team constrains +> - [mmctl group team list](#mmctl-group-team-list) - List team groups +> - [mmctl group team status](#mmctl-group-team-status) - Check group constrain status + +**Options** + +``` sh +-h, --help help for group +``` + +### mmctl group team disable + +**Description** + +Disable group constrains in the specified team. + +**Format** + +``` sh +mmctl group team disable [team] [flags] +``` + +**Examples** + +``` sh +mmctl group team disable myteam +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group team enable + +**Description** + +Enable group constrains in the specified team. + +**Format** + +``` sh +mmctl group team enable [team] [flags] +``` + +**Examples** + +``` sh +mmctl group team enable myteam +``` + +**Options** + +``` sh +-h, --help help for enable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group team list + +**Description** + +List the groups associated with a team. + +**Format** + +``` sh +mmctl group team list [team] [flags] +``` + +**Examples** + +``` sh +mmctl group team list myteam +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl group team status + +**Description** + +Show the group constrain status for the specified team. + +**Format** + +``` sh +mmctl group team status [team] [flags] +``` + +**Examples** + +``` sh +mmctl group channel status myteam +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl group user + +Manage custom user groups. + +> Child Commands +> - [mmctl group user restore](#mmctl-group-user-restore) - Restore custom user group + +**Options** + +``` sh +-h, --help help for group +``` + +### mmctl group user restore + +**Description** + +Restore custom user group. + +**Format** + +``` sh +mmctl group user restore [groupname] [flags] +``` + +**Examples** + +``` sh +mmctl group user restore examplegroup +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl extract + +Manage content extraction jobs. + +> Child Commands +> - [mmctl extract job](#mmctl-extract-job) - List and show content extraction jobs +> - [mmctl extract run](#mmctl-extract-run) - Start a content extraction job + +**Options** + +``` sh +-h, --help help for list +``` + +### mmctl extract job + +List and show content extraction jobs. + +> Child Commands +> - [mmctl extract job list](#mmctl-extract-job-list) - List content extraction jobs +> - [mmctl extract job show](#mmctl-extract-job-show) - Show extract job + +### mmctl extract job list + +**Description** + +List content extraction jobs. + +**Format** + +``` sh +mmctl extract job list [flags] +``` + +**Examples** + +``` sh +mmctl extract job list +``` + +**Options** + +``` sh +--all Fetch all export jobs. --page flag will be ignore if provided +-h, --help help for list +--page int Page number to fetch for the list of export jobs +--per-page int Number of export jobs to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl extract job show + +**Description** + +Show extract job. + +**Format** + +``` sh +mmctl extract job show [extractJobID] [flags] +``` + +**Examples** + +``` sh +mmctl extract job show f3d68qkkm7n8xgsfxwuo498rah +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl extract run + +**Description** + +Start a content extraction job. + +**Format** + +``` sh +mmctl extract run [flags] +``` + +**Examples** + +``` sh +mmctl extract run +``` + +**Options** + +``` sh +--from int The timestamp of the earliest file to extract, expressed in seconds since the unix epoch. +-h, --help help for run +--to int The timestamp of the latest file to extract, expressed in seconds since the unix epoch. Defaults to the current time. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl import + +**Description** + +Manage imports. + +> Child Commands +> - [mmctl import delete](#mmctl-import-delete) - Delete import files +> - [mmctl import job](#mmctl-import-job) - List and show import jobs +> - [mmctl import job list](#mmctl-import-job-list) - List import jobs +> - [mmctl import job show](#mmctl-import-job-show) - Show import job +> - [mmctl import list](#mmctl-import-list) - List all import files +> - [mmctl import list available](#mmctl-import-list-available) - List available import files +> - [mmctl import list incomplete](#mmctl-import-list-incomplete) - List incomplete import files uploads +> - [mmctl import process](#mmctl-import-process) - Start an import job +> - [mmctl import upload](#mmctl-import-upload) - Upload import files +> - [mmctl import validate](#mmctl-import-validate) - Validate an import file + +**Options** + +``` sh +-h, --help help for import +``` + +### mmctl import delete + +**Description** + +Delete import files from the server. + +**Format** + +``` sh +mmctl import delete [import-name] [flags] +``` + +**Examples** + +``` sh +mmctl import delete 35uy6cwrqfnhdx3genrhqqznxc_import.zip +mmctl import delete import1.zip import2.zip +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the import file(s) +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import job + +**Description** + +List and show import jobs. + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import job list + +**Description** + +List import jobs + +**Format** + +``` sh +mmctl import job list [flags] +``` + +**Examples** + +``` sh +mmctl import job list +``` + +**Options** + +``` sh +--all Fetch all import jobs. --page flag will be ignore if provided +-h, --help help for list +--page int Page number to fetch for the list of import jobs +--per-page int Number of import jobs to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import job show + +**Description** + +Show import job. + +**Format** + +``` sh +mmctl import job show [importJobID] [flags] +``` + +**Examples** + +``` sh +mmctl import job show f3d68qkkm7n8xgsfxwuo498rah +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import list + +**Description** + +List all import files. + +**Examples** + +``` sh +mmctl import list +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import list available + +**Description** + +List available import files. + +**Format** + +``` sh +mmctl import list available [flags] +``` + +**Examples** + +``` sh +mmctl import list available +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import list incomplete + +**Description** + +List incomplete import files uploads. + +**Format** + +``` sh +mmctl import list incomplete [flags] +``` + +**Examples** + +``` sh +mmctl import list incomplete +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import process + +**Description** + +Start an import job. + +**Format** + +``` sh +mmctl import process [importname] [flags] +``` + +**Examples** + +``` sh +mmctl import process 35uy6cwrqfnhdx3genrhqqznxc_import.zip +``` + +**Options** + +``` sh +-h, --help help for status +--bypass-upload File is read directly from the filesystem, instead of being processed from the server. Supported in --local mode only. +--extract-content Document attachments will be extracted and indexed during the import process. We recommend disabling this to improve performance. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import upload + +**Description** + +Upload import files. + +**Format** + +``` sh +mmctl import upload [filepath] [flags] +``` + +**Examples** + +``` sh +mmctl import upload import_file.zip +``` + +**Options** + +``` sh +-h, --help help for upload +--resume Set to true to resume an incomplete import upload. +--upload string The ID of the import upload to resume. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl import validate + +**Description** + +Validate an import file. + +**Format** + +``` sh +mmctl import validate [filepath] [flags] +``` + +**Examples** + +``` sh +import validate import_file.zip --team myteam --team myotherteam +``` + +**Options** + +``` sh +--check-missing-teams Check for teams that are not defined but referenced in the archive +--check-server-duplicates Set to false to ignore teams, channels, and users already present on the server (Default true) +-h, --help help for validate +--ignore-attachments Do not check if the attached files are present in the archive +--team stringarray Predefined teams to assume as already present on the destination server. Implies --check-missing-teams. The flag can be repeated +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl integrity + +**Description** + +This command is deprecated from Mattermost v9.3. Performs a relational integrity check which returns information about any orphaned record found. This command can only be run using [local mode](#local-mode). + +**Format** + +``` sh +mmctl integrity [flags] +``` + +**Options** + +``` sh +--confirm Confirm you really want to run a complete integrity check that may temporarily harm system performance +-h, --help help for integrity +-v, --verbose Show detailed information on integrity check results +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl job + +Management of jobs. + +> Child Commands +> - [mmctl job list](#mmctl-job-list) - List the latest jobs +> - [mmctl job update](#mmctl-job-update) - Update the status of a job + +**Options** + +``` sh +-h, --help help for ldap +``` + +### mmctl job list + +**Description** + +List the latest jobs. + +**Format** + +``` sh +mmctl job list [flags] +``` + +**Examples** + +``` sh +job list + job list --ids jobID1,jobID2 + job list --type ldap_sync --status success + job list --type ldap_sync --status success --page 0 --per-page 10 +``` + +**Options** + +``` sh +--all Fetch all import jobs. --page flag will be ignored if provided +-h, --help help for list +--ids strings Comma-separated list of job IDs to which the operation will be applied. All other flags are ignored +--page int Page number to fetch for the list of import jobs +--per-page int Number of import jobs to be fetched (default 5) +--status string Filter by job status +--type string Filter by job type +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl job update + +**Description** + +Update the status of a job. + +<Important> + +The following status rules are permitted: + +- `in_progress` can be changed to `pending` +- `in_progress` or `pending` can be changed to `cancel_requested` +- `cancel_requested` can be changed to `canceled` + +These restrictions can be bypassed with `--force=true`. Bypassing restrictions can have unexpected consequences on your Mattermost server and should be used with caution. + +</Important> + +**Format** + +``` sh +mmctl job update [job] [status] [flags] +``` + +**Examples** + +``` sh +job update myJobID pending + job update myJobID pending --force true + job update myJobID canceled --force true +``` + +**Options** + +``` sh +--force Setting a job status is restricted to certain statuses. You can overwrite these restrictions by using --force. Use this option with caution. +-h, --help help for update +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl ldap + +LDAP-related utilities. + +> Child Commands +> - [mmctl ldap idmigrate](#mmctl-ldap-idmigrate) - Migrate LDAP IdAttribute to a new value +> - [mmctl ldap job](#mmctl-ldap-job) - List and show LDAP synchronization jobs +> - [mmctl ldap sync](#mmctl-ldap-sync) - Sync all LDAP users and groups + +**Options** + +``` sh +-h, --help help for ldap +``` + +### mmctl ldap idmigrate + +**Description** + +Migrate LDAP `IdAttribute` to a new value. Run this utility to change the value of your ID Attribute without your users losing their accounts. After running the command, you can change the ID Attribute to the new value in the System Console. For example, if your current ID Attribute was `sAMAccountName` and you wanted to change it to `objectGUID`, you would: + +1. Wait for an off-peak time when your users won’t be impacted by a server restart. +2. Run the command `mmctl ldap idmigrate objectGUID`. +3. Update the config within the System Console to the new value `objectGUID`. +4. Restart the Mattermost server. + +**Format** + +``` sh +mmctl ldap idmigrate <objectGUID> [flags] +``` + +**Examples** + +``` sh +mmctl ldap idmigrate objectGUID +``` + +**Options** + +``` sh +-h, --help help for idmigrate +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl ldap job + +List and show LDAP synchronization jobs. + +Child Commands +- [mmctl ldap job list](#mmctl-ldap-job-list) - LIst LDAP synchronization jobs +- [mmctl ldap job show](#mmctl-ldap-job-show) - Show LDAP synchronization jobs + +**Options** + +``` sh +-h, --help help for ldap +``` + +### mmctl ldap job list + +**Description** + +List LDAP synchronization jobs. + +**Format** + +``` sh +mmctl ldap job list [flags] +``` + +**Examples** + +``` sh +mmctl ldap job list +``` + +**Options** + +``` sh +--all Fetch all import jobs. The ``--page`` flag will be ignored if provided. +-h, --help help for list +--page int Page number to fetch for the list of import jobs +--per-page int Number of import jobs to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl ldap job show + +**Description** + +Show LDAP synchronization jobs. + +**Format** + +``` sh +mmctl ldap job show [ldapJobID] [flags] +``` + +**Examples** + +``` sh +mmctl ldap show f3d68qkkm7n8xgsfxwuo498rah +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl ldap sync + +**Description** + +Synchronize all LDAP users and groups now. + +**Format** + +``` sh +mmctl ldap sync [flags] +``` + +**Examples** + +``` sh +mmctl ldap sync +``` + +**Options** + +``` sh +-h, --help help for sync +--include-removed-members **Deprecated in v11.0**: Include members who left or were removed from a group-synced team/channel. Useful in cases where synchronized groups are unlinked/re-linked for testing purposes, when LDAP users are deactivated and reactivated, or when a user leaves a team in error. This option is deprecated and will be removed in a future version. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl license + +Manage the Mattermost license. + +> Child Commands +> - [mmctl license get](#mmctl-license-get) - Get the current license +> - [mmctl license remove](#mmctl-license-remove) - Remove the current license +> - [mmctl license upload](#mmctl-license-upload) - Upload a new license +> - [mmctl license upload-string](#mmctl-license-upload-string) - Upload a license from a string + +**Options** + +``` sh +-h, --help help for license +``` + +### mmctl license get + +**Description** + +Get the current Mattermost license. + +**Format** + +``` sh +mmctl license get [flags] +``` + +**Examples** + +``` sh +mmctl license get +``` + +**Options** + +``` sh +-h, --help help for get +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl license remove + +**Description** + +Remove the current license and use Mattermost Team Edition. + +**Format** + +``` sh +mmctl license remove [flags] +``` + +**Examples** + +``` sh +mmctl license remove +``` + +**Options** + +``` sh +-h, --help help for remove +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl license upload + +**Description** + +Upload a license and replace the current license. + +**Format** + +``` sh +mmctl license upload [license] [flags] +``` + +**Examples** + +``` sh +mmctl license upload /path/to/license/mylicensefile.mattermost-license +``` + +**Options** + +``` sh +-h, --help help for upload +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl license upload-string + +**Description** + +Upload a license from a string. Replaces the current license. + +**Format** + +``` sh +mmctl license upload-string [license] [flags] +``` + +**Examples** + +``` sh +license upload-string "mylicensestring" +``` + +**Options** + +``` sh +-h, --help help for upload +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl logs + +**Description** + +Display logs in a human-readable format. As the log format depends on the server, the `--format` flag cannot be used with this command. + +**Format** + +``` sh +mmctl logs [flags] +``` + +**Options** + +``` sh +-h, --help help for logs +-l, --logrus Use logrus for formatting +-n, --number int Number of log lines to retrieve (default 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl oauth + +Manage registered OAuth2 applications. + +> Child Commands +> - [mmctl oauth list](#mmctl-oauth-list) - Remove permissions from a role + +**Options** + +``` sh +-h, --help help for permissions +``` + +### mmctl oauth list + +**Description** + +List all registered OAuth2 applications. + +**Format** + +``` sh +mmctl oauth list [flags] +``` + +**Example** + +``` sh +mmctl list +``` + +**Options** + +``` sh +-h, --help help for add +--page int Page number to fetch for the list of OAuth2 apps +--per-page int Number of OAuth2 apps to be fetched per page (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl permissions + +Manage permissions and roles. + +> Child Commands +> - [mmctl permissions add](#mmctl-permissions-add) - Add permissions to a role +> - [mmctl permissions remove](#mmctl-permissions-remove) - Remove permissions from a role +> - [mmctl permissions reset](#mmctl-permissions-reset) - Reset default permissions for a role +> - [mmctl permissions role assign](#mmctl-permissions-role-assign) - Assign users to role +> - [mmctl permissions role show](#mmctl-permissions-role-show) - Show the role information +> - [mmctl permissions role unassign](#mmctl-permissions-role-unassign) - Unassign users from a role + +**Options** + +``` sh +-h, --help help for permissions +``` + +### mmctl permissions add + +<PlanAvailability slug="ent-plus" /> + +**Description** + +Add one or more permissions to an existing role. + +**Format** + +``` sh +mmctl permissions add <role> <permission...> [flags] +``` + +**Examples** + +``` sh +mmctl permissions add system_user list_open_teams +mmctl permissions add system_manager sysconsole_read_user_management_channels +``` + +**Options** + +``` sh +-h, --help help for add +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl permissions remove + +<PlanAvailability slug="ent-plus" /> + +**Description** + +Remove one or more permissions from an existing role. For classified projects, this command can be used to ensure that team members don't know about members outside of their project, and [@mentions](/end-user-guide/collaborate/mention-people) don't disclose the names of people outside of a classified project. + +**Format** + +``` sh +mmctl permissions remove <role> <permission...> [flags] +``` + +**Examples** + +``` sh +mmctl permissions remove system_user list_open_teams +mmctl permissions remove system_manager sysconsole_read_user_management_channels +mmctl permissions remove system_user view_member +``` + +**Options** + +``` sh +-h, --help help for remove +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl permissions reset + +<PlanAvailability slug="ent-plus" /> + +**Description** + +Reset the given role's permissions to the default settings and overwrite custom settings. + +**Format** + +``` sh +mmctl permissions reset <role_name> [flags] +``` + +**Examples** + +``` sh +# Reset the permissions of the 'system_read_only_admin' role. +$ mmctl permissions reset system_read_only_admin +``` + +**Options** + +``` sh +-h, --help help for reset +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl permissions role assign + +<PlanAvailability slug="ent-plus" /> + +**Description** + +Assign users to a role by username. + +**Format** + +``` sh +mmctl permissions role assign <role_name> <username...> [flags] +``` + +**Examples** + +``` sh +# Assign users with usernames 'john.doe' and 'jane.doe' to the role named 'system_admin'. +mmctl permissions role assign system_admin john.doe jane.doe + +# Examples using other system roles +mmctl permissions role assign system_manager john.doe jane.doe +mmctl permissions role assign system_user_manager john.doe jane.doe +mmctl permissions role assign system_read_only_admin john.doe jane.doe +``` + +**Options** + +``` sh +-h, --help help for assign +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl permissions role show + +**Description** + +Show all the information about a role. + +**Format** + +``` sh +mmctl permissions role show <role_name> [flags] +``` + +**Examples** + +``` sh +mmctl permissions role show system_user +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl permissions role unassign + +<PlanAvailability slug="pro-plus" /> + +**Description** + +Unassign users from a role by username. + +**Format** + +``` sh +mmctl permissions role unassign <role_name> <username...> [flags] +``` + +**Examples** + +``` sh +# Unassign users with usernames 'john.doe' and 'jane.doe' from the role named 'system_admin'. +mmctl permissions unassign system_admin john.doe jane.doe + +# Examples using other system roles +mmctl permissions unassign system_manager john.doe jane.doe +mmctl permissions unassign system_user_manager john.doe jane.doe +mmctl permissions unassign system_read_only_admin john.doe jane.doe +``` + +**Options** + +``` sh +-h, --help help for unassign +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl plugin + +Manage plugins. + +> Child Commands +> - [mmctl plugin add](#mmctl-plugin-add) - Add plugins +> - [mmctl plugin delete](#mmctl-plugin-delete) - Remove plugins +> - [mmctl plugin disable](#mmctl-plugin-disable) - Disable plugins +> - [mmctl plugin enable](#mmctl-plugin-enable) - Enable plugins +> - [mmctl plugin install-url](#mmctl-plugin-install-url) - Install plugin from URL +> - [mmctl plugin list](#mmctl-plugin-list) - List plugins +> - [mmctl plugin marketplace](#mmctl-plugin-marketplace) - Manage Marketplace plugins + +**Options** + +``` sh +-h, --help help for plugin +``` + +### mmctl plugin add + +**Description** + +Add plugins to your Mattermost server. + +**Format** + +``` sh +mmctl plugin add [plugins] [flags] +``` + +**Examples** + +``` sh +mmctl plugin add hovercardexample.tar.gz pluginexample.tar.gz +``` + +**Options** + +``` sh +-f, --force overwrite a previously installed plugin with the same ID, if any +-h, --help help for add +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin delete + +**Description** + +Delete previously uploaded plugins from your Mattermost server. + +**Format** + +``` sh +mmctl plugin delete [plugins] [flags] +``` + +**Examples** + +``` sh +mmctl plugin delete hovercardexample pluginexample +``` + +**Options** + +``` sh +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin disable + +**Description** + +Disable plugins. Disabled plugins are immediately removed from the user interface and logged out of all sessions. + +**Format** + +``` sh +mmctl plugin disable [plugins] [flags] +``` + +**Examples** + +``` sh +mmctl plugin disable hovercardexample pluginexample +``` + +**Options** + +``` sh +-h, --help help for disable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin enable + +**Description** + +Enable plugins for use on your Mattermost server. + +**Format** + +``` sh +mmctl plugin enable [plugins] [flags] +``` + +**Examples** + +``` sh +mmctl plugin enable hovercardexample pluginexample +``` + +**Options** + +``` sh +-h, --help help for enable +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin install-url + +**Description** + +Supply URLs to plugins compressed in a `.tar.gz` file. Plugins must be enabled in the server's config settings. + +**Format** + +``` sh +mmctl plugin install-url <url>... [flags] +``` + +**Examples** + +``` sh +# You can install one plugin +$ mmctl plugin install-url https://example.com/mattermost-plugin.tar.gz + +# Or install multiple plugins at a time +$ mmctl plugin install-url https://example.com/mattermost-plugin-one.tar.gz https://example.com/mattermost-plugin-two.tar.gz +``` + +**Options** + +``` sh +-f, --force overwrite a previously installed plugin with the same ID, if any +-h, --help help for install-url +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin list + +**Description** + +List all enabled and disabled plugins installed on your Mattermost server. + +**Format** + +``` sh +mmctl plugin list [flags] +``` + +**Examples** + +``` sh +mmctl plugin list +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl plugin marketplace + +Manage Marketplace plugins. + +> Child Commands +> - [mmctl plugin marketplace install](#mmctl-plugin-marketplace-install) - Install a plugin from the Plugin Marketplace +> - [mmctl plugin marketplace list](#mmctl-plugin-marketplace-list) - List plugins on the Plugin Marketplace + +**Options** + +``` sh +-h, --help help for marketplace +``` + +### mmctl plugin marketplace install + +**Description** + +Install a plugin available on the Plugin Marketplace server. The latest version of the plugin will be installed. + +**Format** + +``` sh +mmctl plugin marketplace install <id> [flags] +``` + +**Examples** + +``` sh +$ mmctl plugin marketplace install jitsi +``` + +**Options** + +``` sh +-h, --help help for install +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl plugin marketplace list + +**Description** + +Get all plugins available from the Plugin Marketplace server, merging data from locally installed plugins as well as prepackaged plugins shipped with the server. + +**Format** + +``` sh +mmctl plugin marketplace list [flags] +``` + +**Examples** + +``` sh +# You can list all available plugins +$ mmctl plugin marketplace list --all + +# Pagination options can be used +$ mmctl plugin marketplace list --page 2 --per-page 10 + +# Filtering narrows down the search +$ mmctl plugin marketplace list --filter jit + +# You can retrieve only local plugins +$ mmctl plugin marketplace list --local-only +``` + +**Options** + +``` sh +--all Fetch all plugins. --page flag will be ignore if provided +--filter string Filter plugins by ID, name or description +-h, --help help for list +--local-only Only retrieve local plugins +--page int Page number to fetch for the list of users +--per-page int Number of users to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl post + +Manage posts. + +> Child Commands +> - [mmctl post create](#mmctl-post-create) - Create a post +> - [mmctl post delete](#mmctl-post-delete) - Delete a post +> - [mmctl post list](#mmctl-post-list) - List posts for a channel + +**Options** + +``` sh +-h, --help help for post +``` + +### mmctl post create + +**Description** + +Create a post. + +**Format** + +``` sh +mmctl post create [flags] +``` + +**Examples** + +``` sh +mmctl post create myteam:mychannel --message "some text for the post" +``` + +**Options** + +``` sh +-h, --help help for create +-m, --message string Message for the post +-r, --reply-to string Post id to reply to +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl post delete + +**Description** + +Mark a post as deleted and remove it and all attachments from the client without permanently deleting it from the database. Permanently delete a post and all attachments using the `--permanent` flag. + +**Format** + +``` sh +mmctl post delete [posts] [flags] +``` + +**Examples** + +Mark post as deleted: + +``` sh +mmctl post delete udjmt396tjghi8wnsk3a1qs1sw +``` + +Permanently delete a post and its file contents from the database and filestore: + +``` sh +mmctl post delete udjmt396tjghi8wnsk3a1qs1sw --permanent +``` + +Permanently delete multiple posts and their file contents from the database and filestore: + +``` sh +mmctl post delete udjmt396tjghi8wnsk3a1qs1sw 7jgcjt7tyjyyu83qz81wo84w6o --permanent +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the post and a DB backup has been performed +-h, --help help for delete +--permanent Permanently delete the post and its contents from the database +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl post list + +**Description** + +List posts for a channel. + +**Format** + +``` sh +mmctl post list [flags] +``` + +**Examples** + +``` sh +mmctl post list myteam:mychannel +mmctl post list myteam:mychannel --number 20 +``` + +**Options** + +``` sh +-f, --follow Output appended data as new messages are posted to the channel +-h, --help help for list +-n, --number int Number of messages to list (default 20) +-i, --show-ids Show posts ids +-s, --since string List messages posted after a certain time (ISO 8601) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl roles + +**Description** + +Promote users to the system admin role, or remove system admin privileges from users. + +**Format** + +Promote users to the system admin role: + +``` sh +mmctl roles system_admin [users] [flags] +``` + +Remove system admin privileges: + +``` sh +mmctl roles member [users] [flags] +``` + +**Examples** + +Promote a user to the system admin role: + +``` sh +mmctl roles system_admin john_doe +``` + +Promote multiple users to the system admin role: + +``` sh +mmctl roles system_admin john_doe jane_doe +``` + +Remove system admin privileges from a user: + +``` sh +mmctl roles member john_doe +``` + +Remove system admin privileges from multiple users: + +``` sh +mmctl roles member john_doe jane_doe +``` + +**Options** + +``` sh +-h, --help help for roles +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl saml + +SAML-related utilities. + +> Child Commands +> - [mmctl saml auth-data-reset](#mmctl-saml-auth-data-reset) - Reset AuthData field to Email + +**Options** + +``` sh +-h, --help help for system +``` + +### mmctl saml auth-data-reset + +**Description** + +Resets the AuthData field for SAML users to their email. Run this utility after setting the 'id' SAML attribute to an empty value. + +**Format** + +``` sh +mmctl saml auth-data-reset [flags] +``` + +**Examples** + +``` sh +# Reset all SAML users' AuthData field to their email, including deleted users +$ mmctl saml auth-data-reset --include-deleted + +# Show how many users would be affected by the reset +$ mmctl saml auth-data-reset --dry-run + +# Skip confirmation for resetting the AuthData +$ mmctl saml auth-data-reset -y + +# Only reset the AuthData for the following SAML users +$ mmctl saml auth-data-reset --users userid1,userid2 +``` + +**Options** + +``` sh +--dry-run Dry run only +-h, --help help for auth-data-reset +--include-deleted Include deleted users +--users strings Comma-separated list of user IDs to which the operation will be applied +-y, --yes Skip confirmation +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl sampledata + +**Description** + +Generate a sample data file and store it locally, or directly import it to the remote server. + +**Format** + +``` sh +mmctl sampledata [flags] +``` + +**Examples** + +``` sh +# You can create a sampledata file and store it locally +$ mmctl sampledata --bulk sampledata-file.jsonl + +# Or you can simply print it to the STDOUT +$ mmctl sampledata --bulk - + +# You can customize the amount of entities to create +$ mmctl sampledata -t 7 -u 20 -g 4 + +# The sampledata file can be directly imported into the remote server by not specifying a ``--bulk``` flag +$ mmctl sampledata + +# Sample users can be created with profile pictures +$ mmctl sampledata --profile-images ./images/profiles +``` + +**Options** + +``` sh +-b, --bulk string Optional. Path to write a JSONL bulk file instead of uploading into the remote server. +--channel-memberships int The number of sample channel memberships per user in a team. (default 5) +--channels-per-team int The number of sample channels per team. (default 10) +--deactivated-users int The number of deactivated users. +--direct-channels int The number of sample direct message channels. (default 30) +--group-channels int The number of sample group message channels. (default 15) +-g, --guests int The number of sample guests. (default 1) +-h, --help help for sampledata +--posts-per-channel int The number of sample post per channel. (default 100) +--posts-per-direct-channel int The number of sample posts per direct message channel. (default 15) +--posts-per-group-channel int The number of sample posts per group message channel. (default 30) +--profile-images string Optional. Path to folder with images to randomly pick as user profile image. +-s, --seed int Seed used for generating the random data (Different seeds generate different data). (default 1) +--team-memberships int The number of sample team memberships per user. (default 2) +-t, --teams int The number of sample teams. (default 2) +-u, --users int The number of sample users. (default 15) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl system + +System management commands for interacting with the server state and configuration. + +> Child Commands +> - [mmctl system clearbusy](#mmctl-system-clearbusy) - Clear the busy state +> - [mmctl system getbusy](#mmctl-system-getbusy) - Get the current busy state +> - [mmctl system setbusy](#mmctl-system-setbusy) - Set the busy state to `true` +> - [mmctl system status](#mmctl-system-status) - Print the status of the server +> - [mmctl system supportpacket](#mmctl-system-supportpacket) - Download a Support Packet +> - [mmctl system version](#mmctl-system-version) - Print the remote server version build number + +**Options** + +``` sh +-h, --help help for system +``` + +### mmctl system clearbusy + +**Description** + +Clear the busy state which re-enables non-critical services. + +**Format** + +``` sh +mmctl system clearbusy [flags] +``` + +**Examples** + +``` sh +mmctl system clearbusy +``` + +**Options** + +``` sh +-h, --help help for clearbusy +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl system getbusy + +**Description** + +Get the server busy state (high load) and timestamp corresponding to when the server busy flag will be automatically cleared. + +**Format** + +``` sh +mmctl system getbusy [flags] +``` + +**Examples** + +``` sh +mmctl system getbusy +``` + +**Options** + +``` sh +-h, --help help for getbusy +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl system setbusy + +**Description** + +Set the busy state to `true` for the specified number of seconds which disables non-critical services. + +**Format** + +``` sh +mmctl system setbusy -s [seconds] [flags] +``` + +**Examples** + +``` sh +mmctl system setbusy -s 3600 +``` + +**Options** + +``` sh +-h, --help help for setbusy +-s, --seconds uint Number of seconds until server is automatically marked as not busy (default 3600) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl system status + +**Description** + +Print the server status which is calculated using several basic server healthchecks. + +**Format** + +``` sh +mmctl system status [flags] +``` + +**Examples** + +``` sh +mmctl system status +``` + +**Options** + +``` sh +-h, --help help for status +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl system supportpacket + +**Description** + +Generate and download a Support Packet of the Mattermost server to share with Mattermost Support. + +**Format** + +``` sh +mmctl system supportpacket [flags] +``` + +**Examples** + +``` sh +mmctl system supportpacket +``` + +**Options** + +``` sh +-h, --help help for version +-o, --output-file string Output file name. Default is ``mattermost_support_packet_YYYY-MM-DD-HH-MM.zip``. +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl system version + +**Description** + +Print the server version build number of the currently connected Mattermost instance. + +**Format** + +``` sh +mmctl system version [flags] +``` + +**Examples** + +``` sh +mmctl system version +``` + +**Options** + +``` sh +-h, --help help for version +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl team + +Manage teams. + +<Important> + +When specifying team names within mmctl commands, you must use the `team-URL` version of the team name, rather than the display name you see in the channel sidebar. Your `team-URL` does not contain spaces. Run the [mmctl team list](#mmctl-team-list) command to return a list of all teams on the server in `team-URL` format. See the [team name and URL selection](/end-user-guide/collaborate/organize-using-teams#team-name-and-url-selection) documentation for details. + +Child Commands +- [mmctl team archive](#mmctl-team-archive) - Archive some teams +- [mmctl team create](#mmctl-team-create) - Create teams +- [mmctl team delete](#mmctl-team-delete) - Delete teams +- [mmctl team list](#mmctl-team-list) - List teams +- [mmctl team modify](#mmctl-team-modify) - Modify teams +- [mmctl team rename](#mmctl-team-rename) - Rename teams +- [mmctl team restore](#mmctl-team-restore) - Restore teams +- [mmctl team search](#mmctl-team-search) - Search teams +- [mmctl team users](#mmctl-team-users) - Manage team users + +</Important> + +**Options** + +``` sh +-h, --help help for team +``` + +### mmctl team archive + +**Description** + +Archive a team along with all related information including posts from the database. + +**Format** + +``` sh +mmctl team archive [teams] [flags] +``` + +**Examples** + +``` sh +mmctl team archive myteam +``` + +**Options** + +``` sh +--confirm Confirm you really want to archive the team and a database backup has been performed +-h, --help help for archive +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team create + +**Description** + +Create a team. + +**Format** + +``` sh +mmctl team create [flags] +``` + +**Examples** + +``` sh +mmctl team create --name mynewteam --display-name "My New Team" +mmctl team create --name private --display-name "My New Private Team" --private +``` + +**Options** + +``` sh +--display-name string Team Display Name +--email string Administrator Email (anyone with this email is automatically a team admin) +-h, --help help for create +--name string Team Name +--private Create a private team +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team delete + +**Description** + +Permanently delete a team along with all related information including posts from the database. + +<Note> + +Requires the [Enable API Team Deletion](/administration-guide/configure/environment-configuration-settings#enable-api-team-deletion) configuration setting to be set to `true`. If this configuration setting is set to `false`, attempting to delete the team using mmctl fails. + +</Note> + +**Format** + +``` sh +mmctl team delete [teams] [flags] +``` + +**Examples** + +``` sh +mmctl team delete myteam +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the team and a database backup has been performed +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team list + +**Description** + +List all teams on the server. + +**Format** + +``` sh +mmctl team list [flags] +``` + +**Examples** + +``` sh +mmctl team list +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team modify + +**Description** + +Modify a team's privacy setting to public or private. + +**Format** + +``` sh +mmctl team modify [teams] [flag] [flags] +``` + +**Examples** + +``` sh +mmctl team modify myteam --private +``` + +**Options** + +``` sh +-h, --help help for modify +--private Modify team to be private +--public Modify team to be public +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team rename + +**Description** + +Rename an existing team. + +**Format** + +``` sh +mmctl team rename [team] [flags] +``` + +**Examples** + +``` sh +mmctl team rename old-team --display-name 'New Display Name' +``` + +**Options** + +``` sh +--display-name string Team Display Name +-h, --help help for rename +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team restore + +**Description** + +Restore archived teams. + +**Format** + +``` sh +mmctl team restore [teams] [flags] +``` + +**Examples** + +``` sh +mmctl team restore myteam +``` + +**Options** + +``` sh +-h, --help help for restore +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team search + +**Description** + +Search for teams based on name. + +**Format** + +``` sh +mmctl team search [teams] [flags] +``` + +**Examples** + +``` sh +mmctl team search team1 +``` + +**Options** + +``` sh +-h, --help help for search +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl team users + +Manage team users. + +> Child Commands +> - [mmctl team users add](#mmctl-team-users-add) - Add users to a team +> - [mmctl team users remove](#mmctl-team-users-remove) - Remove users from a team + +**Options** + +``` sh +-h, --help help for token +``` + +### mmctl team users add + +**Description** + +Add specified users to a team. + +**Format** + +``` sh +mmctl team users add [team] [users] [flags] +``` + +**Examples** + +``` sh +mmctl team users add myteam user@example.com username +``` + +**Options** + +``` sh +-h, --help help for add +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl team users remove + +**Description** + +Remove specified users from a team. + +**Format** + +``` sh +mmctl team users remove [team] [users] [flags] +``` + +**Examples** + +``` sh +mmctl team users remove myteam user@example.com username +``` + +**Options** + +``` sh +-h, --help help for remove +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl token + +Manage users' access tokens. + +> Child Commands +> - [mmctl token generate](#mmctl-token-generate) - Generate token for a user +> - [mmctl token list](#mmctl-token-list) - List users' tokens +> - [mmctl token revoke](#mmctl-token-revoke) - Revoke tokens for a user + +**Options** + +``` sh +-h, --help help for token +``` + +### mmctl token generate + +**Description** + +Generate token for a user. + +**Format** + +``` sh +mmctl token generate [user] [description] [flags] +``` + +**Examples** + +``` sh +mmctl token generate testuser test-token +``` + +**Options** + +``` sh +-h, --help help for generate +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl token list + +**Description** + +List the tokens belonging to a user. + +**Format** + +``` sh +mmctl token list [user] [flags] +``` + +**Examples** + +``` sh +mmctl user tokens testuser +``` + +**Options** + +``` sh +--active List only active tokens (default true) +--all Fetch all tokens. --page flag will be ignore if provided +-h, --help help for list +--inactive List only inactive tokens +--page int Page number to fetch for the list of users +--per-page int Number of users to be fetched (maximum 200) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl token revoke + +**Description** + +Revoke tokens for a user. + +**Format** + +``` sh +mmctl token revoke [token-ids] [flags] +``` + +**Examples** + +``` sh +mmctl revoke testuser test-token-id +``` + +**Options** + +``` sh +-h, --help help for revoke +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl user + +Manage users. + +> Child Commands +> - [mmctl user activate](#mmctl-user-activate) - Activate a user +> - [mmctl user change-password](#mmctl-user-change-password) - Change a user's password +> - [mmctl user convert](#mmctl-user-convert) - Convert users to bots or convert bots to users +> - [mmctl user create](#mmctl-user-create) - Create user +> - [mmctl user deactivate](#mmctl-user-deactivate) - Deactivate user +> - [mmctl user delete](#mmctl-user-delete) - Delete users +> - [mmctl user deleteall](#mmctl-user-deleteall) - Delete all users and all posts (local command only) +> - [mmctl user demote](#mmctl-user-demote) - Demote users to guests +> - [mmctl user edit](#mmctl-user-edit) - Edit user properties +> - [mmctl user edit authdata](#mmctl-user-edit-authdata) - Edit user authentication data +> - [mmctl user edit email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-email) - Edit user email address +> - [mmctl user edit username](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-username) - Edit user username +> - [mmctl user email](#mmctl-user-email) - (Deprecated) Set user email +> - [mmctl user invite](#mmctl-user-invite) - Invite user +> - [mmctl user list](#mmctl-user-list) - List users +> - [mmctl user migrate-auth](#mmctl-user-migrate-auth) - Bulk migrate user accounts authentication type +> - [mmctl user preference](#mmctl-user-preference) - Manage user preferences +> - [mmctl user promote](#mmctl-user-promote) - Promote guests to users +> - [mmctl user reset-password](#mmctl-user-reset-password) - Reset user password +> - [mmctl user resetmfa](#mmctl-user-resetmfa) - Reset a user's MFA token +> - [mmctl user search](#mmctl-user-search) - Search for a user +> - [mmctl user username](#mmctl-user-username) - (Deprecated) Change username of the user +> - [mmctl user verify](#mmctl-user-verify) - Mark user's email as verified + +**Options** + +``` sh +-h, --help help for user +``` + +### mmctl user activate + +**Description** + +Activate users that have been deactivated. + +**Format** + +``` sh +mmctl user activate [emails, usernames, userIds] [flags] +``` + +**Examples** + +``` sh +mmctl user activate user@example.com +mmctl user activate username +``` + +**Options** + +``` sh +-h, --help help for activate +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user change-password + +**Description** + +Change the password of a user to the one provided. If the user is changing their own password, the flag `--current` must indicate the current password. The flag `--hashed` can be used to indicate that the new password has been introduced as already hashed. + +**Format** + +``` sh +mmctl user change-password <user> [flags] +``` + +**Examples** + +``` sh +# If you have system permissions, you can change other user's passwords +$ mmctl user change-password john_doe --password new-password + +# If you are changing your own password, you need to provide the current one +$ mmctl user change-password my-username --current current-password --password new-password + +# You can ommit these flags to introduce them interactively +$ mmctl user change-password my-username +Are you changing your own password? (YES/NO): YES +Current password: +New password: + +# If you have system permissions, you can update the password with the already hashed new +# password. The hashing method should be the same that the server uses internally. +$ mmctl user change-password john_doe --password HASHED_PASSWORD --hashed +``` + +**Options** + +``` sh +-c, --current string The current password of the user. Use only if changing your own password +--hashed The supplied password is already hashed +-h, --help help for change-password +-p, --password string The new password for the user +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user convert + +**Description** + +Convert user accounts to bots, or convert bots to user accounts. + +**Format** + +``` sh +mmctl user convert (--bot [emails] [usernames] [userIds] | --user <username> --password PASSWORD [--email EMAIL]) [flags] +``` + +**Examples** + +``` sh +# You can convert a user to a bot providing an email, an ID, or a username +$ mmctl user convert user@example.com --bot + +# Or you can convert multiple users at a time +$ mmctl user convert user@example.com anotherUser --bot + +# You can convert a bot to a user and specify the email and password that the user will have after conversion +$ mmctl user convert botusername --email new.email@email.com --password password --user +``` + +**Options** + +``` sh +--bot If supplied, convert users to bots +--email string The email address for the converted user account. Required when the "bot" flag is set +--firstname string The first name for the converted user account. Required when the "bot" flag is set +-h, --help help for convert +--lastname string The last name for the converted user account. Required when the "bot" flag is set +--locale string The locale (e.g., EN, FR) for the converted new user account. Required when the "bot" flag is set +--nickname string The nickname for the converted user account. Required when the "bot" flag is set +--password string The password for converted new user account. Required when "user" flag is set +--system-admin If supplied, the converted user will be a system admin. Defaults to false. Required when the "bot" flag is set +--user If supplied, convert a bot to a user +--username string Username for the converted user account. Required when the "bot" flag is set +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user create + +**Description** + +Create a user. + +**Format** + +``` sh +mmctl user create [flags] +``` + +**Examples** + +``` sh +# You can create a user +$ mmctl user create --email user@example.com --username userexample --password Password1 + +# You can define optional fields like first name, last name, and nickname +$ mmctl user create --email user@example.com --username userexample --password Password1 --firstname User --lastname Example --nickname userex + +# You can also create the user as a system sdmin +$ mmctl user create --email user@example.com --username userexample --password Password1 --system-admin + +# You can verify user on creation if you have the correct permissions +$ mmctl user create --email user@example.com --username userexample --password Password1 --system-admin --email-verified +``` + +**Options** + +``` sh +--disable-welcome-email Optional. If supplied, the new user will not receive a welcome email. Defaults to false +--email string Required. The email address for the new user account +--email-verified Optional. If supplied, the new user will have the email verified. Defaults to false +--firstname string Optional. The first name for the new user account +--guest Optional. If supplied, the new user will be a guest. Defaults to false +-h, --help help for create +--lastname string Optional. The last name for the new user account +--locale string Optional. The locale (ex: en, fr) for the new user account +--nickname string Optional. The nickname for the new user account +--password string Required. The password for the new user account +--system-admin Optional. If supplied, the new user will be a system administrator. Defaults to false +--username string Required. Username for the new user account +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user deactivate + +**Description** + +Deactivate users. Deactivated users are immediately logged out of all sessions and are unable to log back in. + +**Format** + +``` sh +mmctl user deactivate [emails, usernames, userIds] [flags] +``` + +**Examples** + +``` sh +mmctl user deactivate user@example.com +mmctl user deactivate username +``` + +**Options** + +``` sh +-h, --help help for deactivate +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user delete + +**Description** + +Permanently delete users along with all related information including posts from the database. + +<Note> + +Requires the [Enable API User Deletion](/administration-guide/configure/environment-configuration-settings#enable-api-user-deletion) configuration setting to be set to `true`. If this configuration setting is set to `false`, attempting to delete the user using mmctl fails. + +</Note> + +**Format** + +``` sh +mmctl user delete [users] [flags] +``` + +**Examples** + +``` sh +mmctl user delete user@example.com +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the user and a database backup has been performed +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user deleteall + +**Description** + +Permanently delete all users and all related information including posts. This command can only be run in [local mode](#local-mode). + +**Format** + +``` sh +mmctl user deleteall [flags] +``` + +**Examples** + +``` sh +mmctl user deleteall +``` + +**Options** + +``` sh +--confirm Confirm you really want to delete the user and a database backup has been performed +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user demote + +**Description** + +Demote a user to a guest. + +**Format** + +``` sh +mmctl user demote [users] [flags] +``` + +**Examples** + +``` sh +mmctl user demote user1 user2 +``` + +**Options** + +``` sh +-h, --help help for demote +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user edit + +**Description** + +Edit user properties including username, email, and authentication data. This command provides a structured way to modify user properties without direct database access. + +**Format** + +``` sh +mmctl user edit [user] [flags] +``` + +**Examples** + +``` sh +mmctl user edit testuser --help +``` + +**Options** + +``` sh +-h, --help help for edit +``` + +**Child Commands** + +- [mmctl user edit authdata](#mmctl-user-edit-authdata) - Edit user authentication data +- [mmctl user edit email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-email) - Edit user email address +- [mmctl user edit username](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-username) - Edit user username + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user edit authdata + +**Description** + +Edit user authentication data. This command addresses the common customer pain point where SAML-authenticated users need to change their authentication information when SAML configuration uses email as the ID attribute, eliminating the need for direct database manipulation. + +**Format** + +``` sh +mmctl user edit authdata [user] [authdata] [flags] +``` + +**Examples** + +``` sh +# Update SAML authentication data for a user +mmctl user edit authdata john.doe newsamlid@example.com + +# Clear authentication data for a user +mmctl user edit authdata john.doe "" +``` + +**Options** + +``` sh +-h, --help help for authdata +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user edit email + +**Description** + +Edit user email address. This command is particularly useful for SAML-authenticated users who need to change their email addresses when the SAML configuration uses email as the ID attribute. This provides a safer alternative to direct database manipulation. + +<Note> + +From Mattermost v10.9, email addresses enclosed in angle brackets (e.g., `[billy@example.com](mailto:billy@example.com)`) will be rejected. To avoid issues, ensure all user emails comply with the plain address format (e.g., `billy@example.com`). In addition, we strongly recommend taking proactive steps to audit and update Mattermost user data to align with this product change, as impacted users may face issues accessing Mattermost or managing their user profile. You can update these user emails manually using this mmctl command: `mmctl user edit email "[affecteduser@domain.com](mailto:affecteduser@domain.com)" affecteduser@domain.com`. + +</Note> + +**Format** + +``` sh +mmctl user edit email [user] [new email] [flags] +``` + +**Examples** + +``` sh +# Change email for a SAML-authenticated user +mmctl user edit email john.doe newemail@example.com + +# Update email for a user identified by current email +mmctl user edit email oldemail@example.com newemail@example.com +``` + +<Note> + +This command is especially important for SAML environments where email is used as the ID attribute. Previously, changing email addresses for SAML users required direct database manipulation, which posed security and operational risks. + +</Note> + +**Options** + +``` sh +-h, --help help for email +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user edit username + +**Description** + +Edit user username. This command allows changing usernames in a structured and safe manner without direct database access. + +**Format** + +``` sh +mmctl user edit username [user] [new username] [flags] +``` + +**Examples** + +``` sh +# Change username for a user +mmctl user edit username john.doe john.smith + +# Change username using email to identify user +mmctl user edit username user@example.com newusername +``` + +**Options** + +``` sh +-h, --help help for username +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user email + +This command is deprecated in favor of [mmctl user edit email](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-email). + +**Description** + +Change the email address associated with a user. + +<Note> + +From Mattermost v10.9, email addresses enclosed in angle brackets (e.g., `[billy@example.com](mailto:billy@example.com)`) will be rejected. To avoid issues, ensure all user emails comply with the plain address format (e.g., `billy@example.com`). In addition, we strongly recommend taking proactive steps to audit and update Mattermost user data to align with this product change, as impacted users may face issues accessing Mattermost or managing their user profile. You can update these user emails manually using this mmctl command: `mmctl user edit email "[affecteduser@domain.com](mailto:affecteduser@domain.com)" affecteduser@domain.com`. + +</Note> + +**Format** + +``` sh +mmctl user email [user] [new email] [flags] +``` + +**Examples** + +``` sh +mmctl user email testuser user@example.com +``` + +**Options** + +``` sh +-h, --help help for email +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user invite + +**Description** + +Send an email invite to a user to join a team. You can invite a user to multiple teams by listing them. You can specify teams by name or ID. + +**Format** + +``` sh +mmctl user invite [email] [teams] [flags] +``` + +**Examples** + +``` sh +mmctl user invite user@example.com myteam +mmctl user invite user@example.com myteam1 myteam2 +``` + +**Options** + +``` sh +-h, --help help for invite +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user list + +**Description** + +List all users. + +**Format** + +``` sh +mmctl user list [flags] +``` + +**Examples** + +``` sh +mmctl user list +``` + +**Options** + +``` sh +--all Fetch all users. --page flag will be ignore if provided +-h, --help help for list +--page int Page number to fetch for the list of users +--per-page int Number of users to be fetched (maximum 200) +--team string If supplied, only users belonging to this team will be listed +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user migrate-auth + +**Description** + +Migrate accounts from one authentication provider to another. For example, you can upgrade your authentication provider from email to LDAP. + +**Format** + +``` sh +mmctl user migrate-auth [from_auth] [to_auth] [migration-options] [flags] +``` + +**Arguments** + +> **from_auth:** +> The authentication service to migrate users accounts from. Supported options: email, gitlab, google, ldap, office365, saml. +> +> **to_auth:** +> The authentication service to migrate users to. Supported options: ldap, saml. +> +> **migration-options (ldap):** +> match_field: +> The field that is guaranteed to be the same in both authentication services. For example, if the users emails are consistent set to email. Supported options: email, username. +> +> **migration-options (saml):** +> **users_file:** +> The path of a json file with the usernames and emails of all users to migrate to SAML. The username and email must be the same that the SAML service provider store. And the email must match with the email in mattermost database. +> +> ``` javascript +> Example json content: +> { +> "usr1@email.com": "usr.one", +> "usr2@email.com": "usr.two" +> } +> ``` + +**Examples** + +``` sh +mmctl user migrate-auth email saml users.json +``` + +**user.json Example** + +``` json +[ + { + "email": "user1@example.com", + "auth_data": { + "saml": { + "idp_id": "saml_idp_1", + "saml_user_id": "user123" + } + } + }, + { + "email": "user2@example.com", + "auth_data": { + "saml": { + "idp_id": "saml_idp_2", + "saml_user_id": "user456" + } + } + } +] +``` + +**Options** + +``` sh +--auto Automatically migrate all users. Assumes the usernames and emails are identical between Mattermost and SAML services. (saml only) +--confirm Confirm you really want to proceed with auto migration. (saml only) +--force Force the migration to occur even if there are duplicates on the LDAP server. Duplicates will not be migrated. (ldap only) +-h, --help help for migrate-auth +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl user preference + +**Description** + +Manage user preferences. + +> Child Commands +> - [mmctl user preference get](#mmctl-user-preference-get) - Get a specific user preference +> - [mmctl user preference list](#mmctl-user-preference-list) - List user preferences +> - [mmctl user preference set](#mmctl-user-preference-set) - Set a specific user preference +> - [mmctl user preference delete](#mmctl-user-preference-delete) - Delete a specific user preference + +**Options** + +``` sh +-h, --help help for auth +``` + +### mmctl user preference get + +**Description** + +Get a specific user preference. + +**Format** + +``` sh +mmctl user preference get --category [category] --name [name] [users] [flags] +``` + +**Examples** + +``` sh +preference get --category display_settings --name use_military_time user@example.com +``` + +**Options** + +``` sh +-c, --category string The category of the preference +-h, --help help for get +-n, --name string The name of the preference +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user preference list + +**Description** + +List user preferences. + +**Format** + +``` sh +mmctl user preference list [--category category] [users] [flags] +``` + +**Examples** + +``` sh +preference list user@example.com +``` + +**Options** + +``` sh +-c, --category string The optional category by which to filter +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user preference set + +**Description** + +Set a specific user preference. + +**Format** + +``` sh +mmctl user preference set --category [category] --name [name] --value [value] [users] [flags] +``` + +**Examples** + +``` sh +preference set --category display_settings --name use_military_time --value true user@example.com +``` + +**Options** + +``` sh +-c, --category string The category of the preference +-h, --help help for set +-n, --name string The name of the preference +-v, --value string The value of the preference +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user preference delete + +**Description** + +Delete a specific user preference. + +**Format** + +``` sh +mmctl user preference delete --category [category] --name [name] [users] [flags] +``` + +**Examples** + +``` sh +preference delete --category display_settings --name use_military_time user@example.com +``` + +**Options** + +``` sh +-c, --category string The category of the preference +-h, --help help for delete +-n, --name string The name of the preference +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user promote + +**Description** + +Promote a guest to a user. + +**Format** + +``` sh +mmctl user promote [guests] [flags] +``` + +**Examples** + +``` sh +mmctl user promote guest1 guest2 +``` + +**Options** + +``` sh +-h, --help help for promote +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user reset-password + +**Description** + +Send users an email to reset their password. + +**Format** + +``` sh +mmctl user reset-password [users] [flags] +``` + +**Examples** + +``` sh +mmctl user reset-password user@example.com +``` + +**Options** + +``` sh +-h, --help help for reset-password +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user resetmfa + +**Description** + +Turn off multi-factor authentication for a user. If MFA enforcement is enabled, the user will be forced to re-enable MFA as soon as they log in. + +**Format** + +``` sh +mmctl user resetmfa [users] [flags] +``` + +**Examples** + +``` sh +mmctl user resetmfa user@example.com +``` + +**Options** + +``` sh +-h, --help help for resetmfa +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user search + +**Description** + +Search for users based on username, email, or user ID. The command returns user information including usernames, email addresses, first and last names, and account status. From Mattermost v10.10, output includes the user's deactivation status to help system admins identify inactive accounts. From Mattermost v10.11, output includes the user's AuthData field to help system admins verify authentication sources such as LDAP or SAML. + +**Format** + +``` sh +mmctl user search [users] [flags] +``` + +**Examples** + +``` sh +mmctl user search user1@mail.com user2@mail.com +``` + +**Options** + +``` sh +-h, --help help for search +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user username + +This command is deprecated in favor of [mmctl user edit username](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-edit-username) instead. + +**Description** + +Change the username of the user. + +**Format** + +``` sh +mmctl user username [user] [new username] [flags] +``` + +**Examples** + +``` sh +mmctl user username testuser newusername +``` + +**Options** + +``` sh +-h, --help help for version +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl user verify + +**Description** + +Mark user's email as verified without requiring user to complete email verification path. + +**Format** + +``` sh +mmctl user verify [users] [flags] +``` + +**Examples** + +``` sh +mmctl user verify user1 +``` + +**Options** + +``` sh +-h, --help help for version +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl version + +**Description** + +Print the version of mmctl. + +**Format** + +``` sh +mmctl version [flags] +``` + +**Options** + +``` sh +-h, --help help for version +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl webhook + +**Description** + +Manage webhooks. + +> Child Commands +> - [mmctl webhook create-incoming](#mmctl-webhook-create-incoming) - Create an incoming webhook +> - [mmctl webhook create-outgoing](#mmctl-webhook-create-outgoing) - Create an outgoing webhook +> - [mmctl webhook delete](#mmctl-webhook-delete) - Delete webhooks +> - [mmctl webhook list](#mmctl-webhook-list) - List webhooks +> - [mmctl webhook modify-incoming](#mmctl-webhook-modify-incoming) - Modify an incoming webhook +> - [mmctl webhook modify-outgoing](#mmctl-webhook-modify-outgoing) - Modify an outgoing webhook +> - [mmctl webhook show](#mmctl-webhook-show) - Show a webhook + +**Options** + +``` sh +-h, --help help for webhook +``` + +### mmctl webhook create-incoming + +**Description** + +Create an incoming webhook to allow external posting of messages to a specific channel. + +**Format** + +``` sh +mmctl webhook create-incoming [flags] +``` + +**Examples** + +``` sh +mmctl webhook create-incoming --channel [channelID] --user [userID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL] +``` + +**Options** + +``` sh +--channel string Channel ID (required) +--description string Incoming webhook description +--display-name string Incoming webhook display name +-h, --help help for create-incoming +--icon string Icon URL +--lock-to-channel Lock to channel +--user string User ID (required) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook create-outgoing + +**Description** + +Create an outgoing webhook to allow external posting of messages from a specific channel. + +**Format** + +``` sh +mmctl webhook create-outgoing [flags] +``` + +**Examples** + +``` sh +mmctl webhook create-outgoing --team myteam --user myusername --display-name mywebhook --trigger-word "build" --trigger-word "test" --url http://localhost:8000/my-webhook-handler + mmctl webhook create-outgoing --team myteam --channel mychannel --user myusername --display-name mywebhook --description "My cool webhook" --trigger-when start --trigger-word build --trigger-word test --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json" +``` + +**Options** + +``` sh +--channel string Channel name or ID +--content-type string Content-type +--description string Outgoing webhook description +--display-name string Outgoing webhook display name +-h, --help help for create-outgoing +--icon string Icon URL +--team string Team name or ID (required) +--trigger-when string When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word) (default "exact") +--trigger-word stringArray Word to trigger webhook (required) +--url stringArray Callback URL (required) +--user string The username, email, or ID of the user that the webhook should post as (required) +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook delete + +**Description** + +Delete a webhook with a given ID. + +**Format** + +``` sh +mmctl webhook delete [flags] +``` + +**Examples** + +``` sh +mmctl webhook delete [webhookID] +``` + +**Options** + +``` sh +-h, --help help for delete +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook list + +**Description** + +Print a list of all webhooks. + +**Format** + +``` sh +mmctl webhook list [flags] +``` + +**Examples** + +``` sh +mmctl webhook list myteam +``` + +**Options** + +``` sh +-h, --help help for list +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook modify-incoming + +**Description** + +Modify an existing incoming webhook by changing its title, description, channel, or icon URL. + +**Format** + +``` sh +mmctl webhook modify-incoming [flags] +``` + +**Examples** + +``` sh +mmctl webhook modify-incoming [webhookID] --channel [channelID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL] +``` + +**Options** + +``` sh +--channel string Channel ID +--description string Incoming webhook description +--display-name string Incoming webhook display name +-h, --help help for modify-incoming +--icon string Icon URL +--lock-to-channel Lock to channel +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook modify-outgoing + +**Description** + +Modify an existing outgoing webhook by changing its title, description, channel, icon, url, content-type, or triggers. + +**Format** + +``` sh +mmctl webhook modify-outgoing [flags] +``` + +**Examples** + +``` sh +mmctl webhook modify-outgoing [webhookId] --channel [channelId] --display-name [displayName] --description "New webhook description" --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json" --trigger-word test --trigger-when start +``` + +**Options** + +``` sh +--channel string Channel name or ID +--content-type string Content-type +--description string Outgoing webhook description +--display-name string Outgoing webhook display name +-h, --help help for modify-outgoing +--icon string Icon URL +--trigger-when string When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word) +--trigger-word stringArray Word to trigger webhook +--url stringArray Callback URL +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +### mmctl webhook show + +**Description** + +Show the webhook specified by `[webhookId]`. + +**Format** + +``` sh +mmctl webhook show [webhookId] [flags] +``` + +**Examples** + +``` sh +mmctl webhook show w16zb5tu3n1zkqo18goqry1je +``` + +**Options** + +``` sh +-h, --help help for show +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` + +## mmctl websocket + +**Description** + +Display websocket in a human-readable format. + +**Format** + +``` sh +mmctl websocket [flags] +``` + +**Options** + +``` sh +-h, --help help for websocket +``` + +**Options inherited from parent commands** + +``` sh +--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") +--disable-pager disables paged output +--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 +--insecure-tls-version allows to use TLS versions 1.0 and 1.1 +--json the output format will be in json format +--local allows communicating with the server through a unix socket +--quiet prevent mmctl to generate output for the commands +--strict will only run commands if the mmctl version matches the server one +--suppress-warnings disables printing warning messages +``` diff --git a/docs/main/administration-guide/manage/product-limits.mdx b/docs/main/administration-guide/manage/product-limits.mdx new file mode 100644 index 000000000000..df773cf78a2a --- /dev/null +++ b/docs/main/administration-guide/manage/product-limits.mdx @@ -0,0 +1,150 @@ +--- +title: "Product limits" +--- +<PlanAvailability slug="all-commercial" /> + +This page describes some of the product limits that apply to Mattermost, including hard and recommended limits. + +<table> +<thead> +<tr> +<th>Feature</th> +<th>Hard Limit</th> +<th>Recommended Limit</th> +</tr> +</thead> +<tbody> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fcreate-channels">Group messages</a></td> +<td>8 participants</td> +<td>If 8 isn't enough, create a private channel</td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fmake-calls">Call participants</a></td> +<td>Unlimited</td> +<td>50</td> +</tr> +<tr> +<td><a href="mm-ref:administration-guide%2Fconfigure%2Fcustom-branding-tools%3Acustom%20brand%20text">Custom brand text</a></td> +<td>500</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:administration-guide%2Fconfigure%2Fcustom-branding-tools%3Asite%20description">Custom site description</a></td> +<td>1024</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:administration-guide%2Fmanage%2Flogging%3Aadvanced%20logging">Advanced log output</a></td> +<td>500 MB file size, 1000 audit records</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fpreferences%2Fset-your-status-availability%3Aset%20a%20custom%20status">Custom status</a></td> +<td>100 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fchannel-header-purpose%3Achannel%20name">Channel name</a></td> +<td>64 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fchannel-header-purpose%3Achannel%20purpose">Channel purpose</a></td> +<td>250 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fchannel-header-purpose%3Achannel%20header">Channel header</a></td> +<td>1024 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fmanage-channel-bookmarks">Bookmarked links & files</a></td> +<td>50</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fmessage-priority%3Arequest%20acknowledgements">Message acknowledgement</a> response time</td> +<td>5 minutes</td> +<td></td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Forganize-using-custom-user-groups">Custom user group</a> notifications</td> +<td>256 users per group</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Freact-with-emojis-gifs%3Aquick%20emoji%20reactions">Emoji reactions</a> per message</td> +<td>50</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Freact-with-emojis-gifs%3Aupload%20custom%20emojis">Custom emoji uploads</a></td> +<td>6000</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fteam-settings%3Ateam%20description">Team description</a></td> +<td>50 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Asession%20length%20for%20sso">SSO user session duration</a></td> +<td>30 days</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:administration-guide%2Fconfigure%2Fenvironment-configuration-settings%3Asession%20length%20for%20mobile">Mobile user session duration</a></td> +<td>30 days</td> +<td></td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fshare-files-in-messages">Attachments per message</a> (files or images)</td> +<td>10</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fshare-files-in-messages%3Aattachment%20limits%20and%20sizes">Attachment file size</a></td> +<td>100 MB</td> +<td>Configurable</td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fshare-files-in-messages%3Aattachment%20limits%20and%20sizes">Attachment image file size</a></td> +<td>253 MB</td> +<td>Configurable</td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fshare-files-in-messages%3Aattachment%20limits%20and%20sizes">Attachment dimensions</a></td> +<td>7680 pixels x 4320 pixels</td> +<td>Configurable</td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Fshare-files-in-messages%3Aattachment%20limits%20and%20sizes">Attachment image resolution size</a></td> +<td>33 MP (mega pixels) or 8K resolution</td> +<td>Configurable</td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fpreferences%2Fmanage-your-profile">User nickname</a></td> +<td>64 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Fsend-messages">Message length</a></td> +<td>16,383 characters</td> +<td></td> +</tr> +<tr> +<td><a href="mm-ref:end-user-guide%2Fcollaborate%2Forganize-using-teams%3Acreate%20a%20team">Teams per deployment</a></td> +<td>10,000</td> +<td></td> +</tr> +<tr> +<td><a href="mm-doc:%2Fend-user-guide%2Fcollaborate%2Finvite-people">Users per team</a></td> +<td>No enforced limit</td> +<td>Dependent on infrastructure</td> +</tr> +</tbody> +</table> + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/manage/request-server-health-check.mdx b/docs/main/administration-guide/manage/request-server-health-check.mdx new file mode 100644 index 000000000000..0a58a7cbf52b --- /dev/null +++ b/docs/main/administration-guide/manage/request-server-health-check.mdx @@ -0,0 +1,39 @@ +--- +title: "Request a server Health Check" +--- +<PlanAvailability slug="entry-ent" /> + +The Mattermost Health Check is a comprehensive evaluation of your system's current operational health available to Mattermost Enterprise customers. + +This evaluation provides you with insights based on your system’s configuration, user activity, and log events that helps you proactively identify issues, enhance collaboration security, optimize resource utilization and scalability which leads to minimized downtime, improved performance, and significant cost savings for your Enterprise organization. + +<Tip> + +Want to configure your own server health check probes for your self-hosted Mattermost deployment? See the [configure server health check probes](/administration-guide/manage/configure-health-check-probes) documentation for details. + +</Tip> + +## Why request a Mattermost Health Check? + +Regularly assessing the health of your Mattermost environment ensures that: + +- System performance remains optimal, with minimal delays or downtime. +- User experience is consistently reliable, preventing missed messages or slow load times. +- Security and compliance settings are up-to-date and effective. +- Scalability aligns with your evolving usage patterns, supporting growth without issues. + +## Get started + +Getting started with a Mattermost Health Check is simple and involves 3 steps: + +1. [Generate a Support Packet](/administration-guide/manage/admin/generating-support-packet): The Mattermost Support Packet contains critical information about your Mattermost environment, including logs, configurations, and usage data. +2. Submit Your Support Packet: Once you’ve generated the Support Packet, submit it through our Support System as a [standard support request](https://support.mattermost.com/hc/en-us/requests/new). Please include “Health Check Provided” in the subject line. +3. Receive Your Health Check Report: Within 2 weeks of submitting your Support Packet, you will receive a comprehensive performance report. This report will include: + +- Detailed analysis of your current system health. +- Actionable recommendations to enhance performance, reliability, and security. +- Guidance on best practices for future system maintenance. + +## Get help + +If you have any questions or need assistance, contact your Customer Success Manager or Technical Account Manager, the [Mattermost Support Team](https://mattermost.com/support/), or visit the [Mattermost Help Center](https://support.mattermost.com/). diff --git a/docs/main/administration-guide/manage/statistics.mdx b/docs/main/administration-guide/manage/statistics.mdx new file mode 100644 index 000000000000..e4bd6eec45e6 --- /dev/null +++ b/docs/main/administration-guide/manage/statistics.mdx @@ -0,0 +1,150 @@ +--- +title: "Statistics" +--- +<PlanAvailability slug="all-commercial" /> + +Statistics on users, posts, and channels are tracked for each system and team. Enterprise Editions have access to advanced system statistics. + +<Note> + +To maximize performance for large enterprise deployments, statistics for total messages, total hashtag messages, total file messages, messages per day, and activated users with messages per day is configurable by changing the `MaxUsersForStatistics` value [in config.json](/administration-guide/configure/reporting-configuration-settings#maximum-users-for-statistics). + +</Note> + +For advanced metrics for Entry, Enterprise, and Enterprise deployments, [see performance monitoring documentation to learn more](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). + +## Site statistics + +System statistics are viewable under **System Console \> Reporting**. The data shown here is a cumulative sum across all teams on the system. + +Total Users +The total number of active accounts created on your system. Excludes deactivated accounts and single-channel guests. + +Single-channel Guests +The number of active guest accounts that belong to exactly one channel on the server. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. Single-channel guests are counted separately from the primary paid seat count and are free up to a 1:1 ratio with licensed seats. When this count exceeds the allowance, the statistic is highlighted as a warning for system admins. + +Total Teams +The total number of teams created on your system. + +Total Channels +The total number of public channels and private channels created in all the teams on your system, including deleted channels. Doesn't include direct message channels. + +Total Posts +The total number of posts made in all the teams on your system, including deleted posts and posts made using automation. + +Daily Active Users +The total number of users who viewed the Mattermost site in the last 24 hours. Excludes bot users. + +Monthly Active Users +The total number of users who viewed the Mattermost site in the last 30 days. Excludes bot users. + +Total Posts (graph) +The total number of posts made on a certain day in all the teams on your system, including deleted posts and posts made using automation. + +Total Posts from Bots (graph) +The total number of posts made by a [bot account](https://developers.mattermost.com/integrate/admin-guide/admin-bot-accounts/) on a certain day in all the teams on your system, including deleted posts and posts made using automation. + +Active Users with Posts (graph) +Users who made a post on a certain day in all the teams on your system, including system messages posted from the user's account. + +### Advanced system statistics + +<PlanAvailability slug="entry-ent" /> + +Self-hosted deployments include additional system statistics. + +Total Sessions +The number of active user sessions connected to your system. Expired sessions are not counted. + +Total Commands +The number of active slash commands currently set up on your system. Slash commands that are created and then removed in the **Integrations** menu are not counted. + +Incoming Webhooks +The number of active incoming webhooks currently setup on your system. Incoming webhooks that are created and then removed in the **Integrations** menu are not counted. + +Outgoing Webhooks +The number of active outgoing webhooks currently set up on your system. Outgoing webhooks that are created and then removed in the **Integrations** menu are not counted. + +WebSocket Conns +The number of active WebSocket connections currently on your server. + +Master DB Conns +The number of active connections currently on your master database. + +Replica DB Conns +The number of active connections currently on one or more of [your read replica databases](/administration-guide/scale/high-availability-cluster-based-deployment#database-configuration). + +Total Playbooks +The total number of collaborative playbooks on this server. + +Total Playbook Runs +The total number of runs (active and complete) on this server. + +Channel Types +This chart displays the number of public channels and private channels in a visual format, including channels that might have been deleted. + +Posts, Files and Hashtags +This chart displays the number of posts containing files, hashtags, or only text. Posts containing both files and hashtags are counted in both categories, and deleted posts are included. + +## Team statistics + +Team Statistics are viewable under **System Console \> Team Statistics**. The data shown here is a cumulative sum across this team only, and excludes posts made in Direct Message channels, which are not tied to a team. + +Total Users +The total number of active accounts on this team. Excludes deactivated accounts. + +Public Channels +The number of public channels created in this team. Excludes deleted channels. + +Private Channels +The number of private channels created in this team. Excludes deleted channels. + +Total Posts +The total number of posts made in this team, including deleted posts and posts made using automation. Excludes posts made in Direct Message channels, which are not tied to a team. + +Total Posts (graph) +The total number of posts made on a certain day in this team, including deleted posts and posts made using automation. + +Active Users with Posts (graph) +Users who made a post on a certain day in this team, including system messages posted from the user's account. + +Recent Active Users +Twenty most recent users who have logged in and had recent browser activity in Mattermost. + +Newly Created Users +Most recent users who have joined the team. + +## Troubleshooting/FAQ + +### I see an error: "Not enough data for a meaningful representation" + +If the statistics page is loading endlessly and you get an error message saying "Not enough data for a meaningful representation", check whether you're using an ad blocker. An ad blocker can prevent this page from loading data. To test this, temporarily disable your ad blocker, or view the page in a browser without an ad blocker installed. + +### Can team admins review their own team's statistics? + +<PlanAvailability slug="entry-ent" /> + +Yes. With self-hosted deployments, you can enable team admins to see their team's statistics by modifying available delegated granular administration system roles. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration) documentation to learn more about these admin roles, including how to manage privileges and assign roles. + +To enable team admins to access their team's statistics: + +1. Go to **System Console \> User Management \> System Roles**, then edit the **Viewer** system admin role. + +![Enable team admins to access their team's statistics in the System Console by going to User Management \> System Roles, and making changes to the Viewer role.](/images/edit-viewer-system-admin-role.png) + +2. Under **Privileges**, expand the **Reporting** section, set **Team Statistics** to **Read only**, then set **Site Statistics** and **Server Logs** to **No access**. +3. Set all other privileges to **No access** to restrict all users with the **Viewer** role to access only the **Team Statistics** page in the System Console. + +![On the Viewer page, restrict user access to the Team Statistics page by expanding the Reporting section, setting Site Statistics and Server Logs to No Access, and setting all other privileges to No Access.](/images/restrict-role-access.png) + +4. Under **Assigned People**, select **Add People** to assign team admins to the **Viewer** role, and enable them to access their team's statistics. + +![On the Viewer page, specify which users can access the Team Statistics page by assigning specific users the Viewer admin role.](/images/assign-people-to-system-role.png) + +5. Select **Save**. + +<Note> + +System admins must manually add people to or remove people from the **Viewer** system admin role to address team admin changes, such as promotions or demotions. + +</Note> diff --git a/docs/main/administration-guide/manage/system-wide-notifications.mdx b/docs/main/administration-guide/manage/system-wide-notifications.mdx new file mode 100644 index 000000000000..5fd0c6058cce --- /dev/null +++ b/docs/main/administration-guide/manage/system-wide-notifications.mdx @@ -0,0 +1,18 @@ +--- +title: "System-wide notifications" +--- +<PlanAvailability slug="all-commercial" /> + +System admins can configure system-wide notifications visibile in all channels for all users across all teams. + +![System admins can display an announcement banner in all channels.](/images/announcement-banner.png) + +1. Enable system-wide notifications by going to **System Console \> Site Configuration \> System-wide notifications**, and setting **Enable system-wide notifications** to **true**. +2. In the **Banner Text** field, enter the notification text you want to share in channels. +3. Specify the background and text colors for the banner. +4. By default, users can dismiss the banner until they log in again or until you update the banner. To prevent users from dismissing the banner, set **Allow Banner Dismissal** to **false**. +5. Select **Save**. + +Update the banner by either changing the text of the banner or by re-enabling the banner after it's been disabled. + +To disable the banner, set **Enable Announcement Banner** to **false**. diff --git a/docs/main/administration-guide/manage/team-channel-members.mdx b/docs/main/administration-guide/manage/team-channel-members.mdx new file mode 100644 index 000000000000..bf8f769b8e7d --- /dev/null +++ b/docs/main/administration-guide/manage/team-channel-members.mdx @@ -0,0 +1,139 @@ +--- +title: "Manage team and channel members" +--- +<PlanAvailability slug="all-commercial" /> + +System admins can manage channel configuration in the System Console, including: + +- **Management:** Manage synchronization, moderation, and membership settings. +- **Promoting/demoting Team and Channel Admins:** Team admins and channel admins can be demoted via the System Console. +- **View channel members:** System admins can view members of a channel without having to join the channel. +- **Member count:** Total member count in a team or channel. +- **Archive channels:** System admins can archive channels without having to join the channel. + +## Teams + +To view and manage team information, navigate to **System Console \> Teams**. Teams can be managed by **Group Sync** or **Invite Only**. The type of management in use may affect the management options available for that team. + +Select a team to view its configuration options. + +### Team profile + +The name and description of the team. + +System admins can archive or unarchive the team from within **User Management \> Teams \> Team Management**. Archiving a team makes its contents inaccessible for all users. All related information is archived, including posts from the database. Before archiving a team, we recommend that you perform a database backup. + +### Archive a team + +Select **Archive Team**, then select **Save**. Select **Archive** when prompted to confirm the team archive. + +Alternatively, system admins can use the mmctl `mmctl team archive` to archive teams. See the [mmctl product documentation](/administration-guide/manage/mmctl-command-line-tool#mmctl-team-archive) for details. + +### Unarchive a team + +Select **Unarchive Team**, then select **Save**. + +Alternatively, system admins can use the mmctl `mmctl team restore` to archive teams. See the [mmctl product documentation](/administration-guide/manage/mmctl-command-line-tool#mmctl-team-restore) for details. + +### Team management + +<PlanAvailability slug="entry-adv" /> + +- When **Sync Group Members** is enabled, the **Synced Groups** list is visible and additional groups can be added. +- When **Sync Group Members** is not enabled, invitation limitations can be selected. + +### Groups + +<PlanAvailability slug="entry-adv" /> + +You can add and remove groups, as well as promote or demote group members to team admin/member roles. + +### Members + +A list of all members in a channel is visible to system admins. Members can be added and removed from the team members and be promoted or demoted to a team admin/member role. Use the role **Filter** to refine your search results. You can use one filter, or combine filters to search by multiple roles: + +- Guest +- Member +- Team admin +- System admin + +## Channels + +To view and manage channel information, navigate to **System Console \> Channels**. Channels can be managed by **Group Sync** or **Manual Invites**. The type of management in use may affect the management options available for that channel. Use the **Filter** to refine your search results. You can use one filter, or combine filters to search by channel and management type: + +- Public channels +- Private channels +- Archived channels +- Channels that are synchronized to an AD/LDAP Group +- Channels with users who were invited manually (not synced from LDAP) + +Select a channel to view its configuration options. + +### Profile + +The name and description of the channel. To archive the channel, select **Archive Channel \> Save**. The channel is still searchable in the **Channels** list. To unarchive the channel, select **Unarchive Channel** and **Save**. + +### Channel management + +<PlanAvailability slug="entry-adv" /> + +- When **Sync Group Members** is enabled, the **Synced Groups** list is visible and additional groups can be added. +- When **Sync Group Members** is not enabled, you can select whether the channel is **Private** or **Public**. + +### Advanced access controls + +<PlanAvailability slug="entry-adv" /> + +Advanced access control settings enable system admins to restrict actions within specific channels. These actions include: + +- **Make channel read-only:** [Read-only channels](/administration-guide/onboard/advanced-permissions#read-only-channels) enable system admins to turn off posting in specified channels. +- **Restrict reactions:** Turn off the ability for members and guests to post reactions. +- **Restrict channel mentions:** Turn off the ability for users to post channel wide mentions (@all/@channel/@here) in specified channels. +- **Channel member management:** Only admins have the ability to add and remove channel members in the specified channels. +- **Bookmarks management:** Only channel and system admins can [manage channel bookmarks](/end-user-guide/collaborate/manage-channel-bookmarks). + +These settings are modified in **System Console \> User Management \> Channels**. + +<Note> + +These settings are applicable only to Guests and Members. System, team, and channel admins aren't affected. If you wish to grant posting ability to a specific member, you must first promote that member to channel admin. + +</Note> + +The availability of advanced access control settings can also be affected by existing system and team permissions configurations. If there are existing configurations that override the channel settings you would like to apply, it will be indicated in the user interface. These settings can then be adjusted in the relevant panel in the **Permissions** section of the System Console. + +**Configure a channel so that members can post/reply/react but guests can only read and react.** + +1. Navigate to **System Console \> User Management \> Channels**. +2. Select **Edit** next to the name of the channel you want to configure. +3. In the **Create Posts** panel, uncheck **Guests**. +4. In the **Post Reactions** panel, uncheck **Guests** if required. +5. Select **Save**. + +The channel is available for all members and guests to access, but guests can only read messages and react to them. + +**Create an Announcement Channel where only Channel Admins are able to post (read-only).** + +1. Create a new channel (either Public or Private). +2. Navigate to **System Console \> User Management \> Channels**. +3. Select **Edit** next to the name of the channel you just created (you may need to search for it). +4. In the **Create Posts** panel, uncheck **Guests** and **Members**. +5. In the **Post Reactions** panel, uncheck **Guests** and **Members**. +6. Select **Save**. + +The channel is available for all members and guests to access but only Admins can post to the channel. + +### Groups + +<PlanAvailability slug="entry-adv" /> + +You can add and remove groups, as well as promote or demote group members to team admin/member roles. + +### Members + +A list of all members in a channel is visible to system admins. Members can be added and removed from the team members and be promoted or demoted to a team admin/member role. Use the role **Filter** to refine your search results. You can use one filter, or combine filters to search by multiple roles: + +- Guest +- Member +- Channel admin +- System admin diff --git a/docs/main/administration-guide/manage/telemetry.mdx b/docs/main/administration-guide/manage/telemetry.mdx new file mode 100644 index 000000000000..dccc0b5cca24 --- /dev/null +++ b/docs/main/administration-guide/manage/telemetry.mdx @@ -0,0 +1,215 @@ +--- +title: "Telemetry" +--- +As described in the privacy policy in each Mattermost server, telemetry data optionally shared from your Mattermost servers is used to identify security and reliability issues, to analyze and fix software problems, to help improve the quality of Mattermost software and related services, and to make design decisions for future releases. + +Telemetry data is encrypted in transit, does not include personally identifiable information or message contents, and details of how the information is used and processed is available in our [Privacy Policy](https://mattermost.com/privacy-policy/). + +We use the data for the following purposes to: + +- Identify security and reliability issues. +- Analyze and fix software problems. +- Help improve the quality of Mattermost software and related services. +- Make design decisions for future releases. + +<Note> + +Telemetry data collection is enabled by default for all Mattermost deployments. Self-hosted system admins can opt out of sharing telemetry data from Mattermost self-hosted servers within the System Console. Cloud system admins can't disable telemetry for Mattermost Cloud deployments. + +</Note> + +## Security update check feature + +New threats to system security constantly arise. To alert you of relevant, high priority security updates, Mattermost servers are configured to share diagnostic information with Mattermost Inc. so that we can provide appropriate alerts. + +The following data is collected once every 24 hours: + +- Mattermost server build number and version +- Type of build (Enterprise Edition or Team Edition) +- Server operating system +- The server diagnostic ID (same as the ID accessing the push notification proxy, and is used to prevent double-counting of telemetry data) +- Database type +- Database version +- Number of teams +- Number of users +- Number of activated users +- Whether or not the unit tests have been run +- Date and time of the last check for security updates +- The location of the Amazon Cloudfront server used for telemetry data + +### Opt out + +To opt out, you can disable this security update check feature for self-hosted deployments in the System Console by going to **Environment \> SMTP \> Enable Security Alerts**. See the [enable security alerts](/administration-guide/configure/environment-configuration-settings#enable-security-alerts) documentation for details. When this feature is disabled, you will not receive any security alerts. + +## Error and diagnostics reporting feature + +Mattermost error and diagnostic data is collected for the following purposes: + +- To add improvements that are specific to your usage, upgrade, and deployment patterns, including identifying security and reliability issues. +- To analyze and fix software problems. +- To help improve the quality of Mattermost software and related services. +- To make design decisions for future releases. + +<Note> + +Error and diagnostic reporting is sent by Mattermost to the endpoint `https://pdat.matterlytics.com`, a custom Rudder domain. When this feature is enabled, any 500 errors will automatically be sent to the Mattermost-hosted [Sentry](https://sentry.io/welcome/) endpoint. + +</Note> + +### Opt out + +To opt out, you can disable the error and diagnostics reporting feature for self-hosted deployments in the System Console by going to **Environment \> Logging \> Enable Diagnostics and Error Reporting**. See the [enable diagnostics and error reporting](/administration-guide/configure/environment-configuration-settings#enable-diagnostics-and-error-reporting) documentation for details. + +### Deployment and server configuration data + +Reporting frequency + +- When starting the server for the first time: Every 10 minutes for the first hour, then every hour for the first 12 hours. +- At the 24 hour mark and every 24 hours thereafter. + +Deployment configuration information + +> Basic information including Mattermost server version, database and operating system type and version, and count of system admin accounts. + +Deployment type + +- Manual install (includes `wget` installs) +- Docker +- Mattermost Omnibus +- Kubernetes operator +- GitLab Omnibus + +Server Configuration Settings +Non-personally identifiable data from configuration settings file (`config.json`) in the form of `type` ("enumerated integer" or "enumerated boolean") values, `true/false` ("boolean"), and `count` ("integer"). Specifically these include: + +**Type values (enumerated integer and enumerated boolean)** + +**ServiceSettings**: enum WebserverMode, bool EnableSecurityFixAlert, bool EnableInsecureOutgoingConnections, bool EnableIncomingWebhooks, bool EnableOutgoingWebhooks, bool EnableCommands, bool EnableDeveloper, bool EnableOnlyAdminIntegrations, bool EnablePostUsernameOverride, bool EnablePostIconOverride, bool EnableCustomEmoji, enum RestrictCustomEmojiCreation, bool EnableTesting, bool DeveloperFlags, bool EnableClientPerformanceDebugging, bool EnableMultifactorAuthentication, bool EnableOAuthServiceProvider, enum OutgoingIntegrationRequestsDefaultTimeout, enum ConnectionSecurity, bool UseLetsEncrypt, bool Forward80To443, enum ConnectionSecurity, bool TLSStrictTransport, bool EnforceMultifactorAuthentication, bool EnableUserTypingMessages, bool TimeBetweenUserTypingUpdatesMilliseconds, bool EnablePostSearch, bool EnableUserStatuses, bool EnableChannelViewMessages, bool EnableEmojiPicker, bool EnableGifPicker, bool EnableAuthenticationTransfer, enum TeammateNameDisplay, bool EnableUserAccessTokens, enum MaximumLoginAttempts, bool ExtendSessionLengthWithActivity, enum SessionLengthWebInHours, enum SessionLengthMobileInHours, enum SessionLengthSSOInHours, int SessionCacheInMinutes, enum SessionIdleTimeoutInMinutes, enum TimeBetweenUserTypingUpdatesMilliseconds, enum ClusterLogTimeoutMilliseconds, bool CloseUnusedDirectMessages, bool EnablePreviewFeatures, bool EnableTutorial, bool EnableOnboarding, bool ExperimentalEnableDefaultChannelLeaveJoinMessages, bool ExperimentalGroupUnreadChannels, bool AllowCookiesForSubdomains, bool EnableAPITeamDeletion, bool EnableAPITriggerAdminNotifications, bool EnableAPIUserDeletion, bool EnableAPIChannelDeletion, bool ExperimentalEnableHardenedMode, bool DisableLegacyMFA, bool ExperimentalStrictCSRFEnforcement, bool EnableEmailInvitations, bool ExperimentalChannelOrganization, bool EnableLegacySidebar, bool CorsAllowCredentials, bool CorsDebug, bool DisableBotsWhenOwnerIsDeactivated, bool EnableBotAccountCreation, bool RestrictLinkPreviews, bool EnablePermalinkPreviews, bool EnableSVGs, bool EnableLatex, bool EnableInlineLatex, bool Directory, bool RetentionDays, bool EnableLocalMode; **TeamSettings**: bool EnableUserCreation, bool EnableTeamCreation, bool RestrictTeamNames, bool EnableOpenServer, bool EnableUserDeactivation, bool EnableCustomBrand, bool RestrictDirectMessage, enum MaxNotificationsPerChannel, bool EnableConfirmNotificationsToChannel; enum MaxUsersPerTeam, enum MaxChannelsPerTeam, bool EnableJoinLeaveMessageByDefault, bool EnableCustomUserStatuses, bool EnableLastActiveTime, bool RefreshPostStatsRunTime, bool ExperimentalTownSquareIsReadOnly, bool ExperimentalHideTownSquareinLHS, bool EnableXToLeaveChannelsFromLHS, bool ExperimentalEnableAutomaticReplies, bool ExperimentalViewArchivedChannels, bool LockTeammateNameDisplay, bool MaxFieldSize; **ClientRequirementSettings**: enum AndroidLatestVersion; **GuestAccountsSettings**: bool Enable, bool AllowEmailAccounts, bool EnforceMultifactorAuthentication; **SqlSettings**: enum DriverName, bool Trace, enum ConnMaxIdleTimeMilliseconds, bool ConnMaxLifetimeMilliseconds; enum MaxOpenConns, enum QueryTimeout, bool DisableDatabaseSearch; **LogSettings**: bool EnableConsole, enum ConsoleLevel, bool ConsoleJson, bool EnableFile, enum FileLevel, bool FileJson, bool EnableWebhookDebugging; **NotificationLogSettings**: bool EnableConsole, bool ConsoleLevel, bool ConsoleJson, bool EnableFile, bool FileLevel, bool FileJson **PasswordSettings**: bool Lowercase, bool Number, bool Uppercase, bool Symbol, enum MinimumLength; **FileSettings**: bool EnablePublicLink, enum DriverName, enum MaxFileSize, enum FileSettings.MaxImageResolution, enum MaxImageDecoderConcurrency, bool FileSettings.ExtractContent, bool FileSettings.ArchiveRecursion, bool AmazonS3SSL, bool AmazonS3SignV2, bool AmazonS3SSE, bool AmazonS3Trace, bool MaximumPayloadSizeBytes, bool MaximumPayloadSizeBytes, bool EnableFileAttachments, bool EnableMobileUpload, bool EnableMobileDownload; **EmailSettings**: bool EnableSignUpWithEmail, bool EnableSignInWithEmail, bool EnableSignInWithUsername, bool RequireEmailVerification, bool SendEmailNotifications, bool UseChannelInEmailNotifications, bool EmailNotificationContentsType, bool EnableSMTPAuth, enum ConnectionSecurity, bool SendPushNotifications, enum PushNotificationContents, bool EnableEmailBatching, bool SkipServerCertificateVerification, enum EmailBatchingBufferSize, enum EmailBatchingInterval, bool EnablePreviewModeBanner, enum SMTPServerTimeout; **MessageExportSettings**: bool DownloadExportResults; **RateLimitSettings**: bool EnableRateLimiter, bool VaryByRemoteAddr, bool VaryByUser, enum PerSec, enum MaxBurst, enum MemoryStoreSize; **PrivacySettings**: bool ShowEmailAddress, bool ShowFullName; **ThemeSettings**: bool EnableThemeSelection, bool AllowCustomThemes; **GitLabSettings**: bool Enable; **GoogleSettings**: bool Enable; **Office365Settings**: bool Enable; **SupportSettings**: bool CustomTermsOfServiceEnabled, enum CustomTermsOfServiceReAcceptancePeriod, enum ReportAProblemType; **LdapSettings**: bool Enable, bool EnableSync, enum ConnectionSecurity, bool SkipCertificateVerification, enum SyncIntervalMinutes, enum QueryTimeout, enum MaxPageSize, bool EnableAdminFilter; **ComplianceSettings**: bool Enable, bool EnableDaily; **LocalizationSettings**: enum DefaultServerLocale, enum DefaultClientLocale, enum AvailableLocales; **SamlSettings**: bool Enable, bool EnableSyncWithLdap, bool IgnoreGuestsLdapSync, bool EnableSyncWithLdapIncludeAuth, bool Verify, bool Encrypt, bool SignRequest, bool EnableAdminFilter; **ClusterSettings**: bool Enable, bool UseIpAddress, bool ReadOnlyConfig, bool EnableExperimentalGossipEncryption, bool EnableGossipCompression; **MetricsSettings**: bool Enable, bool EnableClientMetrics, bool EnableNotificationMetrics, enum BlockProfileRate; **WebrtcSettings** (only in v5.5 and earlier): bool Enable; **ExperimentalSettings** bool ClientSideCertEnable, bool EnablePostMetadata, bool LinkMetadataTimeoutMilliseconds, bool EnableClickToReply, bool RestrictSystemAdmin, bool CloudBilling, bool AllowSyncedDrafts, bool YoutubeReferrerPolicy; **AnnouncementSettings**: bool EnableBanner, bool AllowBannerDismissal, bool AdminNoticesEnabled, bool UserNoticesEnabled; **ElasticsearchSettings**: bool EnableIndexing, bool EnableSearching, bool Sniff, enum PostIndexReplicas, enum PostIndexShards, enum LiveIndexingBatchSize, enum BatchSize, bool SkipTLSVerification, bool Trace; **PluginSettings**: bool Enable, bool EnableUploads, bool EnableHealthCheck, bool EnableMarketplace, bool EnableRemoteMarketplace, bool AutomaticPrepackagedPlugins, bool RequirePluginSignature; **DataRetentionSettings**: bool EnableMessageDeletion, bool MessageRetentionHours, bool AllowInsecureDownloadUrl, bool EnableFileDeletion, bool FileRetentionHours, enum DeletionJobStartTime; **MessageExportSettings**: bool EnableExport, enum ExportFormat, enum DailyRunTime, enum ExportFromTimestamp, enum BatchSize, enum GlobalRelaySettings.CustomerType; **ExperimentalAuditSettings**: bool SysLogEnabled, bool SysLogInsecure, enum SysLogMaxQueueSize, bool FileEnabled, enum FileMaxSizeMB, enum FileMaxAgeDays, bool FileMaxBackups, bool FileCompress, enum FileMaxQueueSize; **BleveSettings**: bool EnableIndexing, bool EnableSearching, bool EnableAutocomplete, enum BatchSize; bool FeatureFlags + +**Counts (integer)** + +> **SqlSettings**: int DataSourceReplicas, int DataSourceSearchReplicas, int ReplicaLagSettings; **ThemeSettings**: int AllowedThemes; **PluginSettings**: int SignaturePublicKeyFiles + +**True/false (boolean)** value whether setting remains default (true) or non-default (false). **NOTE: No input data is used**: + +> **ServiceSettings**: bool SiteURL, bool WebsocketURL, bool TLSCertFile, bool TLSKeyFile, bool ReadTimeout, bool WriteTimeout,bool IdleTimeout, bool GoogleDeveloperKey, bool AllowCorsFrom, bool CorsExposedHeaders, bool AllowedUntrustedInternalConnections, bool ManagedResourcePaths, bool CollapsedThreads, bool PostPriority, bool AllowPersistentNotifications, bool PersistentNotificationMaxCount, bool PersistentNotificationIntervalMinutes, bool PersistentNotificationMaxRecipients; **TeamSettings**: bool SiteName, bool CustomBrandText, bool CustomDescriptionText, bool UserStatusAwayTimeout, bool ExperimentalPrimaryTeam; **DisplaySettings**: bool CustomUrlSchemes, bool MaxMarkdownNodes; **GuestAccountSettings**: bool RestrictCreationToDomains, bool EnforceMultifactorAuthentication, bool HideTags; **LogSettings**: bool FileLocation; **NotificationLogSettings**: bool FileLocation; **EmailSettings**: bool FeedbackName, bool FeedbackEmail, bool FeedbackOrganization, bool LoginButtonColor, bool LoginButtonBorderColor, bool LoginButtonTextColor, bool ImageProxyType, bool ImageProxyURL, bool ImageProxyOptions; **RateLimitSettings**: bool VaryByHeader; **SupportSettings**: bool TermsOfServiceLink, bool PrivacyPolicyLink, bool AboutLink, bool HelpLink, bool ReportAProblemLink, bool AllowDownloadLogs, bool AppCustomURLSchemes, bool MobileExternalBrowser bool SupportEmail; **ThemeSettings**: bool DefaultTheme; **LdapSettings**: bool FirstNameAttribute, bool LastNameAttribute, bool EmailAttribute, bool UserNameAttribute, bool NicknameAttribute, bool IdAttribute, bool PositionAttribute, bool LoginFieldName, bool LoginButtonColor, bool LoginButtonBorderColor, bool LoginButtonTextColor, bool GroupFilter, bool GroupDisplayNameAttribute, bool GroupIdAttribute, bool GuestFilter, bool AdminFilter; **SamlSettings**: bool SignatureAlgorithm, bool CanonicalAlgorithm, bool ScopingIDPProviderId, bool ScopingIDPName, bool IdAttribute, bool GuestAttribute, bool FirstNameAttribute, bool LastNameAttribute, bool EmailAttribute, bool UserNameAttribute, bool NicknameAttribute, bool LocaleAttribute, bool PositionAttribute, bool LoginIdAttribute, bool LoginButtonText, bool LoginButtonColor, bool LoginButtonBorderColor, bool LoginButtonTextColor, bool AdminFilter; **NativeAppSettings**: bool AppDownloadLink, bool AndroidAppDownloadLink, bool IosAppDownloadLink; **WebrtcSettings** (only in v5.5 and earlier): bool StunURI, bool TurnURI; **ClusterSettings**: bool NetworkInterface, bool BindAddress, bool AdvertiseAddress; **MetricsSettings**: bool BlockProfileRate; **AnalyticsSettings**: bool MaxUsersForStatistics; **ExperimentalSettings** bool ClientSideCertCheck; **AnnouncementSettings**: bool BannerColor, bool BannerTextColor; **ElasticsearchSettings**: bool ConnectionUrl, bool Username, bool Password, bool IndexPrefix; **PluginSettings**: bool MarketplaceUrl, bool SignaturePublicKeyFiles, bool ChimeraOAuthProxyUrl; **MessageExportSettings**: bool GlobalRelaySettings.SmtpUsername, bool GlobalRelaySettings.SmtpPassword, bool GlobalRelaySettings.EmailAddress; **ConnectedWorkspacesSettings**: bool EnableSharedChannels, bool EnableRemoteClusterService, bool DisableSharedChannelsStatusSync, bool DefaultMaxPostsPerSync. + +Commercial License Information (Enterprise Edition only) +Information about commercial license key purchased or trial license key used for Enterprise Edition servers: Company ID, license ID, license issue date, license start date, license expiry date, number of licensed users, license name, list of unlocked subscription features. + +Advanced Access Controls Configuration Information (Enterprise Edition only) +Information related to channel moderation, including number of channel schemes, number of channels with posting messages disabled for users or guests, number of channels with emoji reactions disabled for users or guests, number of channels with managing members disabled, number of channels with channel mentions disabled for users or guests. + +Channel Member Management Information (Enterprise Edition only) +Information related to bulk user management and team and channel filtering, including number of users added, number of users removed, number of users promoted, number of users demoted, number of times archive and unarchive is used from any channel configuration page, and number of times channel search or team search filters are used. + +Groups Configuration Information (Enterprise Edition only) +Information related to AD/LDAP groups, including number of groups synced to Mattermost, teams and channels associated to groups, teams and channels synced with groups, and number of group members. + +Plugin Configuration Information +Basic information including number of active and inactive plugins, which are using webapp or backend portions, which Mattermost plugins are enabled along with their versions, and core plugins disabled count. Some plugins may send summary data such as number of authenticated users of the plugin. The list of plugins is obtained from the Marketplace. If the Marketplace can't be reached, the list of known plugins is used instead. + +Permissions Configuration Information (Enterprise Edition only) +Permissions configured for each role for the System Scheme and each Team Override Scheme created in the system. Scheme ID; team admin permissions; team user permissions; channel admin permissions; channel user permissions; number of teams the scheme is associated with; number of users assigned to each admin role; Number of admin roles not using default privileges; Changes to default privileges of each admin role. + +Aggregated Usage Statistics +Non-personally identifiable summations of basic usage statistics: Number of enabled and disabled accounts, number of user logins in the last 24 hours and the last 30 days, number of users active in the last day/month, whether APIv3 endpoints were used in the last 24 hours, number of posts, channels, teams, guest accounts, bots, and file storage. + +True Up Diagnostics +Requested help from sales with license true up; attempted to download true up packet. + +### Event data + +Reporting Frequency +- Immediately after the specific event occurs. + +<Note> + +The majority of these events have been disabled. Refer to the source file for the [current list of events sent via telemetry](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts#L3069). + +</Note> + +Non-personally Identifiable Error Information, distinguished by end users and system admins +Boolean when the following events occur: + +- *Sign-in Error*: Email login error, AD/LDAP login error, SAML login error + +Boolean when the following events occur, including the error message, recently dispatched Redux actions, and non-identifiable information of the device, operating system, and the app: + +- *Mobile App Errors*: App crashes caused by type errors, exceptions, and failed logins + +Non-personally Identifiable Diagnostic Information, distinguished by end users and system admins +Boolean when the following events occur: + +- *Team and Account Setup Diagnostics:* Account creation via email, invite or UI, account creation page view, account creation completion; tutorial step and tip completion or opt out, team creation page view, team name and URL entry, team creation completion, clicks on all form elements, buttons, textboxes and links on sign up page, team selection page, and team creation pages +- *Sign-in Diagnostics:* Login succeeded or failed for email, LDAP, or SAML/SSO; logout succeeded; switched authentication method from email to LDAP or SAML/SSO or vice versa; reset password; updated password +- *Navigation Discovery Diagnostics:* Joined a channel from the "More" list, through an invite or by clicking a public link; created a channel, direct, or group direct message conversation; renamed, joined, left or deleted an existing channel; updated header or purpose; added or removed members; updated channel notification preferences; loaded more messages in a channel; switched a channel or a team; opened the "More" modal for channels or direct message conversations; updated team name; invited members; updated profile and Channels settings +- *Core Feature Discovery Diagnostics:* Created, edited or deleted a message; posted a message containing a hashtag, link, mention or file attachment; searched for a term; searched for saved posts or recent mentions +- *Advanced Feature Discovery Diagnostics:* Reacted to a message; favorited or unfavorited a channel; saved or unsaved a message; pinned or unpinned a message; replied to a message; expanded the right-hand sidebar; started or finished a WebRTC video call (only in v5.5 and earlier); created or deleted a personal access token; added or removed post:all or post:channels permission; created a category in the sidebar +- *Integration Discovery Diagnostics:* Created or triggered a webhook or slash command; created, authorized or deleted an OAuth 2.0 app; created, posted, or deleted a custom emoji +- *Plugin Discovery Diagnostics:* Number of installed plugins containing either server or webapp portions, or both; number of those plugins being activated +- *Plugin Marketplace Diagnostics:* Plugin ID, current version, and target version for all install and update events. Only sent when the default Marketplace is configured +- *Plugin telemetry:* Search terms used in Marketplace on cloud workspaces will be recorded +- *Commercial License Diagnostics (Enterprise Edition only):* Uploaded an Enterprise license key to the server +- *Mobile Performance Diagnostics:* Load times for starting the app, switching channels, and switching teams +- *Permissions Discovery Diagnostics (Enterprise Edition only):* Provides all the permissions configured for each role for the System Scheme and each Team Override Scheme created in the system. Scheme ID; team admin permissions; Team user permissions; channel admin permissions; Channel user permissions; Number of teams the scheme is associated with +- *Group Discovery Diagnostics:* Provides information related to AD/LDAP (Enterprise Edition only) and custom groups (Enterprise and Professional Edition only), including number of unique users in groups, number of groups synchronized to Mattermost, teams and channels associated to groups, teams and channels synchronized with groups, number of group members, custom group @mentions, changes to existing custom groups, and new custom groups created. +- *System Console Menu Discovery Diagnostics:* Clicks on the hamburger menu items of the System Console, including Administrator's Guide, Troubleshooting Forum, Commercial Support, About Mattermost, and clicks on the left-hand side navigation menu items +- *In Product Notices Diagnostics:* Notices viewed, and the notices on which an action button was clicked. +- *Threaded discussions:* Clicks to reply to a thread, reply using the footer element, filter threads by unread, mark as read, access to global threads section. +- *Custom Groups:* Invite people to a channel by using a custom group, mention a custom group, and modify a custom group. +- *Read-Only Channels:* Navigate to a read-only channel, post a message to a read-only channel, and open a read-only channel. +- *Shared Workspaces:* Navigate to a shared channel, post a message in a shared channel, and mention a remote user. +- *Guest Accounts:* Mention a guest account, directly message a guest, and add a guest to a channel. +- *Passive Keyword Tracking*: Update passive keywords highlighted in channels and threads. + +## Playbooks telemetry + +Collaborative playbooks metadata is collected and sent every 24 hours. Visit the [playbooks telemetry file](https://github.com/mattermost/mattermost-plugin-playbooks/blob/master/server/telemetry/rudder.go) for details about the types of metadata collected. + +## Android Mobile App performance monitoring + +To improve Android app performance, we are collecting trace events and device information, collectively known as metrics, to identify slow performing key areas. Those metrics will be sent only from users using the Android app Beta build starting in version v1.20, who are logged in to servers that allow sending [diagnostic information](/administration-guide/configure/environment-configuration-settings#enable-diagnostics-and-error-reporting). + +Trace events +Includes duration on how long the action took place like startup, team/channel switch, posts loading/update and channel drawer open/close. The naming convention is interpreted as `[start observation]:[end observation]`, e.g. `start:overall` as from app start until fully rendered or `post_list:thread` as on press of post at post list until thread is opened. Complete list of trace events are the following: + +- start:overall +- start:process_packages +- start:content_appeared +- start:select_server_screen +- start:channel_screen +- team:switch +- channel:loading +- channel:switch_loaded +- channel:switch_initial +- channel:close_drawer +- channel:open_drawer +- posts:loading +- post_list:thread +- post_list:permalink + +Device information +The information being collected is non-personally identifiable. Except for system_version, device information is based from [react-native-device-info](https://github.com/mattermost/react-native-device-info#react-native-device-info) library. Refer to the linked documentation to learn more. Complete list of device information are the following: + +- api_level +- build_number +- bundle_id +- brand +- country +- device_id +- device_locale +- device_type +- device_unique_id +- height +- is_emulator +- is_tablet +- manufacturer +- max_memory +- model +- server_version +- system_name +- system_version +- timezone +- version +- width diff --git a/docs/main/administration-guide/manage/user-satisfaction-surveys.mdx b/docs/main/administration-guide/manage/user-satisfaction-surveys.mdx new file mode 100644 index 000000000000..570f2c03e5ff --- /dev/null +++ b/docs/main/administration-guide/manage/user-satisfaction-surveys.mdx @@ -0,0 +1,85 @@ +--- +title: "User satisfaction surveys" +--- +<PlanAvailability slug="all-commercial" /> + +Feedback is used to measure user satisfaction and improve product quality by hearing directly from users. Please refer to our [privacy policy](https://mattermost.com/privacy-policy/) for information on the collection and use of information received through our services. + +<Important> + +**Mattermost User Satisfaction Surveys are deprecated from Mattermost v10.11** and are no longer included as a pre-packaged plugin for new Mattermost deployments. Existing deployments that have this plugin enabled will continue to work, but we strongly recommend migrating to [user surveys](/administration-guide/configure/manage-user-surveys) for enhanced customization options, and local data storage, without telemetry data transmission back to Mattermost. + +</Important> + +## Administration + +### Is the survey enabled by default? + +**For Mattermost Server versions prior to v10.11**: The user satisfaction survey is a pre-packaged plugin, and surveys are enabled by default on all servers. However, the plugin will not be activated on any servers that have [Error and Diagnostic Reporting](/administration-guide/manage/telemetry) disabled, meaning no surveys or data collection occurs. + +**For Mattermost Server v10.11 and later**: The User Satisfaction Survey Plugin is no longer included as a pre-packaged plugin for new deployments. We recommend using the [Mattermost User Survey integration](/administration-guide/configure/manage-user-surveys) instead. + +### How can surveys be disabled? + +Disabling the **User Satisfaction Surveys** plugin from **System Console \> Plugins \> Plugin Management** will disable surveys and all data collection by the plugin. + +<Note> + +- If surveys have been disabled from the plugin configuration in **System Console \> Plugins \> User Satisfaction Surveys**, but the plugin itself is still enabled, surveys won't be scheduled but users can still send written feedback by messaging Surveybot. +- When the plugin or surveys in the plugin configuration are disabled, they remain disabled for subsequent server upgrades. + +</Note> + +### When is the survey scheduled? + +Users will receive surveys 21 days after every server upgrade, assuming the following conditions are true: + +- User Satisfaction Surveys plugin is enabled in **System Console \> Plugins \> Plugin Management**. +- Surveys are enabled in the plugin configuration in **System Console \> Plugins \> User Satisfaction Surveys**. +- User account is greater than 21 days old. +- User has not completed a survey in the last 90 days. +- User has not been sent a survey in the last 90 days. +- Current server version is greater than the server version of the last survey, excluding dot releases. + +The above conditions mean that at maximum frequency a user will receive a survey every 90 days, assuming the server is upgraded within that time period. + +### How will I be notified when a survey is scheduled? + +System admins will receive an email notification and in-product direct message from "Surveybot" mentioning the scheduled date the survey will be triggered. + +![When user satisfaction surveys are enabled in the System Console, Mattermost sends out user satisfaction surveys following every server upgrade. System admins are notified about upcoming surveys by email notification and through an in-product message from a system bot.](/images/nps-admin.png) + +## Survey Data + +### How is the survey received? + +Once the survey is triggered on the server, all users will receive an in-product direct messages from "Surveybot" on their next login or page refresh in Mattermost. + +Users can optionally select a 0-10 score on how likely they are to recommend Mattermost and then provide written feedback about their experience. Selecting a score and providing feedback are optional, and the survey can be ignored without interrupting usage of Mattermost. + +![Once Mattermost sends out a user satisfaction survey, all users receive an in-product message from a system bot the next time they log in or refresh Mattermost. The in-product message asks users to rate how likely they'd recommend Mattermost.](/images/nps-survey.png) + +### What data is collected? + +Data is only collected when a user selects a score or provides written feedback in response to survey questions. Please refer to our [privacy policy](https://mattermost.com/privacy-policy/) for more information on the collection and use of information received through our services. The following **non-personally identifiable information** is collected: + +- Survey information: + - Score (0-10) submitted by the user + - Written feedback submitted by the user (if applicable) + - Timestamp of the survey submission + +- Server information: + - Server/Web App version the survey was submitted on + - Installation date of the server + - Diagnostic ID used for error and diagnostics reporting + - License ID used for error and diagnostics reporting (if applicable) + - Enterprise or Professional (if applicable) + +- User information: + - User role (system admin, team admin, or member) + - Account creation timestamp + - User ID of the surveyed user + +### Will this data be sent through my firewall? + +If Mattermost is self-hosted in a private network with firewall then data from the User Satisfaction Surveys plugin is not sent unless outbound connections are allowed or specifically configured for this plugin. diff --git a/docs/main/administration-guide/onboard/ad-ldap-groups-synchronization.mdx b/docs/main/administration-guide/onboard/ad-ldap-groups-synchronization.mdx new file mode 100644 index 000000000000..4b71fbdc0e72 --- /dev/null +++ b/docs/main/administration-guide/onboard/ad-ldap-groups-synchronization.mdx @@ -0,0 +1,356 @@ +--- +title: "AD/LDAP groups" +draft: true +--- +<PlanAvailability slug="entry-ent" /> + +## Overview + +The groups feature is useful for organizations that have many new users to onboard or that onboard users frequently and want to ensure users are added to default teams and channels that are pertinent to them. The group feature currently supports: + +- Creating groups by synchronization with your AD/LDAP system groups. +- Syncing groups to pre-defined roles in Mattermost. +- AD/LDAP nested groups. +- Using synchronized groups to manage [membership of teams and Private channels](/administration-guide/onboard/ad-ldap-groups-synchronization#synchronize-teams-and-channels). + +For a technical overview of the feature by Martin Kraft, who led the development of the feature, please see [this blog post](https://developers.mattermost.com/blog/ldap-nested-groups-modelling-and-representation-in-code). + +You can also watch a video overview about adding users to Mattermost with AD/LDAP on [YouTube](https://www.youtube.com/watch?v=zyku2ibsG0M). + +<div style={{position: 'relative', paddingBottom: '50%', height: '0', overflow: 'hidden', maxWidth: '100%', height: 'auto'}}> + <iframe src="https://www.youtube.com/embed/zyku2ibsG0M" alt="Video about adding users to Mattermost using AD/LDAP" frameborder="0" allowfullscreen style={{position: 'absolute', top: '0', left: '0', width: '100%', height: '95%'}}></iframe> +</div> + +## Pre-installation notes + +If you have enabled synchronization with AD/LDAP, all groups matching the default filter `(|(objectClass=group)(objectClass=groupOfNames)(objectClass=groupOfUniqueNames))` will be available to be linked in the groups list view at **System Console \> User Management \> Groups**. + +The group filter is an optional configuration setting available in the **User Filters** section of the AD/LDAP wizard (**System Console \> Authentication \> AD/LDAP**) and allows you to specify the groups that should have access in Mattermost. The **Group** filter is independent of the **User** filter; however, it does leverage the Base DN attribute. You may need to adjust your Base DN to ensure group objects can be searched in your AD/LDAP tree. + +The synchronization of groups happens with the synchronization of users, during which Mattermost queries AD/LDAP for updated account information. Please see the [Active Directory/LDAP Set up documentation](/administration-guide/onboard/ad-ldap). for more information. The group feature has no effect on users' authentication to Mattermost. + +## Enable AD/LDAP group synchronization + +To enable this feature, go to **System Console \> User Management \> Groups**. + +## Synchronize AD/LDAP groups to Mattermost + +To synchronize specific AD/LDAP groups to Mattermost, specify the `Group ID Attribute` and the `Group Display Name Attribute` (e.g., "cn" for Common Name) in the **Group Synchronization** section of the AD/LDAP wizard (**System Console \> Authentication \> AD/LDAP**). + +Additionally, you can specify the **Group** filter used to retrieve groups. If the **Group** filter configuration is left blank, then all groups matching the default filter `(|(objectClass=group)(objectClass=groupOfNames)(objectClass=groupOfUniqueNames))` are returned. Attribute values for **Group ID** and **Group Display Name** are case-sensitive. + +![Specify the group filter in the System Console by going to Authentication \> AD/LDAP.](/images/Group_filter.png) + +Group synchronization occurs after user synchronization and results for group synchronization are available on the synchonization status table (located at the bottom of the **AD/LDAP** configuration page). After the AD/LDAP groups have been synchronized, go to **System Console \> User Management \> Groups** to link and configure Mattermost groups. + +<Note> + +The synchronization process doesn't create Mattermost groups. Mattermost groups are created when you “link” the AD/LDAP group as outlined in the next section **Linking AD/LDAP groups to Mattermost groups**. Existing AD/LDAP users are added to the Mattermost groups on the next synchronization and new users are added on their first login. + +</Note> + +On subsequent synchronizations and once groups are linked: + +> - Users that have been added to an AD/LDAP group will be added to the linked Mattermost group and to teams and channels configured for that group. +> - Mattermost groups that are linked to AD/LDAP groups no longer included in your filter are deleted. +> - Users removed from an AD/LDAP group are removed from the linked Mattermost group, but their channel and team membership is only revoked when the channel or team is synchronized to an AD/LDAP group. + +![image](/images/Group_Group_Member_Sync.png) + +## Link AD/LDAP groups to Mattermost groups + +Groups that have been returned from the default filter or your AD/LDAP group filter will be available in a list view on the Groups page. The link action will create Mattermost groups corresponding to the AD/LDAP group. AD/LDAP groups linked to a Mattermost group will display the **Linked** icon. AD/LDAP groups that have not been linked to a Mattermost group will display the **Not Linked** icon. An AD/LDAP group that is not linked does not create a Mattermost group. + +![image](/images/Groups_listing.png) + +You can link groups individually by the inline **Linked** button and use the checkbox next to the group name to select multiple groups and choose **Link Selected Groups**. When selecting multiple groups with a mix of **Linked** and **Not Linked** states, the bulk action of the button will be **Link Selected Groups** until all selected are marked **Linked**. Using the bulk action speeds the process of creating Mattermost groups from your AD/LDAP Groups. + +If you see a **Link Failed** message, either select the message, or check the box alongside the group name to expose the inline link message and try again. + +![image](/images/LinkFailed.png) + +## Configure the linked group + +AD/LDAP groups that have been linked to Mattermost groups can be configured to add team and channels. To configure the group, select **Configure \> Group Configuration** and view the group profile which includes the group name. This name is automatically mapped from the AD/LDAP group common name attribute and is read-only. + +## Add default teams or channels for the group + +To add the teams and channels that you want the group members to default in, select either **Add Team** or **Add Channel** from the **Add Team or Channel** button. You can assign roles to group members using the options provided in the **Assigned Roles** column. Roles are updated on the next scheduled AD/LDAP synchronization. + +![image](/images/Group_Configuration.png) + +Channels are nested below the team they belong to in the team and channel list. The following table describes the icons available on this page and what they indicate: + +<table style={{width: '59%'}}> +<colgroup> +<col style={{width: '27%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<thead> +<tr> +<th><strong>Icon</strong></th> +<th><strong>Description</strong></th> +</tr> +</thead> +<tbody> +<tr> +<td><img src="../../images/%0Aopen_team.png" alt="image" /></td> +<td>Team is open for anyone to join.</td> +</tr> +<tr> +<td><img src="../../images/%0Aprivate_team.png" alt="image" /></td> +<td>Team isn't open for anyone to join.</td> +</tr> +<tr> +<td><img src="../../images/%0Apublic_channel.png" alt="image" /></td> +<td>Public channel.</td> +</tr> +<tr> +<td><img src="../../images/%0Aprivate_channel.png" alt="image" /></td> +<td>Private channel.</td> +</tr> +</tbody> +</table> + +<Note> + +- When a team is added, the `Town Square` and `Off-Topic` channels will also be created automatically, as well as any default channels set in the [ExperimentalDefaultChannels config setting](/administration-guide/configure/experimental-configuration-settings#default-channels). +- When a channel is added without setting the team explicitly, the team will be shown in the **Team and Channel Membership** listing, but it won't be added to the group specifically. Because of this dependency, when the channel is removed, the team will also be removed. Teams are listed in parentheses after the channel name in the channel selector. + +</Note> + +## Synchronize teams and channels + +For new users, default teams and channels will be added when they log in for the first time. For existing users, default teams and channels will be added after the next scheduled AD/LDAP sychronization. + +It may take a few seconds to load all team and channel memberships for a user depending on the number of teams and channels the group is defaulted to. In our testing, it took six seconds for an organization with 200,000 users and 30,000 linked groups. + +<Note> + +Users aren't removed from the team or channel on subsequent synchronizations of the AD/LDAP groups. Users need to be manually removed from the team or channel per the existing functionality. They won't be automatically re-added if they were manually removed or removed themselves. To manage a team or Private channel membership with synchronized groups, please see the section below on **Disable and re-activate AD/LDAP users** for details. + +</Note> + +![image](/images/Team_Channel_Membership_Sync.png) + +## Remove configured teams and channels from a group + +To remove a team or channel configured for a group, select **Remove** to the right of the team or channel name. Users already part of the team and channel won't be removed from that channel by this action. + +## View users belonging to the group + +Users who have logged in and accessed Mattermost will be visible in the members list on the group object. Members are read-only at this time and new members can be added through management in your AD/LDAP system. + +![image](/images/Group_Members.png) + +Users can be removed from the Mattermost group on subsequent synchronizations. However, they won't be removed from teams and channels unless the team or channel is group-synchronized. + +<Note> + +When a member removes themselves manually from a channel, that action is tracked in the **Channel Member History** table. If a system admin manually forces all members in a specific LDAP group to join the teams and channels synchronized to that group, members can potentially be re-added to channels from which they were previously removed. + +</Note> + +## Disable and re-activate AD/LDAP users + +If a member is removed from an AD/LDAP group, deactivated in AD/LDAP, or filtered from the AD/LDAP user filter, that member loses access to Mattermost. + +From Mattermost v7.7, system admins can add members back to all of the member's default teams and channels in the System Console by going to **User Management \> Users**, selecting the user's role, then selecting the **Re-sync user via LDAP groups** option. + +<Tip> + +Using the Mattermost API, system admins can manually re-add all group members back into synchronized teams or channels by forcing members in an LDAP group to join the teams and channels synchronized to that group, even if members left on their own, were removed, were filtered out, or were deactivated. See our [Mattermost API documentation](https://api.mattermost.com/#operation/SyncLdap) for details on synchronizing user attribute changes in the configured AD/LDAP server with Mattermost. + +</Tip> + +## Manage groups + +Once a group has been configured, the default teams and channels can be changed via the **Edit** option on the group list view. + +## Delete groups + +Mattermost groups can be deleted by adjusting your AD/LDAP group filter to remove the group or by unlinking the group on the Groups listing page. If you add the group back by re-adjusting the AD/LDAP group filter and link the group again on the group configuration page, the previous team and channel configurations will be available. + +## Use AD/LDAP synchronized groups to manage team or private channel membership + +Mattermost groups created with synchronized AD/LDAP groups can be used to manage the membership of private teams and private channels. When a team or private channel is managed by synchronized groups, member users will be added and removed based on their membership to the synchronized AD/LDAP group. + +<Note> + +It is not possible to add guests to teams and channels that are managed using groups. + +</Note> + +For instance, you may have an AD/LDAP group that contains your development team that you want to synchronize to a developer team. By using this feature, new developers will get added to the team when they are added to the synchronized AD/LDAP group and they will be removed from the team when removed from the AD/LDAP group. + +Similarly, you may have an AD/LDAP group that contains your leadership team that you want to synchronize to a private channel for coordination and updates. + +This feature helps control the membership of the channel so that guests and member users outside of the synchronized group are prevented from being added to the channel mistakenly. + +On teams that are managed by synchronized groups, guests, and member users outside of the group are restricted from: + +> - Invitation through a team invite link. +> - Invitations through an email invite. + +Similarly on private channels that are managed by synchronized groups, guests and member users outside of the group are restricted from: + +> - Invitation through a mention. +> - Invitation through the `/invite` slash command. +> - Being added to the channel via the **Add Members** menu option. + +Users can remove themselves from teams and Private channels managed by synchronized groups. + +### Manage membership of a team or channel with synchronized groups + +To manage membership of a private team with synchronized groups: + +1. Go to **System Console \> User Management \> Teams**. Select the team you want to manage with group synchronization. +2. Under **Team Management**, enable **Sync Group Members**. If **Anyone can join this team** is enabled or if specific email domains are set, they will be disabled by the Sync Group Members feature. +3. Add one or more groups to the team. If there are groups already associated with default users in the team, they'll be listed. +4. Review the notice in the footer of the screen for any users that are not part of groups who will be removed from the team on the next synchronization. +5. Select **Save**. Members will be updated on the next scheduled AD/LDAP synchronization. + +Alternatively, you can use the mmctl tools to set the team to be managed by groups: + +1. Ensure there is at least one group already associated to the team. You can view and add default teams to a group via **System Console \> User Management \> Groups \> Group Configuration**. Please see more information on adding default teams and channels [here](/administration-guide/onboard/ad-ldap-groups-synchronization#add-default-teams-or-channels-for-the-group). Additionally, you can use the mmctl to confirm if there is already a group associated to the team by running the [mmctl group team list](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-list) command. +2. Ensure **Team Settings \> General \> Allow any user with an account on this server to join this team** is set to **No**. +3. Convert the team to have its membership managed by synchronized groups by running the [mmctl group team enable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-enable) command. + +To manage membership of a private channel with synchronized groups: + +1. Go to **System Console \> User Management \> Channels**. Select the channel you want to manage with group synchronization. +2. Under **Channel Management**, enable **Sync Group Members**. Please ensure the channel is set to **private**. +3. Add one or more groups to the channel. If there are groups already associated with default users in the team, they'll be listed. +4. Review the notice in the footer of the screen for any users that are not part of groups who will be removed from the channel on the next synchronization. +5. Select **Save**. + +Members will be updated on the next scheduled AD/LDAP synchronization. Alternatively, you can use the mmctl to set a private channel to be managed by groups: + +1. Ensure there is at least one group already associated to the channel. You can view and add default channels to a group via **System Console \> User Management \> Groups \> Group Configuration**. Please see more information on adding default teams and channels [here](/administration-guide/onboard/ad-ldap-groups-synchronization#add-default-teams-or-channels-for-the-group). Additionally, you can use the mmctl to view if there is already a group associated to the channel by running the [mmctl group channel list](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-list) command. +2. Convert the team to have its membership managed by synchronized groups by running the [mmctl group channel enable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-enable) command. + +### Assign roles to group members + +Group members can be assigned predefined roles by system admins, which are applied across the group during the scheduled sychronization. The roles are: + +- Member (default) +- Team admin (in teams) +- Channel admin (in channels) + +The permissions for each role can be viewed and modified in **System Console \> Permissions**. + +**To set the Team admin role in a synced group** + +1. Go to **System Console \> User Management \> Teams**. +2. Select **Edit** next to the team you want to configure. +3. Ensure that **Sync Group Members** is enabled. +4. Choose **Add Group** to add one or more groups to the team. If there are groups already associated to default users into the team, they will already be present. +5. Select the arrow next to the current role in the **Roles** column to display and select the **Team Admin** option. +6. Repeat as needed for any other synced groups you have added. +7. Select **Save**. + +Roles are updated on the next scheduled AD/LDAP synchronization. + +**To set the Channel Admin role in a synced group** + +1. Go to **System Console \> User Management \> Channels**. +2. Select **Edit** next to the team you want to configure. +3. Ensure that **Sync Group Members** is enabled. +4. Choose **Add Group** to add one or more groups to the team. If there are groups already associated with default users in the team, they'll be listed. +5. Select the arrow next to the current role in the **Roles** column to display and select the **Channel Admin** option. +6. Repeat as needed for any other synced groups you have added. +7. Select **Save**. + +Roles are updated on the next scheduled AD/LDAP synchronization. + +<Note> + +Members who have been synced as part of a group cannot have their role changed via **View Members** in Mattermost. + +</Note> + +### Add or remove groups from teams + +Once team management is converted to use synchronized groups, team admins and system admins can add additional groups from **Main Menu \> Add Groups to Team**. This will add users to the next AD/LDAP synchronization, and any new users to the group will be added to the team on subsequent synchronizations. Team admins will be prevented from converting the team to a public space by enabling **Team Settings \> Allow any user with an account on this server to join this team**. + +Team admins and system admins can also remove groups from a team from **Main Menu \> Manage Groups**. This will disassociate the group from the team. Users are removed on the next AD/LDAP synchronization. + +The system admin can remove groups from **System Console \> User Management \> Teams \> Team Configuration \> Synced Groups**. + +### Add or remove groups from private channels + +Once the management of the channel is converted to be managed by synchronized groups, team admins and system admins can add additional groups from **Channel Menu \> Add Groups to Channel**. This will add users on the next AD/LDAP synchronization and any new users to the group will be added to the channel on subsequent synchronizations. + +Team admins and system admins can also remove groups from a team from **Main Menu \> Manage Groups**. This will disassociate the group from the team. Users are removed on the next AD/LDAP synchronization. + +The system admin can remove groups from **System Console \> User Management \> Channels \> Channel Configuration \> Synced Groups**. + +### Manage members + +Users are automatically removed from the team or private channel when removed from a synchronized AD/LDAP group that is managing the membership of that team or channel. Additionally, users who are not in the synchronized groups are prevented from being added through the `/invite` and mention flows within a channel. + +A user can remove themselves from the team or from the private channel when it is managed by synchronized groups. They can be added back by users who have permission to manage members for a team or private channel by using the `/invite` slash command or by mentioning the user in a channel. + +If the user is removed from a synchronized group and later re-added to the group, they can be manually added back to the team or Private channel as noted above. + +<Note> + +Users won't be added back by the AD/LDAP synchronization automatically once they remove themselves or are removed by the LDAP synchronized group. + +</Note> + +### Disable group-synchronized management of teams and private channels + +To remove the management of members by synchronized groups in a team, disable **Sync Group Members** under **System Console \> User Management \> Teams \> Team Management**. Alternatively, you can also run the [mmctl group team disable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-disable) command. + +To remove the management of members by synchronized groups in a channel, disable **Sync Group Members** under **System Console \> User Management \> Channels \> Channel Management**. Alternatively, you can also run the [mmctl group channel disable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-disable) command. + +## Frequently asked questions + +### Why do my LDAP users and groups exist in Mattermost, but my groups have no members? + +In order for Mattermost to detect group membership correctly, and to automatically add users to the group configured in the System Console, you must use one of the following AD/LDAP attributes to represent group members in Mattermost: `member` or `uniqueMember`. These attributes use a `Distinguished Name` as the value on groups. + +<Note> + +LDAP installations that use `memberUid` to indicate group membership are not supported because `memberUid` is an attribute of an object class `posixGroup` that does not use `Distinguished Names` as the value on groups. + +</Note> + +### Why can't my existing users see the teams and channels they have been synced to? + +Existing Mattermost users that are members of linked Mattermost groups will be added to teams and channels on the next scheduled synchronization job that is run after teams and channels are added to the Mattermost group. You can manually initiate a synchronization from the **Sync History** section of the AD/LDAP wizard (**System Console \> Authentication \> AD/LDAP \> AD/LDAP Synchronize Now**). + +### How do nested groups work with AD/LDAP Group Sync? + +Users within nested groups are included as members of parent groups. The group filter that you specify can include any type of AD/LDAP group on your system. The `member` AD/LDAP attribute is used to determine nested groups that belong to a parent group. + +### How do I manage a team or private channel membership with synchronized groups? + +You can do this by setting the team or channel management to synced groups instead defaulting a group to a team or channel. See the section above on synchronizing teams and channels to learn more. + +### How do I use AD/LDAP group sync with SAML? + +You can use AD/LDAP group sync with SAML by enabling [SAML Synchronization with AD/LDAP](/administration-guide/onboard/sso-saml-okta#configure-saml-synchronization-with-ad-ldap). You do not need to enable sign-in with LDAP for this feature to work. + +However, it's critical that the unique Mattermost ID identifier that you have chosen as your attribute in your directory service (AD/LDAP) is the same for both the SAML and AD/LDAP configurations. + +For instance, if `ObjectGUID` has been chosen as the Mattermost ID in your AD/LDAP configuration, then an attribute that has the same value should also be mapped to the ID attribute in your SAML assertion. We also recommend that the ID attribute you select is unique and unchanging (such as a `GUID`). + +### Why aren’t public channels supported with synchronized groups? + +Public channels are available to all members to discover and join. Managing membership with synchronized groups removes the ability for Public channels to be accessible to users on the team. Private channels typically require more controlled membership management, which is why this feature applies to Private channels. Groups can be assigned to public teams and public channels as described in [this documentation](/administration-guide/onboard/ad-ldap-groups-synchronization#add-default-teams-or-channels-for-the-group). + +### Does a team with its membership managed by groups have any effect on public channel access? + +Only users that are members of groups synchronized to team are able to discover and join public channels. Private channels can also be managed by synchronized groups when a team is managed by synchronized groups. + +### Why don't users get readded to teams or channels once they have been removed from and then later re-added to the LDAP group? + +The implementation of group removals does not currently differentiate between users who have removed themselves or have been removed by the LDAP synchronization process. Our design optimizes for users who have removed themselves from a team or channel. In the future, we may add the ability for Admins to re-add users who have been removed and even prevent users from leaving a team or channel. + +Additionally, LDAP users who are not accessible to Mattermost based on filters will be removed from the groups and from group synced teams and channels. If they were removed from teams and channels then they would not be re-added to those teams and channels upon becoming subsequently reaccessible to Mattermost. + +### How can I use LDAP attributes or Groups with OpenID? + +At this time, LDAP data isn't compatible with OpenID. If you currently rely on LDAP to manage your users' teams, channels, groups, or attributes, you won't be able to do this automatically with users who have logged in with OpenID. If you need LDAP synced to each user, we suggest using SAML or LDAP as the login provider. Some OpenID providers can use SAML instead, like Keycloak. diff --git a/docs/main/administration-guide/onboard/ad-ldap.mdx b/docs/main/administration-guide/onboard/ad-ldap.mdx new file mode 100644 index 000000000000..0199aac72d63 --- /dev/null +++ b/docs/main/administration-guide/onboard/ad-ldap.mdx @@ -0,0 +1,323 @@ +--- +title: "AD/LDAP setup" +--- +<PlanAvailability slug="all-commercial" /> + +## Overview + +Mattermost offers “Same Sign-On” with Microsoft AD/LDAP (formerly known as Active Directory/LDAP). Enable the same credentials used in on-prem AD/LDAP deployments to be reused in Mattermost, with optional [multi-factor authentication](/administration-guide/onboard/multi-factor-authentication). + +AD/LDAP is a service that stores authentication and authorization details of users on your organization's network. When you integrate your AD/LDAP system with Mattermost, users can log into Mattermost without having to create new credentials. User accounts are managed in AD/LDAP, and changes are synchronized with Mattermost. + +Mattermost provides a step-by-step AD/LDAP setup wizard in the System Console that guides you through the configuration process with sections and incremental testing to ensure each part of your setup works correctly before proceeding to the next step. + +Benefits of integrating AD/LDAP with Mattermost include: + +- **Single sign-on.** Users can log in to Mattermost with their AD/LDAP credentials. +- **Centralized identity management.** Mattermost accounts can display user information from AD/LDAP, such as first and last name, email, and username. +- **Automatic account provisioning.** A Mattermost user account is automatically created the first time a user signs in with their AD/LDAP credentials. +- **Sync groups to predefined roles in Mattermost.** Assign team and channel roles to groups via AD/LDAP Group Sync. +- **Compliance alignment with administrator management.** Manage Administrator access to Mattermost in the System Console using AD/LDAP filters. + +## Pre-installation notes + +If you're using AD/LDAP with **nested security groups** you need to write a PowerShell script, or similar, to flatten and aggregate the tree into a single security group to map into Mattermost. + +We strongly recommend the following as you prepare to set up AD/LDAP: + +Attribute Naming and Case Sensitivity: + +- Attribute names in both AD/LDAP and Mattermost configurations are **case-sensitive**. +- Ensure that the attribute names in the AD/LDAP claim rules **exactly match** the expected attribute names in Mattermost. Case deviations will result in issues. + +Essential attributes: + +- The `NameID` element is required for user identification in SAML assertions. +- All required attributes (e.g., `Email`, `Username`, `FirstName`, and `LastName`) must be included and correctly mapped. + +How to choose a stable unique identifier for `NameID`: + +- Using a stable and unique identifier (`EmployeeID` or `ObjectGUID`) for the `NameID` helps prevent issues in cases where user details could change over time (e.g., `LastName` or `Email`). +- If stable, unique attributes aren't available in AD, using attributes that might change over time can result in future issues. + +## Getting started + +There are two ways to set up AD/LDAP: + +1. **Configure AD/LDAP using the System Console setup wizard** + +> - Log in to your workspace and create a new account using email and password. This is assigned the system admin role as the first user created. +> - Next, use the AD/LDAP setup wizard to configure AD/LDAP step-by-step, testing each section as you go, and then convert your system admin account to use the AD/LDAP login method. + +2. **Configure AD/LDAP by editing \`\`config.json\`\`** + +> - Edit `config.json` to enable AD/LDAP based on the [AD/LDAP settings documentation](/administration-guide/configure/authentication-configuration-settings#ad-ldap). When you log in to Mattermost the first user to log in with valid AD/LDAP credentials will be assigned the system admin role. + +## Configure AD/LDAP login + +1. **Create a system admin account using email authentication.** + +> - Create a new workspace and create an account using email and password, which is automatically assigned the **system admin** role since it is the first account created. You may also assign the role to another account. + +2. **Configure AD/LDAP using the setup wizard.** + +> - Go to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP setup wizard. The wizard is organized into sections that you can navigate through using the sidebar: +> - **Connection Settings**: Configure server connection details +> - **User Filters**: Set up user identification and filtering +> - **Account sync**: Map AD/LDAP attributes to Mattermost user fields +> - **Group Synchronization**: Configure group settings and group attributes (if using LDAP groups) +> - **Sync Performance**: Adjust synchronization timing and performance settings +> - **Sync History**: View synchronization status and manually trigger syncs +> - Each section includes a test button that allows you to verify your configuration before proceeding to the next step. This incremental testing helps identify and resolve issues early in the setup process. + +3. **Confirm that AD/LDAP sign-on is enabled.** + +> - After configuring AD/LDAP through the wizard, confirm that users can log in using AD/LDAP credentials. + +4. **Switch your system admin account from email to AD/LDAP authentication.** + +> - Navigate to your profile, and select **Security \> Sign-in Method \> Switch to AD/LDAP** and log in with your AD/LDAP credentials to complete the switch. + +5. **(Optional) Restrict authentication to AD/LDAP.** + +> - Go to **System Console \> Authentication \> Email** and set **Enable sign-in with email** to **false** and **Enable sign-in with username** to **false**. +> - Then choose **Save** to save the changes. This should leave AD/LDAP as the only login option. + +6. **(Optional) If you configured \`First Name Attribute\` and \`Last Name Attribute\` in the System Console.** + +> - Navigate to **System Console \> Site Configuration \> Users and Teams** and set **Teammate Name Display** to **Show first and last name**. This is recommended for a better user experience. + +<Note> + +If you've made a mistake and lock yourself out of the system somehow, you can set an existing account to system admin using the [mmctl roles](/administration-guide/manage/mmctl-command-line-tool#mmctl-roles) command. + +</Note> + +## Configure AD/LDAP synchronization + +<PlanAvailability slug="entry-ent" /> + +In addition to configuring AD/LDAP sign-in, you can also configure AD/LDAP synchronization. When synchronizing, Mattermost queries AD/LDAP for relevant account information and updates Mattermost accounts based on changes to attributes (first name, last name, and nickname). When accounts are disabled in AD/LDAP users are deactivated in Mattermost, and their active sessions are revoked once Mattermost synchronizes the updated attributes. + +The AD/LDAP synchronization depends on email. Make sure all users on your AD/LDAP server have an email address, or ensure their account is deactivated in Mattermost. + +When Mattermost is configured to use AD/LDAP for user authentication, the following user attribute changes can't be made through the API: first name, last name, position, nickname, email, profile picture, or username. LDAP must be the authoritative source for these user attributes. + +To configure AD/LDAP synchronization with AD/LDAP sign-in: + +1. Go to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard and navigate to the **Connection Settings** section. Set **Enable Synchronization with AD/LDAP** to **true**. +2. Navigate to the **Sync Performance** section and configure the **Synchronization Interval (minutes)** to specify how often Mattermost accounts synchronize attributes with AD/LDAP. The default setting is 60 minutes. + +<Note> + +- The profile picture attribute is only synchronized when the user logs in. +- From Mattermost v11, if a profile picture in AD/LDAP is removed, the next time the user logs in, their Mattermost profile picture is also removed and returns to the default image. +- Additionally, after configuring profile pictures in AD/LDAP configuration, all AD/LDAP user accounts in Mattermost will synchronize to use the profile picture from AD/LDAP on their next login. +- If you want to synchronize immediately after disabling an account, use the **AD/LDAP Synchronize Now** button in the **Sync History** section of the wizard. +- To configure AD/LDAP synchronization with SAML sign-in, see the [SAML documentation](/administration-guide/onboard/sso-saml). + +</Note> + +<Note> + +- Ensure at least one AD/LDAP user is in Mattermost or the sync won't complete. +- Synchronization with AD/LDAP settings in the System Console can be used to determine the connectivity and availability of arbitrary hosts. System admins concerned about this can use custom admin roles to limit access to modifying these settings. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration#edit-privileges-of-admin-roles-advanced)) documentation for details. + +</Note> + +3. From Mattermost v10.9, you can configure Mattermost to automatically [re-add members of an LDAP group to group-synchronized teams or channels](/administration-guide/configure/authentication-configuration-settings#re-add-removed-members-on-sync) during LDAP synchronization, even if those members were previously removed. This option enables you to maintain uninterrupted collaboration and address specific organizational needs, ensuring users who were unintentionally removed due to changes in LDAP group membership, synchronization errors, or exceptions to the standard group sync rules can be seamlessly restored. + +> <div class="note"> +> +> <div class="title"> +> +> Note +> +> </div> +> +> The [mmctl ldap sync](/administration-guide/manage/mmctl-command-line-tool#mmctl-ldap-sync) command takes precedence over this server configuration setting. If you have this setting disabled, and run the mmctl command with the `--include-removed-members` flag, removed members will be re-added during LDAP synchronization. +> +> </div> + +## Configure AD/LDAP sign-in using filters + +Using filters assigns roles to specified users on login. To access AD/LDAP filter settings, navigate to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard and go to the **User Filters** section. + +### User filter + +(Optional) Enter an AD/LDAP filter to use when searching for user objects. Only the users selected by the query will be able to access Mattermost. For AD/LDAP, the query to filter out disabled users is `(&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))`. + +1. Navigate to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard. +2. Go to the **User Filters** section and complete the **User Filter** field. +3. Use the **Test Filters** button to verify your filter works correctly. +4. Choose **Save**. + +When the user accesses Mattermost, they log in with same username and password that they use for organizational logins. + +Filters can also be used for excluding users who belong to certain groups. For AD/LDAP, the query to filter out groups is `(&(memberof=cn=ACME_ALL,ou=Users,dc=sademo,dc=com)(!(memberof=cn=DEV_OPS,ou=Users,dc=sademo,dc=com)))`. + +### Guest filter + +(Optional) When enabled, the Guest Filter in Mattermost identifies external users whose AD/LDAP role is guest and who are invited to join your Mattermost workspace. These users will have the Guest role applied immediately upon first login instead of the default member user role. This eliminates having to manually assign the role in the System Console. + +If this filter is removed/changed, active guests will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console \> User Management**. + +1. Navigate to **System Console \> Authentication \> Guest Access** and set Guest Access to `true`. +2. Navigate to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard. +3. Go to the **User Filters** section and expand **Configure additional filters**. +4. Complete the **Guest Filter** field. +5. Use the **Test Filters** button to verify your filter works correctly. +6. Choose **Save**. + +When a guest logs in for the first time they are presented with a default landing page until they are added to channels. + +See the [Guest Accounts documentation](/administration-guide/onboard/guest-accounts) for more information about this feature. + +### Admin filter + +(Optional) Enter an AD/LDAP filter to use for designating system admins. The users selected by the query will have access to your Mattermost workspace as system admins. By default, system admins have complete access to the Mattermost System Console. Existing members that are identified by this attribute will be promoted from member to system admin upon next login. + +The next login is based upon Session lengths set in **System Console \> Session Lengths**. It is recommended that users are demoted to members manually in **System Console \> User Management** to ensure access is restricted immediately. + +1. Navigate to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard. +2. Go to the **User Filters** section and expand **Configure additional filters**. +3. Set **Enable Admin Filter** to **true**. +4. Complete the **Admin Filter** field. +5. Use the **Test Filters** button to verify your filter works correctly. +6. Choose **Save**. + +<Note> + +If the Admin Filter is set to `false`, the member's role as system admin is retained. However if this filter is removed/changed, system admins that were promoted via this filter will be demoted to members and won't retain access to the System Console. + +</Note> + +When this filter isn't in use, members can be manually promoted/demoted via **System Console \> User Management**. + +## Configure AD/LDAP deployments with multiple domains + +Organizations using multiple domains can integrate with Mattermost using a "Forest" configuration to bring together multiple domains. Please see [Forests as Collections of Domain Controllers that Trust Each Other](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc759073(v=ws.10)?redirectedfrom=MSDN) for more information. + +For forest configurations that contain multiple domains which do NOT share a common root, you can search across all of the domains using the Global Catalog. To do so, update your `config.json` as follows: + +- Set the LdapPort to 3268 (instead of 389) +- Set the BaseDN to " " (A single space character) + +See [Global Catalog and LDAP Searches](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc978012(v=technet.10)?redirectedfrom=MSDN) for additional details. + +## Troubleshooting/FAQ + +The following are frequently asked questions and troubleshooting suggestions on common error messages and issues. It is recommended that you check your logs for errors as they can provide an idea of what the issue is. + +### If the **Test Connection** button fails, how can I troubleshoot the connection? + +Check that your AD/LDAP connection settings are correct by running an AD/LDAP user query in an external system. See [LDAP Connection Test Example](https://ldaptool.sourceforge.net/). If the AD/LDAP connection is verified to be working outside of Mattermost, try the following: + +- Check your AD/LDAP system to verify your `Bind Username` format. +- Check your **AD/LDAP Port** and **Connection Security** settings in the System Console. (**AD/LDAP Port** set to 389 typically uses **Connection Security** set to `None`. **AD/LDAP Port** set to 636 typically ties to **Connection Security** set to **TLS**). +- If you're seeing `x509: certificate signed by unknown authority` in your logs, try installing an intermediate SSL certificate or have your LDAP server send the complete certificate chain. + +If these options don't work, please [contact our support team](https://mattermost.com/support/). + +### When I first set up and synchronize AD/LDAP, are the users automatically created in Mattermost? + +No, each user is created on their first login. + +### When I try to synchronize AD/LDAP, why does the status show as `Pending` and not complete? + +Go to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard, navigate to the **Connection Settings** section, and make sure that the **Enable Synchronization with AD/LDAP** setting is set to **true**. + +If the issue persists, try selecting the **Test Filters** button to test that the User Filter is correctly formatted. Refer to this [document](/administration-guide/configure/authentication-configuration-settings#user-filter) for guidance on setting a correct syntax format. + +Make sure that you also have at least one AD/LDAP user in Mattermost or the synchronization will not complete. + +### What's the difference between the Username Attribute, ID Attribute, and Login ID Attribute? + +There are three AD/LDAP attributes that apear to be similar but serve a different purpose: + +1. **Username Attribute:** Used within the Mattermost user interface to identify and mention users. For example, if **Username Attribute** is set to `john.smith`, a user typing `@john` will see `@john.smith` in their autocomplete options and posting a message with `@john.smith` will send a notification to that user that they’ve been mentioned. +2. **ID Attribute:** Used as the unique identifier in Mattermost. It should be an AD/LDAP attribute with a value that does not change, such as `ObjectGUID`. If a user's ID attribute changes, it will create a new Mattermost account unassociated with their old one. If you need to change this field after users have already logged in, use the [mattermost ldap idmigrate mmctl tool](/administration-guide/manage/mmctl-command-line-tool#mmctl-ldap-idmigrate). +3. **Login ID Attribute:** The attribute in the AD/LDAP server used to log in to Mattermost. Normally this attribute is the same as the **Username Attribute** field above, or another field that users can easily remember. + +### How do I deactivate users? + +If a user has logged into Mattermost through AD/LDAP or SAML, you can choose how they are deactivated, whether manually or automatically. + +There are three main ways to do this: + +1. **User deletion:** If the user is completely removed from the AD/LDAP server, they will be deactivated in Mattermost on the next synchronization. +2. **User filter:** Set the [user filter](/administration-guide/configure/authentication-configuration-settings#user-filter) to only select the subset of AD/LDAP users you want to have access to Mattermost. When someone is removed from the selected group, they will be deactivated in Mattermost on the next synchronization. +3. **Manually deactivate**: Go to **System Console \> User Management \> Users**, select a user's role, and select **Deactivate**. When you manually deactivate a user, they can reactivate themselves by logging back in. + +For AD/LDAP, to filter out deactivated users you must set the user filter to: + +`(&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))` + +Filters can also be used for excluding users who belong to certain groups. For AD/LDAP, the query to filter out groups is: + +`(&(memberof=cn=ACME_ALL,ou=Users,dc=sademo,dc=com)` + +`(!(memberof=cn=DEV_OPS,ou=Users,dc=sademo,dc=com)))` + +When a user is deactivated in Mattermost via options one or two above, all the user's current sessions are revoked and they will be unable to log in or access Mattermost. + +### Can I connect to multiple AD/LDAP servers? + +There is currently no built-in way to connect to multiple AD/LDAP servers. You will need to connect the instances in a forest before connecting to Mattermost. Consider upvoting the [feature request](https://portal.productboard.com/mattermost/33-what-matters-to-you) on our forum. + +### When trying to log in, I see the error `AD/LDAP not available on this server` + +This indicates that there is a problem somewhere with your configuration. We recommend that you check your Mattermost configuration settings to ensure that AD/LDAP is enabled, and the settings are correct. + +If you're still having issues, you can [contact support](https://mattermost.com/support/) for additional troubleshooting. + +### I see the error `User not registered on AD/LDAP server` + +This means the query sent back to the AD/LDAP server returned no results. We recommend that you: + +1. Check that the user credentials were entered properly - you should log in with the field set as the [\*ID Attribute\*](/administration-guide/configure/authentication-configuration-settings#id-attribute). +2. Check that the user account exists in the AD/LDAP server. +3. Check the AD/LDAP configuration settings are correct. + +If you're still having issues, you can [contact Mattermost Support](https://mattermost.com/support/) for additional troubleshooting. + +### I updated a user account in AD/LDAP, and they can no longer log in to Mattermost + +If the user can no longer log in to Mattermost with their AD/LDAP credentials - for example, they get an error message `An account with that email already exists`, or a new Mattermost account is created when they try to log in - this means the **ID Attribute** for their account has changed. + +The issue can be fixed by changing the value of the field used for the **ID Attribute** back to the old value. If you're currently using a field that sometimes changes for an **ID Attribute** (e.g. username, email that changes when someone gets married), we recommend you switch to using a non-changing field such as a GUID. + +To do this, you can set the [Login ID Attribute](/administration-guide/configure/authentication-configuration-settings#id-attribute) to whatever you would like users to log in with (e.g. username or email). + +<Note> + +Currently the value is case sensitive. If the **ID Attribute** is set to the username and the username changes from `John.Smith` to `john.smith`, the user will experience problems logging in. + +</Note> + +### I see the log error `LDAP Result Code 4 "Size Limit Exceeded"` + +This indicates that your AD/LDAP server configuration has a maximum page size set and the query coming from Mattermost is returning a result set in excess of that limit. + +To address this issue you can set the [max page size](/administration-guide/configure/authentication-configuration-settings#maximum-page-size) in your Mattermost configuration to match the limit on your AD/LDAP server. This will return a sequence of result sets that do not exceed the max page size, rather than returning all results in a single query. A max page size setting of 1500 is recommended. + +If the error is still occurring, it is likely that no AD/LDAP users have logged into Mattermost yet. Ensure that at least one AD/LDAP user has logged into Mattermost and re-run the synchronization. The error should disappear at that point. + +### I see the log error `Missing NameID Element` + +This indicates that the AD/LDAP server configuration doesn't include the `NameID` element in the SAML assertion. The `NameID` element is required for user identification in SAML assertions. Ensure the `NameID` is mapped to a unique user identifier, such as the user's email address or another stable attribute that isn't subject to change over time. + +### I see the log error `Username Attribute is Missing` + +The `Username` attribute in the SAML assertion was either missing or is incorrectly named. Verify that all required attributes are included in the SAML assertion. Attribute names are case-sensitive and must match exactly what Mattermost expects. Update the claim rules in AD/LDAP to correctly map LDAP attributes to the expected outgoing claim types, ensuring proper casing (e.g., `Username` instead of `UserName`). + +### Can the Enter ID User Filter read security groups? + +Yes it can, but make sure that: + +- Permissions are correctly configured on the service account you are using. +- Each user object is a direct member of the security group. + +### How do I know if an AD/LDAP sync job fails? + +Mattermost provides the status of each AD/LDAP sync job in the **Sync History** section of the AD/LDAP wizard (**System Console \> Authentication \> AD/LDAP**). Here you can see the number of users updated and if the job succeeded or failed. diff --git a/docs/main/administration-guide/onboard/advanced-permissions-backend-infrastructure.mdx b/docs/main/administration-guide/onboard/advanced-permissions-backend-infrastructure.mdx new file mode 100644 index 000000000000..5e14eaf5edce --- /dev/null +++ b/docs/main/administration-guide/onboard/advanced-permissions-backend-infrastructure.mdx @@ -0,0 +1,1072 @@ +--- +title: "Advanced permissions: backend infrastructure" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +This document outlines the backend server infrastructure for permissions in Mattermost and is recommended only for technical Admins or developers looking to make modifications to their installation. + +## Entity definitions + +### Permissions + +A **permission** describes a permitted action which may be carried out on an object. It describes the action that users may perform in the context in which they have been assigned the role granting the permission. + +### Roles + +A **role** is something to which permissions are granted, that is then assigned to users in contexts in order to grant them the assigned permissions in that context. One user may end up with different sets of permissions granted by different roles in different contexts. + +### Scope + +Permissions live within a given scope. There are three scopes in the Mattermost system: System, Team and Channel. Permissions cascade down the scopes from the context in which they are applied. For example, if a “Channel” scoped permission is applied to a “Team” context, the permission applies to any channels within that team. A permission is considered, + +- **System scope** if it makes sense only on the system level. For example, `manage_oauth`. +- **Team scope** if it makes sense at the team level and system level. For example, `create_public_channel`. +- **Channel scope** if it makes sense at channel, team and system level. For example, `manage_public_channel_properties`. + +### Context + +A **context** is an instance of a scope. For example, a channel called "Developers Hangout" is an instance of channel scope. Contexts have hierarchical relationships between them that reflect the hierarchical ordering of scopes. Each context has one parent, and may have multiple children, with the ultimate parent context being the system context: + +- A channel context has a parent team context, whose parent is the system context. For example, the "Developers Hangout" channel is the channel context, with parent team context "Contributors Team", with parent system context. +- A team context has a parent system context and child channel contexts. For example, the "Contributors Team" is the team context, with parent system context, and with children channel contexts such as "Developers Hangout", "Reception" and "Marketing". + +When determining whether a user is allowed to carry out a given action in a given context, the union of the permissions of all roles that user has been assigned in the current context and its parent contexts is calculated. This enables permissions to cascade down the scope hierarchy. For example, if a users is granted the `manage_public_channel_properties` permission in a role in the system context, then the user has permissions to manage public channel properties in all channels, in all teams, of which they are a member. + +### Schemes + +Schemes describe the default roles applied to users in a context, and all child contexts. Schemes are either defined specifically for a context, or if they are not specified, the relevant parts of the parent context’s scheme are applied, ultimately climbing the hierarchy to the System Scheme, which serves the purpose of providing the system-wide defaults. For example, if Team A does not have a team-scoped scheme defined, the System Scheme will provide the defaults for all contexts in Team A. + +Additionally, the lowest-scoped scheme always takes precedence in the context. For example, if Team B has a team-scoped scheme, that scheme takes precedence over the System Scheme defaults for all contexts in Team B. + +## Data structure + +### Permissions + +Permissions in Mattermost are a property of the server code base and are not created or modified dynamically. The current set of permissions are as described in the table below. + +**Mattermost permissions** + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '18%'}} /> +<col style={{width: '3%'}} /> +<col style={{width: '76%'}} /> +<col style={{width: '0%'}} /> +</colgroup> +<thead> +<tr> +<th>Name (i18n)</th> +<th>Scope</th> +<th>Description</th> +<th></th> +</tr> +</thead> +<tbody> +<tr> +<td>invite_user</td> +<td>team</td> +<td>Invite users to the team using Send Email Invite or Get Team Invite Link.</td> +<td></td> +</tr> +<tr> +<td>add_user_to_team</td> +<td>team</td> +<td>Add existing server users to the current team.</td> +<td></td> +</tr> +<tr> +<td>manage_slash_commands</td> +<td>system</td> +<td>Create, edit, and delete your own slash commands.</td> +<td></td> +</tr> +<tr> +<td>manage_others_slash_commands</td> +<td>system</td> +<td>Edit or delete other users' slash commands.</td> +<td></td> +</tr> +<tr> +<td>create_public_channel</td> +<td>team</td> +<td>Create public channels.</td> +<td></td> +</tr> +<tr> +<td>create_private_channel</td> +<td>team</td> +<td>Create private channels.</td> +<td></td> +</tr> +<tr> +<td>manage_public_channel_members</td> +<td>channel</td> +<td>Manage public channel members.</td> +<td></td> +</tr> +<tr> +<td>manage_private_channel_members</td> +<td>channel</td> +<td>Manage private channel members.</td> +<td></td> +</tr> +<tr> +<td>assign_system_admin_role</td> +<td>system</td> +<td>Grant other users the system admin role.</td> +<td></td> +</tr> +<tr> +<td>manage_roles</td> +<td>system</td> +<td>Manage other users' system-wide roles.</td> +<td></td> +</tr> +<tr> +<td>manage_team_roles</td> +<td>team</td> +<td>Add and remove team members.</td> +<td></td> +</tr> +<tr> +<td>manage_channel_roles</td> +<td>channel</td> +<td>Add and remove channel members.</td> +<td></td> +</tr> +<tr> +<td>manage_system</td> +<td>system</td> +<td>Access to System Console.</td> +<td></td> +</tr> +<tr> +<td>sysconsole_read_usermanagement_system_roles</td> +<td>system</td> +<td>View system roles.</td> +<td></td> +</tr> +<tr> +<td>sysconsole_write_usermanagement_system_roles</td> +<td>system</td> +<td>Add, remove, and assign system roles.</td> +<td></td> +</tr> +<tr> +<td>create_direct_channel</td> +<td>system</td> +<td>Open Direct Message channels.</td> +<td></td> +</tr> +<tr> +<td>create_group_channel</td> +<td>system</td> +<td>Open Group Message channels.</td> +<td></td> +</tr> +<tr> +<td>manage_public_channel_properties</td> +<td>channel</td> +<td>Edit public channel name, header, and purpose, as well as create public channel checklists.</td> +<td></td> +</tr> +<tr> +<td>manage_private_channel_properties</td> +<td>channel</td> +<td>Edit private channel name, header, and purpose, as well as create private channel checklists.</td> +<td></td> +</tr> +<tr> +<td>list_public_teams</td> +<td>system</td> +<td>View public teams listed in the "Join Another Team" menu accessed from the main menu.</td> +<td></td> +</tr> +<tr> +<td>join_public_teams</td> +<td>system</td> +<td>Join public teams listed in the "Join Another Team" menu accessed from the main menu.</td> +<td></td> +</tr> +<tr> +<td>list_private_teams</td> +<td>system</td> +<td>View private teams listed in the "Join Another Team" menu accessed from the main menu.</td> +<td></td> +</tr> +<tr> +<td>join_private_teams</td> +<td>system</td> +<td>Join private teams listed in the "Join Another Team" menu accessed from the main menu.</td> +<td></td> +</tr> +<tr> +<td>list_team_channels</td> +<td>team</td> +<td>List public channels in a team.</td> +<td></td> +</tr> +<tr> +<td>join_public_channels</td> +<td>team</td> +<td>Join public channels.</td> +<td></td> +</tr> +<tr> +<td>delete_public_channel</td> +<td>channel</td> +<td>Archive public channels.</td> +<td></td> +</tr> +<tr> +<td>delete_private_channel</td> +<td>channel</td> +<td>Archive private channels.</td> +<td></td> +</tr> +<tr> +<td>edit_other_users</td> +<td>system</td> +<td>Edit values on the <code>user</code> object of other users.</td> +<td></td> +</tr> +<tr> +<td>read_channel</td> +<td>channel</td> +<td>View posts in a channel.</td> +<td></td> +</tr> +<tr> +<td>read_channel_contents</td> +<td>channel</td> +<td>Read the contents of a channel.</td> +<td></td> +</tr> +<tr> +<td>read_public_channel</td> +<td>team</td> +<td>View and access public channels on a team.</td> +<td></td> +</tr> +<tr> +<td>add_reaction</td> +<td>channel</td> +<td>Add emoji reactions to posts.</td> +<td></td> +</tr> +<tr> +<td>remove_reaction</td> +<td>channel</td> +<td>Remove emoji reactions from posts.</td> +<td></td> +</tr> +<tr> +<td>remove_others_reactions</td> +<td>channel</td> +<td>Remove other users emoji reactions from posts.</td> +<td></td> +</tr> +<tr> +<td>permanent_delete_user (deprecated)</td> +<td>system</td> +<td>Permanently delete other users.</td> +<td></td> +</tr> +<tr> +<td>upload_file</td> +<td>channel</td> +<td>Upload file attachments to posts.</td> +<td></td> +</tr> +<tr> +<td>get_public_link</td> +<td>system</td> +<td>Get permalink for posts.</td> +<td></td> +</tr> +<tr> +<td>manage_incoming_webhooks</td> +<td>team</td> +<td>Create, edit, and delete your own incoming webhooks.</td> +<td></td> +</tr> +<tr> +<td>manage_outgoing_webhooks</td> +<td>team</td> +<td>Create, edit, and delete your own outgoing webhooks.</td> +<td></td> +</tr> +<tr> +<td>manage_others_webhooks(deprecated)</td> +<td>team</td> +<td>Edit and delete other users' incoming or outgoing webhooks.</td> +<td></td> +</tr> +<tr> +<td>manage_others_incoming_webhooks</td> +<td>team</td> +<td>Edit and delete other users' incoming webhooks.</td> +<td></td> +</tr> +<tr> +<td>manage_others_outgoing_webhooks</td> +<td>team</td> +<td>Edit and delete other users' outgoing webhooks.</td> +<td></td> +</tr> +<tr> +<td>manage_oauth</td> +<td>system</td> +<td>Create, edit, and delete your own OAuth 2.0 apps.</td> +<td></td> +</tr> +<tr> +<td>manage_system_wide_oauth</td> +<td>system</td> +<td>Edit or delete other users' OAuth 2.0 apps.</td> +<td></td> +</tr> +<tr> +<td>create_post</td> +<td>channel</td> +<td>Post in channels.</td> +<td></td> +</tr> +<tr> +<td>create_post_public</td> +<td>channel</td> +<td>Create a system message within a channel.</td> +<td></td> +</tr> +<tr> +<td>create_post_ephermal</td> +<td>channel</td> +<td>Create an ephemeral message within a channel.</td> +<td></td> +</tr> +<tr> +<td>edit_post</td> +<td>channel</td> +<td>Authors edit their own posts.</td> +<td></td> +</tr> +<tr> +<td>edit_others_posts</td> +<td>channel</td> +<td>Edit other users' posts.</td> +<td></td> +</tr> +<tr> +<td>delete_post</td> +<td>channel</td> +<td>Authors delete their own posts.</td> +<td></td> +</tr> +<tr> +<td>delete_others_posts</td> +<td>channel</td> +<td>Delete other users' posts.</td> +<td></td> +</tr> +<tr> +<td>remove_user_from_team</td> +<td>team</td> +<td>Remove users from team.</td> +<td></td> +</tr> +<tr> +<td>create_team</td> +<td>system</td> +<td>Create teams.</td> +<td></td> +</tr> +<tr> +<td>manage_team</td> +<td>team</td> +<td>Access Team Settings.</td> +<td></td> +</tr> +<tr> +<td>import_team</td> +<td>system</td> +<td>Import teams in Team Settings.</td> +<td></td> +</tr> +<tr> +<td>view_team</td> +<td>team</td> +<td>Read the Team object.</td> +<td></td> +</tr> +<tr> +<td>create_bot</td> +<td>team</td> +<td>Create bot accounts.</td> +<td></td> +</tr> +<tr> +<td>assign_bot</td> +<td>team</td> +<td>Assign bots to users other than who created the bot.</td> +<td></td> +</tr> +<tr> +<td>read_bot</td> +<td>team</td> +<td>View own bots created.</td> +<td></td> +</tr> +<tr> +<td>read_others_bots</td> +<td>team</td> +<td>View bots created by others.</td> +<td></td> +</tr> +<tr> +<td>manage_bots</td> +<td>team</td> +<td>Edit and delete own bots.</td> +<td></td> +</tr> +<tr> +<td>manage_others_bots</td> +<td>team</td> +<td>Edit and delete bots created by others.</td> +<td></td> +</tr> +<tr> +<td>view_members</td> +<td>team</td> +<td>List all members on the team.</td> +<td></td> +</tr> +<tr> +<td>list_users_without_team</td> +<td>system</td> +<td>List users without a team.</td> +<td></td> +</tr> +<tr> +<td>create_user_access_token</td> +<td>system</td> +<td>Create user access tokens.</td> +<td></td> +</tr> +<tr> +<td>read_user_access_token</td> +<td>system</td> +<td>Read user access tokens by ID.</td> +<td></td> +</tr> +<tr> +<td>revoke_user_access_token</td> +<td>system</td> +<td>Revoke user access tokens.</td> +<td></td> +</tr> +<tr> +<td>manage_jobs</td> +<td>system</td> +<td>Create and cancel jobs.</td> +<td></td> +</tr> +<tr> +<td>create_emojis</td> +<td>team</td> +<td>Create custom emoji.</td> +<td></td> +</tr> +<tr> +<td>delete_emojis</td> +<td>team</td> +<td>Delete own custom emoji.</td> +<td></td> +</tr> +<tr> +<td>delete_others_emojis</td> +<td>team</td> +<td>Delete custom emoji created by others.</td> +<td></td> +</tr> +<tr> +<td>invite_guest</td> +<td>system</td> +<td>Invite guest users via email invite or add existing guests to teams.</td> +<td></td> +</tr> +<tr> +<td>promote_guest</td> +<td>system</td> +<td>Promote guests to member users.</td> +<td></td> +</tr> +<tr> +<td>demote_to_guest</td> +<td>system</td> +<td>Demote member users to guests.</td> +<td></td> +</tr> +<tr> +<td colspan="4">manage_remote_clusters (deprecated in v5.36) | system | Add, remove, and view remote clusters for shared channels. Deprecated in v5.36; renamed to <code>manage_secure_connections</code>.</td> +</tr> +<tr> +<td>manage_shared_channels</td> +<td>system</td> +<td>Share and unshare channels with existing connections to remote servers.</td> +<td></td> +</tr> +<tr> +<td>manage_secure_connections</td> +<td>system</td> +<td>Create, manage, and remove secure connections to remote servers.</td> +<td></td> +</tr> +<tr> +<td>manage_post_bleve_indexes_job</td> +<td>system</td> +<td>Manage the status of a Bleve post indexing job.</td> +<td></td> +</tr> +<tr> +<td>manage_data_retention_job</td> +<td>system</td> +<td>Manage the status of a data retention job.</td> +<td></td> +</tr> +<tr> +<td>manage_compliance_export_job</td> +<td>system</td> +<td>Manage the status of a compliance export job.</td> +<td></td> +</tr> +<tr> +<td>manage_elasticsearch_post_indexing_job</td> +<td>system</td> +<td>Manage the status of an Elasticsearch post indexing job.</td> +<td></td> +</tr> +<tr> +<td>manage_elasticsearch_post_aggregation_job</td> +<td>system</td> +<td>Manage the status of an Elasticsearch post aggregation job.</td> +<td></td> +</tr> +<tr> +<td>manage_ldap_sync_job</td> +<td>system</td> +<td>Manage the status of an LDAP synchronization job.</td> +<td></td> +</tr> +<tr> +<td>add_bookmark_public_channel</td> +<td>channel</td> +<td>Add bookmarks to a public channel.</td> +<td></td> +</tr> +<tr> +<td>add_bookmark_private_channel</td> +<td>channel</td> +<td>Add bookmarks to a private channel.</td> +<td></td> +</tr> +<tr> +<td>edit_bookmark_public_channel</td> +<td>channel</td> +<td>Make changes to bookmarks in a public channel.</td> +<td></td> +</tr> +<tr> +<td>edit_bookmark_private_channel</td> +<td>channel</td> +<td>Make changes to bookmarks in a private channel.</td> +<td></td> +</tr> +<tr> +<td>delete_bookmark_public_channel</td> +<td>channel</td> +<td>Delete bookmarks in a public channel.</td> +<td></td> +</tr> +<tr> +<td>delete_bookmark_private_channel</td> +<td>channel</td> +<td>Delete bookmarks in a private channel.</td> +<td></td> +</tr> +<tr> +<td>order_bookmark_public_channel</td> +<td>channel</td> +<td>Reorder bookmarks in a public channel.</td> +<td></td> +</tr> +<tr> +<td>order_bookmark_private_channel</td> +<td>channel</td> +<td>Reorder bookmarks in a private channel.</td> +<td></td> +</tr> +<tr> +<td>manage_channel_banner</td> +<td>channel</td> +<td>Manage channel banners.</td> +<td></td> +</tr> +<tr> +<td>manage_channel_access_rules</td> +<td>channel</td> +<td>Manage attribute-based access control rules for channels.</td> +<td></td> +</tr> +</tbody> +</table> + +### `Roles` field + +Roles are applied to objects that represents that user’s membership in a context. These are referenced in the `Roles` field of the `User`, `TeamMember`, `ChannelMember` and `Schemes` Tables. + +In the `TeamMember` and `ChannelMember` tables, it's the `Roles` field that contains custom roles and the `SchemeAdmin` and `SchemeUser` booleans that indicate the member object should inherit the respective roles from the relevant scheme, either the default or custom scheme assigned to the relevant team. + +### `Roles` table + +Roles are dynamic and user configurable, necessitating a database table with the following fields: + +- `Id` (Autoincrement, Primary Key) +- `Name` (Unique String with Character Constraints, e.g. “team_user”). +- `Display Name` (String) +- `Description` (String) +- `Permissions` (String): Space-separated permissions names +- `Scheme Managed` (bool): Indicates whether this role is managed as part of a scheme. +- `BuiltIn` (bool): Indicates if this role is built-in to the Mattermost system and not removable by the user. + +### Built-in roles + +The System Scheme is built-in to the product, and its roles are defined as `BuiltIn: true` in the `Roles` table. You can use the Mattermost API to [retrieve a list of permissions by role name](https://api.mattermost.com/#tag/roles/paths/~1roles~1names/post). + +The following built-in roles with default permissions are available: + +*channel_admin* + +- manage_private_channel_members +- read_public_channel_groups +- use_channel_mentions +- create_post +- use_group_mentions +- add_reaction +- read_private_channel_groups +- remove_reaction +- manage_public_channel_members +- manage_channel_roles +- add_bookmark_public_channel +- edit_bookmark_public_channel +- delete_bookmark_public_channel +- order_bookmark_public_channel +- add_bookmark_private_channel +- edit_bookmark_private_channel +- delete_bookmark_private_channel +- order_bookmark_private_channel +- manage_channel_banner +- manage_channel_access_rules + +*channel_guest* + +- read_channel +- read_channel_contents +- add_reaction +- remove_reaction +- upload_file +- edit_post +- create_post +- use_channel_mentions + +*channel_user* + +- manage_public_channel_properties +- use_group_mentions +- add_reaction +- delete_private_channel +- manage_private_channel_members +- read_private_channel_groups +- delete_public_channel +- read_public_channel_groups +- use_channel_mentions +- read_channel +- read_channel_contents +- delete_post +- get_public_link +- remove_reaction +- manage_public_channel_members +- upload_file +- manage_private_channel_properties +- create_post +- edit_post +- add_bookmark_public_channel +- edit_bookmark_public_channel +- delete_bookmark_public_channel +- order_bookmark_public_channel +- add_bookmark_private_channel +- edit_bookmark_private_channel +- delete_bookmark_private_channel +- order_bookmark_private_channel + +*system_admin* + +- manage_others_slash_commands +- sysconsole_write_user_management_permissions +- edit_brand +- remove_reaction +- manage_incoming_webhooks +- sysconsole_write_user_management_groups +- create_public_channel +- manage_private_channel_members +- sysconsole_write_authentication +- join_private_teams +- create_post_ephemeral +- list_users_without_team +- sysconsole_write_reporting +- join_public_channels +- invite_guest +- list_private_teams +- sysconsole_write_user_management_channels +- manage_others_bots +- read_user_access_token +- add_user_to_team +- view_members +- edit_post +- demote_to_guest +- delete_others_posts +- sysconsole_write_plugins +- delete_private_channel +- sysconsole_read_user_management_system_roles +- sysconsole_read_user_management_users +- revoke_user_access_token +- read_others_bots +- read_public_channel_groups +- sysconsole_write_user_management_teams +- sysconsole_write_billing +- convert_public_channel_to_private +- remove_user_from_team +- manage_team +- add_reaction +- manage_oauth +- list_team_channels +- create_team +- read_jobs +- invite_user +- manage_shared_channels +- remove_others_reactions +- manage_secure_connections +- sysconsole_write_user_management_users +- sysconsole_read_experimental +- sysconsole_write_compliance +- edit_others_posts +- assign_bot +- manage_bots +- manage_others_outgoing_webhooks +- manage_system_wide_oauth +- delete_others_emojis +- manage_others_incoming_webhooks +- promote_guest +- sysconsole_write_experimental +- sysconsole_read_plugins +- create_group_channel +- sysconsole_read_environment +- manage_roles +- use_channel_mentions +- manage_public_channel_properties +- manage_channel_roles +- get_public_link +- sysconsole_read_billing +- sysconsole_write_integrations +- download_compliance_export_result +- manage_slash_commands +- assign_system_admin_role +- create_post +- delete_post +- create_direct_channel +- list_public_teams +- create_post_public +- read_private_channel_groups +- sysconsole_read_integrations +- read_other_users_teams +- manage_jobs +- sysconsole_read_site +- manage_outgoing_webhooks +- sysconsole_write_environment +- manage_system +- sysconsole_read_user_management_permissions +- manage_public_channel_members +- sysconsole_write_about +- import_team +- sysconsole_write_user_management_system_roles +- sysconsole_read_reporting +- upload_file +- read_channel +- read_channel_contents +- sysconsole_read_user_management_teams +- delete_emojis +- manage_private_channel_properties +- view_team +- sysconsole_read_user_management_groups +- create_private_channel +- create_bot +- join_public_teams +- delete_public_channel +- read_public_channel +- sysconsole_read_about +- read_bots +- sysconsole_read_authentication +- edit_other_users +- sysconsole_read_user_management_channels +- convert_private_channel_to_public +- use_group_mentions +- create_user_access_token +- sysconsole_write_site +- manage_team_roles +- sysconsole_read_compliance +- create_emojis +- manage_post_bleve_indexes_job +- manage_data_retention_job +- manage_compliance_export_job +- manage_elasticsearch_post_indexing_job +- manage_elasticsearch_post_aggregation_job +- manage_ldap_sync_job +- add_bookmark_public_channel +- edit_bookmark_public_channel +- delete_bookmark_public_channel +- order_bookmark_public_channel +- add_bookmark_private_channel +- edit_bookmark_private_channel +- delete_bookmark_private_channel +- order_bookmark_private_channel +- manage_channel_banner +- manage_channel_access_rules + +*system_custom_group_admin* + +- create +- edit +- delete +- manage members +- restore + +*system_shared_channel_manager* + +- manage_shared_channels + +*system_guest* + +- create_group_channel +- create_direct_channel + +*system_manager* + +- sysconsole_write_user_management_permissions +- sysconsole_read_about +- sysconsole_read_user_management_channels +- join_private_teams +- delete_private_channel +- view_team +- read_jobs +- sysconsole_read_user_management_teams +- sysconsole_read_plugins +- manage_channel_roles +- manage_public_channel_members +- remove_user_from_team +- sysconsole_read_environment +- list_private_teams +- manage_private_channel_members +- manage_private_channel_properties +- edit_brand +- add_user_to_team +- convert_public_channel_to_private +- read_private_channel_groups +- sysconsole_write_environment +- manage_jobs +- sysconsole_read_reporting +- read_public_channel +- manage_team +- read_channel +- sysconsole_read_integration +- read_public_channel_groups +- list_public_teams +- manage_team_roles +- sysconsole_read_user_management_groups +- manage_public_channel_properties +- sysconsole_write_user_management_groups +- sysconsole_read_user_management_permissions +- sysconsole_write_site +- sysconsole_read_site +- sysconsole_write_user_management_channels +- sysconsole_write_integrations +- delete_public_channel +- sysconsole_write_user_management_teams +- join_public_teams + +*system_post_all* + +- create_post +- use_channel_mentions +- use_group_mentions + +*system_post_all_public* + +- create_post_public +- use_group_mentions +- use_channel_mentions + +*system_read_only_admin* + +- sysconsole_read_compliance +- read_other_users_teams +- sysconsole_read_reporting +- list_private_teams +- sysconsole_read_experimental +- read_jobs +- read_public_channel +- view_team +- sysconsole_read_user_management_users +- sysconsole_read_plugins +- sysconsole_read_user_management_teams +- read_public_channel_groups +- sysconsole_read_user_management_channels +- sysconsole_read_user_management_permissions +- sysconsole_read_about +- download_compliance_export_result +- read_channel +- sysconsole_read_authentication +- sysconsole_read_site +- list_public_teams +- sysconsole_read_integrations +- read_private_channel_groups +- sysconsole_read_environment +- sysconsole_read_user_management_groups + +*system_user* + +- list_public_teams +- join_public_teams +- create_direct_channel +- create_group_channel +- view_members +- create_team +- create_emojis +- delete_emojis + +*system_user_access_token* + +- create_user_access_token +- read_user_access_token +- revoke_user_access_token + +*system_user_manager* + +- manage_public_channel_members +- sysconsole_write_user_management_groups +- manage_private_channel_properties +- read_channel +- sysconsole_read_authentication +- manage_private_channel_members +- read_jobs +- view_team +- sysconsole_read_user_management_groups +- list_private_teams +- join_public_teams +- manage_team +- list_public_teams +- add_user_to_team +- sysconsole_read_user_management_channels +- sysconsole_write_user_management_teams +- read_public_channel +- sysconsole_read_user_management_permissions +- manage_public_channel_properties +- join_private_teams +- convert_public_channel_to_private +- manage_channel_roles +- sysconsole_read_user_management_teams +- read_public_channel_groups +- delete_public_channel +- remove_user_from_team +- manage_team_roles +- delete_private_channel +- sysconsole_write_user_management_channels +- read_private_channel_groups + +*team_admin* + +- remove_user_from_team +- manage_others_slash_commands +- manage_team_roles +- manage_public_channel_members +- use_group_mentions +- manage_others_outgoing_webhooks +- manage_slash_commands +- manage_team +- manage_others_incoming_webhooks +- manage_channel_roles +- read_public_channel_groups +- remove_reaction +- delete_post +- manage_outgoing_webhooks +- use_channel_mentions +- manage_incoming_webhooks +- delete_others_posts +- read_private_channel_groups +- create_post +- manage_private_channel_members +- convert_public_channel_to_private +- add_reaction +- import_team +- add_bookmark_public_channel +- edit_bookmark_public_channel +- delete_bookmark_public_channel +- order_bookmark_public_channel +- add_bookmark_private_channel +- edit_bookmark_private_channel +- delete_bookmark_private_channel +- order_bookmark_private_channel +- manage_channel_banner +- manage_channel_access_rules + +*team_guest* + +- view_team + +*team_post_all* + +- create_post +- use_group_mentions +- use_channel_mentions + +*team_post_all_public* + +- use_group_mentions +- create_post_public +- use_channel_mentions + +*team_user* + +- invite_user +- add_user_to_team +- list_team_channels +- join_public_channels +- read_public_channel +- view_team +- create_public_channel +- create_private_channel + +### `Schemes` table + +Schemes are dynamic and user configurable, necessitating a database table with the following fields: + +- `Id` (Autoincrement, Primary Key) +- `Name` (Unique String with Character Constraints, e.g. “corporate_scheme”) +- `Display` Name +- `Description` (String) +- `Scope` (String): Team or Channel +- `Team Admin Role` (String): Empty if Channel Scope +- `Team User Role` (String): Empty if Channel Scope +- `Team Guest Role` (String): Empty if Channel Scope +- `Channel Admin Role` (String): Always provided +- `Channel User Role` (String): Always provided +- `Channel Guest Role` (String): Always provided diff --git a/docs/main/administration-guide/onboard/advanced-permissions.mdx b/docs/main/administration-guide/onboard/advanced-permissions.mdx new file mode 100644 index 000000000000..405e67547746 --- /dev/null +++ b/docs/main/administration-guide/onboard/advanced-permissions.mdx @@ -0,0 +1,213 @@ +--- +title: "Advanced permissions" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost system admins using Mattermost Cloud or Mattermost Server can use Advanced Permissions to customize which users can perform specific actions, such as creating teams, managing channels, and configuring webhooks. The Mattermost permission system is based on a modified RBAC (role-based access control) architecture, using roles to determine which users have the ability to perform various actions. + +Two permission schemes are provided in Mattermost: + +- **System Scheme**: Applies permissions universally across all teams and channels. +- **Team Override Schemes**: Allow admins to customize permissions for each team. + +This document describes the types of permissions that can be given to users of Mattermost using schemes as well as channel settings and roles. The [permissions backend documentation](/administration-guide/onboard/advanced-permissions-backend-infrastructure) provides additional technical details around permissions. + +## Permissions structure + +The Mattermost System Console provides a number of elements for Admins to control the permissions in their system. + +### System scheme + +You can set the default permissions granted to system admins, team admins, channel admins, guests (if enabled), and all members. The permissions granted in the System Scheme apply system-wide, meaning: + +- **Guests:** If Guest Accounts are enabled, permissions apply to guest users in all channels, in all teams. +- **All Members:** Permissions apply to all members, including admins, in all channels, in all teams. +- **Channel Administrators:** Permissions apply to all channel admins in all channels, in all teams. +- **Team Administrators:** Permissions apply to all team admins, in all teams. + +To override the System Scheme default permissions in a specific team, you must set up a Team Override Scheme. + +You can access the System Scheme interface by going to **System Console \> User Management \> Permissions \> System Scheme**. + +![image](/images/system-scheme.png) + +### Team override scheme + +<PlanAvailability slug="entry-adv" /> + +On systems with multiple [Mattermost teams](/end-user-guide/collaborate/organize-using-teams#single-team-versus-multiple-teams), each team may operate and collaborate in a unique way. Team Override Schemes give Admins the flexibility to tailor permissions to the needs of each team. + +When you use this permission scheme: + +- The permissions granted in a Team Override Scheme apply only in the teams which are assigned to the scheme. +- The System Scheme does not apply to teams that are added to a Team Override Scheme. +- Teams can only belong to one Team Override Scheme. + +You can access the Team Override Scheme interface by going to **System Console \> User Management \> Permissions \> Team Override Schemes**. + +![image](/images/team-scheme.png) + +## Channel permissions + +The channel permissions interface is accessed in **System Console \> User Management \> Channels**. + +### Advanced access controls + +<PlanAvailability slug="entry-adv" /> + +See the [team and channel management](/administration-guide/manage/team-channel-members#advanced-access-controls) documentation for details on available channel access controls. + +## Recipes + +This section provides some examples of common permissions use cases for team management, channel management, and overall permissions. + +### Team management + +<PlanAvailability slug="entry-adv" /> + +#### Ensure users only see each other when in the same team or channel + +Example: A classified organization wants to use Mattermost teams for classified projects. In each project, team members can't know about members outside of their project, and [@mentions](/end-user-guide/collaborate/mention-people) can't disclose the names of people outside of a classified project. + +Use the [mmctl permissions remove](/administration-guide/manage/mmctl-command-line-tool#mmctl-permissions-remove) command to revoke the `view_member` permission from the `system_user` role: `mmctl permissions remove system_user view_member`. + +#### Only allow admins, in a specific team, to add members + +Example: In Team A, only allow system and team admins to add new team members. As the default for all other teams, allow all users to add and invite new members. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members \> Teams** panel, check the box for **Add Team Members**. This sets the system default for all teams. +4. Select **Save**. +5. Select the back arrow to return to the **Permission Schemes** menu. +6. Select **New Team Override Scheme**. + +> 1. Name and describe the scheme. For example, `Authorized Personnel Only` with description `Restrict adding team members to eam and System Admins.` +> 2. Select **Add Teams** to add Team B to the **Select teams to override permissions** list, locate Team B, then select **Add**. +> 3. In the **All Members** panel, uncheck the box for **Add Team Members**. +> 4. In the **Team Administrators** panel, check the box for **Add Team Members**. + +7. Select **Save**. +8. Select the back arrow to return to the **Permission Schemes** menu. + +### Public and private channel management + +<PlanAvailability slug="entry-adv" /> + +#### Restrict who can rename & edit channels + +Example: As the default for the entire system, restrict renaming channels and editing headers and purposes to admins only. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members** panel, uncheck the box for **Manage Public Channels \> Manage Channel Settings**. + +The **Manage Channel Settings** option is now only available to channel admins, team admins, and system admins. + +#### Restrict who can create channels in specific teams + +Example: In Team C, restrict public channel creation to admins. As the default for all other teams, allow everyone to create public channels. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members** panel, in the **Manage Public Channels** menu, check the box for **Create Channels**. This sets the system default to allow creation of public channels on all teams. +4. Select **Save**. +5. Select the arrow to return to the **Permission Schemes** interface. +6. Select **New Team Override Scheme**. + +> 1. Name and describe the scheme. For example, `Contractor Scheme` with description `Restrict public channel creation to Admins only`. +> 2. Select **Add Teams** to add Team B to the **Select teams to override permissions** list, locate Team B, then select **Add**. +> 3. In the **All Members** panel, in the **Manage Public Channels** section, uncheck the box for **Create Channels**. +> 4. In the **Team Administrators** panel, in the **Manage Public Channels** section, check the box for **Create Channels**. + +### Convert public channels to private channels + +#### Allow anyone to convert public channels to private channels + +Example: Set the default setting to allow all members, team admins, and channel admins to convert public channels to private. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members** panel, uncheck the box for **Manage Public Channels \> Convert Channels**. + +This permission is applied to all other roles (excluding the Guest role). When this permission is not enabled for all members, it must be manually applied to team admins and channel admins if required. + +### Read-only channels + +<PlanAvailability slug="entry-adv" /> + +#### Members can participate but guests can only read and react + +1. Go to **System Console \> User Management \> Channels**. +2. Select **Edit** next to the name of the channel you want to configure. +3. In the **Create Posts** panel, uncheck **Guests**. +4. In the **Post Reactions** panel, uncheck **Guests** if required. +5. Select **Save**. + +The channel is available for all members and guests to access, but guests can only read messages and react to them. + +#### Create an announcement channel where only channel admins can post + +1. Create a new channel (either public or private). +2. Navigate to **System Console \> User Management \> Channels**. +3. Select **Edit** next to the name of the channel you just created (you may need to search for it). +4. In the **Create Posts** panel, uncheck **Guests** and **Members**. +5. In the **Post Reactions** panel, uncheck **Guests** and **Members**. +6. Select **Save**. + +The channel is available for all members and guests to access but only admins can post. + +### Message management + +#### Restrict who can delete messages + +Example: As the default for the entire system, restrict deleting posts to only system and team admins. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members** and **Channel Administrators** panels, in the **Delete Posts** section, uncheck the boxes for **Delete Own Posts** and **Delete Others' Posts**. +4. In the **Channel Administrators** and **Team Administrators** panels, in the **Delete Posts** section, check the boxes for **Delete Own Posts** and **Delete Others' Posts**. + +#### Restrict who can edit messages + +Example: As the default for the entire system, only allow users to edit their own posts for five minutes after posting. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members**, **Channel Administrators**, and **Team Administrators** panels, in the **Manage Posts** section, check the box for **Edit Posts**. +4. From any panel, select the gear button to set the global time limit to `300` seconds. + +### Integration management + +From Mattermost v11.2, the System Console provides enhanced controls for managing integrations (webhooks, slash commands, OAuth apps), including separate permissions for managing your own integrations versus other users' integrations. + +#### Restrict who can manage webhooks and slash commands + +Example: As the default for the entire system, only allow system admins to create, edit and delete integrations. + +1. Go to **System Console \> User Management \> Permissions**. +2. Select **Edit Scheme**. +3. In the **All Members** and **Team Administrators** panels, in the **Integrations & Customizations** section, uncheck the boxes for **Manage Incoming Webhooks**, **Manage Outgoing Webhooks**, and **Manage Slash Commands**. + +## Administration tools + +There are a number of API and mmctl tools available for admins to help in configuring and troubleshooting the permissions system: + +1. Reset all permissions to the default on new installations using the [mmctl permissions reset](/administration-guide/manage/mmctl-command-line-tool#mmctl-permissions-reset) command. +2. Use the [GetAllRoles](https://api.mattermost.com/#tag/roles/operation/GetAllRoles) API endpoint to get a list of all roles. +3. Add permissions to a role using the [mmctl permissions add](/administration-guide/manage/mmctl-command-line-tool#mmctl-permissions-add) command. + +## Backend infrastructure + +Technical admins or developers looking for a deeper understanding of the permissions backend can refer to our [permissions backend documentation](/administration-guide/onboard/advanced-permissions-backend-infrastructure). + +## Glossary + +- **Permission:** The ability to execute certain actions. Permissions are granted to roles. +- **Roles:** A set of permissions. Users or groups are assigned to roles. +- **Group:** A set of users, usually synced from AD/LDAP. Groups are assigned to roles in the context of teams, channels, or system-wide. +- **Default Roles:** All Members, Guests (if enabled), channel admins, team admins, system admins. +- **System Scheme:** A set of default roles that apply system-wide. +- **Team Override Scheme:** A set of default roles that apply only in the team specified. Permissions granted to roles in a Team Override Scheme overrides roles in the System Scheme. +- **System-wide:** Applies across the entire system, including all teams of which the user is a member. +- **Team-wide:** Applies in a specific team only. diff --git a/docs/main/administration-guide/onboard/bulk-loading-data.mdx b/docs/main/administration-guide/onboard/bulk-loading-data.mdx new file mode 100644 index 000000000000..ed64ee7dd4f1 --- /dev/null +++ b/docs/main/administration-guide/onboard/bulk-loading-data.mdx @@ -0,0 +1,1522 @@ +--- +title: "Bulk loading data" +draft: true +--- +<PlanAvailability slug="all-commercial" /> + +Large quantities of data can be imported from a [JSONL](https://jsonlines.org) file into Mattermost at the command line using the bulk loading feature. This feature is most suitable for migrating data from an existing system, or for pre-populating a new installation with data. + +You can import the following data types: + +- Teams +- Threaded discussions +- Channels (public and private) +- Users +- Users' team memberships +- Users' channel memberships +- Users' notification preferences +- Users' custom status +- Posts (regular, non-reply posts) +- Posts' replies +- Posts' reactions +- Posts' file attachments +- Direct message and group message channels +- Direct message and group message channels' read/unread status +- Direct messages and group messages +- Direct messages from a user to themselves +- Permissions schemes +- Custom emoji +- Bot users + +Importing additional types of posts is not yet supported. + +## About the bulk loading command + +**The bulk loading command is interruptible and idempotent** + +If the import is interrupted for any reason, it continues from where it left off the next time you run it. You can run the command repeatedly with the same data file, and the data is imported only once. Posts with matching timestamps to incoming posts will have their attachments replaced by the incoming data. Prior to v5.20 any updates to posts with matching timestamps were appended to older posts. + +**You can run the bulk loading command on a live system** + +Although you don't need to shut down Mattermost to run the command, changes made by users of the system between runs can be overwritten if the corresponding fields exist in the data file. + +**Some data fields are optional** + +Not all fields are mandatory. If an optional field is missing from the object that is being imported, the field's current value in the database is not changed. + +**The bulk loading command is not a synchronization tool** + +You cannot use the bulk loading command to remove any objects or their fields from the Mattermost database. The command only creates or overwrites fields. + +<Important> + +The bulk loading command runs in the mmctl and operates in the security context of the mmctl. This means it has full permissions to access and alter everything in the Mattermost database. + +</Important> + +## Bulk load data + +Before running the bulk loading command, you must first create a [JSONL](https://jsonlines.org) file that contains the data that you want to import in your Mattermost directory. The file can have any name, but in this example it's called `data.jsonl`. The format of the file is described in the [data-format](/administration-guide/onboard/bulk-loading-data#data-format) section. + +Next, zip it by running the `zip -r data.zip data.jsonl` command. + +### Using mmctl local mode + +From Mattermost v9.5, the mmctl bulk import process command in [local mode](/administration-guide/manage/mmctl-command-line-tool#local-mode) supports processing an import file without uploading it to the server. + +Run `mmctl import process --bypass-upload <file>.zip --local` to start your import and enable the Mattermost server to read from the file directly. + +### Not using mmctl local mode + +If you're not running mmctl commands in local mode: + +1. Upload the ZIP file to the database by running the [mmctl import upload](/administration-guide/manage/mmctl-command-line-tool#mmctl-import-upload) command. For example: `mmctl import upload data.zip`. After uploading, two IDs are returned: the first line contains the upload session ID, and the second line contains the filename. +2. Confirm that the file is uploaded and ready for use by running the [mmctl import list available](/administration-guide/manage/mmctl-command-line-tool#mmctl-import-list-available) command. +3. Import your uploaded file by running the [mmctl import process](/administration-guide/manage/mmctl-command-line-tool#mmctl-import-process) command using the upload session ID (not the filename). For example: `mmctl import process <upload_session_id>_data.zip` where `<upload_session_id>` is the upload session ID returned from the upload command. + +## Data format + +The input data file must be a valid [JSONL](https://jsonlines.org) file with the following objects, each on its own line in the file. The objects must occur in the file in the order listed. + +Version +Mandatory. The Version object must be the first line in the file, and must occur only once. The version is the version of the bulk importer tool, which is currently `1`. + +Scheme +Optional. If present, Scheme objects must occur after the Version object but before any Team objects. + +Emoji +Optional. If present, Emoji objects must occur after the Version objects but before any Team objects. + +Team +Optional. If present, Team objects must occur after any Scheme objects and before any Channel objects. + +Channel +Optional. If present, Channel objects must occur after all Team objects and before any User objects. + +User +Optional. If present, User objects must occur after the Team and Channel objects in the file and before any Post objects. Each User object defines the teams and channels that the user is a member of. If the corresponding teams and channels are not in the data file, then they must exist in the Mattermost database. + +Post +Optional. If present, Post objects must occur after the last User object but before any DirectChannel objects. Each Post object defines the team, the channel, and the username of the user who posted the message. If the corresponding team, channel, or user are not in the data file, then they must exist in the Mattermost database. + +DirectChannel +Optional. If present, DirectChannel objects must occur after all Post objects in the file and before any DirectPost objects. + +DirectPost +Optional. If present, DirectPost objects must occur after all other objects in the file. Each DirectPost object defines the usernames of the channel members and the username of the user who posted the message. If the corresponding usernames are not in the data file, then they must exist in the Mattermost database. + +With the exception of the Version object, each object has a field or a combination of fields that is used as the unique identifier of that object. The bulk loader uses the unique identifier to determine if the object being imported is a new object or an update to an existing object. + +The identifiers for each object are listed in the following table: + +<table> +<caption>Objects and their unique identifiers</caption> +<thead> +<tr> +<th>Object</th> +<th>Unique Identifier</th> +</tr> +</thead> +<tbody> +<tr> +<td>Version</td> +<td>Not Applicable</td> +</tr> +<tr> +<td>Scheme</td> +<td><em>name</em></td> +</tr> +<tr> +<td>Role</td> +<td><em>name</em></td> +</tr> +<tr> +<td>Emoji</td> +<td><em>name</em></td> +</tr> +<tr> +<td>Team</td> +<td><em>name</em></td> +</tr> +<tr> +<td>Channel</td> +<td><em>name</em>, <em>team</em></td> +</tr> +<tr> +<td>User</td> +<td><em>username</em></td> +</tr> +<tr> +<td>UserNotifyProps</td> +<td><em>username</em></td> +</tr> +<tr> +<td>UserTeamMembership</td> +<td><em>team</em>, <em>username</em></td> +</tr> +<tr> +<td>UserChannelMembership</td> +<td><em>team</em>, <em>channel</em>, <em>username</em></td> +</tr> +<tr> +<td>Post</td> +<td><em>channel</em>, <em>message</em>, <em>create_at</em></td> +</tr> +<tr> +<td>Reply</td> +<td><em>post</em>, <em>message</em>, <em>create_at</em></td> +</tr> +<tr> +<td>Reaction</td> +<td><em>post</em>, <em>emoji_name</em>, <em>create_at</em></td> +</tr> +<tr> +<td>Attachment</td> +<td><em>path</em></td> +</tr> +<tr> +<td>DirectChannel</td> +<td><em>members</em></td> +</tr> +<tr> +<td>DirectPost</td> +<td><em>channel_members</em>, <em>user</em>, <em>message</em>, <em>create_at</em></td> +</tr> +</tbody> +</table> + +The following fragment is from a file that imports two teams, each with two channels, many users, and many posts. + +``` javascript +{ "type": "version", ... } +{ "type": "team", "team": { "name": "TeamA", ...} } +{ "type": "team", "team": { "name": "TeamB", ...} } +{ "type": "channel", "channel": { "team": "TeamA", "name": "channel_a1", ...} } +{ "type": "channel", "channel": { "team": "TeamA", "name": "channel_a2", ...} } +{ "type": "channel", "channel": { "team": "TeamB", "name": "channel_b1", ...} } +{ "type": "channel", "channel": { "team": "TeamB", "name": "channel_b2", ...} } +{ "type": "user", "user": { "username": "user001", ...} } +{ "type": "user", "user": { "username": "user002", ...} } +{ "type": "user", "user": { "username": "user003", ...} } +{ "type": "user", ... } +{ "type": "user", ... } +{ "type": "user", ... } +. +. +. +{ "type": "post", { "team": "TeamA", "name": "channel_a1", "user": "user001", ...} } +{ "type": "post", { "team": "TeamA", "name": "channel_a1", "user": "user001", ...} } +{ "type": "post", { "team": "TeamA", "name": "channel_a1", "user": "user001", ...} } +. +. +. +``` + +## Version object + +The Version object must be the first object in the data file, and can appear only once. The version represents the version of the bulk import tool and currently is `1`. + +### Example Version object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "version", + "version": 1 +} +``` + +### Fields of the Version object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>Must be the string "version"</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">version</td> + <td valign="middle">number</td> + <td>Must be the number 1.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> +</table> + +## Scheme object + +Scheme objects represent Permissions Schemes in the Mattermost permissions system. If present, Scheme objects must occur after the Version object and before any Team objects. + +### Example Scheme object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "scheme", + "scheme": { + "name": "custom_scheme_name", + "display_name": "Custom Scheme Name", + "description": "This is a custom override scheme.", + "scope": "team", + "default_team_admin_role": { + "name": "custom_scheme_team_admin_role", + "display_name": "Custom Scheme Team Admin Role", + "description": "This is the default team admin role for the custom scheme.", + "permissions": ["add_user_to_team", "manage_team_roles"], + }, + "default_team_user_role": { + "name": "custom_scheme_team_user_role", + "display_name": "Custom Scheme Team User Role", + "description": "This is the default team user role for the custom scheme.", + "permissions": ["create_public_channel", "create_private_channel"], + }, + "default_channel_admin_role": { + "name": "custom_scheme_channel_admin_role", + "display_name": "Custom Scheme Channel Admin Role", + "description": "This is the default channel admin role for the custom scheme.", + "permissions": ["manage_private_channel_members", "manage_channel_roles"], + }, + "default_channel_user_role": { + "name": "custom_scheme_channel_user_role", + "display_name": "Custom Scheme Channel User Role", + "description": "This is the default channel user role for the custom scheme.", + "permissions": ["manage_public_channel_members", "manage_public_channel_properties"], + }, + } +} +``` + +### Fields of the Scheme object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The scheme name. Must start with and contain only lowercase letters <kbd>([a-z0-9])</kbd> or <kbd>_</kbd>, and must be between 2-64 characters in length.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the scheme.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">scope</td> + <td valign="middle">string</td> + <td>The scope for the scheme. Must be either "team" or "channel".</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">description</td> + <td valign="middle">string</td> + <td>The description of the scheme.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">default_team_admin_role</td> + <td valign="middle"><b>Role</b> object</td> + <td>The default role applied to team admins in teams using this scheme. This field is mandatory if the scheme scope is set to "team", otherwise must <b>not</b> be present.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">default_team_user_role</td> + <td valign="middle"><b>Role</b> object</td> + <td>The default role applied to Team Users in teams using this scheme. This field is mandatory if the scheme scope is set to "team", otherwise must <b>not</b> be present.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">default_channel_admin_role</td> + <td valign="middle"><b>Role</b> object</td> + <td>The default role applied to channel admins in channels using this scheme. This field is mandatory for both "team" and "channel" scope schemes.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">default_channel_user_role</td> + <td valign="middle"><b>Role</b> object</td> + <td>The default role applied to Channel Users in channels using this scheme. This field is mandatory for both "team" and "channel" scope schemes.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> +</table> + +### Fields of the Role object + +This object is a member of the Scheme object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The scheme name.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the scheme.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">description</td> + <td valign="middle">string</td> + <td>The description of the scheme.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">permissions</td> + <td valign="middle">array</td> + <td>The permissions the role should grant. This is an array of strings where the strings are the names of individual permissions in the Mattermost permissions system.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## Emoji object + +Emoji objects represent custom Emoji. If present, Emoji objects must occur after the Version object and before any Team objects. + +### Example Emoji object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ +"type": "emoji", +"emoji": { + "name": "custom-emoji-troll", + "image": "bulkdata/emoji/trollolol.png" + } +} +``` + +### Fields of the Emoji object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The emoji name.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">image</td> + <td valign="middle">string</td> + <td>The path (either absolute or relative to the current working directory) to the image file for this emoji.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">Yes</td> + </tr> +</table> + +## Team object + +If present, Team objects must occur after the Version object and before any Channel objects. + +### Example Team object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ +"type": "team", +"team": { + "name": "team-name", + "display_name": "Team Display Name", + "type": "O", + "description": "The Team Description", + "allow_open_invite": true + } +} +``` + +### Fields of the Team object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot><tr><td colspan="5">[1] Not validated, but an error occurs if no such scheme exists when running in apply mode.</td></tr></tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The team name.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the team.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>The type of team. Can have one the following values:<br /> <kbd>O</kbd> for an open team<br /> <kbd>I</kbd> for an invite-only team.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">description</td> + <td valign="middle">string</td> + <td>The team description.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">allow_open_invite</td> + <td valign="middle">bool</td> + <td>Whether to allow open invitations. Must have one of the following values:<br /> <kbd>true</kbd><br /> <kbd>false</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">scheme</td> + <td valign="middle">string</td> + <td>The name of the Scheme that should be applied to this team.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## Channel object + +If present, Channel objects must occur after all Team objects and before any User objects. + +### Example Channel object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "channel", + "channel": { + "team": "team-name", + "name": "channel-name", + "display_name": "Channel Name", + "type": "O", + "header": "The Channel Header", + "purpose": "The Channel Purpose", + } +} +``` + +### Fields of the Channel object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot><tr><td colspan="5">[1] Not validated, but an error occurs if no such team/scheme exists when running in apply mode.</td></tr></tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">team</td> + <td valign="middle">string</td> + <td>The name of the team this channel belongs to.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the channel. Must start with and contain only lowercase letters <kbd>([a-z0-9])</kbd> or <kbd>-</kbd> or <kbd>_</kbd>.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">display_name</td> + <td valign="middle">string</td> + <td>The display name for the channel.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">type</td> + <td valign="middle">string</td> + <td>The type of channel. Can have one the following values:<br /> <kbd>O</kbd> for a public channel.<br /> <kbd>P</kbd> for a private channel.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">header</td> + <td valign="middle">string</td> + <td>The channel header.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">purpose</td> + <td valign="middle">string</td> + <td>The channel purpose.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">scheme</td> + <td valign="middle">string</td> + <td>The name of the Scheme that should be applied to this team.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## User object + +If present, User objects must occur after the Team and Channel objects in the file and before any Post objects. + +### Example User object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "user", + "user": { + "profile_image": "profile-picture.png", + "username": "username", + "email": "email@example.com", + "auth_service": "", + "password": "passw0rd", + "nickname": "bobuser", + "first_name": "Bob", + "last_name": "User", + "position": "Senior Developer", + "roles": "system_user", + "locale": "pt_BR", + "teams": [ + { + "name": "team-name", + "theme": "{ + \"awayIndicator\":\"#DBBD4E\", + \"buttonBg\":\"#23A1FF\", + \"buttonColor\":\"#FFFFFF\", + \"centerChannelBg\":\"#ffffff\", + \"centerChannelColor\":\"#333333\", + \"codeTheme\":\"github\", + \"linkColor\":\"#2389d7\", + \"mentionBg\":\"#2389d7\", + \"mentionColor\":\"#ffffff\", + \"mentionHighlightBg\":\"#fff2bb\", + \"mentionHighlightLink\":\"#2f81b7\", + \"newMessageSeparator\":\"#FF8800\", + \"onlineIndicator\":\"#7DBE00\", + \"sidebarBg\":\"#fafafa\", + \"sidebarHeaderBg\":\"#3481B9\", + \"sidebarHeaderTextColor\":\"#ffffff\", + \"sidebarText\":\"#333333\", + \"sidebarTextActiveBorder\":\"#378FD2\", + \"sidebarTextActiveColor\":\"#111111\", + \"sidebarTextHoverBg\":\"#e6f2fa\", + \"sidebarUnreadText\":\"#333333\", + }", + "roles": "team_user team_admin", + "channels": [ + { + "name": "channel-name", + "roles": "channel_user", + "notify_props": { + "desktop": "default", + "mark_unread": "all" + } + } + ] + } + ] + } +} +``` + +### Fields of the User object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">profile_image</td> + <td valign="middle">string</td> + <td>The user’s profile image. This must be an existing file path.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">username</td> + <td valign="middle">string</td> + <td>The user’s username. This is the unique identifier for the user.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email</td> + <td valign="middle">string</td> + <td>The user’s email address.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">auth_service</td> + <td valign="middle">string</td> + <td>The authentication service to use for this user account. If not provided, it defaults to password-based authentication. Must be one of the following values:<br /> <kbd>""</kbd> or not provided - password authentication.<br /> <kbd>"gitlab"</kbd> - GitLab authentication.<br /> <kbd>"ldap"</kbd> - LDAP authentication (Enterprise and Professional)<br /> <kbd>"saml"</kbd> - Generic SAML based authentication (Enterprise)<br /> <kbd>"google"</kbd> - Google OAuth authentication (Enterprise)<br /> <kbd>"office365"</kbd> - Microsoft Entra ID OAuth Authentication (Enterprise)</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">auth_data</td> + <td valign="middle">string</td> + <td>The authentication data if <kbd>auth_service</kbd> is used. The value depends on the <kbd>auth_service</kbd> that is specified.<br /> The data comes from the following fields for the respective auth_services:<br /> <kbd>""</kbd> or not provided - must be omitted.<br /> <kbd>"gitlab"</kbd> - The value of the Id attribute provided in the GitLab auth data.<br /> <kbd>"ldap"</kbd> - The value of the LDAP attribute specified as the "ID Attribute" in the Mattermost LDAP configuration.<br /> <kbd>"saml"</kbd> - The value of the SAML Email address attribute.<br /> <kbd>"google"</kbd> - The value of the OAuth Id attribute.<br /> <kbd>"office365"</kbd> - The value of the OAuth Id attribute.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">password</td> + <td valign="middle">string</td> + <td>A password for the user. Can be present only when password-based authentication is used. When password-based authentication is used and the password is not present, the bulk loader generates a password.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">nickname</td> + <td valign="middle">string</td> + <td>The user’s nickname.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">first_name</td> + <td valign="middle">string</td> + <td>The user’s first name.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">last_name</td> + <td valign="middle">string</td> + <td>The user’s last name.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">position</td> + <td valign="middle">string</td> + <td>The user’s position.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The user’s roles. Must be one of the following values:<br /> <kbd>"system_user"</kbd><br /> <kbd>"system_admin system_user"</kbd></td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">locale</td> + <td valign="middle">string</td> + <td>The user’s locale. This must be a valid locale for which Mattermost has been localised.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">delete_at</td> + <td valign="middle">int64</td> + <td>Timestamp for when the user was deactivated.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">teams</td> + <td valign="middle">array</td> + <td>The teams which the user will be made a member of. Must be an array of <b>UserTeamMembership</b> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">theme</td> + <td valign="middle">string</td> + <td>The user’s theme. Formatted as a Mattermost theme string.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">military_time</td> + <td valign="middle">string</td> + <td>How times should be displayed to this user. Must be one of the following values:<br /> <kbd>"true"</kbd> - Use 24 hour clock.<br /> <kbd>"false"</kbd> - Use 12 hour clock.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">collapse_previews</td> + <td valign="middle">string</td> + <td>Whether to collapse or expand link previews by default. Must be one of the following values:<br /> <kbd>"true"</kbd> - Collapsed by default.<br /> <kbd>"false"</kbd> - Expanded by default.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message_display</td> + <td valign="middle">string</td> + <td>Which style to use for displayed messages. Must be one of the following values:<br /> <kbd>"clean"</kbd> - Use the standard style.<br /> <kbd>"compact"</kbd> - Use the compact style.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel_display_mode</td> + <td valign="middle">string</td> + <td>How to display channel messages. Must be one of the following values:<br /> <kbd>"full"</kbd> - Use the full width of the screen.<br /> <kbd>"centered"</kbd> - Use a fixed width, centered block.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">tutorial_step</td> + <td valign="middle">string</td> + <td>Where to start the user tutorial. Must be one of the following values:<br /> <kbd>"1"</kbd>, <kbd>"2"</kbd> or <kbd>"3"</kbd> - Start from the specified tutorial step.<br /> <kbd>"999"</kbd> - Skip the user tutorial.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">use_markdown_preview</td> + <td valign="middle">bool</td> + <td>Enable preview of message markdown formatting. Can have one the following values:<br /> <kbd>"True"</kbd> <br /> <kbd>"False"</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">use_formatting</td> + <td valign="middle">bool</td> + <td>Enable post formatting for links, emoji, text styles and line breaks. Can have one the following values:<br /> <kbd>"True"</kbd> <br /> <kbd>"False"</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">show_unread_section</td> + <td valign="middle">bool</td> + <td>Enable showing unread messages at top of channel sidebar. Can have one the following values:<br /> <kbd>"True"</kbd> <br /> <kbd>"False"</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email_interval</td> + <td valign="middle">string</td> + <td>Specify an email batching interval during bulk import. Can have one of the following values:<br /> <kbd>"immediately"</kbd> - Emails are sent immediately. <br /> <kbd>"fifteen"</kbd> - Emails are batched and sent every 15 minutes.<br /> <kbd>"hour"</kbd> - Emails are batched and sent every hour.<br /> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">notify_props</td> + <td valign="middle"><b>UserNotifyProps</b> object</td> + <td>The user’s notify preferences, as defined by the <b>UserNotifyProps</b> object.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the UserNotifyProps object + +This object is a member of the User object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot><tr><td colspan="5">[1] Not validated, but an error occurs if no such team exists when running in apply mode.</td></tr></tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop</td> + <td valign="middle">string</td> + <td>Preference for sending desktop notifications. Must be one of the following values:<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop_sound</td> + <td valign="middle">string</td> + <td>Preference for whether desktop notification sound is played. Must be one of the following values:<br /> <kbd>"true"</kbd> - Sound is played.<br /> <kbd>"false"</kbd> - Sound is not played.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">email</td> + <td valign="middle">string</td> + <td>Preference for email notifications. Must be one of the following values:<br /> <kbd>"true"</kbd> - Email notifications are sent based on the email_interval setting <br /> <kbd>"false"</kbd> - Email notifications are not sent.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile</td> + <td valign="middle">string</td> + <td>Preference for sending mobile push notifications. Must be one of the following values:<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile_push_status</td> + <td valign="middle">string</td> + <td>Preference for when push notifications are triggered. Must be one of the following values:<br /> <kbd>"online"</kbd> - When online, away or offline.<br /> <kbd>"away"</kbd> - When away or offline.<br /> <kbd>"offline"</kbd> - When offline.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel</td> + <td valign="middle">string</td> + <td>Whether @all, @channel and @here trigger mentions. Must be one of the following values:<br /> <kbd>"true"</kbd> - Mentions are triggered.<br /> <kbd>"false"</kbd> - Mentions are not triggered.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">comments</td> + <td valign="middle">string</td> + <td>Preference for reply mention notifications. Must be one of the following values:<br /> <kbd>"any"</kbd> - Trigger notifications on messages in reply threads that the user starts or participates in.<br /> <kbd>"root"</kbd> - Trigger notifications on messages in threads that the user starts.<br /> <kbd>"never"</kbd> - Do not trigger notifications on messages in reply threads unless the user is mentioned.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mention_keys</td> + <td valign="middle">string</td> + <td>Preference for custom non-case sensitive words that trigger mentions. Words must be separated by commas.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the UserTeamMembership object + +This object is a member of the User object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot><tr><td colspan="5">[1] Not validated, but an error occurs if no such team exists when running in apply mode.</td></tr></tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the team this user should be a member of.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">theme</td> + <td valign="middle">string</td> + <td>The user’s theme for the specified team. Formatted as a Mattermost theme string.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The roles the user should have within this team. Must be one of the following values:<br /> <kbd>"team_user"</kbd><br /> <kbd>"team_admin team_user"</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channels</td> + <td valign="middle">array</td> + <td>The channels within this team that the user should be made a member of. Must be an array of <b>UserChannelMembership</b> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the UserChannelMembership object + +This object is a member of the TeamMembership object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot><tr><td colspan="5">[1] Not validated, but an error occurs if the parent channel does not exist when running in apply mode.</td></tr></tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">name</td> + <td valign="middle">string</td> + <td>The name of the channel in the parent team that this user should be a member of.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">roles</td> + <td valign="middle">string</td> + <td>The roles the user should have within this channel. Must be one of the following values:<br /> <kbd>"channel_user"</kbd><br /> <kbd>"channel_user channel_admin"</kbd> </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">notify_props</td> + <td valign="middle">object</td> + <td>The notify preferences for this user in this channel. Must be a <b>ChannelNotifyProps</b> object</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">favorite</td> + <td valign="middle">boolean</td> + <td>Whether to favorite the channel. Must be one of the following values:<br /> <kbd>"true"</kbd> - Yes.<br /> <kbd>"false"</kbd> - No.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the ChannelNotifyProps object + +This object is a member of the ChannelMembership object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">desktop</td> + <td valign="middle">string</td> + <td>Preference for sending desktop notifications. Must be one of the following values:<br /> <kbd>"default"</kbd> - Global default.<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mobile</td> + <td valign="middle">string</td> + <td>Preference for sending mobile notifications. Must be one of the following values:<br /> <kbd>"default"</kbd> - Global default.<br /> <kbd>"all"</kbd> - For all activity.<br /> <kbd>"mention"</kbd> - Only for mentions.<br /> <kbd>"none"</kbd> - Never.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">mark_unread</td> + <td valign="middle">string</td> + <td>Preference for marking channel as unread. Must be one of the following values:<br /> <kbd>"all"</kbd> - For all unread messages.<br /> <kbd>"mention"</kbd> - Only for mentions. </td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## Post object + +If present, Post objects must occur after the last User object in the file, but before any DirectChannel objects. + +### Example Post object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "post", + "post": { + "team": "team-name", + "channel": "channel-name", + "user": "username", + "message": "The post message", + "props": { + "attachments": [{ + "pretext": "This is the attachment pretext.", + "text": "This is the attachment text." + }] + }, + "create_at": 140012340013, + "flagged_by": [ + "username1", + "username2", + "username3" + ], + "replies": [{ + "user": "username4", + "message": "The reply message", + "create_at": 140012352049, + "attachments": [{ + "path": "/some/valid/file/path/1" + }], + }, { + "user": "username5", + "message": "Other reply message", + "create_at": 140012353057, + }], + "reactions": [{ + "user": "username6", + "emoji_name": "+1", + "create_at": 140012356032, + }, { + "user": "username7", + "emoji_name": "heart", + "create_at": 140012359034, + }], + "attachments": [{ + "path": "/some/valid/file/path/1" + }, { + "path": "/some/valid/file/path/2" + }] + } +} +``` + +### Fields of the Post object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot> + <tr> + <td colspan="5">[1] Not validated, but an error occurs if the team does not exist when running in apply mode.<br /> [2] Not validated, but an error occurs if the channel does not exist in the corresponding team when running in apply mode.<br /> [3] Not validated, but an error occurs if the user does not exist when running in apply mode. </td> + </tr> + </tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">team</td> + <td valign="middle">string</td> + <td>The name of the team that this post is in.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">channel</td> + <td valign="middle">string</td> + <td>The name of the channel that this post is in.</td> + <td align="center" valign="middle">No [2]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this post.</td> + <td align="center" valign="middle">No [3]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the post contains.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">props</td> + <td valign="middle">object</td> + <td>The props for a post. Contains additional formatting information used by integrations and bot posts. For a more detailed explanation see the <a href="https://docs.mattermost.com/developer/message-attachments.html">message attachments documentation</a>.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the post, in milliseconds since the Unix epoch.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">flagged_by</td> + <td valign="middle">array</td> + <td>Must contain a list of members who have flagged the post.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">replies</td> + <td valign="middle">array</td> + <td>The posts in reply to this post. Must be an array of <a href="#fields-of-the-reply-object">Reply</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">reactions</td> + <td valign="middle">array</td> + <td>The emoji reactions to this post. Must be an array of <a href="#fields-of-the-reaction-object">Reaction</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">attachments</td> + <td valign="middle">array</td> + <td>File attachments associated with this post. Must be an array of <a href="#fields-of-the-attachment-object">Attachment</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the Reply object + +This object is a member of the Post/DirectPost object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this reply.</td> + <td align="center" valign="middle">No [3]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the reply contains.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the reply, in milliseconds since the Unix epoch.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">flagged_by</td> + <td valign="middle">array</td> + <td>Must contain a list of members who have flagged the post.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">reactions</td> + <td valign="middle">array</td> + <td>The emoji reactions to this post. Must be an array of <a href="#fields-of-the-reaction-object">Reaction</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">attachments</td> + <td valign="middle">array</td> + <td>The file attachments to this post. Must be an array of <a href="#fields-of-the-attachment-object">Attachment</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +### Fields of the Reaction object + +This object is a member of the Post/DirectPost object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this reply.</td> + <td align="center" valign="middle">No [3]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">emoji_name</td> + <td valign="middle">string</td> + <td>The emoji of the reaction.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the reply, in milliseconds since the Unix epoch.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> +</table> + +### Fields of the Attachment object + +This object is a member of the Post/DirectPost object. + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot> + <tr> + <td colspan="5"> [1] Not validated, but an error occurs if the file path is not found or accessible when running in apply mode. </td> + </tr> + </tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">path</td> + <td valign="middle">string</td> + <td>The path to the file to be attached to the post.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> +</table> + +## DirectChannel object + +A direct channel can have from two to eight users as members of the channel. If there are only two members, Mattermost treats it as a Direct Message channel. If there are three or more members, Mattermost treats it as a Group Message channel. + +### Example DirectChannel object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "direct_channel", + "direct_channel": { + "members": [ + "username1", + "username2", + "username3" + ], + "header": "The Channel Header", + "favorited_by": [ + "username1", + "username2", + "username3" + ] + } +} +``` + +### Fields of the DirectChannel object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot> + <tr> + <td colspan="5">[1] Not validated, but an error occurs if one or more of the users don't exist when running in apply mode. </td> + </tr> + </tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">members</td> + <td valign="middle">array</td> + <td>Must contain a list of members, with a minimum of two usernames and a maximum of eight usernames.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">header</td> + <td valign="middle">string</td> + <td>The channel header.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">favorited_by</td> + <td valign="middle">array</td> + <td>Must contain a list of members who have favorited the channel.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## DirectPost object + +DirectPost objects must occur after all other objects in the file. + +### Example DirectPost object + +For clarity, the object is shown using regular JSON formatting, but in the data file it cannot be spread across several lines. It must be all on one line. + +``` javascript +{ + "type": "direct_post", + "direct_post": { + "channel_members": [ + "username1", + "username2", + "username3", + ], + "user": "username2", + "message": "Hello Group Channel", + "create_at": 140012340013, + "flagged_by": [ + "username1", + "username2", + "username3" + ], + "replies": [{ + "user": "username4", + "message": "The reply message", + "create_at": 140012352049, + }, { + "user": "username5", + "message": "Other reply message", + "create_at": 140012353057, + }], + "reactions": [{ + "user": "username6", + "emoji_name": "+1", + "create_at": 140012356032, + }, { + "user": "username7", + "emoji_name": "heart", + "create_at": 140012359034, + }] + } +} +``` + +### Fields of the DirectPost object + +<table width="100%" border="1" cellpadding="5px" style={{marginBottom: '20px'}}> + <tfoot> + <tr> + <td colspan="5">[1] Not validated, but an error occurs if no channels contain an identical list when running in apply mode.<br />[2] Not validated, but an error occurs if the user does not exist when running in apply mode. </td> + </tr> + </tfoot> + <tr class="row-odd"> + <th class="head">Field name</th> + <th class="head">Type</th> + <th class="head">Description</th> + <th class="head">Validated</th> + <th class="head">Mandatory</th> + </tr> + <tr class="row-odd"> + <td valign="middle">channel_members</td> + <td valign="middle">array</td> + <td>Must contain a list of members, with a minimum of two usernames and a maximum of eight usernames.</td> + <td align="center" valign="middle">No [1]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">user</td> + <td valign="middle">string</td> + <td>The username of the user for this post.</td> + <td align="center" valign="middle">No [2]</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">message</td> + <td valign="middle">string</td> + <td>The message that the post contains.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">create_at</td> + <td valign="middle">int</td> + <td>The timestamp for the post, in milliseconds since the Unix epoch.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">Yes</td> + </tr> + <tr class="row-odd"> + <td valign="middle">flagged_by</td> + <td valign="middle">array</td> + <td>Must contain a list of members who have flagged the post.</td> + <td align="center" valign="middle">No</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">replies</td> + <td valign="middle">array</td> + <td>The posts in reply to this direct post. Must be an array of <a href="#fields-of-the-reply-object">Reply</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">reactions</td> + <td valign="middle">array</td> + <td>The emoji reactions to this direct post. Must be an array of <a href="#fields-of-the-reaction-object">Reaction</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> + <tr class="row-odd"> + <td valign="middle">attachments</td> + <td valign="middle">array</td> + <td>The attachments to this direct post. Must be an array of <a href="#fields-of-the-attachment-object">Attachment</a> objects.</td> + <td align="center" valign="middle">Yes</td> + <td align="center" valign="middle">No</td> + </tr> +</table> + +## Common issues + +Run the bulk import command as the *mattermost* user. Running it as *root* or any other user will cause issues with file permissions on imported attachments. + +Ensure that [file attachments are enabled](/administration-guide/configure/site-configuration-settings#allow-file-sharing), that you have enough free space in your [file storage system](/administration-guide/configure/environment-configuration-settings#file-storage-system) to support the incoming attachments, and that your [maximum file size](/administration-guide/configure/environment-configuration-settings#maximum-file-size) is appropriate. + +Make sure you have enough free space for logs on the Mattermost server as well as free space on the database server for both the database itself and transaction logs. + +Disable anti-virus or any other plugins that might interfere with attachment uploading. They could potentially block uploading of attachments and cause the import to fail if configured incorrectly. If you need anti-virus scanning, scan the attachment folder before the import. + +## Troubleshooting + +### Running bulk loading tool hangs and doesn't complete + +If you have Bleve search indexing enabled, temporarily disable it in **System Console \> Experimental \> Bleve** and run the command again. + +Bleve does not support multiple processes opening and manipulating the same index. Therefore, if the Mattermost server is running, an attempt to run the bulk loading tool will lock when trying to open the indeces. diff --git a/docs/main/administration-guide/onboard/certificate-based-authentication.mdx b/docs/main/administration-guide/onboard/certificate-based-authentication.mdx new file mode 100644 index 000000000000..0b8d062c7791 --- /dev/null +++ b/docs/main/administration-guide/onboard/certificate-based-authentication.mdx @@ -0,0 +1,42 @@ +--- +title: "Certificate-based authentication (Experimental)" +--- +<PlanAvailability slug="ent-plus" /> + +<Important> + +**Experimental certificate-based authentication has been deprecated from Mattermost v11.0.** From Mattermost v11, you must [disable this feature](/administration-guide/configure/experimental-configuration-settings#enable-client-side-certification) to start the server. Enabling this setting will prevent the server from starting. + +</Important> + +Prior to v11, certificate-based authentication (CBA) is available as an experimental feature to identify a user or a device before granting access to Mattermost and provide an additional layer of security to access the system. + +Before you begin, follow the [official guides to install Mattermost](/deployment-guide/deployment-guide-index) on your system, including NGINX configuration as a proxy with SSL and HTTP/2, and a valid SSL certificate such as Let's Encrypt. + +Then, follow the steps below to configure user CBA for your browser and Mattermost Desktop Apps. You can manage certificate distribution for each personal device (BYOD) and their life cycle management with a service like [OpenSSL](https://www.openssl.org/). + +## Set up mutual TLS authentication for the Web App + +[Setting up mutual TLS authentication](/administration-guide/onboard/ssl-client-certificate) is the first step to set up certificate-based authentication. + +## Set up Mattermost server to log in with a client certificate + +1. Make sure your Mattermost server is licensed with a valid Enterprise license. +2. In `ExperimentalSettings` of the `config.json` file, set `ClientSideCertEnable` to `true` and `ClientSideCertCheck` to one of the following values: + +- `primary` - After the client side certificate is verified, user's email is retrieved from the certificate and is used to log in without a password. +- `secondary` - After the client side certificate is verified, user's email is retrieved from the certificate and matched against the one supplied by the user. + +If they match, the user logs in with regular email/password credentials. + +The `config.json` file should then have the following lines + +``` text +"ExperimentalSettings": { + "ClientSideCertEnable": true, + "ClientSideCertCheck": "secondary" +}, +``` + +3. Restart the Mattermost server. +4. Go to `https://example.mattermost.com` and try to log in. The server should require the x.509 cert to have an `emailAddress` equal to the Mattermost user's email. diff --git a/docs/main/administration-guide/onboard/common-converting-oauth-to-openidconnect.mdx b/docs/main/administration-guide/onboard/common-converting-oauth-to-openidconnect.mdx new file mode 100644 index 000000000000..60ef7a580dcc --- /dev/null +++ b/docs/main/administration-guide/onboard/common-converting-oauth-to-openidconnect.mdx @@ -0,0 +1,11 @@ +--- +--- +Using the System Console, Mattermost Enterprise and Professional customers can migrate OAuth configuration to the OpenID Connect standard. A one-time, one-click conversion tool is available within the existing **OAuth 2.0** page. You can also go to **System Console \> Authentication \> OpenID Connect**. + +Select **Convert to OpenID Connect** to migrate your active service provider configuration to the new standard. No further changes are required. + +<Note> + +\- Inactive service providers configured for OAuth 2.0 are also migrated to the new OpenID Connect standard. + +</Note> diff --git a/docs/main/administration-guide/onboard/connected-workspaces.mdx b/docs/main/administration-guide/onboard/connected-workspaces.mdx new file mode 100644 index 000000000000..7cf54358797f --- /dev/null +++ b/docs/main/administration-guide/onboard/connected-workspaces.mdx @@ -0,0 +1,364 @@ +--- +title: "Connected workspaces" +--- +<PlanAvailability slug="entry-ent" /> + +Communicate across organizations, as well as external partners and vendors using Mattermost by synchronizing messages, emoji reactions, and file sharing in real-time through secured, connected Mattermost workspaces. + +Connected workspaces in Mattermost behave like regular public and private channels and offer the same user experience and functionality. All members using secure connections, including local members and remote members, can [send and receive channel messages](/end-user-guide/collaborate/send-messages), [use emojis](/end-user-guide/collaborate/react-with-emojis-gifs) to react to messages, [share files](/end-user-guide/collaborate/share-files-in-messages), and [search message history](/end-user-guide/collaborate/search-for-messages). Content is synchronized across all participating Mattermost instances. + +A channel's permissions and access continues to be governed by each server separately. [Advanced access control](/administration-guide/manage/team-channel-members#advanced-access-controls) permissions can be applied to a shared channel, and be in effect on the local Mattermost server while not being in effect on a remote Mattermost server. + +## Set up connected workspaces + +The process of connecting Mattermost workspaces involves the following 5 steps: + +1. Ensure that all Mattermost Enterprise servers are running v10.2 or later. +2. [Enable the connected workspaces functionality](#enable-connected-workspaces) for each Mattermost Enterprise instance you want to connect. +3. System admins must [create a secure and trusted connection](#create-a-secure-connection) with other Mattermost Enterprise instances using the System Console or slash commands. This process involves creating a password-protected, encrypted invitation, creating a strong decryption password, then sending the invitation and password to the admin of a remote Mattermost instance. From Mattermost v11.0, remote cluster invitations use PBKDF2 key derivation for enhanced security. +4. When a remote system admin receives the invitation, they must [accept the invitation](#accept-a-secure-connection-invitation) using the System Console or slash commands. +5. Once a trusted relationship is established between 2 Mattermost servers, system admins or users with the **Shared Channel Manager** role can [share specific public or private channels](#share-channels-with-secure-connections) with secure connections. + +<Note> + +- System admins can create secure connections with other Mattermost Enterprise instances. System admins or users with the **Shared Channel Manager** [delegated administration role](/administration-guide/onboard/delegated-granular-administration) can share channels with secured connections. +- System admins creating secure connections must use Mattermost to generate a password-protected encrypted invitation code. However, sending secure connection invitations is not completed using Mattermost. System admins must have an independent way to extend the secure connection invitation, such as by email. +- A channel shared by a host organization cannot be shared from the receiving organization to another organization. Organizations can't share a channel originating from another organization. + +</Note> + +## Enable connected workspaces + +System admins must enable connected workspaces functionality for their Mattermost instance. Ensure the following configuration settings are set to `true` in `config.json`: + +- `ConnectedWorkspacesSettings.EnableRemoteClusterService = true` +- `ConnectedWorkspacesSettings.EnableSharedChannels = true` + +See the [Site Configuration Settings](/administration-guide/configure/site-configuration-settings#enable-connected-workspaces) documentation for details. + +<Note> + +Following an upgrade to Mattermost v10.2 or later, existing configuration values for shared channels, including `EnableSharedChannels` and `EnableRemoteClusterService` are automatically converted to [connected workspace configuration settings](/administration-guide/configure/site-configuration-settings#enable-connected-workspaces) in the `config.json` file. The [deprecated shared channels experimental settings](/administration-guide/configure/deprecated-configuration-settings#shared-channels-settings) remain in the `config.json` file to support backwards compatibility. + +</Note> + +## Create a secure connection + +<div class="tab"> + +System Console + +Only system admins can create workspace connections using the System Console. + +1. Go to **Site Configuration \> Connected Workspaces**. +2. Under **Connected Workspaces**, select **Add a connection**, and then select **Create a connection**. +3. Specify the **Organization Name** for this connection. The remote system admin must specify this name when accepting a connection invitation. +4. Select the **Destination Team** as the default team where shared channels will be added. This team will be used as the default location for organizing shared channels from this connected workspace. +5. Select **Save**. + +An invitation consisting of a password-protected AES 256-bit encrypted code blob is generated. From Mattermost v11.0, password protection uses PBKDF2 key derivation for enhanced security. The connection is labeled as **Connection Pending** until the remote system admin accepts the invitation. + +</div> + +<div class="tab"> + +Slash Commands + +By default, only system admins can use slash commands to create workspace connections. You can delegate channel sharing capabilities using the built-in **Shared Channel Manager** [delegated administration role](/administration-guide/onboard/delegated-granular-administration). Alternatively, you can grant the ability to **Manage Shared Channels** to Mattermost users by modifying permissions of the [system scheme](/administration-guide/onboard/advanced-permissions#system-scheme) or [team override scheme](/administration-guide/onboard/advanced-permissions#team-override-scheme). + +System admins can [run the following slash command](/integrations-guide/run-slash-commands) to create a secure connection invitation: + +`/secure-connection create --name <--displayname> --password` + +For example: + +`/secure-connection create --name AcmeUS --displayname "AcmeUSA" --password examplepassword` + +This slash command creates an invitation consisting of a password-protected AES 256-bit encrypted code blob for a remote Mattermost entity known locally as `AcmeUS` with a password of `examplepassword`. From Mattermost v11.0, password protection uses PBKDF2 key derivation for enhanced security. Within Mattermost, this shared connection displays to the local system admin based on the `name` and `displayname` provided. + +</div> + +### Extend the invitation + +You must use a system, other than Mattermost, to share invitation codes and passwords. We strongly recommend sharing invitation codes separately from passwords to ensure that no one has all of the data necessary to take action if the message were compromised. Ensure the remote Mattermost instance can access your Mattermost workspace URL. + +<div class="tab"> + +System Console + +Once you've created a connection in the System Console, you're prompted to share the invitation code and password with the system admin of the remote Mattermost server you want to connect with. Copy both the invitation code and password to a safe location, then select **Done**. + +</div> + +<div class="tab"> + +Slash Commands + +Copy the invitation code blob in the System message, then share the code blob and the decryption password to the remote Mattermost system admin you want to securely connect with. + +</div> + +## Accept a connection invitation + +<div class="tab"> + +System Console + +1. Go to **Site Configuration \> Connected Workspaces**. +2. Under **Connected Workspaces**, select **Add a connection**, and then select **Accept an invitation**. +3. Specify the **Organization Name** for this invitation. This must be the same name specified when creating the connection. +4. Select the **Destination Team** where shared channels will be added. This team will serve as the default location for organizing shared channels from this connected workspace. +5. Paste the encrypted invitation code and password you've been provided to connect with the remote workspace. +6. Select **Accept**. + +The system admin who accepts the connection invitation is automatically added to all shared channels. + +</div> + +<div class="tab"> + +Slash Commands + +Run the following slash command to accept a secure connection invitation from a remote Mattermost instance: + +`/secure-connection accept --name --displayname --password --invite [code blob]` + +For example: + +`/secure-connection accept --name AcmeUS --displayname "AcmeUSA" --password examplepassword --invite [code-blob]` + +This slash command accepts a secure connection invitation from `AcmeUS`. + +</div> + +## Share channels with secure connections + +Once a connection is established between two Mattermost servers, system admins or users with the **Shared Channel Manager** role can share channels across secured workspaces. + +<div class="tab"> + +System Console + +1. Under **Shared Channels**, select **Add channels**. +2. Specify the channels you want to share between Mattermost servers. + +Shared channels and members of those shared channels display a shared <img src="/img/ui/circle-multiple-outline_F0695.svg" alt="Shared icon indicates channels and their members that are shared across connected Mattermost servers." /> icon to distinguish them from channels and channel members of the local server. + +</div> + +<div class="tab"> + +Slash Commands + +Run the following slash command to specify the public or private channels to share: + +`/share-channel invite --connectionID <--readonly>` + +You can extend an invitation that permits remote members to participate in the channel based on their channel and member permissions. + +Alternatively, you can extend a read-only invitation to a secure connection by appending the optional `--readonly` parameter to this command. Remote members can't post or reply to messages within shared read-only channels. + +<Tip> + +To convert a read-only shared channel to a participation channel, remove the original secured connection from the channel, then re-extend an invitation to that secure connection while omitting the optional `--readonly` parameter. For example: + +`/share-channel invite --connectionID` + +This slash command invites the shared connection to the current channel based on its `connectionID`. + +See [Reviewing Secure Connection Status](#review-secure-connection-status) to find the `connectionID` for a shared connection. + +</Tip> + +</div> + +## Direct message delivery + +From Mattermost v10.10, creating a direct or group message with remote users across connected workspaces is only available when the feature flag `EnableSharedChannelsDMs` is enabled. + +When `EnableSharedChannelsDMs` is disabled, the direct message option on a user's profile is disabled and unavailable to ensure users can't attempt direct messages with remote users when connected workspaces isn't enabled on the other Mattermost instance. + +## Plugin component interaction + +From Mattermost v10.10, plugin interactions such as slash commands, interactive buttons, and other plugin-generated components aren't displayed or accessible in shared channels by default to ensure a consistent experience across different Mattermost instances. + +System admins can enable the `EnableSharedChannelsPlugins` feature flag to enable these plugin interactions in shared channels. When plugin components are enabled in shared channels, we recommend ensuring that all connected Mattermost instances have the same plugins installed and configured to avoid inconsistent user experiences. Plugin behaviors can vary between instances if different plugin versions or configurations are used. + +## Remote user discovery + +From Mattermost v10.10, remote users across connected workspaces can be discovered for direct or group messages when the feature flag `EnableSyncAllUsersForRemoteCluster` is enabled. This feature implements global user synchronization between connected Mattermost instances, making remote users discoverable without requiring them to post in a shared channel first. When enabled, Mattermost uses cursor-based synchronization to efficiently sync user information between connected instances. The system: + +- Synchronizes users in configurable batch sizes to prevent timeouts and reduce memory usage +- Tracks synchronization progress using timestamps to enable efficient resumption +- Filters out users from their original cluster to prevent syncing users back to their home instance +- Only syncs users that have been updated since the last synchronization + +The feature includes configuration options for [automatically syncing users when connections are established](/administration-guide/configure/site-configuration-settings#sync-users-on-connection-open) and [controlling batch processing sizes](/administration-guide/configure/site-configuration-settings#global-user-sync-batch-size) for optimal performance. + +When `EnableSyncAllUsersForRemoteCluster` is disabled, remote users are only discoverable in the DM/GM creation modal after they have participated in a shared channel. + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +## Channel membership synchronization + +From Mattermost v10.10, channel membership synchronization between connected workspaces is controlled by the feature flag `EnableSharedChannelsMemberSync`. When this feature flag is enabled, channel membership changes are automatically synchronized across all connected workspaces that share the same channel. + +When `EnableSharedChannelsMemberSync` is enabled: + +- Users added to a shared channel on one workspace are automatically added to the corresponding shared channel on all connected workspaces +- Users removed from a shared channel on one workspace are automatically removed from the corresponding shared channel on all connected workspaces +- Membership changes are processed in configurable batch sizes to optimize performance and prevent timeouts +- The system uses cursor-based synchronization to efficiently track and sync membership changes + +The feature includes a configuration option for [controlling batch processing sizes for member synchronization](/administration-guide/configure/site-configuration-settings#member-sync-batch-size) to ensure optimal performance during large membership changes. + +When `EnableSharedChannelsMemberSync` is disabled, channel membership changes are not synchronized between connected workspaces, and users must be manually added or removed from shared channels on each workspace. + +<Note> + +Enabling these features can increase the load on your Mattermost server’s CPU, memory, and database due to frequent updates, database queries, and API communication. Excessive sync frequency and retries can overwhelm system resources, potentially causing performance degradation or instability. Monitor your system carefully when enabling these features. + +</Note> + +## Manage connections and invitations + +System admins can [edit](#edit-a-connected-workspace) or [delete](#delete-a-connected-workspace) a connected workspace, [review connection status](#review-connection-status), and [regenerate invitation codes and passwords](#regenerate-invitation-codes-for-pending-connections) for pending connections. + +### Edit a connected workspace + +In the System Console, system admins can change the **Organization Name**, the **Destination Team** (which serves as the default location for organizing shared channels from this connected workspace), or channels shared with a remote Mattermost instance as well as channels shared with your local Mattermost instance. + +1. Under **Connected Workspaces**, identify the connected workspace you want to change. +2. Select the **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> icon to the right of the connected workspace, and then select **Edit**. + +### Remove all connections from the current channel + +Run the following slash command to remove all secure connections from the current channel: + +`/share-channel unshare` + +This slash command removes all secure connections from the current channel. A System message notifies you that the channel is no longer shared. Secure connections may continue to be invited to other shared channels. + +### Delete a connected workspace + +Deleting a connected server severs the trust relationship between the local Mattermost server and the remote Mattermost server. + +From Mattermost v10.10, removing a shared channel from a connected workspace removes the channel from all connected workspaces. The channel is deleted from both the local and remote Mattermost servers. Prior to Mattermost v10.10, removing a shared channel from a connected workspace stops synchronizing the channel with the remote Mattermost server; however, the channel continues to function for local users. + +<div class="tab"> + +System Console + +1. Under **Connected Workspaces**, identify the connected workspace you want to remove. +2. Select the **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> icon to the right of the connected workspace, and then select **Delete**. + +</div> + +<div class="tab"> + +Slash Commands + +Using slash commands, you can uninvite or delete a secure connection from your Mattermost instance. + +Run the following slash command to uninvite a secure connection: + +`/share-channel uninvite --connectionID` + +This slash command removes a secure connection from the current channel based on its `connectionID`. The secure connection may continue to be invited to other shared channels. + +Run the following slash command to delete a secure connection: + +`/secure-connection remove --connectionID` + +For example: + +`/secure-connection remove --connectionID` + +This slash command severs the trust relationship between the local Mattermost server and a remote Mattermost server based on its `connectionID` and removes the secure connection from all shared Mattermost channels. + +</div> + +### Review connection status + +<div class="tab"> + +System Console + +Under **Connected Workspaces**, you can review all connected workspaces and their current status as one of: **Connected**, **Offline**, or **Connection Pending**. + +</div> + +<div class="tab"> + +Slash Commands + +Run the following slash command to review the current status of all secure connections established for your Mattermost instance: + +`/secure-connection status` + +Status details include: + +- Connection ID +- Connection URL +- Description +- Invite accepted (Yes/No) +- Online (Yes/No) +- Last ping timestamp (UTC) +- Deleted + +</div> + +### Regenerate invitation codes for pending connections + +When using the System Console to manage connected workspaces, system admins can re-generate invitation codes and passwords for pending connections. + +1. Under **Connected Workspaces**, identify the pending connection whose invitation and password you want to regenerate. +2. Select the **More** <img src="/img/ui/dots-horizontal_F01D8.svg" alt="Use the More icon to access additional message options." className="theme-icon" /> icon to the right of the connected workspace, and then select **Regenerate invitation code**. + +<Note> + +Regenerating doesn't invalidate the existing password, and the existing password can continue to be used in addition to the newly-generated password. Once a connection invitation is accepted and the workspace displays a status of **Connected**, invitation codes and passwords can't be regenerated. + +</Note> + +## Frequently Asked Questions + +### Are special characters supported in secure connection names? + +No. When using slash commands, `--name` can include periods, hyphens, and/or underscores. You must surround `--name` using quotation marks (") when the value contains spaces. + +### What happens if two Mattermost instances contain different emojis? + +In cases where one Mattermost instance has different emojis than another instance, emoji text displays in place of a missing emoji image. + +### Is a Display Name required for all secure connections? + +No. When using slash commands, `--displayname` is optional. When omitted, `--name` is displayed and used instead. + +### What information is synchronized between connected workspaces? + +By default, member status and availability for all members of shared channels is synchronized between connected workspaces. + +When a user is added to a shared channel, member status is synchronized within a few seconds of the member's status changing. Status updates aren't immediate and don't necessarily display in real-time. + +When using Mattermost in a web browser, Mattermost polls the server every minute. Refreshing the browser page triggers immediate synchronization. + +By default, a maximum of 50 messages are synchronized at a time, and [this value is configurable](/administration-guide/configure/site-configuration-settings#default-maximum-posts-per-sync). + +Channel as well as member status and availability synchronization [can be disabled](/administration-guide/configure/site-configuration-settings#disable-shared-channel-status-sync). + +From Mattermost v10.10, channel membership can be synchronized between connected workspaces when the feature flag `EnableSharedChannelsMemberSync` is enabled. When a user is added to or removed from a shared channel on one workspace, that membership change is automatically applied to the corresponding shared channel on all connected workspaces. This ensures consistent channel membership across all participating Mattermost instances. Additionally, connected workspaces also synchronize message priority, message acknowledgements, and persistent notifications between connected servers. This ensures that important message indicators and user interactions are consistently reflected across all connected workspace instances. + +### Do connection interruptions affect message synchronization? + +Yes. A System message is posted in the channel visible to all channel members when message synchronization is interrupted for more than 5 minutes. Once connectivity is restored, a full synchronization will happen for all missed messages, including direct messages and channel links. + +### What happens if two secure connections share the same usernames? + +In cases where members share the same usernames across Mattermost secure connections, usernames on the local server instance are appended with the secure connection name of the remote server. + +For example, if multiple members named John Smith exist after two Mattermost instances establish a secure connection with one another, all remote John Smith members include their Secure Connection ID following their username to help differentiate members across multiple Mattermost instances. diff --git a/docs/main/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect.mdx b/docs/main/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect.mdx new file mode 100644 index 000000000000..c7a8faebc33c --- /dev/null +++ b/docs/main/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect.mdx @@ -0,0 +1,17 @@ +--- +title: "Converting OAuth 2.0 Service Providers to OpenID Connect" +--- +import Inc0_common_converting_oauth_to_openidconnect from './common-converting-oauth-to-openidconnect.mdx'; + +<PlanAvailability slug="all-commercial" /> + +<Inc0_common_converting_oauth_to_openidconnect /> + +## Configuring OpenID Connect Single Sign-On + +For details on configuring Mattermost to use a service provider as a Single Sign-on (SSO) service for team creation, account creation, and user sign-in using OpenID Connect in your self-hosted deployment, refer to the following documentation: + +- [OpenID Connect Single Sign-On](/administration-guide/onboard/sso-openidconnect) +- [GitLab Single Sign-On](/administration-guide/onboard/sso-gitlab) +- [Google Apps Single Sign-On](/administration-guide/onboard/sso-google) +- [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) diff --git a/docs/main/administration-guide/onboard/delegated-granular-administration.mdx b/docs/main/administration-guide/onboard/delegated-granular-administration.mdx new file mode 100644 index 000000000000..55860a771957 --- /dev/null +++ b/docs/main/administration-guide/onboard/delegated-granular-administration.mdx @@ -0,0 +1,300 @@ +--- +title: "Delegated granular administration" +draft: true +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost supports the creation and customization of system administration roles with specific granular permissions and System Console access. This allows senior administrators in large organizations to delegate and de-centralize specialized administration and administrative tasks with specific admin roles. + +These admin roles permit granular access to specific areas of the System Console and related API endpoints. These roles enable users to perform certain administrative tasks without requiring access to all system administration areas. These system roles never supersede the user's original role or the user's permissions configured by the Permissions scheme. + +<Warning> + +Even when a role is set to **No Access** or **Read Only** for a System Console page, granting **Can Edit** on any System Console page enables access to the underlying configuration endpoint (`PUT /api/v4/config/patch`). This means a user with write access in one area can modify configuration values across all areas. Administrators should assign **Can Edit** permissions with caution. + +</Warning> + +## Available roles + +A system admin can configure the following delegated granular administration roles in the System Console. Each role has a set of default permissions, which can be adjusted as needed. + +- **System Manager:** This role can be configured to have read/write permissions in different management areas. +- **User Manager:** This role can be configured to have read/write to all the user management areas and to authentication +- **Custom Group Manager** This role has permissions to [create, edit, restore, and delete custom user groups](/end-user-guide/collaborate/organize-using-custom-user-groups). This role can be used to assign individual users the ability to manage custom groups when **Custom Groups** permissions are removed for **All Members** via **System Console \> Permissions \> Edit Scheme \> Custom Groups**. +- **Shared Channel Manager** This role has the `manage_shared_channels` permission, allowing assigned users to share and unshare channels with existing connections to remote servers. +- **Viewer:** The Viewer role can view all areas of the System Console, and can be configured with write access where needed. + +When a user is assigned a system role, they have role-based access to the System Console and the underlying API endpoints. Each role has a different set of default permissions, and what users can access or view depends on the role they've been assigned. + +The table below lists the default permissions for each role. Admins should carefully review and configure these settings to align with their organization's needs. Particular caution should be exercised with Permissions write access, as it enables modifications to the permissions of any role, except for the delegated granular administrator roles. + +<table style={{width: '73%'}}> +<colgroup> +<col style={{width: '19%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '33%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>System role</strong></td> +<td><strong>Read/Write access</strong></td> +<td><strong>Read Only access</strong></td> +</tr> +<tr> +<td>System Manager</td> +<td><ul><li>User Management<ul><li>Groups</li><li>Teams</li><li>Channels</li><li>Permissions</li></ul></li><li>Environment</li><li>Site Configuration</li><li>Integrations</li></ul></td> +<td><ul><li>Edition/License</li><li>Reporting</li><li>Authentication</li><li>Plugins</li></ul></td> +</tr> +<tr> +<td>User Manager</td> +<td><ul><li>User Management<ul><li>Groups</li><li>Teams</li><li>Channels</li></ul></li></ul></td> +<td><ul><li>(User Management) Permissions</li><li>Authentication</li></ul></td> +</tr> +<tr> +<td>Custom Group Manager</td> +<td>Custom User Groups</td> +<td>N/A</td> +</tr> +<tr> +<td>Shared Channel Manager</td> +<td>Shared Channels</td> +<td>N/A</td> +</tr> +<tr> +<td>Viewer</td> +<td>N/A</td> +<td><ul><li>All pages within the System Console</li></ul></td> +</tr> +</tbody> +</table> + +## Assign admin roles + +There are two ways to assign roles: + +1. In the System Console under **User Management \> Delegated Granular Administration**. +2. Using the [mmctl tool](/administration-guide/manage/mmctl-command-line-tool). This can be done either locally or remotely. + +<table style={{width: '99%'}}> +<colgroup> +<col style={{width: '18%'}} /> +<col style={{width: '47%'}} /> +<col style={{width: '30%'}} /> +<col style={{width: '2%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>You want to</strong></td> +<td><strong>Using the System Console</strong></td> +<td><strong>Using mmctl</strong></td> +<td></td> +</tr> +<tr> +<td>Assign roles</td> +<td>Go to <strong>System Console > User Management > Delegated Granular Administration > Assigned People</strong></td> +<td><code>mmctl permissions role assign [role_name] [username...]</code></td> +<td></td> +</tr> +<tr> +<td>Grant the System Manager role to a user</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>System Manager</strong> role.</li><li>Under <strong>Assigned People</strong>, select <strong>Add People</strong>.</li><li>Search for and select the user name, then select <strong>Add</strong> to grant the System Manager role to that user.</li></ol></td> +<td><code>mmctl permissions role assign system_manager user-name</code></td> +<td></td> +</tr> +<tr> +<td>Grant the User Manager role to two users</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>User Manager</strong> role.</li><li>Under <strong>Assigned People</strong>, select <strong>Add People</strong>.</li><li>Search for and select the two users, then select <strong>Add</strong> to grant the User Manager role to those users.</li></ol></td> +<td><code>mmctl permissions role assign system_user_manager user-name1 user-name2</code></td> +<td></td> +</tr> +<tr> +<td>Grant the Viewer role to a user</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>Viewer</strong> role.</li><li>Under <strong>Assigned People</strong>, select <strong>Add People</strong>.</li><li>Search for and select the user name, then select <strong>Add</strong> to grant the Viewer role to that user.</li></ol></td> +<td><code>mmctl permissions role assign system_read_only_admin user-name</code></td> +<td></td> +</tr> +<tr> +<td>Grant the Custom Group Manager role to two users</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>Custom Group Manager</strong> role.</li><li>Under <strong>Assigned People</strong>, select <strong>Add People</strong>.</li><li>Search for and select the two users, then select <strong>Add</strong> to grant the Custom Group Manager role to those users.</li><li>All users have the ability to create custom user groups by default. When you assign users to the Custom Group Manager role, you must manually remove these permissions from all users by going to <strong>System Console > User Management > Permissions > Edit Scheme</strong>. Under <strong>All Members</strong>, clear all of the <strong>Custom Groups</strong> permissions, including <strong>Create</strong>, <strong>Manage members</strong>, <strong>Edit</strong>, and <strong>Delete</strong>.</li></ol></td> +<td><code>mmctl permissions role assign system_custom_group_admin user-name1 user-name2</code></td> +<td></td> +</tr> +<tr> +<td>Grant the Shared Channel Manager role to a user</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>Shared Channel Manager</strong> role.</li><li>Under <strong>Assigned People</strong>, select <strong>Add People</strong>.</li><li>Search for and select the user name, then select <strong>Add</strong> to grant the Shared Channel Manager role to that user.</li></ol></td> +<td colspan="2"><dl><dt><code>mmctl permissions role assign system_shared_channel_manager user-name</code></dt><dd><h3 id="section">|</h3></dd></dl></td> +</tr> +<tr> +<td>Remove the System Manager role from a single user</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>System Manager</strong> role.</li><li>Under <strong>Assigned People</strong>, search for the user, then select <strong>Remove</strong>.</li></ol></td> +<td><code>mmctl permissions role unassign system_manager bob-smith</code></td> +<td></td> +</tr> +</tbody> +</table> + +## Edit privileges of admin roles (advanced) + +System admins can grant read/write access to other areas of the System Console, as well as remove read/write access (including default access), for all system roles except the Custom Group Manager and Shared Channel Manager roles. + +There are two ways to assign roles: + +1. In the System Console under **User Management \> Delegated Granular Administration**. +2. Using the [mmctl tool](/administration-guide/manage/mmctl-command-line-tool). This can be done either locally or remotely. + +<table style={{width: '100%'}}> +<colgroup> +<col style={{width: '18%'}} /> +<col style={{width: '49%'}} /> +<col style={{width: '31%'}} /> +</colgroup> +<tbody> +<tr> +<td><strong>You want to</strong></td> +<td><strong>Using the System Console</strong></td> +<td><strong>Using mmctl</strong></td> +</tr> +<tr> +<td>Edit role privileges</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>System Manager</strong>, <strong>User Manager</strong>, or <strong>Viewer</strong> role.</li><li>For each set of privileges, select the access level as <strong>Can edit</strong>, <strong>Read only</strong>, or <strong>No access</strong>.</li></ol><div class="note"><p>If you set privilege subsections to different access levels, then the privilege access level displays as <strong>Mixed Access</strong>.</p></div></td> +<td><code>mmctl permissions add [role_name] [permission...]</code> <code>mmctl permissions reset system_read_only_admin</code></td> +</tr> +<tr> +<td>Grant write access to the Authentication section of the System Console for all users with the User Manager role</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>User Manager</strong> role.</li><li>Under <strong>Privileges > Authentication</strong> select <strong>Can edit</strong>, then select <strong>Save</strong>.</li></ol></td> +<td><code>mmctl permissions add system_user_manager sysconsole_write_authentication</code></td> +</tr> +<tr> +<td>Grant read-only access to the Authentication section of the System Console for all users with the User Manager role</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>. then select the <strong>User Manager</strong> role.</li><li>Under <strong>Privileges > Authentication</strong> select <strong>Read only</strong>, then select <strong>Save</strong>.</li></ol></td> +<td><code>mmctl permissions remove system_user_manager sysconsole_read_authentication</code></td> +</tr> +<tr> +<td>Remove write access to the Authentication section of the System Console for all users with the User Manager role</td> +<td><ol type="1"><li>Go to <strong>System Console > User Management > Delegated Granular Administration</strong>, then select the <strong>User Manager</strong> role.</li><li>Under <strong>Privileges > Authentication</strong> select <strong>No access</strong>, then choose <strong>Save</strong>.</li></ol></td> +<td><code>mmctl permissions remove system_user_manager sysconsole_write_authentication</code></td> +</tr> +<tr> +<td>Reset a role to its default set of permissions</td> +<td>This is completed using the mmctl tool only.</td> +<td><code>mmctl permissions reset [role_name]</code> For example, to reset the permissions of the <code>system_read_only_admin</code> role: <code>mmctl permissions reset system_read_only_admin</code></td> +</tr> +</tbody> +</table> + +## Admin roles and privileges + +#### Roles + +- `system_manager` +- `system_user_manager` +- `system_custom_group_admin` +- `system_shared_channel_manager` +- `system_read_only_admin` + +#### Privileges + +<table style={{width: '83%'}}> +<colgroup> +<col style={{width: '20%'}} /> +<col style={{width: '62%'}} /> +</colgroup> +<thead> +<tr> +<th>System Console section</th> +<th>Permissions</th> +</tr> +</thead> +<tbody> +<tr> +<td>About</td> +<td><blockquote><ul><li>PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE</li><li>PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE</li></ul></blockquote></td> +</tr> +<tr> +<td>Reporting</td> +<td><dl><dt><strong>Site Statistics</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS</li><li>PERMISSION_SYSCONSOLE_WRITE_REPORTING_SITE_STATISTICS</li></ul></dd><dt><strong>Team Statistics</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_REPORTING_TEAM_STATISTICS</li><li>PERMISSION_SYSCONSOLE_WRITE_REPORTING_TEAM_STATISTICS</li></ul></dd><dt><strong>Server Logs</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS</li><li>PERMISSION_SYSCONSOLE_WRITE_REPORTING_SERVER_LOGS</li></ul></dd></dl></td> +</tr> +<tr> +<td>User Management</td> +<td><dl><dt><strong>Users</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS</li><li>PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_USERS</li></ul></dd><dt><strong>Groups</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS</li><li>PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_GROUPS</li></ul></dd><dt><strong>Teams</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_TEAMS</li><li>PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_TEAMS</li></ul></dd><dt><strong>Channels</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS</li><li>PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS</li></ul></dd><dt><strong>Permissions</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS</li><li>PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS</li></ul></dd></dl></td> +</tr> +<tr> +<td>Environment</td> +<td><dl><dt><strong>Web Server</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_WEB_SERVER</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_WEB_SERVER</li></ul></dd><dt><strong>Database</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DATABASE</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DATABASE</li></ul></dd><dt><strong>Elasticsearch</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH</li></ul></dd><dt><strong>File Storage</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_FILE_STORAGE</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_FILE_STORAGE</li></ul></dd><dt><strong>Image Proxy</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_IMAGE_PROXY</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_IMAGE_PROXY</li></ul></dd><dt><strong>SMTP</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SMTP</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SMTP</li></ul></dd><dt><strong>Push Notification Server</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PUSH_NOTIFICATION_SERVER</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PUSH_NOTIFICATION_SERVER</li></ul></dd><dt><strong>High Availability</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_HIGH_AVAILABILITY</li></ul></dd><dt><strong>Rate Limiting</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_RATE_LIMITING</li></ul></dd><dt><strong>Logging</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_LOGGING</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_LOGGING</li></ul></dd><dt><strong>Session Lengths</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SESSION_LENGTHS</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SESSION_LENGTHS</li></ul></dd><dt><strong>Performance Monitoring</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PERFORMANCE_MONITORING</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PERFORMANCE_MONITORING</li></ul></dd><dt><strong>Developer</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DEVELOPER</li><li>PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DEVELOPER</li></ul></dd></dl></td> +</tr> +<tr> +<td>Site Configuration</td> +<td><dl><dt><strong>Customization</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_CUSTOMIZATION</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_CUSTOMIZATION</li></ul></dd><dt><strong>Localization</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_LOCALIZATION</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_LOCALIZATION</li></ul></dd><dt><strong>Users and Teams</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_USERS_AND_TEAMS</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS</li></ul></dd><dt><strong>Notifications</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_NOTIFICATIONS</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_NOTIFICATIONS</li></ul></dd><dt><strong>Announcement Banner</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_ANNOUNCEMENT_BANNER</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_ANNOUNCEMENT_BANNER</li></ul></dd><dt><strong>Emoji</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_EMOJI</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_EMOJI</li></ul></dd><dt><strong>Posts</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_POSTS</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_POSTS</li></ul></dd><dt><strong>File Sharing and Downloads</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_FILE_SHARING_AND_DOWNLOADS</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_FILE_SHARING_AND_DOWNLOADS</li></ul></dd><dt><strong>Public Links</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_PUBLIC_LINKS</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_PUBLIC_LINKS</li></ul></dd><dt><strong>Notices</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_SITE_NOTICES</li><li>PERMISSION_SYSCONSOLE_WRITE_SITE_NOTICES</li></ul></dd></dl></td> +</tr> +<tr> +<td>Authentication</td> +<td><dl><dt><strong>Signup</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SIGNUP</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SIGNUP</li></ul></dd><dt><strong>Email</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_EMAIL</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_EMAIL</li></ul></dd><dt><strong>Password</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_PASSWORD</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_PASSWORD</li></ul></dd><dt><strong>MFA</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_MFA</li></ul></dd><dt><strong>AD/LDAP</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_MFA</li></ul></dd><dt><strong>SAML 2.0</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SAML</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SAML</li></ul></dd><dt><strong>OpenID Connect</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_OPENID</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_OPENID</li></ul></dd><dt><strong>Guest Access</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_GUEST_ACCESS</li><li>PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_GUEST_ACCESS</li></ul></dd></dl></td> +</tr> +<tr> +<td>Plugin</td> +<td><blockquote><ul><li>PERMISSION_SYSCONSOLE_READ_PLUGINS</li><li>PERMISSION_SYSCONSOLE_WRITE_PLUGINS</li></ul></blockquote></td> +</tr> +<tr> +<td>Integrations</td> +<td><dl><dt><strong>Integration Management</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT</li><li>PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_INTEGRATION_MANAGEMENT</li></ul></dd><dt><strong>Bot Accounts</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_BOT_ACCOUNTS</li><li>PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_BOT_ACCOUNTS</li></ul></dd><dt><strong>GIF (Beta)</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_GIF</li><li>PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_GIF</li></ul></dd><dt><strong>CORS</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS</li><li>PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_CORS</li></ul></dd></dl></td> +</tr> +<tr> +<td>Compliance</td> +<td><dl><dt><strong>Data Retention Policy</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY</li><li>PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_DATA_RETENTION_POLICY</li></ul></dd><dt><strong>Compliance Export</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_EXPORT</li><li>PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_EXPORT</li></ul></dd><dt><strong>Compliance Monitoring</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_MONITORING</li><li>PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_MONITORING</li></ul></dd><dt><strong>Custom Terms of Service</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE</li><li>PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE</li></ul></dd></dl></td> +</tr> +<tr> +<td>Experimental</td> +<td><dl><dt><strong>Features</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURES</li><li>PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_FEATURES</li></ul></dd><dt><strong>Feature Flags</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURE_FLAGS</li><li>PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_FEATURE_FLAGS</li></ul></dd><dt><strong>Bleve</strong></dt><dd><ul><li>PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_BLEVE</li><li>PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_BLEVE</li></ul></dd></dl></td> +</tr> +</tbody> +</table> + +## Frequently Asked Questions + +#### Can a User Manager or System Manager reset an administrator’s email or password without their knowledge? + +This is not possible with the default privileges of these roles. The ability to reset passwords or email addresses of administrators is limited to system admins. + +#### Can a User Manager or System Manager access the configuration file? + +Yes. However, they will only have access to read actual values and modify values in accordance with their permissions. If appropriate read permissions do not exist, the default key values will be displayed. + +#### Are all actions of admin roles logged? + +Every change made by any admin is included in the audit log. + +#### Can a System Manager change their own permissions or elevate their role? + +No. System Managers can't elevate their role, and aren't able to elevate other members' roles. + +#### Can any of the new roles view API keys/passwords or other sensitive information within the System Console (such as SMTP, AWS, Elastic Search)? + +No, password information is only visible to system admins and is obfuscated for other roles. + +#### If download links for compliance exports are enabled in the System Console, can a Read Only Admin download the reports? + +Only roles that are explicitly granted access to **System Console \> Compliance** have access to download compliance reports. + +#### Can any of the new roles force-join Private channels? + +Yes at this time they can, however, we will be improving on this behavior in the future with a prompt that lets them know they are entering a private channel. We are also planning on adding a permission which would remove the ability to access Private channels. + +#### Can I create a new role or clone an existing role? + +No, but we are actively seeking feedback on this capability. + +#### Can I use an LDAP filter to assign these roles? + +No, but we are considering this functionality for a future enhancement. + +#### Can I rename the roles? + +This is being considered for future development. + +#### Can a System Manager or User Manager demote or deactivate another Admin or Manager? + +A System or User Manager can demote or deactivate another System or User Manager, but can't demote or deactivate a system admin. + +#### Can a System Manager or User Manager assign or unassign admin roles? + +Only the system admin has access to edit system roles. diff --git a/docs/main/administration-guide/onboard/guest-accounts.mdx b/docs/main/administration-guide/onboard/guest-accounts.mdx new file mode 100644 index 000000000000..24b9e82019e6 --- /dev/null +++ b/docs/main/administration-guide/onboard/guest-accounts.mdx @@ -0,0 +1,175 @@ +--- +title: "Guest accounts" +--- +<PlanAvailability slug="all-commercial" /> + +Guest accounts in Mattermost are a way to collaborate with individuals, such as vendors and contractors, outside of your organization by controlling their access to channels and team members. For example, guest accounts can be used to collaborate with customers on a support issue or work on a website project with resources from an external design firm. + +<Important> + +- A system admin must [enable guest access](/administration-guide/configure/authentication-configuration-settings#guest-access) before guests can be invited. +- Mattermost Enterprise and Professional customers can [control who can invite guests](/administration-guide/onboard/advanced-permissions) in their organization. By default, only system admins can invite guests. +- Guest accounts don't all consume a licensed seat in the same way. Guests in exactly one channel are treated as single-channel guests and don't count toward the primary paid seat count. They're free up to a 1:1 ratio with licensed seats. Guests in multiple channels continue to count as paid active users. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. +- You'll identify guest users in Mattermost based on their **GUEST** badge next to their name and profile picture. Channels that contain guests also display the message **\*This channel has guests** in the channel header. + +</Important> + +## Guests account limits + +Guests can: + +- Pin messages to channels +- Use slash commands (excluding restricted commands such as invite members, rename channels, change headers, etc) +- Favorite channels +- Mute channels +- Update their profile +- Use different authentication methods than other users +- Leave channels to which they were added (including Town Square). + +Guests cannot: + +- Discover public channels +- Join open teams +- Create direct messages or group messages with members who aren’t within the same channel +- Invite people +- Create channel checklists + +## Guest authentication + +Guests can access the Mattermost server via email invitation, and be authenticated using AD/LDAP, SAML 2.0, or magic link passwordless authentication. + +Before you proceed, ensure that the authentication method you wish to use is correctly configured on your server and enabled in Mattermost. For configuration steps and technical documentation, see [Active Directory/LDAP setup](/administration-guide/onboard/ad-ldap) and [SAML Single-Sign-On](/administration-guide/onboard/sso-saml). + +Converting a member user to a guest won't change the channels they are in. However, they will be restricted from discovering additional channels and are unable to direct message/group message users outside of the channels they are in. They can be added to channels by system admins and other roles that have the correct permissions to invite guests. + +### Configure magic links for guests + +<PlanAvailability slug="entry-ent" /> + +From Mattermost v11.3, magic links allow guest users to access Mattermost without a password by using a secure link sent to their email address. This provides a streamlined passwordless authentication option for guest users. + +To configure magic link authentication for guests: + +1. Ensure [guest access is enabled](/administration-guide/configure/authentication-configuration-settings#enable-guest-magic-link-authentication) in **System Console \> Authentication \> Guest Access**. +2. Set **Enable passwordless authentication for guests using magic links via email** to **True**. +3. Select **Save**. + +When a guest is initially invited to Mattermost, they will receive an email with a link that allows them to log in without a password. The link expires in 48 hours for security purposes. When that guest returns to Mattermost and enters their email address, Mattermost sends them a new link to their email address that expires in 5 minutes. See the [magic link login for guests](/end-user-guide/access/access-your-workspace#magic-link-login-for-guests) documentation for details on how guests can use magic links to log in. + +### Configure AD/LDAP authentication + +When enabled, the **Guest Filter** in Mattermost identifies external users whose AD/LDAP role is `guest` and who are invited to join your Mattermost server. These users will have the `guest` role applied immediately upon first login instead of the default member user role. This eliminates having to manually assign the role in the System Console. + +1. Go to **System Console \> Authentication \> Guest Access** to enable guest access. +2. Go to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard, navigate to the **User Filters** section, then expand **Configure additional filters**. +3. Complete the **Guest Filter** field. +4. Select **Save**. + +If a Mattermost guest user has the `guest` role removed in the AD/LDAP system, the synchronization process will not automatically promote them to a member user role. This is done manually via **System Console \> User Management**. If a member user has the **Guest Attribute** added, the synchronization processes will automatically demote the member user to the guest role. + +When a guest logs in without having any channels assigned to their account, they're advised to talk to a Mattermost system admin. + +### Configure SAML 2.0 authentication + +When enabled, the **Guest Attribute** in Mattermost identifies external users whose SAML assertion is guest and who are invited to join your Mattermost server. These users will have the `guest` role applied immediately upon first login instead of the default member user role. This eliminates having to manually assign the role in the System Console. + +If a Mattermost guest user has the guest role removed in the SAML system, the synchronization processes will not automatically promote them to a member user role. This is done manually via **System Console \> User Management**. If a member user has the **Guest Attribute** added, the synchronization processes will automatically demote the member user to the guest role. + +1. Go to **System Console \> Guest Access** to enable guest access. +2. Go to **System Console \> Authentication \> SAML 2.0**. +3. Complete the **Guest Attribute** field. +4. Select **Save**. + +When a guest logs in without having any channels assigned to their account, they're advised to talk to a Mattermost system admin. + +## Manage guests + +See the following documentation to learn more about managing guests: + +- [invite people](/end-user-guide/collaborate/invite-people) to teams and channels +- [manage channel members](/end-user-guide/collaborate/manage-channel-members#remove-other-members-from-a-channel) +- [remove people from teams](/end-user-guide/collaborate/organize-using-teams#remove-people-from-teams) + +<Tip> + +You can also use the `/kick` or `/remove` slash commands to remove a guest from a channel. + +</Tip> + +When a guest has been removed from all channels within a team, and if they belong to other teams, they will default into the last channel on the last team they have accessed. If they are removed from all channels on all teams, they'll be taken to a screen letting them know they have no channels assigned. + +### Promote and demote user roles + +System admins can demote a user from a member to a guest by updating the user's role in **System Console \> User Management \> Users**. Select the member, then select **Demote to Guest**. All system and custom roles assigned to the demoted user are removed. System admins should also purge all of the demoted guest's sessions by selecting the guest user, then selecting **Revoke Sessions**. + +The demoted guest user retains their existing channel and team memberships, but is restricted from discovering public channels and collaborating with users outside of the channels they're in. This is useful if you're already collaborating with external contractors, and want to restrict their abilities within Mattermost. + +System admins can also promote a guest to member by updating their role in **System Console \> User Management \> Users**. Select the guest, then select **Promote to Member**. + +<Note> + +You can filter the list in **System Console \> User Management \> Users** to view **Guests (all)**, **Guests in a single channel**, or **Guests in multiple channels**. + +</Note> + +### Disable guest accounts + +To disable the guest accounts feature, go to **System Console \> Authentication \> Guest Access**, then set **Enable Guest Access** to **False**. To deactivate individual guest accounts, go to **System Console \> User Management \> Users**. Select a user, then select **Deactivate**. You can re-activate individual guest accounts by selecting **Activate**. + +- When a single guest account is deactivated or the guest account feature is disabled, guests are marked as `deactivated`, are logged out of Mattermost, and all guest sessions are revoked. In Mattermost Server versions prior to 5.18, disabling the guest account feature leaves current guest accounts as activated until they are manually deactivated. +- If you're using AD/LDAP and the guest access setting is disabled, the `guest` filter and existing guest users in System Console are deactivated. Additionally, no new guests can be invited or added using the filter as an authentication method. If a previous guest's credentials match the user filter (the only filter which is active when guest access is disabled), they will be reactivated and promoted to a member user upon their next login. +- Similarly, for SAML, when the guest access setting is disabled, the `guest` attribute and existing guest users in System Console are deactivated. Additionally, no new guests can be invited or added using the attribute as an authentication method. If a previous guest's credentials match the user attribute (the only attribute which is active when guest access is disabled), they will be reactivated and promoted to a member user upon their next login. + +You can disable individual guest accounts in **System Console \> User Management** via **Manage Members**. When a single guest account is disabled or the feature is disabled, the guest will be marked as `deactivated`, be logged out of Mattermost, and all their sessions will be revoked. + +### Reinstate guest accounts + +When guest access is re-enabled for AD/LDAP, the `guest` filter is reinstated. + +New users matching the `guest` filter will be authenticated as new guest users on login. + +Previous guest users will be activated with the next synchronization. If their credentials still match the `guest` filter, they will retain their guest status. If they no longer match the `guest` filter but do match the `user` filter, they will be not be promoted to member user automatically on login - this must be done manually. If a previous guest was reactivated as a member user when guest access was disabled, and now are identified by the `guest` filter once again, they will automatically be demoted to Guest upon their login. + +Similarly, for SAML, when guest access is re-enabled, the SAML `guest` attribute is reinstated. New users matching the `guest` attribute will be authenticated as new guest users on login. + +Previous guest users will be activated with the next synchronization. If their credentials still match the `guest` attribute, they will retain their guest status. If they no longer match the `guest` attribute but do match the `user` filter, they will be not be promoted to member user automatically on login - this must be done manually. If a previous guest was reactivated as a member user when guest access was disabled, and now are identified by the `guest` attribute once again, they will automatically be demoted to guest upon their login. + +## Frequently asked questions + +### How am I charged for guest accounts? + +Guest billing depends on how many channels a guest can access: + +- Guests in exactly one channel are treated as single-channel guests. They don't count toward the primary paid seat count and are free up to a 1:1 ratio with your licensed seats. +- Guests in multiple channels continue to count as regular paid active users. +- Direct messages and group messages don't change whether a guest is treated as a single-channel guest. + +If your single-channel guest count exceeds the 1:1 allowance, Mattermost shows soft warnings to system admins. Guest creation and guest access aren't blocked. + +### Why doesn’t Mattermost have single-channel guests? + +Mattermost now supports single-channel guests. + +Guests who belong to exactly one channel are counted separately from your primary paid seat count and are free up to a 1:1 ratio with licensed seats. Guests who belong to multiple channels continue to count as paid active users. Direct messages and group messages don't change whether a guest is treated as a single-channel guest. + +If the number of single-channel guests exceeds the 1:1 allowance, Mattermost shows dismissible warning indicators to system admins on the relevant reporting and license pages. Mattermost doesn't block adding guests or starting the server when this limit is exceeded. + +### Can I set an expiration date for guests? + +Currently, you cannot. This feature may be added at a later stage. + +### Can MFA be applied selectively? + +If MFA is enforced for your users, it can be applied to guest accounts. Guests can configure MFA in by going to their profile picture and selecting **Profile \> Security**. If MFA is not enforced for your users, it can't be applied to guest accounts. + +### Has the guest accounts feature been reviewed by an external security firm? + +The guest account feature was reviewed by the Mattermost security team. We do not have an external firm review scheduled but will include this feature in future reviews. + +### How can I validate my guests' identity? + +Guests can be authenticated via SAML and/or AD/LDAP to ensure that only the named guest can log in. Alternatively, you can whitelist domains via **System Console \> Authentication \> Guest Access \> Whitelisted Guest Domains**. + +### Can I restrict guests' ability to upload content? + +It is not currently possible to selectively disable upload/download functionality as it is a server-wide configuration. diff --git a/docs/main/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups.mdx b/docs/main/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups.mdx new file mode 100644 index 000000000000..a6d44a3150bd --- /dev/null +++ b/docs/main/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups.mdx @@ -0,0 +1,106 @@ +--- +title: "Using AD/LDAP synchronized groups to manage team or private channel membership" +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost groups created with [synchronized AD/LDAP groups](/administration-guide/onboard/ad-ldap-groups-synchronization) can be used to manage the membership of private teams and private channels. When a team or private channel is managed by synchronized groups, users will be added and removed based on their membership to the synchronized AD/LDAP group. + +For instance, you may have an AD/LDAP group that contains your development team that you want to synchronize to a developer team. By using this feature, new developers will get added to the team when they are added to the synchronized AD/LDAP group and they will be removed from the team when removed from the AD/LDAP group. + +Similarly, you may have an AD/LDAP group that contains your leadership team that you want to synchronize to a private channel for coordination and updates. This feature will help control the membership of the channel so that users outside of the synchronized group are prevented from being added to the channel mistakenly. + +On teams that are managed by synchronized groups, users outside of the group are restricted from: + +> - Invitation through a team invite link +> - Invitation through an email invite + +Similarly on private channels that are managed by synchronized groups, users outside of the group are restricted from: + +> - Invitation through a mention +> - Invitation through the `/invite` slash command +> - Being added to the channel with **Add members** + +Users can remove themselves from teams and private channels managed by synchronized groups. + +## Managing membership of a team or channel with synchronized groups + +To manage membership of a private team with synchronized groups: + +1. Navigate to **System Console \> User Management \> Teams**. +2. Select the team you want to manage with group synchronization. +3. Under **Team Management**, enable **Sync Group Members**. If **Anyone can join this team** is enabled or if specific email domains are set, they will be disabled by the sync group members feature. +4. Add one or more groups to the team. If there are groups already associated to default users into the team, they will already be present. +5. Review the notice in the footer of the screen for any users that are not part of groups who will be removed from the team on the next synchronization. +6. Select **Save**. Members will be updated on the next scheduled AD/LDAP synchronization. + +Alternatively you can use the mmctl tools to set the team to be managed by groups: + +1. Ensure there's at least one group already associated to the team. You can view and add default teams to a group via **System Console \> User Management \> Groups \> Group Configuration**. See the [mmctl group team list](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-list) documentation for more information on adding default teams and channels and confirming whether if there is already a group associated to the team. +2. Ensure **Team Settings \> General \> Allow any user with an account on this server to join this team** is set to `No`. +3. Convert the team to have its membership managed by synchronized groups by running the [mmctl group team enable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-enable) command. + +To manage membership of a private channel with synchronized groups: + +1. Navigate to **System Console \> User Management \> Channels**. +2. Select the channel you want to manage with group synchronization. +3. Under **Channel Management**, enable **Sync Group Members**. Please ensure the channel is set to `private`. +4. Add one or more groups to the channel. If there are groups already associated to default users in the channel, they'll already be present. +5. Review the notice in the footer of the screen for any users that are not part of groups who will be removed from the channel on the next synchronization. +6. Select **Save**. Members will be updated on the next scheduled AD/LDAP synchronization. + +Alternatively you can use the mmctl tool to set a private channel to be managed by groups: + +1. Ensure there's at least one group already associated to the channel. You can view and add default channels to a group via **System Console \> User Management \> Groups \> Group Configuration**. See our [AD/LDAP](/administration-guide/onboard/ad-ldap-groups-synchronization#add-default-teams-or-channels-for-the-group) documentation for more information on adding default teams and channels. Additionally, you can use the mmctl to view if there is already a group associated to the channel by running the [mmctl group channel list](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-list) command. +2. Convert the team to have its membership managed by synchronized groups by running the [mmctl group channel enable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-enable) command. + +## Add or remove groups from teams + +Once the management of the team is converted to be managed by synchronized groups, a team admin or system admin can add additional groups from **Main Menu \> Add Groups to Team**. This will add users on the next AD/LDAP synchronization and any new users to the group will be added to the team on subsequent synchronizations. Team admins will be prevented from changing the team to public by enabling **Team Settings \> Allow any user with an account on this server to join this team**. + +Team admins or system admins can also remove groups from a team from **Main Menu \> Manage Groups**. This will disassociate the group from the team. Users are removed on the next AD/LDAP synchronization. + +The system admin can also remove groups from **System Console \> User Management \> Teams \> Team Configuration \> Synced Groups**. + +## Add or remove groups from private channels + +Once the management of the channel is converted to be managed by synchronized groups, a team admin or system admin can add additional groups from **Channel Menu \> Add Groups to Channel**. This will add users on the next AD/LDAP synchronization and any new users to the group will be added to the channel on subsequent synchronizations. + +Team admins and system admins can also remove groups from a team from **Main Menu \> Manage Groups**. This will disassociate the group from the team. Users are removed on the next AD/LDAP synchronization. + +The system admin can also remove groups from **System Console \> User Management \> Channels \> Channel Configuration \> Synced Groups**. + +## Managing members + +Users are automatically removed from the team or private channel when removed from a synchronized AD/LDAP group that is managing the membership of that team or channel. Additionally, users who are not in the synchronized groups are prevented from being added through the `/invite` and mention flows within a channel. + +A user can remove themselves from the team or from the private channel when it is managed by synchronized groups. They can be added back by users who have permission to manage members for a team or private channel by using the `/invite` slash command or by mentioning the user in a channel. + +If the user is removed from a synchronized group and later readded to the group, they can be manually added back to the team or private channel as noted above. + +<Note> + +Users will not be automatically added back by the AD/LDAP synchronization once they remove themselves or are removed by the LDAP synchronized group. + +</Note> + +## Disabling group synchronized management of teams and private channels + +To remove the management of members by synchronized groups in a team, disable **Sync Group Members** under **System Console \> User Management \> Teams \> Team Management**, or run the [mmctl group team disable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-team-disable) command. + +To remove the management of members by synchronized groups in a channel, disable **Sync Group Members** under **System Console \> User Management \> Channels \> Channel Management**, or run the [mmctl group channel disable](/administration-guide/manage/mmctl-command-line-tool#mmctl-group-channel-disable) command. + +## Frequently asked questions + +**Why aren’t public channels supported with this feature?** + +Public channels are available to all members to discover and join. Managing membership with synchronized groups removes the ability for public channels to be accessible to users on the team. Private channels typically require a more controlled membership management, which is why this feature applies to Private channels. Groups can be assigned to public teams and public channels as described in [this documentation](/administration-guide/onboard/ad-ldap-groups-synchronization#add-default-teams-or-channels-for-the-group). + +**Does a team with its membership managed by groups have any effect on Public channel access?** + +Only users that are members of groups synchronized to team are able to discover and join public channels. Private channels can also be managed by synchronized groups when a team is managed by synchronized groups. + +**Why don't users get readded to teams or channels once they have been removed from and then later re-added to the LDAP group?** + +The implementation of group removals does not currently differentiate between users who have removed themselves or have been removed by the LDAP synchronization process. Our design optimizes for users who have removed themselves from a team or channel. In the future, we may add the ability for admins to re-add users who have been removed, and even prevent users from leaving a team or channel. + +Additionally, LDAP users who aren't accessible to Mattermost based on filters will be removed from the groups and from group-synced teams and channels. If they were removed from teams and channels then they will not be re-added to those teams and channels upon becoming subsequently re-accessible to Mattermost. diff --git a/docs/main/administration-guide/onboard/migrate-from-slack.mdx b/docs/main/administration-guide/onboard/migrate-from-slack.mdx new file mode 100644 index 000000000000..a23201511d99 --- /dev/null +++ b/docs/main/administration-guide/onboard/migrate-from-slack.mdx @@ -0,0 +1,416 @@ +--- +title: "Migrate from Slack" +--- +<PlanAvailability slug="all-commercial" /> + +## Overview + +Mattermost provides a reliable migration path from Slack, enabling you to bring your organization’s collaboration history into a secure, self-hosted Mattermost environment. The migration process supports full workspaces, including users, channels and message history, direct messages, and threads so your teams can continue working without losing valuable context. + +This process generally involves preparing your environment, exporting data from Slack, converting that data into a compatible format, and then importing it into Mattermost. Migrating from Slack is a multi-step process that can be complex, particularly for larger organizations or those with multiple Slack workspaces. + +Additionally, please consider that Slack's data control policies or export capabilities may change at any time, or they may charge fees to customers for exporting data stored in Slack. Support for negotiating export of customer IP from Slack Enterprise can be requested by contacting a [Mattermost Expert](https://mattermost.com/contact-sales/). + +1. [Preparations](#preparations): + - Answer key scoping questions. + - Gather environment and export details. + - Validate Mattermost server capacity and configuration. + - Back up your Mattermost environment before importing. +2. [Export Slack data](#export-slack-data): + - Generate an export from Slack. +3. [Transform the export for Mattermost](#transform-the-export-for-mattermost): + - Validate the Slack export using `mmetl check slack`. + - Use the `mmetl` tool to parse and transform Slack exports. +4. [Import into Mattermost](#import-data-into-mattermost): + - Upload and process transformed archives with `mmctl`. +5. Validate and test: + - Confirm channel and user data imported correctly. + - Run database queries to fix any unread states. +6. Go live: + - Communicate the cutover plan to users. + +### Migration timeline + +These instructions outline a *best effort* migration path designed to preserve the majority of your messages, files, and workspace structure. Mattermost provides tools and guidance to help streamline the process, but manual adjustments during the data transformation and import steps are often required. Successful migration depends on careful planning and dedicating sufficient time, technical resources, and technical skills to the effort. + +Depending on the size and complexity of your Slack environment, a full migration can take anywhere from several days to multiple weeks of dedicated effort. Larger organizations with multiple workspaces, extensive message history, and many files should expect the process to require significant iteration and testing before completion. It’s important to plan for this timeline in advance by allocating the necessary resources, scheduling time for trial imports in a development environment, and coordinating across teams. Building in extra time for adjustments during the transformation and import steps will help ensure a smoother transition and reduce disruption to your users. + +Scoping the migration appropriately during the preparation step can significantly reduce processing time and allow for faster iteration. Before beginning, carefully consider what data is essential to bring over to Mattermost. Many organizations find that not every channel or file needs to be migrated, and focusing only on what is truly needed can save substantial processing time and manual effort. By setting clear boundaries early, you’ll minimize the amount of data that requires manual intervention and testing, which in turn shortens the migration timeline and helps avoid unnecessary complexity. + +<Note> + +Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs support migrating from Slack to Mattermost. + +</Note> + +## Migrations Steps + +### 1. Preparations + +Before beginning the migration, it’s important to properly prepare your environment. Careful preparation helps reduce processing time, allows for faster iteration, and minimizes the chance of running into avoidable issues during the import. + +This document assumes you already have a Mattermost Server deployed that is ready to accept your Slack data. If not, consider the recommendations in this section in conjunction with the appropriate [deployment documentation](/deployment-guide/server/server-deployment-planning#deployment-options) to make informed decisions about your supporting database and file storage infrastructure. + +#### Scope definition + +Start by defining the scope of your migration: + +- **Slack edition**: Migrating from Slack Enterprise Grid involves additional [steps and planning](#faq). +- **Data history**: Decide how much history is necessary to import. Importing a smaller time window (e.g., the last six months) can significantly reduce complexity and processing time. +- **Export size**: Consider the size of your Slack export file as you progress through this guide. File size directly impacts how long the import will take - for example, files under ~25 GB often complete within a day, while exports over 100 GB can take several days, significantly lengthening the time between iterations and the overall timeline to complete the migration. +- **File attachments**: Consider whether you can exclude very large or non-critical attachments (for example, public software download packages, videos, or outdated media assets) to reduce import size and speed up processing. + +#### Infrastructure considerations + +The environment where you run the import can significantly affect performance: + +- **Test environment**: Always run the migration in a development or staging environment first. Most migrations require multiple iterations before a production import is successful. +- **Operating system**: The `mmetl` tool is supported on Linux and macOS. Windows is not supported, and we do not recommend using Windows Subsystem for Linux (WSL) since the file system is not performant enough for the heavier processes involved in migration. +- **Storage requirements**: Ensure your server can store both the Slack export archive and the fully unpacked data. As a best practice, plan for at least three times the size of your Slack export in available server storage. +- **File Storage**: Imports into S3 file storage typically complete faster than imports into local storage or NFS. For large imports, we recommend using AWS S3 or another S3-compatible storage service for best performance. + +#### Mattermost server considerations + +Carefully preparing your environment and making these adjustments up front will help ensure the migration proceeds smoothly and reduces the need for repeated trial-and-error. + +- **Fresh server**: The most reliable imports happen on a fresh Mattermost installation. If importing into an existing server, never import over an existing team. +- **Server version**: Make sure you are running the latest supported version of [Mattermost](/product-overview/mattermost-server-releases) to benefit from the most up-to-date functionality and fixes. +- **Backups**: When importing into an already existing Mattermost environment, back up both the Mattermost database and the data directory before starting. If an import fails, you’ll need to roll back or reset. + - If merging multiple Slack workspaces into a single team is the desired end-result, we recommend completing the import to separate teams, validating the results, then using [mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-move) to move channels between teams. +- **Configuration settings**: Adjust the following settings before starting the import: + - `TeamSettings.MaxChannelsPerTeam`: Set this to a number much higher than the number of channels you are migrating. + - `TeamSettings.MaxUsersPerTeam`: Set this to a number much higher than the number of users you are migrating. + - **Team Settings \> Allow any user with an account on this server to join this team**: Ensure this is enabled for the team receiving the import. + - `EmailSettings.EnableSignUpWithEmail` and `EmailSettings.EnableSignInWithEmail`: Both must be set to `true` + - `FileSettings.MaxFileSize`: Set this higher than the largest file in your Slack export. + - `ElasticsearchSettings.EnableIndexing`, `ElasticsearchSettings > EnableSearching` and `ElasticsearchSettings.EnableAutocomplete`: All must be set to `false` during the import to prevent performance issues. After the import, you can purge and reindex before enabling Elasticsearch. + +### 2. Export Slack data + +Slack offers two ways to [export your data from their product](https://slack.com/help/articles/201658943-Export-your-workspace-data). + +1. **Public channels export** - Contains only public channel messages and file links. Available on all Slack plans. Generate this from **Slack \> Admin \> Workspace settings \> Security \> Import & export data \> Export**. +2. **All channels and conversations export** - Contains all messages including public channels, private channels, DMs, and group messages. Available on Business+ (requires application approval from the workspace primary owner) and Enterprise Grid plans. + +You will receive a zip file containing the following contents: + +- Channels (`channels.json`) +- Users (`users.json`) +- Direct messages (`dms.json`) (All channels export) +- Private channels (`groups.json`) (All channels export) +- Group direct messages (`mpims.json`) (All channels export) +- App activity logs (`integration_logs.json`) +- Folders containing posts for every public channel +- Folders containing posts for every private channel (All channels export) + +<Note> + +- Refer to the [Slack help article](https://slack.com/help/articles/220556107-How-to-read-Slack-data-exports) for additional details on zip file contents. +- As a proprietary SaaS service, Slack is able to change its export format quickly and without notice. +- Workspaces on the Slack Free plan can only export file links from the last 90 days. + +</Note> + +<Important> + +Avoid unzipping and rezipping the Slack export. Doing so can modify the directory structure of the archive which could cause issues with the import process. + +</Important> + +### 3. Transform the export for Mattermost + +Now that you have a Slack export file, let's convert it into Mattermost's bulk import format using the import preparation tool `mmetl`. + +[Download the latest release of mmetl](https://github.com/mattermost/mmetl/releases/) for your OS and architecture. Run `mmetl help` to learn more about using the tool. + +#### Validate the Slack export + +Before transforming, validate the integrity of your Slack export using the `mmetl check` command: + +``` sh +./mmetl check slack --file <SLACK EXPORT FILE> +``` + +This checks for structural issues in the export archive and reports any problems that may cause the transform or import to fail. + +#### Run the transform + +Run the command below to create a Mattermost bulk import file. Replace `<TEAM-NAME>` with the name of your team in Mattermost. Note that the name needs to be one word and lowercase (i.e. if you named your team `My Team`, `<TEAM-NAME>` would be `my-team`). + +<Note> + +The team must already exist on your Mattermost server before importing, and **Allow any user with an account on this server to join this team** must be enabled for that team. + +</Note> + +``` sh +./mmetl transform slack --team <TEAM-NAME> --file <SLACK EXPORT FILE> --output mattermost_import.jsonl +``` + +The tool outputs a [.jsonl](https://jsonlines.org/examples) file containing all of your users, channels, and posts. It also creates a `data` folder that contains all of your attachments. It doesn't matter what you name the `.jsonl` file. You can name it what you want with the `--output` flag as shown above. It just needs to be a `.jsonl` file. + +#### Useful transform flags + +The `mmetl transform slack` command supports several optional flags that can help with common migration scenarios: + +- `--skip-attachments` / `-a`: Skip copying attachments from the import file. Useful for faster iteration when testing the import process before including attachments. +- `--allow-download` / `-l`: Allow downloading attachments from URLs. +- `--default-email-domain <DOMAIN>`: When a user's email is missing from the export, generate one from their username and the provided domain (e.g., `--default-email-domain example.com`). +- `--skip-empty-emails`: Allow users with empty email addresses to be included in the output. Note that this results in invalid import data that will need to be manually corrected before importing. +- `--discard-invalid-props` / `-p`: Discard posts with invalid properties. By default, such posts are kept but imported without their properties. + +#### Debug transform + +The `mmetl transform` process produces a `transform-slack.log` file that records INFO level output by default. + +If you run the import commands with the `--debug` flag, the log will include additional `DEBUG` level entries. These entries provide more granular detail on each phase of the process, which can help identify where the transformation may be slowing down or failing. + +#### MMETL parsing phases + +When parsing a Slack export file with the `mmetl` tool, the process runs through four phases. You can track progress by monitoring the log output during each phase. Understanding these phases helps set expectations for how long the parsing step may take. + +**1. Reading the import file** + +In this phase, `mmetl` reads through the Slack export file. Example log line: + +`{"file":"parse.go:359","level":"info","msg":"Processing file 1 of 10335: aluminum-white-lightbulb/","time":"2024-03-11T20:41:09-04:00"}` + +This step usually takes 5–10 minutes depending on the size of the export archive. + +**2. Converting user mentions** + +During this phase, `mmetl` converts Slack user mentions into Mattermost-compatible format. Example log line: + +`{"file":"parse.go:224","level":"debug","msg":"Slack Import: converting user mentions for channel touchscreen-headphones-sleek. 1 of 400","time":"2024-03-11T20:41:10-04:00"}` + +This step can be time-consuming on large imports and may take several hours. + +**3. Converting channel mentions** + +In this phase, channel references are updated. Example log line: + +`{"file":"parse.go:259","level":"debug","msg":"Slack Import: converting channel mentions for channel robust-smart-home-device-matrix. 95 of 400","time":"2024-03-11T20:41:48-04:00"}` + +This step typically completes in about half the time required for user mentions. + +**4. Converting post markup** + +Finally, Slack message formatting is converted into Mattermost-compatible Markdown. Example log line: + +`{"file":"parse.go:330","level":"debug","msg":"Slack Import: converting markdown for channel vertex-robust-vacuum. 120 of 400","time":"2024-03-11T20:41:58-04:00"}` + +This is the fastest step and usually completes quickly. + +### 4. Import data into Mattermost + +You can upload the export through Mattermost's API from the server or from another computer using mmctl commands. The server will save the import in its file store before running the import (e.g. AWS S3), so there will be time spent uploading/downloading the file in this case. + +The migration is idempotent, meaning that you can run multiple imports that contain the same posts, and there won't be duplicated created posts in Mattermost. Each post is imported with the correct user/author and `created_at` value from your Slack instance. + +Ensure you have the Mattermost command line tool `mmctl` installed. This allows you to perform different tasks that communicate to Mattermost's API. You'll also want to [configure authentication](/administration-guide/manage/mmctl-command-line-tool#mmctl-auth) for the tool. + +To prepare our files to be uploaded to the server, we need to put both the `.jsonl` file and `data` folder together into a zip file. + +``` sh +zip -r mattermost-bulk-import.zip data mattermost_import.jsonl +``` + +Validate the import file locally before uploading. This checks the file structure and content without needing to upload it to the server: + +``` sh +mmctl import validate ./mattermost-bulk-import.zip +``` + +Then we can upload the zip file to our Mattermost server. These files can be very large, so getting them onto the server can be challenging. You have two primary options for this step: + +- You can use the `mmctl` tool: + + ``` sh + mmctl import upload ./mattermost-bulk-import.zip + ``` + +- Alternatively, you can move the file directly to the data directory under `data/import` and give it a unique name. + +Run this command to list the available imports: + +``` sh +mmctl import list available +``` + +Run this command to process the import. Replace `<IMPORT FILE NAME>` with the name you got from the `mmctl import list available` command: + +``` sh +mmctl import process <IMPORT FILE NAME> +``` + +Finally, run this command to view the status of the import process job. If the job status shows as `pending`, then wait before running the command again. The `--json` flag is required to view the possible error message. Replace `<JOB ID>` with the id you got from the `mmctl import job list` command: + +``` sh +mmctl import job show <JOB ID> --json +``` + +#### Debug imports + +You can use the `mmctl import job show` command to view any relevant errors that may have occurred. + +#### Fixing unread channels and threads + +After importing, all messages may appear as unread for users. To resolve this issue, run the following SQL queries directly against the Mattermost database: + +``` sql +begin; +UPDATE channelmembers +SET + msgcount = channels.totalmsgcount, + lastupdateat = channels.lastpostat, + lastviewedat = channels.lastpostat, + msgcountroot = channels.totalmsgcountroot +FROM channels +WHERE channelmembers.channelid = channels.id; + +INSERT INTO preferences (UserId, Category, Name, Value) +SELECT + cm.userid, + 'channel_approximate_view_time', + cm.channelid, + cm.lastupdateat +FROM + channelmembers cm +ON CONFLICT (userid, category, name) +DO UPDATE SET + Value = EXCLUDED.Value; + +update preferences + set value = false + where category = 'direct_channel_show'; + +update preferences + set value = false + where category = 'group_channel_show'; + +commit; +``` + +#### Address placeholder emails + +During the import process, the emails and usernames from Slack are used to create new Mattermost accounts. If emails are not present in the Slack export archive, then placeholder values will be generated and the system admin will need to update these manually. We recommend administrators search the final import `jsonl` file for `user` lines with `@example.com` in the email property to address and resolve the missing information prior to import. + +### Email verification behavior + +The email verification process during Slack import depends on who performs the import: + +**System administrator imports:** + +- Email addresses are automatically verified during the import process. +- Users can immediately use the **Password Reset** feature to set their password. +- No email verification steps are required before password reset. + +**Non-administrator imports:** + +- Email addresses remain unverified after import. +- Users must first verify their email addresses before they can reset their password. +- Additional email verification steps are required before account access. + +### Account activation + +- Slack users activate their new Mattermost accounts by using Mattermost's **Password Reset** screen with their email addresses from Slack to set new passwords for their Mattermost accounts. See the instructions on how to [migrate user authenticatation to LDAP or SAML](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-migrate-auth). + - For imports performed by System Admins: Users can immediately use the **Password Reset** feature (no email verification is required). + - For imports performed by non-administrators: Users must first verify their email addresses, then use the **Password Reset** feature. +- Once logged in, Mattermost users will have access to previous Slack messages in the public channels imported from Slack. + +## FAQ + +What additional considerations are there for Slack Enterprise Grid? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Slack Enterprise Grid combines multiple workspaces under a single management plane and the associated export reflects that complexity. An Enterprise Grid export is a single archive containing all workspaces and shared channels. + +Mattermost does not support shared channels between teams, so Slack Shared Channels must be mapped to a single team in Mattermost. We can create this mapping by determining the originating teams in Slack and creating a `team.json` mapping file for use with `mmetl`. Because of the manual effort required to identify and map team IDs, Enterprise Grid migrations are typically more time-consuming than single-workspace migrations. Plan additional time and resources to complete this step successfully. + +#### Export structure + +At the root level, you’ll see shared channels that span across Slack workspaces, and under `/teams/` you’ll find per-workspace data such as channels and users files. A typical structure looks like: + +``` text +Enterprise Grid Export/ +├── channel1/ +│ ├── 2023-01-01.json +│ └── 2023-01-02.json +├── channel2/ +│ ├── 2023-05-01.json +│ └── 2023-05-02.json +├── teams/ +│ ├── team1/ +│ │ ├── channel3/ +│ │ │ ├── 2023-05-01.json +│ │ │ └── 2023-05-02.json +│ │ ├── channels.json +│ │ ├── mpims.json +│ │ ├── dms.json +│ │ ├── users.json +│ │ └── groups.json +│ └── team2/ +│ ├── channel4/ +│ │ ├── 2023-05-01.json +│ │ └── 2023-05-02.json +│ ├── channels.json +│ ├── mpims.json +│ ├── dms.json +│ ├── users.json +│ └── groups.json +├── channels.json +├── org_users.json +├── mpims.json +├── dms.json +└── groups.json +``` + +#### Mapping shared channels to Mattermost teams + +1. Download the full Enterprise Grid export from Slack. +2. To determine where each shared channel belongs in Mattermost, look for a `team` attribute on the first post in each shared channel. These `team` values map the channel back to its originating workspace in Slack. This is where each shared channel will live in Mattermost once imported. + +> ``` json +> { +> "client_msg_id": "", +> "type": "", +> "text": "", +> "user": "U1", +> "ts": "1695219722.430309", +> "blocks": [ ], +> "team": "team1", +> "user_team": "team1", +> "source_team": "team1", +> "user_profile": { } +> }, +> ``` + +3. Create a `teams.json` file that maps Slack team IDs to each `team` attribute you found above. For example: + +> ``` json +> { +> "T0001" : "team1", +> "T0002" : "team2" +> } +> ``` + +4. Run the `mmetl grid-transform` command to split the Enterprise Grid export into per-team files: + +> ``` bash +> ./mmetl grid-transform -f slackexport.zip -t teams.json +> ``` + +This process outputs a new archive for each team defined in `teams.json`. Once split, you can continue the standard Mattermost import process on each file. + +### Are there features of Slack that are not supported for migration to Mattermost? + +The Slack import process focuses on preserving core collaboration data such as messages, files, channels, and users. However, certain Slack features are not supported by the Mattermost product and thus will not be migrated using the import tools in this document: + +- **Slack apps and integrations**: Installed apps, bots, slash commands, webhooks, workflow builder and other integrations do not migrate. Most integrations supported by Slack can be recreated using the [integration and automation](/integrations-guide/integrations-guide-index) options in Mattermost. +- **Starred conversations**: Starred conversations are not preserved. +- **User groups**: User groups from Slack are not preserved, however they can be recreated in Mattermost using the [Custom Groups](/end-user-guide/collaborate/organize-using-custom-user-groups) feature. +- **Threaded conversations**: Slack threads are mostly supported, however some threading relationships may not always be preserved given the differences in how Mattermost and Slack threading works. +- **Canvases**: Canvases are not supported in Mattermost and will not be migrated. +- **User presence and profiles**: User status (online/away), profile pictures, and custom profile fields do not carry over. Users will need to update their profiles in Mattermost. +- **Channel memberships for deactivated users**: Deactivated or deleted Slack users are not migrated to Mattermost. + +Because of these limitations, some manual reconfiguration is typically required after the import, especially for workflows and integrations. Support from a [Mattermost expert is available](https://mattermost.com/contact-sales/) for your Slack migration. diff --git a/docs/main/administration-guide/onboard/migrate-gitlab-omnibus.mdx b/docs/main/administration-guide/onboard/migrate-gitlab-omnibus.mdx new file mode 100644 index 000000000000..a0f1cf08cc75 --- /dev/null +++ b/docs/main/administration-guide/onboard/migrate-gitlab-omnibus.mdx @@ -0,0 +1,131 @@ +--- +title: "Migrating from GitLab Omnibus to Mattermost Standalone" +--- +## Overview + +GitLab has announced the [deprecation of Mattermost from the GitLab Omnibus package](https://docs.gitlab.com/update/deprecations/#mattermost-bundled-with-linux-package) with GitLab 19.0. As part of this transition, GitLab will continue to support Mattermost **up to version 10.11 ESR** within the Omnibus installation until the final removal date. + +To ensure continuity and long-term support, organizations using Mattermost within GitLab Omnibus should plan to migrate to a **standalone Mattermost installation**. This approach provides ongoing access to the latest Mattermost releases, security updates, and enterprise capabilities independent of GitLab’s release cycle. + +Migrating to a standalone deployment also enables greater flexibility in managing infrastructure, upgrading PostgreSQL, and scaling Mattermost independently to meet performance and compliance requirements. + +## Prerequisites + +Before you begin: + +- Administrative (root or sudo) access to the GitLab Omnibus server. +- A new standalone **PostgreSQL** server prepared and accessible. +- Sufficient disk space for the Mattermost database dump. +- A planned maintenance window, as Mattermost downtime is required. +- A current full backup of your Mattermost instance, including database and file storage. + +## Migration Steps + +Follow the steps below to safely migrate from GitLab Omnibus to a standalone Mattermost installation. + +<Note> + +The following procedure assumes your Mattermost database name is `mattermost_production` and your PostgreSQL user is `mmuser`. Adjust as needed for your environment. + +</Note> + +### Step 1: Create a Database Dump from GitLab Omnibus + +Use the GitLab Omnibus PostgreSQL tools to create a dump of the Mattermost database. Run this command on the GitLab server: + +``` bash +sudo gitlab-psql -- /opt/gitlab/embedded/bin/pg_dump -h /var/opt/gitlab/postgresql --no-owner mattermost_production | gzip > mattermost_dbdump_$(date --rfc-3339=date).sql.gz +``` + +This will create a compressed SQL dump file of your Mattermost database. + +### Step 2: Prepare the New PostgreSQL Server + +Set up your new PostgreSQL server following the official [Mattermost database preparation guidelines](/deployment-guide/server/preparations#database-preparation). This includes: + +- Installing the correct PostgreSQL version supported by your Mattermost server. +- Creating a new Mattermost database and user with appropriate permissions. + +### Step 3: Transfer and Restore the Database Dump + +Transfer the database dump file to your new PostgreSQL server, then restore it: + +``` bash +zcat /tmp/mattermost_dbdump.sql.gz | psql -U mmuser -d mattermost +``` + +Verify that the database restoration completes successfully without errors. + +### Step 4: Update Mattermost Configuration + +On your standalone Mattermost server, update the `config.json` file to point to the new PostgreSQL server. Locate the `SqlSettings.DataSource` parameter and update it as follows: + +``` json +"SqlSettings": { + "DriverName": "postgres", + "DataSource": "postgres://mmuser:password@new-postgres-server:5432/mattermost?sslmode=disable&connect_timeout=10" +} +``` + +Ensure that credentials, hostnames, and connection settings match your new PostgreSQL configuration. + +### Step 5: Migrate the Mattermost Application and Data + +To move Mattermost application files from the GitLab server to a new standalone server: + +1. **Install the same or newer version** of Mattermost on the new server. See the [Server Deployment Planning](/deployment-guide/server/server-deployment-planning#deployment-options). + +2. **Copy your existing configuration and data** from the GitLab Omnibus instance: + + ``` bash + # On the GitLab server + sudo cp /var/opt/gitlab/mattermost/config/config.json /tmp/ + sudo cp -r /var/opt/gitlab/mattermost/data /tmp/mattermost_data + + # Transfer to new Mattermost server + scp /tmp/config.json mattermost@new-server:/opt/mattermost/config/ + scp -r /tmp/mattermost_data mattermost@new-server:/opt/mattermost/data/ + ``` + +3. Ensure permissions are correctly set on the new server: + + ``` bash + sudo chown -R mattermost:mattermost /opt/mattermost + ``` + +### Step 6: Start Mattermost + +Start the Mattermost service on your new standalone installation: + +``` bash +sudo systemctl start mattermost +``` + +Mattermost will now connect to your standalone PostgreSQL database. + +### Step 7: Verify the Migration + +After starting Mattermost, perform the following checks: + +- Confirm that Mattermost starts successfully with no database connection errors. +- Review server logs for any startup or connection issues. +- Log into Mattermost and verify that all teams, channels, and users are present. +- Post test messages and upload files to confirm functionality. +- Validate user authentication and permissions. +- Confirm that database queries are directed to the new PostgreSQL server. + +## Important Considerations + +- Always maintain a **full backup** of your Mattermost database before migration. +- Schedule a **maintenance window** to minimize user disruption. +- Validate performance and monitoring configurations post-migration. +- Ensure that your new PostgreSQL server follows Mattermost’s security and tuning best practices. + +## Troubleshooting + +If you encounter errors during the migration: + +- Review PostgreSQL logs for permission or connection issues. +- Verify that the Mattermost PostgreSQL user has full access to the restored database. +- Ensure that the `config.json` file contains the correct database connection string. +- Restart the Mattermost service and check `mattermost.log` for detailed errors. diff --git a/docs/main/administration-guide/onboard/migrating-to-mattermost.mdx b/docs/main/administration-guide/onboard/migrating-to-mattermost.mdx new file mode 100644 index 000000000000..82a7bd4628bf --- /dev/null +++ b/docs/main/administration-guide/onboard/migrating-to-mattermost.mdx @@ -0,0 +1,71 @@ +--- +title: "Migration guide" +--- +<PlanAvailability slug="all-commercial" /> + +Migrations help you move your Mattermost deployment or data from one environment to another with minimal disruption. Whether you’re transitioning your Mattermost server to new infrastructure, restructuring your database, or moving from another collaboration platform like Slack, this guide provides step-by-step instructions for each supported path. Use the sections below to quickly find the scenario that matches your needs and follow the recommended process to ensure a smooth migration. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. + +## Move Mattermost to a new server + +The following instructions migrate Mattermost from one server to another by backing up and restoring the Mattermost database and `config.json` file. For these instructions, `SOURCE` refers to the Mattermost server *from which* your system will be migrated and `DESTINATION` refers to the Mattermost server *to which* your system will be migrated. + +1. Back up your SOURCE Mattermost server. See [Backup and Disaster Recovery documentation](/deployment-guide/backup-disaster-recovery). +2. Upgrade your SOURCE Mattermost server to the latest major build version. See [Upgrading Mattermost Server documentation](/administration-guide/upgrade/upgrading-mattermost-server). +3. Install the latest major build of Mattermost server as your `DESTINATION`. + +> - Make sure your new instance is properly configured and tested. The database type (MySQL or PostgreSQL) and version of `SOURCE` and `DESTINATION` deployments need to match. +> - Stop the `DESTINATION` server using `sudo stop mattermost`, then back up the database and `config.json` file. + +4. Migrate database from `SOURCE` to `DESTINATION`. Backup the database from the `SOURCE` Mattermost server and restore it in place of the database to which the `DESTINATION` server is connected. +5. Migrate `config.json` from `SOURCE` to `DESTINATION`. Copy `config.json` file from `SOURCE` deployment to `DESTINATION`. +6. If you use local storage (`FileSettings.DriverName` is set to `local`), migrate `./data` from `SOURCE` to `DESTINATION`. + +> - Copy the `./data` directory from `SOURCE` deployment to `DESTINATION`. +> - If you use a directory other than `./data`, copy that directory instead. + +7. Start the `DESTINATION` deployment by running `sudo start mattermost`. Then go to the **System Console**, make a minor change, and save it to upgrade your `config.json` schema to the latest version using default values for any new settings added. +8. Test that the system is working by going to the URL of an existing team. You may need to refresh your Mattermost browser page in order to get the latest updates from the upgrade. + +Once your migration is complete and verified, you can optionally [upgrade the Team Edition of Mattermost to Enterprise Edition using the upgrade guide](/administration-guide/upgrade/upgrading-mattermost-server#upgrade-team-edition-to-enterprise-edition). + +## Move from Slack + +See the [Migrate from Slack](/administration-guide/onboard/migrate-from-slack) documentation for details on migrating from Slack to Mattermost. + +## Move from Jabber + +BrightScout helped a major U.S. Federal Agency rapidly migrate from Jabber to Mattermost and open sourced their Extract, Transform and Load (ETL) tool at [https://github.com/Brightscout/mattermost-etl](https://github.com/Brightscout/mattermost-etl). Read more about their [case study](https://mattermost.com/blog/u-s-federal-agency-migrates-from-jabber-to-mattermost-the-open-source-way/) online. + +## Move from Pidgin + +In some cases, people are using Pidgin clients with different backends to communicate. To continue using Pidgin with a Mattermost backend, consider using [Mattermost ETL tool](https://github.com/Brightscout/mattermost-etl), created by BrightScout, to migrate data from your existing backend into Mattermost. + +Then use the [Pidgin-Mattermost plugin](https://github.com/EionRobb/purple-mattermost) (complete with an installer for end user machines) to continue to support legacy Pidgin users while offering a whole new Mattermost experience on web, mobile, and PC. + +## Move from Bitnami + +Bitnami uses MySQL, and renames the Mattermost database tables by converting the names to all lower case. For example, in non-Bitnami installations, the Users table is named `Users`, but in Bitnami, the table is `users` (with a lowercase `u`). As a result, when you migrate your data from Bitnami to a non-Bitnami installation, you must modify the MySQL startup script so that it starts MySQL in lowercase table mode. + +You can modify the script by adding the `--lower-case-table-names=1` switch to the MySQL start command. The location of the start-up script generally depends on how you installed MySQL, whether by using the package manager for the operating system, or by manually installing MySQL. You must modify the start-up script before migrating the data. + +For more information about letter case in MySQL table names and the `--lower-case-table-names` switch, see the [Identifier Case Sensitivity](https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html) topic in the MySQL documentation. + +## Move from bespoke messaging solutions + +Mattermost is often selected to replace bespoke solutions by IT and DevOps teams as a stable, enterprise-grade, commercially-supported solution on an open source platform that meets and exceeds the flexibility and innovation of bespoke solutions. + +Migrating from bespoke messengers to Mattermost can be challenging. Because of the difficulty of upgrading and maintaining bespoke solutions, the format for storing data is unpredictable, and the community around any single legacy release is small. + +If your data in the bespoke messenger is vital, consider: + +1. [Mattermost bulk load tool](/administration-guide/onboard/bulk-loading-data): Use the Mattermost bulk load tool to ETL from your bespoke system to Mattermost. +2. [Mattermost ETL framework from BrightScout](https://github.com/Brightscout/mattermost-etl): Consider the Mattermost ETL framework from BrightScout to custom-configure an adapter to plug in to the Bulk Load tool mentioned above. +3. **Legacy Slack import:** If you only recently switched from Slack to a bespoke tool, consider going back to import the data and users from the old Slack instance directly into Mattermost, leveraging the extensive support for Slack-import provided. +4. **Export to Slack, then import to Mattermost:** [Export Flowdock, Campfire, Chatwork, Hall, or CSV files to Slack](https://slack.com/help/articles/217872578-Import-data-from-one-Slack-workspace-to-another) and then export to a Slack export file and import the file into Mattermost. + +If your data in the bespoke messenger is not vital, consider: + +1. **Parallel systems:** Running Mattermost in parallel with your bespoke system until the majority of workflow and collaboration has moved to Mattermost +2. **Hard switch:** Announce a "hard switch" to Mattermost after a period of time of running both systems in parallel. Often this has been done due to security concerns in bespoke products or products nearing end-of-life. diff --git a/docs/main/administration-guide/onboard/migration-announcement-email.mdx b/docs/main/administration-guide/onboard/migration-announcement-email.mdx new file mode 100644 index 000000000000..a63d5e88e578 --- /dev/null +++ b/docs/main/administration-guide/onboard/migration-announcement-email.mdx @@ -0,0 +1,33 @@ +--- +title: "Migration announcement email" +--- +<PlanAvailability slug="all-commercial" /> + +To notify your end users of your migration to Mattermost, we created a sample email template that you can use. + +Remember to replace all the items in bold with your information. + +## Email template + +To: End users + +Subject: Moving to Mattermost + +Hi all, + +As some of you already know, we are moving from **\[System\]** to Mattermost as our collaboration platform. We have imported our existing users and data into Mattermost so we can continue to communicate, share files and collaborate. + +To get started: + +1. Open a browser on your computer, go to **\[Mattermost URL\]** and select “I forgot my password” to set your new password for Mattermost using the email address you used on the previous system. +2. Once you reset your password, use your email and new password to log in. +3. [Download](https://mattermost.com/apps) the Mattermost apps for desktop and mobile. Refer to the [Use Mattermost](/end-user-guide/end-user-guide-index) end user documentation on how to get up and running quickly. +4. Remember to bookmark the URL so you can use it to log in next time! + +Questions? + +If you have any questions, feel free to post in the **\[~Mattermost channel\]** or email us at **\[Support email\]**. + +Happy collaborating! + +**\[Sign-off\]** diff --git a/docs/main/administration-guide/onboard/multi-factor-authentication.mdx b/docs/main/administration-guide/onboard/multi-factor-authentication.mdx new file mode 100644 index 000000000000..15c530ba5582 --- /dev/null +++ b/docs/main/administration-guide/onboard/multi-factor-authentication.mdx @@ -0,0 +1,44 @@ +--- +title: "Multi-factor authentication" +--- +<PlanAvailability slug="all-commercial" /> + +Multi-factor authentication (MFA) is a secondary layer of user authentication applied to your Mattermost server that applies to all users on all teams within your Mattermost workspace. + +With MFA enabled, users need to provide a secure one-time code in addition to their username and password in order to log in to Mattermost. MFA is useful in organizations that have specific security and compliance policies. It can also be used in organizations where Mattermost is not behind a firewall and doesn't have access to existing MFA infrastructure. + +Mattermost offers a smartphone-based MFA check in addition to email-password or Active Directory/LDAP authentication to log in to the Mattermost server. + +Supported devices include iOS, Android, or other devices that are able to install a software-based authenticator such as FreeOTP, Google Authenticator, Microsoft Authenticator, 1Password, LastPass, or a similar app. After the app is installed, the device does not require internet access. + +<Note> + +As the MFA implementation relies on Time-based One-time passwords (TOTP) ensure that your server system time is accurate. If there is a discrepancy, users may not be able to log in successfully. + +</Note> + +## Enabling MFA + +System admins can enable this option by going to **System Console \> Authentication \> MFA**, then setting **Enable Multi-factor Authentication** to **true**. + +Once enabled, users can choose to [set up multi-factor authentication](/end-user-guide/preferences/manage-your-security-preferences) on their account by selecting **Profile \> Security \> Multi-factor Authentication** from their profile picture. + +### Disabling MFA + +System admins can disable this option by going to **System Console \> Authentication \> MFA**. When **Enable Multi-factor Authentication** is set to **false**, users can't opt to use or disable multi-factor authentication on their account via **Profile \> Security \> Multi-factor Authentication**. + +MFA can be disabled for user accounts using the API. See the [Mattermost API Reference](https://api.mattermost.com/#tag/users/paths/~1users~1{user_id}~1mfa/put) for details. + +## Enforcing MFA + +Admins can fulfill Multi-Factor Authentication (MFA) compliance requirements by enforcing an MFA requirement for login with email and LDAP accounts. Go to **System Console \> Authentication \> MFA**, then set **Enforce Multi-factor Authentication** to **true**. + +When MFA enforcement is set to **true**, users with email or LDAP authentication who don't have MFA set up will be directed to the MFA setup page when they log in to Mattermost. They will not be able to access the site until MFA setup is complete. Any new users will be required to set up MFA during the sign up process. + +Users will not be able to remove MFA from their account while enforcement is on. + +<Note> + +Turning on MFA enforcement prevents users from accessing the site until set up is complete. We recommended that you turn on enforcement during non-peak hours when people are less likely to be using Mattermost. + +</Note> diff --git a/docs/main/administration-guide/onboard/ssl-client-certificate.mdx b/docs/main/administration-guide/onboard/ssl-client-certificate.mdx new file mode 100644 index 000000000000..1c46a63b7008 --- /dev/null +++ b/docs/main/administration-guide/onboard/ssl-client-certificate.mdx @@ -0,0 +1,133 @@ +--- +title: "SSL client certificate setup" +--- +<PlanAvailability slug="all-commercial" /> + +Follow these steps to configure SSL client certificates for your browser and the Mattermost desktop apps on Windows, macOS, and Linux. + +Before you begin, follow the [official guides to install Mattermost](/deployment-guide/deployment-guide-index) on your system, including NGINX configuration as a proxy with SSL and HTTP/2, and a valid SSL certificate such as Let's Encrypt. + +For the purposes of this guide, the Mattermost server domain name is `example.mattermost.com`, and the user account is `mmuser` with email `mmuser@mattermost.com` and password `mmuser-password`. + +<Important> + +\- Generating the client certificates in this section is optional if you have already generated them before. - We strongly recommend configuring an SSL certificate (or a self-signed certificate) for security, privacy, compliance, as well as to avoid browser limitations that can prevent Mattermost product features from working that copy data using the user's local clipboard, including [sharing message links](/end-user-guide/collaborate/share-links#share-message-links) and [inviting people](/end-user-guide/collaborate/invite-people). - SSL client certificates are not yet supported on the Mattermost mobile apps. + +</Important> + +## Set up mutual TLS authentication for the web app + +1. Create a [certificate authority (CA) key](https://en.wikipedia.org/wiki/Certificate_authority) and a certificate for signing the client certificate. When establishing a TLS connection, the NGINX proxy server requests and validates a client certificate provided by the web app. + +``` sh +openssl genrsa -des3 -out ca.mattermost.key 4096 +``` + +``` text +pass phrase: capassword +``` + +``` sh +openssl req -new -x509 -days 365 -key ca.mattermost.key -out ca.mattermost.crt +``` + +``` text +Country Name: US +State: Maryland +Locality Name: Meade +Organization Name: Mattermost +Organization Unit: Smarttotem +Common Name: example.mattermost.com +Email Address: admin@mattermost.com +``` + +2. Create the client side key for `mmuser` with a passphrase, and the certificate signing request: + +``` sh +openssl genrsa -des3 -out mmuser-mattermost.key 1024 +``` + +``` text +passphrase: mmuser-passphrase +``` + +``` sh +openssl req -new -key mmuser-mattermost.key -out mmuser-mattermost.csr +``` + +``` text +Country Name: US +State: Maryland +Locality Name: Meade +Organization Name: Mattermost +Organization Unit: Smarttotem +Common Name: mmuser +Email Address: mmuser@mattermost.com + +Challenge password: mmuser-passphrase +``` + +3. Sign the user's client certificate with the previously created CA certificate: + +``` sh +openssl x509 -req -days 365 -in mmuser-mattermost.csr -CA ca.mattermost.crt -CAkey ca.mattermost.key -set_serial 01 -out mmuser-mattermost.crt +``` + +4. Check the newly generated client certificate for `mmuser`: + +``` sh +openssl x509 -in mmuser-mattermost.crt -text -noout +``` + +5. Open the file `/etc/nginx/sites-available/mattermost` and modify the following lines, so that the NGINX proxy server requests and verifies the client certificate: + +``` text +ssl on; +ssl_certificate /etc/letsencrypt/live/example.mattermost.com/fullchain.pem; +ssl_certificate_key /etc/letsencrypt/live/example.mattermost.com/privkey.pem; +ssl_client_certificate /opt/mattermost/config/ca.mattermost.crt; +ssl_verify_client on; + +... + +location ~ /api/v[0-9]+/(users/)?websocket$ { + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_set_header X-SSL-Client-Cert-Subject-DN $ssl_client_s_dn; + +... + +location / { + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_set_header X-SSL-Client-Cert-Subject-DN $ssl_client_s_dn; + +... +``` + +6. Confirm the CA key for `mmuser` works by the following curl command to the proxy: + +``` sh +curl -v -s -k --key mmuser-mattermost.key --cert mmuser-mattermost.crt:mmuser-passphrase https://example.mattermost.com +``` + +You should see the Mattermost login page. If you see: + +> - `No required SSL certificate was sent`, something went wrong. Review the above steps and try again. +> - `Error reading X.509 key or certificate file: Decryption has failed.`, make sure the passphrase is included together with the certificate, because curl doesn't prompt for it separately. + +7. Generate a PKCS12 file from the CA key and certificate, to install the certificate into your client machine for your browser to use: + +``` sh +openssl pkcs12 -export -out mmuser-mattermost.p12 -inkey mmuser-mattermost.key -in mmuser-mattermost.crt -certfile ca.mattermost.crt +``` + +``` text +Enter Export Password: mmuser-passphrase +``` + +8. Repeat steps 2-7 above for other users as needed. +9. Import the generated `.p12` file in step 7 into your key chain. In the Chrome browser on macOS: + +> 1. Go to **Settings \> Advanced \> Privacy and security \> Manage certificates**. This opens the Keychain Access app. +> 2. Go to **File \> Import Items** and select the `mmuser-mattermost.p12` file. + +10. Go to `https://example.mattermost.com`. You should see a popup for the client certificate request. diff --git a/docs/main/administration-guide/onboard/sso-entraid.mdx b/docs/main/administration-guide/onboard/sso-entraid.mdx new file mode 100644 index 000000000000..e97d4627a6f7 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-entraid.mdx @@ -0,0 +1,107 @@ +--- +title: "Entra ID Single Sign-On" +--- +<PlanAvailability slug="all-commercial" /> + +## Configuring EntraID as a Single Sign-On (SSO) service + +<Note> + +- This documentation covers configuring Entra ID for **OpenID Connect** authentication. If you need to configure Entra ID for **SAML** authentication instead, see the [Configure SAML with Microsoft Entra ID](/administration-guide/onboard/sso-saml-entraid) documentation. +- The system must be using SSL as Microsoft only allows OAuth redirect URIs that are SSL-enabled. + +</Note> + +Follow these steps to configure Mattermost to use your Entra ID logon credentials and Azure Active Directory account as a Single Sign-on (SSO) service for team creation, account creation, and sign-in. + +### Step 1: Register an application in Azure Portal + +1. Log in to the [Azure Portal](https://portal.azure.com/) with the account that relates to the Azure Active Directory tenant where you want to register the application. You can confirm the tenant in the top right corner of the portal. +2. In the left-hand navigation pane, select the **Microsoft EntraID**, then toward the bottom select **Add application registrations**. +3. Give your new registration a **Name**. +4. Define which **Supported account types** can access the application. For example, if this is to be only accessed from your enterprise's Azure AD accounts, then select **Accounts in this organizational directory only**. +5. Define the **Redirect URI** as Web client, then input the URL with the host name that will be specific to your Mattermost service followed by `/signup/office365/complete`. An example below is: `https://your.mattermost.com/signup/office365/complete` + +![image](/images/AzureApp_New_Registration.png) + +![image](/images/AzureApp_SetupMenuv2.png) + +Once the App Registration has been created, you can configure it further. See the standard [Azure AD documentation](https://learn.microsoft.com/en-gb/azure/active-directory/develop/quickstart-register-app) for reference. + +### Step 2: Generate a new client secret in Azure Portal + +1. From the overview page of the newly created **Registered App**, select **Certificates and Secrets** from the menu, then select the button to generate a **New Client secret**. + +![image](/images/AzureApp_Client_Secret_Setup.png) + +2. Provide a description, define the expiry for the token, then select **Add**. + +![image](/images/AzureApp_Client_Secret_Expiry.png) + +3. Store the **value** of the new secret somewhere secure. +4. In Azure Portal, select **Overview** from the menu, then copy and paste both the Application (client) ID and the Directory (tenant) ID to a temporary location. You will enter these values as an **Application ID** and as part of an **Auth Endpoint** and **Token Endpoint** URL in the Mattermost System Console. + +![image](/images/AzureApp_App_Directory_IDsv2.png) + +5. Grant admin concent for the configured permissions under **App Registrations \> \<Your App\> \> Manage \> API Permissions** + +![image](/images/AzureApp_App_Directory_Grant_Admin_Consent.png) + +### Step 3: Configure Mattermost for Entra ID SSO + +1. Log in to Mattermost, then go to **System Console \> Authentication \> OpenID Connect**. +2. Select **Entra ID** as the service provider. +3. Paste the **Directory (tenant) ID** from the Azure Portal as the **Directory (tenant) ID** in Mattermost. +4. The **Discovery Endpoint** for OpenID Connect with Entra ID is prepopulated with `https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration`. +5. Paste the **Application (client) ID** from the Azure Portal as the **Client ID** in Mattermost. +6. Paste the **client secret** value from the Azure Portal as the **Client Secret** in Mattermost. +7. Select **Save**. + +<Note> + +When Mattermost is configured to use OpenID Connect or OAuth 2.0 for user authentication, the following user attribute changes can't be made through the Mattermost API: first name, last name, or username. OpenID Connect or OAuth 2.0 must be the authoritative source for these user attributes. + +</Note> + +### Note about Microsoft Active Directory Tenants + +A Microsoft Active Directory (AD) tenant is a dedicated instance of Azure Active Directory (Azure AD) that you own and would have received when signing up for a Microsoft cloud service, such as Azure or Entra ID. Tenants are commonly used by organizations who want to store information about their users, such as passwords, user profile data, and permissions. See the Microsoft Entra ID \[https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-create-new-tenant\](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-create-new-tenant\)\`\_ documentation to learn more about getting an Azure AD tenant. + +To allow your Azure AD users to log in to Mattermost using Entra ID SSO, you must register Mattermost in the Microsoft Azure AD tenant that contains the users' information. The registration can be done from the [Microsoft Azure portal](https://portal.azure.com). The steps to register the Mattermost account in the tenant should be similar to those provided above, and you can find more information about [integrating apps with Azure AD here](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant). + +If you don't register Mattermost in the Microsoft Azure AD tenant your organization uses, Entra ID SSO will likely fail for your users. + +<Note> + +If you do not use Azure Active Directory, you may register Mattermost with your Entra ID or Azure account (a personal, work, or school account), then set up Entra ID SSO with Mattermost using the steps provided above. + +</Note> + +### Configure Mattermost `config.json` for Entra ID SSO + +Instead of using the System Console, you can add the Entra ID settings directly to the `config.json` file on your Mattermost server. + +1. Open `config.json` as *root* in a text editor. It’s usually in `/opt/mattermost/config` but it might be elsewhere on your system. +2. Locate the `Office365Settings` section, then add or update the following information: + +``` text +"Office365Settings": { + "Enable": false, + "Secret": "i.hddd6Pu3--5dg~cRddddqOrBdd1a", + "Id": "28ddd714-1f2f-4f9c-9486-90b8dddd27", + "Scope": "profile openid email", + "AuthEndpoint": "", + "TokenEndpoint": "", + "UserApiEndpoint": "", + "DiscoveryEndpoint": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", + "DirectoryId": "common" +} +``` + +3. Save your changes, then restart your Mattermost server. After the server restarts, users must change their login method before they can log in with Entra ID. + +## Frequently Asked Questions + +### How can I use LDAP attributes or Groups with OpenID? + +At this time, LDAP data isn't compatible with OpenID. If you currently rely on LDAP to manage your users' teams, channels, groups, or attributes, you won't be able to do this automatically with users who have logged in with OpenID. If you need LDAP synced to each user, we suggest using SAML or LDAP as the login provider. Some OpenID providers can use SAML instead, like Keycloak. diff --git a/docs/main/administration-guide/onboard/sso-gitlab.mdx b/docs/main/administration-guide/onboard/sso-gitlab.mdx new file mode 100644 index 000000000000..f761e2859f6f --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-gitlab.mdx @@ -0,0 +1,64 @@ +--- +title: "GitLab Single Sign-On" +--- +<PlanAvailability slug="all-commercial" /> + +## Configuring GitLab as a Single Sign-On (SSO) service + +Follow these steps to configure Mattermost to use GitLab as a Single Sign-on (SSO) service for team creation, account creation, and user login. + +<Important> + +\- Only the default GitLab SSO is officially supported. - "Double SSO", where GitLab SSO is chained to other SSO solutions, is not supported. It may be possible to connect GitLab SSO with AD, LDAP, SAML, or MFA add-ons in some cases, but because of the special logic required, they're not officially supported, and they're known not to work in some cases. - [Mattermost Free (self-hosted only)](/product-overview/editions-and-offerings) supports the OAuth 2.0 standard. - [Mattermost Professional](/product-overview/editions-and-offerings) and [Mattermost Enterprise](/product-overview/editions-and-offerings) support the OpenID Connect standard. + +</Important> + +### Step 1: Add a Mattermost application to your GitLab account + +1. Log in to your GitLab account, then go to `https://{gitlab-site-name}/profile/applications`. For *{gitlab-site-name}* use the name of your GitLab instance. If you're using GitLab itself as your service provider, use `gitlab.com`. +2. Add a new application: + +> 1. In the **Name** field, enter `Mattermost`. +> 2. In the **Redirect URI** field, add the following two lines using your own value for *{mattermost-site-name}*. +> +> > ``` text +> > https://{mattermost-site-name}/login/gitlab/complete +> > https://{mattermost-site-name}/signup/gitlab/complete +> > ``` +> > +> > If your GitLab instance is not set up to use SSL, your URIs must begin with `http://` instead of `https://`. +> +> 3. Select scopes. +> - For Mattermost Team Edition, select `read_user`. +> - For Mattermost Enterprise, select `read_user`, `openid`, `profile`, and `email`. + +3. Select **Save application**. +4. Keep the GitLab window open. You need the *Application Id* and *Application Secret Key* when you configure Mattermost. + +### Step 2: Configure Mattermost for GitLab SSO + +1. Log in to Mattermost, then go to **System Console \> Authentication \> OpenID Connect**. +2. Select **GitLab** as the service provider. +3. Enter the **GitLab Site URL** of your GitLab instance. If your GitLab instance is not set up to use SSL, start the URL with `http://` instead of `https://`. If you are using GitLab itself as your provider, use `gitlab.com`. +4. The **Discovery Endpoint** for OpenID Connect with GitLab is prepopulated with `https://gitlab.com/.well-known/openid-configuration`. +5. Paste the **Application ID** from GitLab as the **Client ID** in Mattermost. +6. Paste the **Application Secret Key** from GitLab as the **Client Secret** in Mattermost. +7. Update the `config.json` file and specify the scopes you selected in GitLab under the `GitLabSettings` property. At a minimum, `openid` is a required scope for Mattermost Enterprise and Professional, and `read_user` is a required scope for Mattermost Team Edition. Mattermost Team Edition does not work with scopes other than `read_user`. Changes to this setting require a server restart before taking effect. +8. Select **Save**. + +<Note> + +- When Mattermost is configured to use OpenID Connect or OAuth 2.0 for user authentication, the following user attribute changes can't be made through the Mattermost API: first name, last name, or username. OpenID Connect or OAuth 2.0 must be the authoritative source for these user attributes. +- If you are using Mattermost behind a load balancer and you have SSL configured, you may need to set <code>X-Forwarded-Proto</code> header to https at your load balancer. + +</Note> + +### (Optional) Step 3: Force users to sign up using SSO only + +To force all users to sign-up with SSO only, set **System Console \> Authentication \> Email \> Enable sign-in with email** to `false` Users must change their login method before they can log in to Mattermost with GitLab. + +## Frequently Asked Questions + +### How can I use LDAP attributes or Groups with OpenID? + +At this time, LDAP data isn't compatible with OpenID. If you currently rely on LDAP to manage your users' teams, channels, groups, or attributes, you won't be able to do this automatically with users who have logged in with OpenID. If you need LDAP synced to each user, we suggest using SAML or LDAP as the login provider. Some OpenID providers can use SAML instead, like Keycloak. diff --git a/docs/main/administration-guide/onboard/sso-google.mdx b/docs/main/administration-guide/onboard/sso-google.mdx new file mode 100644 index 000000000000..0d76a475d818 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-google.mdx @@ -0,0 +1,86 @@ +--- +title: "Google Single Sign-On" +--- +<PlanAvailability slug="all-commercial" /> + +## Configuring Google Apps as a Single Sign-On (SSO) service + +Follow these steps to configure Mattermost to use Google as a Single Sign-on (SSO) service for team creation, account creation, and login. + +<Note> + +The [Google People API](https://developers.google.com/people) has replaced the Google+ API, which was deprecated by Google as of March 7th, 2019 [per their notice](https://developers.google.com/+/api-shutdown). + +</Note> + +### Step 1: Create OpenID Connect project in Google API Manager + +1. Go to Google Cloud Platform. +2. Select **Credentials** in the left-hand sidebar. +3. Select **Create Credentials**, then select **OAuth client ID**. +4. Select the **Web application** as the application type. +5. Enter `Mattermost-<your-company-name>` as the **Name**, replacing `<your-company-name>` with the name of your organization. +6. Under **Authorized redirect URIs**, select **Add URL**, then enter `{your-mattermost-url}/signup/google/complete`. For example: `http://localhost:8065/signup/google/complete`. +7. Select **Create**. +8. Copy and paste the **Your Client ID** and **Your Client Secret** values to a temporary location. You will enter these values in the Mattermost System Console. + +![image](/images/create-google-sso-credentials.png) + +![image](/images/select-google-sso-web-app.png) + +![image](/images/google-sso-web-app-name.png) + +![image](/images/google-sso-redirect-uri.png) + +![image](/images/google-sso-credentials.png) + +### Step 2: Enable Google People API + +Go to the [Google People API](https://developers.google.com/people), then select **Enable** in the header. This might take a few minutes to propagate through Google's systems. + +### Step 3: Configure Mattermost for Google Apps SSO + +1. Log in to Mattermost, then go to **System Console \> Authentication \> OpenID Connect**. +2. Select **Google Apps** as the service provider. +3. The **Discovery Endpoint** for OpenID Connect with Google Apps is prepopulated with `https://accounts.google.com/.well-known/openid-configuration`. +4. Paste in the **Client ID** from Google in Mattermost. +5. Paste in the **Client Secret** from Google in Mattermost. +6. Select **Save**. + +<Note> + +When Mattermost is configured to use OpenID Connect or OAuth 2.0 for user authentication, the following user attribute changes can't be made through the Mattermost API: first name, last name, or username. OpenID Connect or OAuth 2.0 must be the authoritative source for these user attributes. + +Username and email address changes made in Google Workspace are not automatically synced to Mattermost. + +</Note> + +### Configure Mattermost `config.json` for Google Apps SSO + +Instead of using the System Console, you can add the Google settings directly to the `config.json` file directly on your Mattermost server. + +1. Open `config.json` as *root* in a text editor. It’s usually in `/opt/mattermost/config`, but it might be elsewhere on your system. +2. Locate the `GoogleSettings` section, then add or update the following information: + +``` text +"GoogleSettings": { + "Enable": true, + "Secret": "P-k9R-7E7ayX9LdddddWdXVg", + "Id": "1022ddddd5846-bkddddd4a1ddddd9d88j1kb6eqc.apps.googleusercontent.com", + "Scope": "profile openid email", + "AuthEndpoint": "", + "TokenEndpoint": "", + "UserApiEndpoint": "", + "DiscoveryEndpoint": "https://accounts.google.com/.well-known/openid-configuration", + "ButtonText": "", + "ButtonColor": "" +} +``` + +3. Save your changes, then restart your Mattermost server. After the server restarts, users must change their login method before they can log in with Google Apps. + +## Frequently Asked Questions + +### How can I use LDAP attributes or Groups with OpenID? + +At this time, LDAP data isn't compatible with OpenID. If you currently rely on LDAP to manage your users' teams, channels, groups, or attributes, you won't be able to do this automatically with users who have logged in with OpenID. If you need LDAP synced to each user, we suggest using SAML or LDAP as the login provider. Some OpenID providers can use SAML instead, like Keycloak. diff --git a/docs/main/administration-guide/onboard/sso-openidconnect.mdx b/docs/main/administration-guide/onboard/sso-openidconnect.mdx new file mode 100644 index 000000000000..e0ee55d2f123 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-openidconnect.mdx @@ -0,0 +1,37 @@ +--- +title: "OpenID Connect Single Sign-On" +--- +<PlanAvailability slug="all-commercial" /> + +Mattermost provides OpenID Connect support for [GitLab](/administration-guide/onboard/sso-gitlab), [Google Apps](/administration-guide/onboard/sso-google), and [Entra ID](/administration-guide/onboard/sso-entraid). With OpenID Connect, users can also use their login to Keycloak, Atlassian Crowd, Apple, Microsoft, Salesforce, Auth0, Ory.sh, Facebook, Okta, OneLogin, and Azure AD, as well as others, as a Single Sign-on (SSO) service for team creation, account creation, and user login. + +Follow these steps to configure a service provider using OpenID Connect. + +## Step 1: Create an OpenID Connect Application + +1. Follow service provider documentation for creating an OpenID Connect application. Most OpenID Connect service providers require authorization of all redirect URIs. +2. In the appropriate field, enter `{your-mattermost-url}/signup/openid/complete` For example: `http://domain.com/signup/openid/complete` +3. Copy and paste values for the **Discovery Endpoint**, **Client ID**, and **Client Secret** values to a temporary location. You will enter these values when you configure Mattermost. + +## Step 2: Configure Mattermost for an OpenID Connect SSO + +1. Log in to Mattermost, then go to **System Console \> Authentication \> OpenID Connect**. +2. Select **OpenID Connect (Other)** as the service provider. +3. Enter the **Discovery Endpoint**. +4. Enter the **Client ID**. +5. Enter the **Client Secret**. +6. Specify a **Button Name** and **Button Color** for the OpenID Connect option on the Mattermost login page. +7. Select **Save**. +8. Restart your Mattermost server to see the changes take effect. + +<Note> + +\- When Mattermost is configured to use OpenID Connect for user authentication, the following user attribute changes can't be made through the Mattermost API: first name, last name, or username. OpenID Connect must be the authoritative source for these user attributes. - Admins can configure Mattermost to use the `preferred_username` claim from the OpenID token as the Mattermost username. Enable the **Use preferred username** option in the provider's settings under **System Console \> Authentication \> OpenID Connect**. See the [authentication configuration settings](/administration-guide/configure/authentication-configuration-settings#openid-connect) for details. - The **Discovery Endpoint** setting can be used to determine the connectivity and availability of arbitrary hosts. System admins concerned about this can use custom admin roles to limit access to modifying these settings. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration#edit-privileges-of-admin-roles-advanced)) documentation for details. + +</Note> + +## Frequently Asked Questions + +### How can I use LDAP attributes or Groups with OpenID? + +At this time, LDAP data isn't compatible with OpenID. If you currently rely on LDAP to manage your users' teams, channels, groups, or attributes, you won't be able to do this automatically with users who have logged in with OpenID. If you need LDAP synced to each user, we suggest using SAML or LDAP as the login provider. Some OpenID providers can use SAML instead, like Keycloak. diff --git a/docs/main/administration-guide/onboard/sso-saml-adfs-msws2016.mdx b/docs/main/administration-guide/onboard/sso-saml-adfs-msws2016.mdx new file mode 100644 index 000000000000..0ce5f9915814 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-adfs-msws2016.mdx @@ -0,0 +1,216 @@ +--- +title: "Configure SAML with Microsoft ADFS using Microsoft Windows Server 2016" +--- +import Inc0_sso_saml_before_you_begin from './sso-saml-before-you-begin.mdx'; +import Inc1_sso_saml_faq from './sso-saml-faq.mdx'; +import Inc2_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; + +<PlanAvailability slug="all-commercial" /> + +This document provides steps to configure SAML 2.0 with Microsoft ADFS for Mattermost and Microsoft Windows Server 2016. + +<Inc0_sso_saml_before_you_begin /> + +## Prerequisites + +- An Active Directory instance where all users have specified email and username attributes. For Mattermost servers running 3.3 and earlier, users must also have their first name and last name attributes specified. +- A running Microsoft Server. The screenshots used in this guide are from Microsoft Server 2012R2, but similar steps should work for other versions. +- An SSL certificate to sign your ADFS login page. +- ADFS installed on your Microsoft Server. You can find a detailed guide for deploying and configuring ADFS in [this Microsoft article](https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/deployment-administrators-guide/gg188612(v=crm.8)?redirectedfrom=MSDN). + +On your ADFS installation, open the ADFS console. Select **Service**, then select **Endpoints**. In the **Type** column, search for `SAML 2.0/WS-Federation` and note down the value of **URL Path** column. This is also known as the **SAML SSO URL Endpoint** in this guide. If you chose the defaults for the installation, this will be `/adfs/ls`. + +## Add a relying party trust + +1. Open the ADFS management snap-in, then select **AD FS \> Relying Party Trusts \> Add Relying Party Trust** from the right sidebar. You can also right-click **Relying Party Trusts**, then select **Add Relying Party Trust** from the context menu. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_000.png) + +2. On the **Welcome** screen of the configuration wizard, select **Claims aware**, then select **Start**. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_001.png) + +3. On the **Select Data Source** screen, select **Enter data about the relying party manually**. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_002.png) + +4. On the **Specify Display Name** screen, enter a **Display Name** (e.g., `Mattermost`). You can add optional notes. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_003.png) + +5. On the **Configure Certificate** screen, leave the certificate settings at their default values. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_004.png) + +If you would like to set up encryption for your SAML connection, select **Browse**, then upload your Service Provider Public Certificate. + +> ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_005.png) + +6. On the **Configure URL** screen, select **Enable Support for the SAML 2.0 WebSSO protocol**, then enter the **SAML 2.0 SSO service URL** in the following format:`https://<your-mattermost-url>/login/sso/saml` where `<your-mattermost-url>` should typically match the [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url). + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_006.png) + +7. On the **Configure Identifiers** screen, enter the **Relying party trust identifier**. This identifies the claims being requested. The **SAML 2.0 SSO service URL** format should be `https://<your-mattermost-url>/login/sso/saml` where `<your-mattermost-url>` matches your [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url). Then choose **Next**. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_007.png) + > + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_008.png) + +This string must match the **Service Provider Identifier** string. For more information about the Relying party trust identifier and how prefix matching is applied see [this documentation](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/technical-reference/how-uris-are-used-in-ad-fs). + +Add your **SAML 2.0 SSO service URL** using this same process. + +8. On the **Choose Access Control Policy** screen, select the access control policy suitable for your environment. This guide assumes the default values **Permit everyone** and an unchecked box. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_009.png) + +9. On the **Ready to Add Trust** screen, review your settings. + + > ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_010.png) + +10. On the **Finish** screen, select **Configure claims issuance policy for this application**, then select **Close**. + + ![image](/images/SSO-SAML-ADFS_add-new-relying-party-trust_011.png) + +## Create claim rules + +1. In the **Issuance Transform Rules** tab of the **Claim Rules** editor, select **Add Rule…**. + + > ![image](/images/SSO-SAML-ADFS_create-claim-rules_001.png) + +2. On the **Choose Rule Type** screen, select **Send LDAP Attributes as Claims** from the drop-down menu, then select **Next**. + + > ![image](/images/SSO-SAML-ADFS_create-claim-rules_002.png) + +3. On the **Configure Claim Rule** screen, enter a **Claim Rule Name** of your choice, select **Active Directory** as the **Attribute Store**, then add the following mapping: + +> - From the **LDAP Attribute column**, select `E-Mail-Addresses`. From the **Outgoing Claim Type**, type `Email`. +> - From the **LDAP Attribute column**, select `E-Mail-Addresses`. From the **Outgoing Claim Type**, type `Name ID`. +> - From the **LDAP Attribute column**, select `Given-Name`. From the **Outgoing Claim Type**, type `FirstName`. +> - From the **LDAP Attribute column**, select `Surname`. From the **Outgoing Claim Type**, type `LastName`. +> - From the **LDAP Attribute column**, select `SAM-Account-Name`. From the **Outgoing Claim Type**, type `Username`. + +The `FirstName` and `LastName` attributes are optional. + +Select **Finish** to add the rule. + +The entries in the **Outgoing Claim Type** column can be modified. The entries may contain dashes but no spaces. They are used to map the corresponding fields in Mattermost. + +> ![image](/images/SSO-SAML-ADFS_create-claim-rules_003.png) + +4. Select **Add Rule** to create another new rule. + +5. On the **Choose Rule Type** screen, select **Transform an Incoming Claim** from the drop-down menu, then select **Next**. + + > ![image](/images/SSO-SAML-ADFS_create-claim-rules_004.png) + +6. On the **Configure Claim Rule** screen, enter a **Claim Rule Name** of your choice, then: + +> - Select **Name ID** for the **Incoming claim type** +> - Select **Unspecified** for the **Incoming name ID format** +> - Select **E-Mail Address** for the **Outgoing claim type** + +Select **Pass through all claim values**, then select **Finish**. + +> ![image](/images/SSO-SAML-ADFS_create-claim-rules_005.png) + +7. Select **Finish** to create the claim rule, then select **OK** to finish creating rules. +8. Open Windows PowerShell as an administrator, then run the following command: + +> `Set-ADFSRelyingPartyTrust -TargetName <display-name> -SamlResponseSignature "MessageAndAssertion"` + +where `<display-name>`is the name you specified in step 4 when you added a relying party trust. In this example, `<display-name>` would be `mattermost`. + +This action adds the signature to SAML messages, making verification successful. + +## Export identity provider certificate + +Next, export the identity provider certificate, which will be later uploaded to Mattermost to finish SAML configuration. + +1. Open the ADFS management snap-in, select **AD FS \> Service \> Certificates**, then double-click on the certificate under **Token-signing**. You can also right-click the field, then select **View Certificate** in the context menu. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_001.png) + +2. On the **Certificate** screen, open the **Details** tab, select **Copy to File**, then select **OK**. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_003.png) + +3. On the **Certificate Export Wizard** screen, select **Next**. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_004.png) + +4. Select **Base-64 encoded X.509 (.CER)**, then select **Next** again. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_005.png) + +5. On the **Certificate Export Wizard** screen, select **Browse** to specify the location where you want the Identity Provider Certificate to be exported, then specify the file name. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_006.png) + +6. Select **Save**. On the **Certificate Export Wizard** screen, verify the file path is correct, then select **Next**. + +7. In the **Completing the Certificate Export Wizard**, select **Finish**, then select **OK** to confirm the export was successful. + + > ![image](/images/SSO-SAML-ADFS_export-id-provider-cert_007.png) + +## Configure SAML Sign-On for Mattermost + +Create a metadata URL by appending "FederationMetadata/2007-06/FederationMetadata.xml" to the root URL of the ADFS server, for example: `https://<adfs.domain.com>/federationmetadata/2007-06/FederationMetadata.xml>`. + +Next, start the Mattermost server, then log in to Mattermost as a system admin. Go to **System Console \> Authentication \> SAML**, paste the metadata URL in the **Identity Provider Metadata URL** field, then select **Get SAML Metadata from IdP**. + +This populates the **SAML SSO URL** and the **Identity Provider Issuer URL** fields automatically. The Identity Provider Public Certificate is also downloaded from the server and set locally. + +The following fields can be selected: +- Set **Enable Login With SAML 2.0** to **true**. +- Set **Enable Synchronizing SAML Accounts With AD/LDAP** to suit your environment. +- Set **Override SAML bind data with AD/LDAP information** to suit your environment. + +If you don't plan to use a metadata URL, you can manually enter the following fields: +- For **SAML SSO URL** use the `SAML 2.0/W-Federation URL ADFS Endpoint` you copied at the beginning of the process. + +- For **Identity Provider Issuer URL** use the `Relying party trust identifier` from ADFS. + +- For **Identity Provider Public Certificate** use the`X.509 Public Certificate`. + + ![image](/images/SSO-SAML-ADFS_configure-saml_001.png) + +2. Configure Mattermost to verify the signature. + +> - Set **Verify Signature** to `true`. +> +> - For **Service Provider Login URL** use the `SAML 2.0 SSO service URL` you specified in ADFS. +> +> ![image](/images/SSO-SAML-ADFS_configure-saml_002.png) + +3. Enable encryption. + +> - Set **Enable Encryption** to `true`. +> +> - For **Service Provider Private Key** use the Service Provider Private Key generated at the start of this process. +> +> - For **Service Provider Public Certificate** use the Service Provider Public Certificate you generated at the start of this process. +> +> - Set **Sign Request** to suit your environment. +> +> ![image](/images/SSO-SAML-ADFS_configure-saml_003.png) + +4. Set attributes for the SAML Assertions, which will be used to update user information in Mattermost. Attributes for email and username are required and should match the values you entered in ADFS earlier. See [documentation on SAML configuration settings](#saml-enterprise) for more detail. + +For Mattermost servers running 3.3 and earlier, the first name and last name attributes are also required fields. + +> ![image](/images/SSO-SAML-ADFS_configure-saml_004.png) + +5. Select **Save**. +6. (Optional) If you configured `First Name` Attribute and the `Last Name` Attribute, go to **System Console \> Site Configuration \> Users and Teams**, then set **Teammate Name Display** to **Show first and last name**. This is recommended for a better user experience. + +You’re done! If you’d like to confirm SAML SSO is successfully enabled, switch your system admin account from email to SAML-based authentication from your profile picture via **Profile \> Security \> Sign-in Method \> Switch to SAML SSO**, then log in with your SAML credentials to complete the switch. + +We also recommend that you post an announcement about how the migration will work to your users. + +You may also configure SAML for ADFS by editing the `config.json` file to enable SAML based on [SAML configuration settings](#saml-enterprise). You must restart the Mattermost server for the changes to take effect. + +<Inc1_sso_saml_faq /> + +<Inc2_sso_saml_ldapsync /> + :start-after: :nosearch: diff --git a/docs/main/administration-guide/onboard/sso-saml-adfs.mdx b/docs/main/administration-guide/onboard/sso-saml-adfs.mdx new file mode 100644 index 000000000000..6882ef0fc378 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-adfs.mdx @@ -0,0 +1,201 @@ +--- +title: "Configure SAML with Microsoft ADFS for Windows Server 2012" +--- +import Inc0_sso_saml_before_you_begin from './sso-saml-before-you-begin.mdx'; +import Inc1_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; +import Inc2_sso_saml_faq from './sso-saml-faq.mdx'; + +<PlanAvailability slug="all-commercial" /> + +The following process provides steps to configure SAML 2.0 with Microsoft ADFS for Mattermost. + +<Inc0_sso_saml_before_you_begin /> + +The following are basic requirements to use ADFS for Mattermost: +- An Active Directory instance where all users have a specified email and username attributes. For Mattermost servers running 3.3 and earlier, users must also have their first name and last name attributes specified. +- A Microsoft Server running. The screenshots used in this guide are from Microsoft Server 2012R2, but similar steps should work for other versions. +- An SSL certificate to sign your ADFS login page. +- ADFS installed on your Microsoft Server. You can find a detailed guide for deploying and configuring ADFS in [this Microsoft article](https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/deployment-administrators-guide/gg188612(v=crm.8)?redirectedfrom=MSDN). + +On your ADFS installation, note down the value of the **SAML 2.0/W-Federation URL** in ADFS Endpoints section, also known as the **SAML SSO URL Endpoint** in this guide. If you chose the defaults for the installation, this will be `/adfs/ls/`. + +## Add a relying party trust + +1. In the ADFS management sidebar, go to **AD FS \> Trust Relationships \> Relying Party Trusts**, then select **Add Relying Party Trust**. A configuration wizard opens for adding a new relying party trust. + + > ![image](/images/adfs_1_add_new_relying_party_trust.png) + +2. On the **Welcome** screen, select **Start**. + + > ![image](/images/adfs_2_start_wizard.png) + +3. On the **Select Data Source** screen, select **Enter data about the relying party manually**. + + > ![image](/images/adfs_3_select_data_source.png) + +4. On the **Specify Display Name** screen, enter a **Display Name** to recognize the trust, such as `Mattermost`, then add any notes you want to make. + + > ![image](/images/adfs_4_specify_display_name.png) + +5. On the **Choose Profile** screen, select **AD FS profile**. + + > ![image](/images/adfs_5_choose_profile.png) + +6. On the **Configure Certificate** screen, leave the certificate settings at their default values. + + > ![image](/images/adfs_6_configure_certificate_default.png) + +However, if you would like to set up encryption for your SAML connection, select **Browse**, then upload your Service Provider Public Certificate. + +> ![image](/images/adfs_7_configure_certificate_encryption.png) + +7. On the **Configure URL** screen, select **Enable Support for the SAML 2.0 WebSSO protocol**, then enter the **SAML 2.0 SSO service URL**, similar to `https://<your-mattermost-url>/login/sso/saml` where `<your-mattermost-url>` should typically match the [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url). + + > ![image](/images/adfs_8_configure_url.png) + +8. On the **Configure Identifiers** screen, enter the **Relying party trust identifier** (also known as the **Identity Provider Issuer URL**) of the form `https://<your-idp-url>/adfs/services/trust`, then click **Add**. + + > ![image](/images/adfs_9_configure_identifiers.png) + +9. On the **Configure Multi-factor Authentication Now** screen, you may enable multi-factor authentication. This is beyond the scope of this documentation. + + > ![image](/images/adfs_10_configure_mfa.png) + +10. On the **Choose Issuance Authorization Rules** screen, select **Permit all users to access this relying party**. + + ![image](/images/adfs_11_authorization.png) + +11. On the **Ready to Add Trust** screen, review your settings. + + ![image](/images/adfs_12_ready_to_add_trust.png) + +12. On the **Finish** screen, select **Open the Edit Claim Rules dialog for this relying party trust when the wizard closes**, then select **Close**. You exit the configuration wizard, and a **Claim Rules** editor opens. + + ![image](/images/adfs_13_finish_trust.png) + +## Create claim rules + +1. In the **Issuance Transform Rules** section of the **Claim Rules** editor, select **Add Rule…** to open an **Add Transform Claim Rule Wizard**. + + > ![image](/images/adfs_14_claim_rules_editor.png) + +2. On the **Choose Rule Type** screen, select **Send LDAP Attributes as Claims** from the drop-down menu, then select **Next**. + + > ![image](/images/adfs_15_choose_rule_type.png) + +3. In the **Configure Claim Rule** screen, enter a **Claim Rule Name** of your choice, select **Active Directory** as the **Attribute Store**, then complete the following: + +> - From the **LDAP Attribute column**, select `E-Mail-Addresses`. From the **Outgoing Claim Type**, type `Email`. +> - From the **LDAP Attribute column**, select `E-Mail-Addresses`. From the **Outgoing Claim Type**, type `Name ID`. +> - From the **LDAP Attribute column**, select `Given-Name`. From the **Outgoing Claim Type**, type `FirstName`. +> - From the **LDAP Attribute column**, select `Surname`. From the **Outgoing Claim Type**, type `LastName`. +> - From the **LDAP Attribute column**, select `SAM-Account-Name`. From the **Outgoing Claim Type**, type `Username`. + +The `FirstName` and `LastName` attributes are optional. + +Select **Finish** to add the rule. + +Note that the entries in the **Outgoing Claim Type** column can be chosen to be something else. They can contain dashes but no spaces. They will be used to map the corresponding fields in Mattermost later. + +> ![image](/images/adfs_16_configure_claim_rule.png) + +4. Create another new rule by selecting **Add Rule**. + +5. On the **Choose Rule Type** screen, select **Transform an Incoming Claim** from the drop-down menu, then select **Next**. + + > ![image](/images/adfs_17_transformation_of_incoming_claim.png) + +6. On the **Configure Claim Rule** screen, enter a **Claim Rule Name** of your choice, then: + +> - Select **Name ID** for the **Incoming claim type**. +> - Select **Unspecified** for the **Incoming name ID format**. +> - Select **E-Mail Address** for the **Outgoing claim type**. + +Select **Pass through all claim values**, then select **Finish**. + +> ![image](/images/adfs_18_configure_incoming_claim.png) + +7. Select **Finish** to create the claim rule, then select **OK** to finish creating rules. +8. Open Windows PowerShell as an administrator, then run the following command: + +> `Set-ADFSRelyingPartyTrust -TargetName <display-name> -SamlResponseSignature "MessageAndAssertion"` + +where `<display-name>` is the name you specified in step 4 when adding a relying party trust. In this example, `<display-name>` would be `mattermost`. + +This action adds the signature to SAML messages, making verification successful. + +## Export identity provider certificate + +Next, export the identity provider certificate, which will be later uploaded to Mattermost to finish SAML configuration. + +1. In the ADFS management sidebar, go to **AD FS \> Service \> Certificates**, then double click on the certificate under **Token-signing**. Alternatively, you can right-click on the field, then select **View Certificate**. + + > ![image](/images/adfs_19_export_idp_cert_start.png) + +2. On the **Certificate** screen, go to the **Details** tab, then select **Copy to File**, followed by **OK**. This opens a **Certificate Export Wizard**. + + > ![image](/images/adfs_20_export_idp_cert_copy.png) + +3. On the **Certificate Export Wizard** screen, select **Next**, then, select the option **Base-64 encoded X.509 (.CER)**, and select **Next** again. + + > ![image](/images/adfs_21_export_idp_cert_wizard.png) + +4. On the **Certificate Export Wizard** screen, select **Browse** to specify the location where you want the Identity Provider Certificate to be exported, then specify the file name. + + > ![image](/images/adfs_21-2_export_idp_cert_wizard.png) + +5. Select **Save**. In the **Certificate Export Wizard** screen, verify the file path is correct, then select **Next**. + +6. In the **Completing the Certificate Export Wizard**, select **Finish**, then select **OK** to confirm the export was successful. + + > ![image](/images/adfs_21-3_export_idp_cert_wizard.png) + +## Configure SAML Sign-On for Mattermost + +Create a metadata URL by appending "FederationMetadata/2007-06/FederationMetadata.xml" to the root URL of the ADFS server, for example: `https://<adfs.domain.com>/federationmetadata/2007-06/FederationMetadata.xml>`. + +Next, start the Mattermost server and log in to Mattermost as a system admin. Go to **System Console \> Authentication \> SAML**, paste the metadata URL in the **Identity Provider Metadata URL** field, then select **Get SAML Metadata from IdP**. + +This populates the **SAML SSO URL** and the **Identity Provider Issuer URL** fields automatically. The Identity Provider Public Certificate is also downloaded from the server and set locally. + +Alternatively you can enter the following fields manually: +- **SAML SSO URL**: **SAML 2.0/W-Federation URL** ADFS Endpoint you copied earlier. + +- **Identity Provider Issuer URL**: `Relying party trust identifier` from ADFS you specified earlier. + +- **Identity Provider Public Certificate**: `X.509 Public Certificate` you downloaded earlier. + + ![image](/images/adfs_22_mattermost_basics.png) + +2. Configure Mattermost to verify the signature. The **Service Provider Login URL** is the SAML 2.0 SSO service URL you specified in ADFS earlier. + + > ![image](/images/adfs_23_mattermost_verification.png) + +3. Enable encryption by uploading the Service Provider Private Key and Service Provider Public Certificate you generated earlier. + + > ![image](/images/adfs_24_mattermost_encryption.png) + +4. Configure Mattermost to sign SAML requests using the Service Provider Private Key. + +5. Set attributes for the SAML Assertions, which will be used to update user information in Mattermost. Attributes for email and username are required and should match the values you entered in ADFS earlier. See [documentation on SAML configuration settings](#saml-enterprise) for more detail. + +For Mattermost servers running 3.3 and earlier, the `FirstName` and `LastName` attributes are also required fields. + +> ![image](/images/adfs_25_mattermost_attributes.png) + +6. (Optional) Customize the login button text. + +> ![image](/images/adfs_26_mattermost_login_button.png) + +7. Select **Save**. +8. (Optional) If you configured a `FirstName` and `LastName` Attribute, go to **System Console \> Site Configuration \> Users and Teams**, then set **Teammate Name Display** to **Show first and last name**. This is recommended for a better user experience. + +If you’d like to confirm SAML SSO is successfully enabled, switch your system admin account from email to SAML-based authentication from your profile picture via **Profile \> Security \> Sign-in Method \> Switch to SAML SSO**, then log in with your SAML credentials to complete the switch. + +We recommend that you post an announcement about how the migration will work for your users. + +You may also configure SAML for ADFS by editing the `config.json` file to enable SAML based on [SAML configuration settings](#saml-enterprise). You must restart the Mattermost server for the changes to take effect. + +<Inc1_sso_saml_ldapsync /> + +<Inc2_sso_saml_faq /> diff --git a/docs/main/administration-guide/onboard/sso-saml-before-you-begin.mdx b/docs/main/administration-guide/onboard/sso-saml-before-you-begin.mdx new file mode 100644 index 000000000000..aa3ebf83be54 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-before-you-begin.mdx @@ -0,0 +1,7 @@ +--- +title: "Before you begin" +--- +Before you begin, you need to generate encryption certificates for encrypting the SAML connection. + +1. You can use the [Bash script](https://github.com/mattermost/docs/tree/master/source/scripts/generate-certificates) from the `mattermost/docs` repository on GitHub, or any other suitable method. See the [generate self-signed certificates](/scripts/generate-certificates/gencert) documentation for details on generating a self-signed x509v3 certificate for use with multiple URLs / IPs. +2. Save the two files that are generated. They are the private key and the public key. In the System Console, they are referred to as the **Service Provider Private Key** and the **Service Provider Public Certificate** respectively. diff --git a/docs/main/administration-guide/onboard/sso-saml-entraid.mdx b/docs/main/administration-guide/onboard/sso-saml-entraid.mdx new file mode 100644 index 000000000000..254f0fe44175 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-entraid.mdx @@ -0,0 +1,84 @@ +--- +title: "Configure SAML with Microsoft Entra ID" +--- +import Inc0_sso_saml_before_you_begin from './sso-saml-before-you-begin.mdx'; +import Inc1_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; +import Inc2_sso_saml_faq from './sso-saml-faq.mdx'; + +<PlanAvailability slug="all-commercial" /> + +This page provides guidance on configuring SAML with Microsoft Entra ID for Mattermost. + +<Tip> + +- Need to configure Entra ID for **OpenID Connect** authentication instead? See the [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) documentation for details. +- See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +</Tip> + +<Inc0_sso_saml_before_you_begin /> + +## Prerequisites + +- A Microsoft Entra tenant containing applicable user data. +- A verified custom domain for your tenant. See Microsoft's [Add your custom domain name to your tenant](https://learn.microsoft.com/en-us/entra/fundamentals/add-custom-domain) documentation for details. +- A Microsoft Entra ID P1 or P2 license. + +## Set up an enterprise app for Mattermost SSO in Entra ID + +1. Log into the Microsoft Azure portal and select the **Microsoft Entra ID** service. +2. In the left menu, select **Manage \> Enterprise applications**. +3. Select the **New application** button. +4. In the **Search application** field, search for **Microsoft Entra SAML Toolkit** and select **Microsoft Entra SAML Toolkit**. +5. In the **Name** field, enter **Mattermost SAML** then select the **Create** button. +6. In the **Mattermost SAML** enterprise application settings, select **Manage \> Users and Groups** to assign users and/or groups to the application **or** select **Manage \> Properties** then set **Assignment required?** to **No** then select **Save**. +7. In the **Mattermost SAML** enterprise application settings, select **Manage \> Single sign-on** then select **SAML** under **Select a single sign-on method**. +8. Select **Edit** in the **Basic SAML Configuration section** then set the below fields then select **Save**: + +> - **Identity (Entity ID)**: `https://<your-mattermost-url>` +> - **Reply URL (Assertion Consumer Service URL)**: `https://<your-mattermost-url>/login/sso/saml` +> - **Sign on URL**: `https://<your-mattermost-url>/login` + +9. Select **Edit** in the **Attributes & Claims** section then set the below attributes: + +> 1. Set the the **Unique User Identifier (Name ID)** required claim **Name identifier format** and **Source attribute** values as required for your environment. Setting the **Source attribute** to an immutable value such as `user.objectid` is recommended. +> 2. Edit claim names and namespaces under **Additional claims** to match SAML attribute settings you wish to set in Mattermost. Configurable settings are Email, Username, Id, Guest, Admin, First Name, Last Name, Nickname, Position, and Preferred Language. + +10. Select **Edit** in the **SAML Certificates** section. Select **Sign SAML response and assertion** for **Signing Option** and **SHA-256** for **Signing Algorithm** then select **Save**. +11. Select the **Certificate (Base64)** Download link in the **SAML Certificates** section. This is the **Identity Provider Public Certificate** to be uploaded to Mattermost. +12. In the **Mattermost SAML** enterprise application settings, select **Security \> Token encryption**. Select **Import Certificate** to import the Service Provider certificate. If you used the Bash script referenced in the **Before you begin** section, this is the `mattermost-x509.crt` file. The Import dialog says to upload a certificate with a file extension `.cer`, but `.crt` files are also accepted. Upload the file then select **Add**. +13. Select the `...` to the right of the imported certificate details, select **Activate token encryption certificate**, then select **Yes** to activate. +14. On the **Home** page for **Microsoft Entra ID**, select the **Overview** link in the left navigation menu and copy the **Tenant ID** value. The **Tenant ID** will be used in Mattermost **SAML 2.0** URL settings. +15. In the left navigation menu, select **Manage \> Enterprise applications**. Select the **Mattermost SAML** application then copy the **Application ID**. The **Application ID** will be used in the **Identity Provider Metadata URL** setting in the Mattermost **SAML 2.0** settings. + +## Configure SAML Sign-On for Mattermost + +1. In the Mattermost **System Console**, select **Authentication \> SAML 2.0**. +2. Set **Enable Login With SAML 2.0** to **True**. +3. Set **Identity Provider Metadata URL**: `https://login.microsoftonline.com/<your-tenant-id>/federationmetadata/2007-06/federationmetadata.xml?appid=<your-app-id>` +4. Select **Get SAML Metadata From IdP** to verify that the SAML metadata can be retrieved successfully. +5. Set **SAML SSO URL**: `https://login.microsoftonline.com/<your-tenant-id>/saml2` +6. Set **Identity Provider Issuer URL** (trailing slash is required): `https://sts.windows.net/<your-tenant-id>/` +7. Choose the **Identity Provider Public Certificate** file from step 11 of **Set up an enterprise app for Mattermost SSO in Entra ID** then upload. +8. Set **Verify Signature** to **True**. +9. Set **Service Provider Login URL**: `https://<your-mattermost-url>/login/sso/saml` +10. Set **Service Provider Identifier**: `https://<your-mattermost-url>` +11. Set **Enable Encryption** to **True** +12. Choose your **Service Provider Private Key** file then upload. If you used the Bash script referenced in the **Before you begin** section, this is the `mattermost-x509.key` file. +13. Choose your **Service Provider Public Certificate** then upload. If you used the Bash script referenced in the **Before you begin** section, this is the `mattermost-x509.crt` file. +14. Set **Sign Request** to suit your environment. The **Signature Algorithm** must match the algorithm set in Entra ID (**RSAwithSHA256** is recommended). + +<Note> + +The **Test single sign-on with Mattermost SAML** tool in Microsoft Entra ID does not sign the request even if **Sign Request** is set to **True** in Mattermost. Depending on your security settings and key length, the Entra ID testing tool may successfully sign in while an actual sign in request from your Mattermost login page results in the error **AADSTS90015: Requested query string is too long.** since Entra ID handles the initial request with an HTTP GET redirect rather than HTTP POST. + +</Note> + +15. Set attribute settings to match attributes configured in step 9 of the **Set up an enterprise app for Mattermost SSO in Entra ID** section. +16. Set the **Login Button Text** to suit your environment. +17. Select the **Save** button. + +<Inc1_sso_saml_ldapsync /> + +<Inc2_sso_saml_faq /> + :start-after: :nosearch: diff --git a/docs/main/administration-guide/onboard/sso-saml-faq.mdx b/docs/main/administration-guide/onboard/sso-saml-faq.mdx new file mode 100644 index 000000000000..cbf6355b47dc --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-faq.mdx @@ -0,0 +1,51 @@ +--- +title: "Frequently Asked Questions" +--- +## What encryption options are supported for SAML? + +See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +## How to bind authentication to Id attribute instead of email + +Alternatively, you can use an `Id` attribute instead of email to bind the user. We recommend choosing an ID that is unique and will not change over time. + +Configuring with an `Id` attribute allows you to reuse an email address for a new user without the old user's information being exposed. For instance, if a user with an email address [joe.smith@mattermost.com](mailto:joe.smith@mattermost.com) was once an employee, a new employee named Joe Smith can use the same email. This configuration is also useful when a user's name changes and their email needs to be updated. + +This process was designed with backwards compatibility to email binding. Here is the process applied to new account creations and to accounts logging in after the configuration: + +- A user authenticated with SAML is bound to the SAML service user using the Id Attribute (as long as it has been configured) or bound by email using the email received from SAML. +- When the user tries to login and the SAML server responds with a valid authentication, then the server uses the "Id" field of the SAML authentication to search the user. +- If a user bound to that ID already exists, it logs in as that user. +- If a user bound to that ID does not exist, it will search base on the email. +- If a user bound to the email exists, it logs in with email and updates the autentication data to the ID, instead of the email. +- If a user bound to the ID or email does not exist, it will create a new Mattermost account bound to the SAML account by ID and will allow the user to log in. + +<Note> + +Existing accounts won't update until they log in to the server. + +</Note> + +## Can SAML via Microsoft ADFS be configured with Integrated Windows Authentication (IWA)? + +Yes. IWA is supported on the browser, with support added to iOS and Android mobile apps in Q2/2019 (mobile apps v1.18 and later). + +However, IWA is not supported on the Mattermost Desktop Apps due to a limitation in Electron. As a workaround you may create a browser desktop shortcut for quick access to Mattermost, just like a Desktop App. + +## Can I provision and deprovision users who log in via SAML? + +Yes, but this relies on AD/LDAP to do so. Currently, we do not support SCIM. See ["How do I deactivate users?"](/administration-guide/onboard/ad-ldap#how-do-i-deactivate-users) for more information. + +## How do I migrate users from one authentication method (e.g. email) to SAML? + +See the [mmctl user migrate-auth](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-migrate-auth) command documentation for details. + +## How is SAML different from OAuth 2.0 and OpenId Connect? + +OAuth 2.0 was primarily intended for delegated authorization, where an app is authorized to access resources, such as Google contact list. It doesn’t deal with authentication. + +OpenID Connect is built on top of OAuth 2.0, which supports authentication and thus direct SSO. + +SAML is like OpenID Connect, except typically used in enterprise settings. OpenID Connect is more common in consumer websites and web/mobile apps. + +Learn more at [https://hackernoon.com/demystifying-oauth-2-0-and-openid-connect-and-saml-12aa4cf9fdba](https://hackernoon.com/demystifying-oauth-2-0-and-openid-connect-and-saml-12aa4cf9fdba). diff --git a/docs/main/administration-guide/onboard/sso-saml-keycloak.mdx b/docs/main/administration-guide/onboard/sso-saml-keycloak.mdx new file mode 100644 index 000000000000..075e005a6437 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-keycloak.mdx @@ -0,0 +1,244 @@ +--- +title: "Configure SAML with Keycloak" +--- +import Inc0_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; +import Inc1_sso_saml_faq from './sso-saml-faq.mdx'; + +<PlanAvailability slug="all-commercial" /> + +The following process provides steps to configure SAML with Keycloak for Mattermost. + +See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +## Set up Keycloak for Mattermost SSO + +<Note> + +This was tested with Keycloak v26.4.0. We recommend adding Mattermost as a client to your primary realm. + +</Note> + +1. Log in to Keycloak as an administrator. +2. Select **Clients**, then **Create client**. You'll use this client ID in a later step. + +> - **Client type**: `SAML` +> - **Client ID**: `mattermost` + +3. Click **Next** and update the following values: + +> - **Root URL**: `http://your-mattermost-url.com` +> - **Home URL**: `/login/sso/saml` +> - **Valid redirect URIs**: `/login/sso/saml` + +4. **Save** the client. +5. Under the **Settings** tab, update the following values: + +> - **Enabled**: **On** +> - **Name ID format**: `email` +> - **Force Name ID format**: **On** +> +> ![In Keycloak, create the Mattermost client, specify the Client ID and Client Protocol, then save your changes.](/images/keycloak_1_client_settings.png) +> +> ![In Keycloak, create the Mattermost client, specify the Client ID and Client Protocol, then save your changes.](/images/keycloak_1_client_settings_2.png) + +6. Under the **Signature and Encryption** section, update the following values: + +> - **Sign Documents**: **Off** +> - **Sign Assertions**: **On** +> - **Signature Algorithm**: `RSA_SHA1` +> - **SAML signature key name**: `NONE` +> - **Canonicalization Method**: `EXCLUSIVE` +> - **Encryption Algorithm**: `AES_256_GCM` +> - **Key Transport Algorithm**: `RSA_OAEP_MGF1P` +> - **Digest method for RSA-OAEP**: `SHA1` +> +> ![In Keycloak, configure the Signature and Encryption settings for the Mattermost client.](/images/keycloak_1_client_signature_encryption.png) +> +> <div class="warning"> +> +> <div class="title"> +> +> Warning +> +> </div> +> +> Mattermost only supports `RSA_SHA1` for Keycloak SAML, because Keycloak is using `xmlenc` for `RSA_SHA512` and `RSA_SHA256`, wheras Mattermost currently only supports `xmldsig`. So make sure to use `RSA_SHA1` as the *Signature Algorithm* and *Digest Method* as described in this section. +> +> </div> + +7. Navigate to the **Keys** tab. + +> - **Client signature required**: **Off** +> +> - **Encrypt Assertions**: **On** +> +> 1. Click **Generate** +> 2. Download the **private.key** file. +> 3. Click **Confirm** +> +> ![In Keycloak, on the Keys tab, generate new keys for encryption.](/images/keycloak_2_saml_keys.png) +> +> <div class="warning"> +> +> <div class="title"> +> +> Warning +> +> </div> +> +> Mattermost does not support request signing with Keycloak so make sure to disable the Client signature setting as mentioned above. +> +> </div> +> +> Next, click **Export** and update the following values and download the keystore.p12 file. +> +> - **Archive Format**: `PKCS12` +> - **Key Alias**: `mattermost` +> - **Key Password**: `mattermost` +> - **Store Password**: `mattermost` +> +> ![In Keycloak, on the Keys tab, generate new keys, export using the values documented, then select Download.](/images/keycloak_2_saml_keys_2.png) + +8. Navigate to the **Client scopes** tab. + + First we add the predefined mappers for email, first name, and last name. + + 1. Select **mattermost-dedicated** + 2. Click **Add predefined mapper** + 3. Select the **X500 email**, **X500 givenName**, and **X500 surname** attributes. + 4. Click **Add**. + + Next, we add the mappers for username and id. + + 1. Select **Add Mapper** -\> **By Configuration** -\> User Property. + 2. Set **Name** to `Username`. + 3. Set **Property** to `username` (This is case sensitive and must be lowercase). + 4. Set **SAML Attribute Name** to `username`. + 5. Select **Save**. + + ![In Keycloak, on the Mappers tab, create a protocol mapper, then save your changes.](/images/keycloak_4_create_username_attribute.png) + + 6. Repeat the above steps and use the custom property of `id` to create the ID Attribute. + + ![In Keycloak, on the Mappers tab, create a protocol mapper for the ID attribute, then save your changes.](/images/keycloak_4_create_id_attribute.png) + +<Note> + +If you're planning to sync your SAML users with LDAP within Mattermost, the ID value used here must match with your Mattermost LDAP `ID Attribute`. + +</Note> + +Once done your Mappers should look like this: + +![Example of protocol mapper configuration.](/images/keycloak_4_create_username_attribute_finished.png) + +9. Get the metadata URL from Keycloak: + + 1. Within your Realm, select **Realm Settings**. + 2. At the bottom of the **General** tab you should see a **SAML 2.0 Identity Provider Metadata** endpoint. Right-click and copy this URL. Store for the next step. + + ![Within your Realm, select Realm Settings. At the bottom of the General tab, you should see a SAML 2.0 Identify Provider Metadata endpoint. Copy this URL for the next step.](/images/keycloak_5_export_metadata.png) + +## Configure SAML in Mattermost + +1. In the Mattermost **System Console** go to **Authentication \> SAML**. + +2. Set the **Identity Provider Metadata URL** to the value you copied from the step above and select **Get SAML Metadata from IdP**. The metadata import will populate fields related to your Keycloak configuration. + + If you have any issues with this import, you can check the `mattermost.log` file for more information. [Enable debug logging](/administration-guide/manage/logging#how-do-i-enable-debug-logging) and try again. + + > ![In Mattermost, configure SAML in the System Console by going to Authentication \> SAML. Set the Identity Provider Metadata URL to the value you copied in the previous step. When you select Get SAML Metadata from IdP, fields related to your Keycloak configuration are populated.](/images/keycloak_6_get_metadata.png) + +<Note> + +- If Mattermost does not correctly pull the **Identity Provider Public Certificate** you can manually add it by opening the metadata URL in a browser, copying the certificate value, and use a tool like [OneLogin's X.509 formatter](https://www.samltool.com/format_x509cert.php) that can format the certificate for you. Then save the correctly formatted certificate to a file and upload it to the **Identity Provider Public Certificate** field in the Mattermost System Console. +- If Mattermost can not pull the metadata and is throwing a connection issue enable debug logging and see if you need to add your Keycloak url to the **Allowed Untrusted Internal Connections** list in the System Console under **Environment \> Developer** and restart the server. See the [Allowed Untrusted Internal Connections](/administration-guide/configure/environment-configuration-settings#allow-untrusted-internal-connections) documentation for details. + +</Note> + +3. Set the below fields: + + - **Verify Signature**: **false** + - **Service Provider Login URL**: `http://your-mattermost-url.com/login/sso/saml` + - **Service Provider Identifier**: `mattermost` + + The Service Provider Identifier will match the **Client ID** that you configured in the second Keycloak step. + + ![In the System Console, configure SAML as documented, where the Service Provider Identifier matches the Client ID you configured in Keycloak.](/images/keycloak_7_mattermost_config.png) + +4. Configure the Encryption using the key you downloaded in step 6 of the Keycloak config. + + 1. Generate the `.crt` file from the `.p12` file. + + ``` console + openssl pkcs12 -password pass:mattermost -in keystore.p12 -out mattermost.crt -nodes -legacy + ``` + + 2. Generate the `.key` file from the `.p12` file. + + ``` console + openssl pkcs12 -password pass:mattermost -in keystore.p12 -out mattermost.key -nodes -nocerts -legacy + ``` + + 3. Upload both of these files within the Mattermost System Console. Make sure to select **Upload**. + + > - **Service Provider Private Key**: `mattermost.key` + > - **Service Provider Private Certificate**: `mattermost.crt` + > - **Sign Request**: **true** + > - **Signature Algorithm**: `RSAwithSHA256` + > - **Canonicalization Algorithm**: `Exclusive XML Canonicalization 1.0 (omits comments)` + > + > ![In the System Console, upload both the Service Provider Private Key and the Service Provider Private Certificate.](/images/keycloak_8_mattermost_encryption.png) + +5. Set attributes for the SAML Assertions, which will update user information in Mattermost. + + The attributes below are from steps 7 and 8 above. These values must be the **SAML Attribute Name** within Keycloak. See [documentation on SAML configuration settings](/administration-guide/configure/authentication-configuration-settings#saml-2-0) for more details. + + - **Email Attribute**: `email` + - **Username Attribute**: `username` + - **Id Attribute**: `id` + + ![Set attributes for the SAML assertions which updates user information in Mattermost.](/images/keycloak_9_mattermost_attributes.png) + +6. Select **Save**. + +To confirm SAML is working correctly, log out of Mattermost or open Mattermost in a new Incognito Browser Window and select **Sign in with SAML** on the login page and login with an existing Keycloak account. + +If you have existing users in Mattermost that are going to be migrated to SAML login, make sure to plan for user migration and update your users accordingly. + +You may also configure SAML for Keycloak by editing `config.json`. Before starting the Mattermost server, edit `config.json` to enable SAML based on [SAML configuration settings](/administration-guide/configure/authentication-configuration-settings#saml-2-0). You must restart the Mattermost server for the changes to take effect. + +## Configuing a SAML user as a Guest in Keycloak + +1. In Mattermost, go to **System Console \> Authentication \> SAML**. + +2. Set the **Guest Attribute** to designate which SAML users are guests. + + ![In Mattermost, configure the SAML guest attribute](/images/mm-guset-config.png) + +3. In the Keycloak administration interface, add a user attribute mapper for guests. + +> 1. Select **Clients** from the LHS menu. +> 2. Select **mattermost** from the list. +> +> > - Select the *Client Scopes* tab +> > - Select *mattermost dedicated* from the list of scopes +> > - Click the *Add mapper* drop down and select *By configuration* +> > - Select *User Attribute* on the model that opens +> > - Add values for *Name*, *User Attribute* and *SAML Attribute Name* as shown +> > +> > ![\<Add attribute mapper\>](/images/keycloak-mapper-details.png) + +4. In Keycloak specify which users are guest by adding the attribute under **User details** + +> 1. Select **Users** from the LHS menu. +> 2. Select the username of the desired user. +> 3. Select the **Attribute** tab and select **+ add an attribute**. +> 4. Add the key and value. +> +> > ![An example of adding an attribute to a user.](/images/guest-user-attribute.png) + +<Inc0_sso_saml_ldapsync /> + +<Inc1_sso_saml_faq /> +:start-after: :nosearch: diff --git a/docs/main/administration-guide/onboard/sso-saml-ldapsync.mdx b/docs/main/administration-guide/onboard/sso-saml-ldapsync.mdx new file mode 100644 index 000000000000..bb2f1cff1968 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-ldapsync.mdx @@ -0,0 +1,53 @@ +--- +title: "Configure SAML synchronization with AD/LDAP" +--- +In addition to configuring SAML sign-in, you can optionally configure synchronizing SAML accounts with AD/LDAP. When configured: + +- Mattermost queries AD/LDAP for relevant account information and updates SAML accounts based on changes to attributes (first name, last name, and nickname) +- Accounts disabled in AD/LDAP are deactivated in Mattermost, and their active sessions are revoked once Mattermost synchronizes attributes. + +To configure SAML synchronization with AD/LDAP: + +1. Go to **System Console \> Authentication \> SAML 2.0**, then set **Enable Synchronizing SAML Accounts With AD/LDAP** to **true**. + +2. Go to **System Console \> Authentication \> AD/LDAP** to open the AD/LDAP wizard, navigate to the **Connection Settings** section, then set **Enable Synchronization with AD/LDAP** to **true**. + +3. To ignore guest users when sychronizing, go to **System Console \> Authentication \> SAML 2.0**, then set **Ignore Guest Users when Synchronizing with AD/LDAP** to **true**. + +4. Set the rest of the AD/LDAP settings based on [configuration settings documentation](/administration-guide/configure/authentication-configuration-settings#ad-ldap) to connect Mattermost with your AD/LDAP server. + + If you don't want to enable AD/LDAP sign-in, go to **System Console \> Authentication \> AD/LDAP** wizard, navigate to the **Connection Settings** section, then set **Enable sign-in with AD/LDAP** to **false**. + +5. To specify how often Mattermost synchronizes SAML user accounts with AD/LDAP, go to **System Console \> Authentication \> AD/LDAP** wizard, navigate to the **Sync Performance** section, then set a **Synchronization Interval** in minutes. The default setting is 60 minutes. If you want to synchronize immediately after disabling an account, go to the **Sync History** section and select **AD/LDAP Synchronize Now**. + +6. To confirm that Mattermost can successfully connect to your AD/LDAP server, go to **System Console \> Authentication \> AD/LDAP** wizard, navigate to the **Connection Settings** section, then select **Test Connection**. + +Once the synchronization with AD/LDAP is enabled, user attributes are synchronized with AD/LDAP based on their email address. If a user with a given email address doesn't have an AD/LDAP account, they will be deactivated in Mattermost on the next AD/LDAP sync. + +To re-activate the account: + +1. Add the user to your AD/LDAP server. +2. Purge all caches in Mattermost by going to **System Console \> Environment \> Web Server**, then select **Purge All Caches**. +3. Run AD/LDAP synchronization by going to **System Console \> Authentication \> AD/LDAP** wizard, navigating to the **Sync History** section, then select **AD/LDAP Synchronize Now**. +4. Purge all caches again in Mattermost by going to **System Console \> Environment \> Web Server**, then select **Purge All Caches** again. This re-activates the account in Mattermost. + +<Note> + +\- If a user is deactivated from AD/LDAP, they will be deactivated in Mattermost on the next sync. They will be shown as "Deactivated" in the System Console users list, all of their sessions will expire and they won't be able to log back in to Mattermost. - If a user is deactivated from SAML, their session won't expire until they're deactivated from AD/LDAP. However, they won't be able to log back in to Mattermost. - SAML synchronization with AD/LDAP is designed to pull user attributes such as first name and last name from your AD/LDAP, not to control authentication. In particular, the user filter cannot be used to control who can log in to Mattermost, this should be controlled by your SAML service provider's group permissions. + +</Note> + +See [technical description of SAML synchronization with AD/LDAP](#administration-guide-onboard-sso-saml-technical) for more details. + +## Override SAML data with AD/LDAP data + +Alternatively, you can choose to override SAML bind data with AD/LDAP information. For more information on binding a user with the SAML ID Attribute, please refer to this [documentation](/administration-guide/onboard/sso-saml-okta#how-to-bind-authentication-to-id-attribute-instead-of-email). + +This process overrides SAML email address with AD/LDAP email address data or SAML Id Attribute with AD/LDAP Id Attribute if configured. We recommend using this configuration with the SAML ID Attribute to help ensure new users are not created when the email address changes for a user. + +To ensure existing user accounts do not get disabled in this process, ensure the SAML IDs match the LDAP IDs by exporting data from both systems and comparing the ID data. Mapping ID Attributes for both AD/LDAP and SAML within Mattermost to fields that hold the same data will ensure the IDs match as well. + +1. Set the SAML `Id Attribute` by going to **System Console \> Authentication \> SAML 2.0 \> Id Attribute**. +2. Set **System Console \> Authentication \> SAML 2.0 \> Override SAML bind data with AD/LDAP information** to **true**. +3. Set **System Console \> Authentication \> SAML 2.0 \> Enable Synchronizing SAML Accounts With AD/LDAP** to **true**. +4. Run AD/LDAP sync by going to **System Console \> Authentication \> AD/LDAP** wizard, navigating to the **Sync History** section, then select **AD/LDAP Synchronize Now**. diff --git a/docs/main/administration-guide/onboard/sso-saml-okta.mdx b/docs/main/administration-guide/onboard/sso-saml-okta.mdx new file mode 100644 index 000000000000..1a64c23f0743 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-okta.mdx @@ -0,0 +1,126 @@ +--- +title: "Configure SAML with Okta" +--- +import Inc0_sso_saml_before_you_begin from './sso-saml-before-you-begin.mdx'; +import Inc1_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; +import Inc2_sso_saml_faq from './sso-saml-faq.mdx'; + +<PlanAvailability slug="all-commercial" /> + +The following process provides steps to configure SAML 2.0 with Okta for Mattermost. + +See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +<Inc0_sso_saml_before_you_begin /> + +## Set Up a connection app for Mattermost Single Sign-On + +1. Log in to Okta as an administrator. + +2. Switch to the **Classic UI**, using the drop-down in the upper left. + +3. Go to **Admin Dashboard \> Applications \> Add Application**. + +4. Select **Create New App**, then choose **SAML 2.0** as the Sign on method. + + > ![In Okta, switch to the Classic UI, then go to the Admin Dashboard \> Applications \> Add Application to create a new app. Choose SAML 2.0 as the Sign on method.](/images/okta_1_new_app.png) + +5. Enter **General Settings** for the application, including **App name** and **App logo** (optional). It's recommended to display the application icon to users, including in the Okta Mobile app. If you’d like to use a Mattermost logo for the application, you can download one [from our page](https://handbook.mattermost.com/operations/operations/publishing/publishing-guidelines/brand-and-visual-design-guidelines). + + > ![In Okta, under General Settings, enter an App name and an optional logo. Mattermost recommends displaying the application icon to users and within the Okta mobile app. Select Next to continue.](/images/okta_2_general_settings.png) + +6. Enter **SAML Settings**, including: + +> - **Single sign on URL:** `https://<your-mattermost-url>/login/sso/saml` where `https://<your-mattermost-url>` should typically match the [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url). +> +> - **Audience URI:** For instance, `mattermost` +> +> - **Name ID format:** `unspecified` +> +> - **Application username:** `Email` +> +> > ![In Okta, under Configure SAML, enter required SAML settings.](/images/okta_3_initial_saml_settings.png) + +7. To set up encryption for your SAML connection, select **Show Advanced Settings**. + + ![In Okta, under Configure SAML, set up encryption for your SAML connection by selecting Show Advanced Settings.](/images/okta_4_initial_saml_settings.png) + +8. Set **Assertion Encryption** as **Encrypted**, then upload the Service Provider Public Certificate you generated earlier to the **Encryption Certificate** field. + + > ![In Advanced Settings, set the Assertion Encryption as Encrypted, then upload the generated Service Provider Public Certificate to the Encryption Certificate field](/images/okta_5_advanced_saml_settings.png) + +9. Enter attribute statements used to map attributes between Okta and Mattermost. For more information on which attributes are configurable, see our [documentation on SAML configuration settings](/administration-guide/configure/authentication-configuration-settings#saml-2-0). Email and username attributes are required. For SAML with Okta, an [ID attribute](/administration-guide/configure/authentication-configuration-settings#id-attribute) is also required, and that ID must be mapped to `user.id`. + + > ![Enter attribute statements used to map attributes between Okta and Mattermost. Email and username attributes are required. Okta also requires an ID attribute that must be mapped to user.id.](/images/okta_6_attribute_statements.png) + +10. Select **Next**. Then, set Okta support parameters for the application. Recommended settings: + +> - **I’m an Okta customer adding an internal app** +> +> - **This is an internal app that we have created** +> +> > ![Set recommended Okta support parameters for the application, including I'm an Okta customer adding an internal app and This is an internal app that we have created.](/images/okta_7_support_configuration.png) + +11. Select **Finish**. + +12. In the Mattermost System Console, go to **Authentication \> SAML 2.0**, then set **Override SAML bind data with AD/LDAP information** to **false** if currently set to **true**. You can re-enable [this configuration setting](/administration-guide/configure/authentication-configuration-settings#override-saml-bind-data-with-ad-ldap-information) later when once setup is complete. + +13. On the next screen, select the **Sign On** tab, then select **View Setup Instructions**. + +14. Select the **Identity Provider metadata** link, then copy the link from the browser URL field. This will be used during the SAML configuration steps in the next section. + + ![In the Mattermost System Console, after disabling the Override SAML bind data with AD/LDAP information setting, select the Sign On tab, then select View Setup Instructions. Select the Identity Provider metadata link, then copy the link from the browser URL field to a convenient location.](/images/okta_8_view_instructions.png) + +15. Take note of **Identity Provider Single Sign-On URL** (also known as **SAML SSO URL**), and the Identity Provider Issuer, as both may be needed to configure SAML for Mattermost. + +16. Download the X.509 Certificate file and save it. You may need to upload it to Mattermost in a later step. + + ![Download the X.509 certificate file and save it. You'll upload this certificate file to Mattermost later.](/images/okta_9_view_instructions.png) + +## Configure SAML Sign-On for Mattermost + +Start the Mattermost server and log in to Mattermost as a system admin. Go to **System Console \> Authentication \> SAML 2.0**, then paste the copied Identity Provider Metadata URL in the **Identity Provider Metadata URL** field and select **Get SAML Metadata from IdP**. + +This populates the **SAML SSO URL** and the **Identity Provider Issuer URL** fields automatically. The Identity Provider Public Certificate is also downloaded from the server and set locally. + +Alternatively you can enter the following fields manually: +- **SAML SSO URL:** `Identity Provider Single Sign-On URL` from Okta, specified earlier. + +- **Identity Provider Issuer URL:** `Identity Provider Issuer` from Okta, specified earlier. + +- **Identity Provider Public Certificate:** X.509 Public Certificate file you downloaded from Okta earlier. + + > ![In the Mattermost System Console, go to Authentication \> SAML 2.0 to manually enter the SAML SSO URL and Identity Provider Issuer URL, and upload the Identity Provider Public Certificate manually.](/images/okta_10_mattermost_basics.png) + +2. Configure Mattermost to verify the signature. The **Service Provider Login URL** is the `Single sign on URL` you specified in Okta earlier. + + > ![On the SAML 2.0 page, configure Mattermost to verify the signature, and set the Service Provider Login ULR as the Single sign on URL configured in Okta.](/images/okta_11_mattermost_verification.png) + +3. Enable encryption based on the parameters provided earlier. + + > ![On the SAML 2.0 page, enable encryption and upload both the Service Provider Private Key and the Service Provider Public Certificate.](/images/okta_12_mattermost_encryption.png) + +4. Configure Mattermost to sign SAML requests using the Service Provider Private Key. + +5. Set attributes for the SAML Assertions used to update user information in Mattermost. + - Attributes for Email, Username, and Id are required and should match the values you entered in Okta earlier. + + ![Set attributes for the SAML Assertions used to update user information in Mattermost. Attributes for Email, Username, and Id are required and should match the values set in Okta.](/images/okta_13_mattermost_attributes.png) + +6. (Optional) Customize the login button text. + + > ![You can customize the login button text. By default, the text displays as "With SAML".](/images/okta_14_mattermost_login_button.png) + +7. Select **Save**. + +8. (Optional) If you configured `First Name` Attribute and `Last Name` Attribute, go to **System Console \> Site Configuration \> Users and Teams**, then set **Teammate Name Display** to **Show first and last name**. This is recommended for a better user experience. + +Once complete, and to confirm SAML SSO is successfully enabled, switch your system admin account from email to SAML-based authentication from your profile picture via **Profile \> Security \> Sign-in Method \> Switch to SAML SSO**, then log in with your SAML credentials to complete the switch. + +We also recommend that you post an announcement for your users to explain how the migration will work. + +You may also configure SAML for Okta by editing the `config.json` file to enable SAML based on [SAML configuration settings](#saml-enterprise). You must restart the Mattermost server for the changes to take effect. + +<Inc1_sso_saml_ldapsync /> + +<Inc2_sso_saml_faq /> diff --git a/docs/main/administration-guide/onboard/sso-saml-onelogin.mdx b/docs/main/administration-guide/onboard/sso-saml-onelogin.mdx new file mode 100644 index 000000000000..da4daeb2f093 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-onelogin.mdx @@ -0,0 +1,175 @@ +--- +title: "Configure SAML with OneLogin" +draft: true +--- +import Inc0_sso_saml_before_you_begin from './sso-saml-before-you-begin.mdx'; +import Inc1_sso_saml_ldapsync from './sso-saml-ldapsync.mdx'; +import Inc2_sso_saml_faq from './sso-saml-faq.mdx'; + +<PlanAvailability slug="all-commercial" /> + +The following process provides steps to configure SAML 2.0 with OneLogin for Mattermost. + +See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +<Inc0_sso_saml_before_you_begin /> + +## Create a OneLogin connection app for Mattermost SSO + +1. Add a SAML test connector app. + +> 1. Log in to OneLogin as an administrator. +> 2. Go to **Apps \> Add Apps**. +> 3. Search for "SAML Test Connector", then select **SAML Test Connector (Advanced)**. +> +> ![In OneLogin, go to Apps \> Add Apps, search for SAML Test Connector, then select the matching result in the list](/images/onelogin_1_new_app.png) +> +> 4. In the **Display Name** field, enter a name for the application, then optionally upload an app icon. You can use the Mattermost logo for the icon, which you can download from [Branding Guidelines](https://handbook.mattermost.com/operations/operations/publishing/publishing-guidelines/brand-and-visual-design-guidelines) page. +> +> ![Enter a display name for the application in the Display Name field. You can optionally upload an app icon. Ensure the Visible in portal option is enabled, and save your OneLogin changes.](/images/onelogin_2_basic_configuration.png) +> +> 5. Make sure that the **Visible in portal** option is enabled. +> 6. Select **Save**. + +2. Configure the app. + +> 1. Select the **Configuration** tab, then enter the following values: +> +> > - **RelayState**: leave blank +> > - **Audience**: leave blank +> > - **Recipient**: `https://<your-mattermost-url>/login/sso/saml` where `https://<your-mattermost-url>` should typically match the [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url). +> > - **ACS (Consumer) URL Validator**: `https:\/\/<your-mattermost-url>\/login\/sso\/saml` +> > - **ACS (Consumer) URL**: `https://<your-mattermost-url>/login/sso/saml` +> +> ![In OneLogin, select the Configuration tab to configure the SSO integration with required values.](/images/onelogin_3_configuration_1.png) +> +> 2. In System Console, [enable encryption](/administration-guide/configure/authentication-configuration-settings#enable-encryption), then select **Save**. You're redirected to the **Info** tab. From there, select the **Configuration** tab to access the **SAML Encryption** field. +> 3. Paste the Public Key that you generated earlier into the **SAML Encryption** field at the bottom of the page. This field displays in OneLogin only when encryption is enabled in Mattermost. +> +> ![In the Mattermost System Console, enable encryption and save your changes. When you return to OneLogin, return to the Configuration tab, access the SAML Encryption field, and paste the generated Public Key into the SAML Encryption field. This field isn't visible in OneLogin until encryption is enabled in Mattermost. Save your OneLogin changes.](/images/onelogin_4_configuration_2.png) +> +> 4. Select **Save**. + +3. Enter the attribute parameters. The following attributes are recommended: + +<table style={{width: '26%'}}> +<colgroup> +<col style={{width: '14%'}} /> +<col style={{width: '11%'}} /> +</colgroup> +<thead> +<tr> +<th>Name</th> +<th>Value</th> +</tr> +</thead> +<tbody> +<tr> +<td>ID</td> +<td>UUID</td> +</tr> +<tr> +<td>Email</td> +<td>Email</td> +</tr> +<tr> +<td>FirstName</td> +<td>First Name</td> +</tr> +<tr> +<td>LastName</td> +<td>Last Name</td> +</tr> +<tr> +<td>Name ID value</td> +<td>Email</td> +</tr> +<tr> +<td>Username</td> +<td>Username</td> +</tr> +</tbody> +</table> + +> Attribute parameters map attributes between OneLogin and Mattermost. For more information on which attributes are configurable, see our [documentation on SAML configuration settings](#saml-enterprise). +> +> *Email* attributes are required. +> +> 1. Select the **Parameters** tab. +> 2. Select **Add Parameter**. +> +> ![In OneLogin, select the Parameters tab, then select Add parameter. Map attribute parameters between OneLogin and Mattermost. Email attributes are required.](/images/onelogin_5_parameters_add.png) +> +> 3. In the **Field name** field, enter an attribute parameter such as `Email`. +> 4. Select the **Include in SAML assertion** checkbox. +> 5. Select **Save**. +> +> ![For each field you map in OneLogin, ensure the Include in SAML assertion flag is enabled.](/images/onelogin_6_parameters_add_2.png) +> +> 6. Select **Edit**. +> 7. In the **Value** field, select the OneLogin value that corresponds to the attribute parameter. +> +> ![For each field you map in OneLogin, select the OneLogin value that corresponds to the attribute parameter.](/images/onelogin_7_parameters_add_3.png) +> +> 8. Repeat the steps above to add any other attributes that you need. After you've added all the attributes you want to use, the parameter list should look similar to the following image: +> +> > ![Example of attribute parameters mapped between OneLogin and Mattermost.](/images/onelogin_8_parameters_add_4.png) + +4. Copy the SSO information. + +> 1. Select the **SSO** tab. +> 2. Copy the values in the **Issuer URL** and **SAML 2.0 Endpoint (HTTP)** fields, then save them for later use. +> +> ![In OneLogin, select the SSO tab, copy the Issuer URL and SAML 2.0 Endpoint (HTTP) values to a convenient location.](/images/onelogin_9_sso.png) +> +> 3. Select **View Details** to view the X.509 certificate. +> 4. Make sure that the **X.509 PEM** option is selected in the drop-down. +> +> ![On the SSO tab in OneLogin, select View Details to access the X.509 certificate. Ensure that the X.509 PEM option is selected. Select Download and save the file in a convenient location.](/images/onelogin_10_sso_certificate.png) +> +> 5. Select **DOWNLOAD**, then save the file in a convenient location for later use. + +5. Save all your changes. + +## Configure SAML Sign-On for Mattermost + +1. Start the Mattermost server, then log in to Mattermost as a system admin. Go to **System Console \> Authentication \> SAML**. + +> 1. Enter the **OneLogin Issuer URL** into the **Identity Provider Metadata URL** field. +> 2. Select **Get SAML Metadata from IdP** to download the metadata. + +2. Configure Mattermost to verify the signature. + +> 1. In the **Verify Signature** field, select **True**. +> 2. In the **Service Provider Login URL**, enter `https//<your-mattermost-url>/login/sso/saml`. +> +> ![On the System Console SAML page, enable the Verify Signature option by setting it to true, then enter your specific Service Provider Login URL based on your Mattermost URL](/images/okta_11_mattermost_verification.png) + +3. Configure Mattermost to sign SAML requests using the Service Provider Private Key. +4. Enable encryption. + +> 1. In the **Enable Encryption** field, select **True**. +> 2. In the **Service Provider Private Key** field, upload the private key that you generated earlier. +> 3. In the **Service Provider Public Certificate** field, upload the public key that you generated earlier. +> +> ![On the System Console SAML page, enable encryption, then upload both the private and public generated keys.](/images/okta_12_mattermost_encryption.png) + +5. Set attributes for the SAML Assertions, which are used for updating user information in Mattermost. + +> The **Email Atttribute** field and the **Username Attribute** field are required, and should match the values that you entered earlier when you configured the SAML Test Connector on OneLogin. +> +> ![On the System Console SAML page, set attributes for the SAML Assertions used to update user information in Mattermost. Both Email Attribute and Username Attribute are required, and should match the values entered when configuring the SAML Test Connector in OneLogin.](/images/okta_13_mattermost_attributes.png) + +6. (Optional) Customize the login button text. +7. Select **Save**. +8. (Optional) If you configured `First Name` Attribute and `Last Name` Attribute, go to **System Console \> Site Configuration \> Users and Teams**, then set **Teammate Name Display** to **Show first and last name**. This is recommended for a better user experience. + +To confirm that SAML SSO is successfully enabled, switch your system admin account from email to SAML-based authentication from your profile picture via **Profile \> Security \> Sign-in Method \> Switch to SAML SSO**, then log in with your SAML credentials to complete the switch. + +We also recommend that you post an announcement to your users detailing how the migration will work. + +You can also configure SAML for OneLogin by editing the `config.json` file to enable SAML based on [SAML configuration settings](#saml-enterprise). You must restart the Mattermost server for the changes to take effect. + +<Inc1_sso_saml_ldapsync /> + +<Inc2_sso_saml_faq /> diff --git a/docs/main/administration-guide/onboard/sso-saml-technical.mdx b/docs/main/administration-guide/onboard/sso-saml-technical.mdx new file mode 100644 index 000000000000..5f5a5eb9f514 --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml-technical.mdx @@ -0,0 +1,186 @@ +--- +title: "SAML Single Sign-On: technical documentation" +--- +<PlanAvailability slug="all-commercial" /> + +Security Assertion Markup Language (SAML) is an open standard that allows identity providers (IdP), like OneLogin, to pass authorization credentials to service providers (SP), like Mattermost. + +In simpler terms, it means you can use one set of credentials to log in to many different sites. With a SAML identity provider account, you can log in to Mattermost and other sites securely with the same account. + +The main benefit is that it helps administrators centralize user management by controlling which sites users have access to with their SAML identity provider credentials. + +Mattermost supports using a single metadata URL to retrieve configuration information for the Identity Provider using your single sign-on URL to generate an IdP metadata URL. The IdP metadata XML file contains the IdP certificate, the entity ID, the redirect URL, and the logout URL. + +Using this URL populates the SAML SSO URL and the Identity Provider Issuer URL fields in the configuration process automatically and the Identity Provider Public Certificate is also downloaded from the server and set locally. + +This is currently supported for Okta and Microsoft ADFS server 2012 and 2016. + +For detailed steps, view the [Configure SAML with Okta](/sso-saml-okta), [Configure SAML with Microsoft ADFS for Windows Server 2012](/sso-saml-adfs), and [Configure SAML with Microsoft ADFS using Microsoft Windows Server 2016](/sso-saml-adfs-msws2016) documentation. See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML, including AES-192-GCM and AES-256-GCM encryption support introduced in v10.9. + +## SAML providers + +**Identity Providers (IdP)**: An identity provider performs the authentication. When a user clicks to log in, the identity provider confirms who the user is, and sends data to the service provider with the proper authorization to access the site. + +*Examples*: OneLogin, Okta, Microsoft Active Directory (ADFS) or Azure. + +**Service Providers (SP)**: A service provider gets authentication and authorization information from an IdP. Once received, it gives the user access to the system and logs the user in. + +*Examples*: Mattermost, Zendesk, Zoom, Salesforce. + +## SAML request (AuthNRequest) + +When Mattermost initiates an SP-initiated SAML request flow, it generates a **HTTP-Redirect** binding request to the IdP that contains an XML payload as a base64 string + +``` text +bM441nuRIzAjKeMM8RhegMFjZ4L4xPBHhAfHYqgnYDQnSxC++Qn5IocWuzuBGz7JQmT9C57nxjxgbFIatiqUCQN17aYrLn/mWE09C5mJMYlcV68ibEkbR/JKUQ+2u/N+mSD4/C/QvFvuB6BcJaXaz0h7NwGhHROUte6MoGJKMPE= +``` + +AuthNRequests can also be signed by Mattermost, in which case the XML payload is similar to: + +<Note> + +From Mattermost v11, the default signature algorithm has been updated from SHA-1 to SHA-256 for improved security. The example below reflects the new default SHA-256 algorithm. + +</Note> + +``` XML +<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlsig="https://www.w3.org/2000/09/xmldsig#" ID="_u5mpjadp1fdozfih4cj8ap4brh" Version="2.0" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://localhost:8065/login/sso/saml" IssueInstant="2019-06-08T16:00:31Z"> + <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://www.okta.com/exkoxukx1D8OIfY03356</saml:Issuer> + <samlsig:Signature Id="Signature1"> + <samlsig:SignedInfo> + <samlsig:CanonicalizationMethod Algorithm="https://www.w3.org/2001/10/xml-exc-c14n#"></samlsig:CanonicalizationMethod> + <samlsig:SignatureMethod Algorithm="https://www.w3.org/2000/09/xmldsig#rsa-sha256"></samlsig:SignatureMethod> + <samlsig:Reference URI="#_u5mpjadp1fdozfih4cj8ap4brh"> + <samlsig:Transforms> + <samlsig:Transform Algorithm="https://www.w3.org/2000/09/xmldsig#enveloped-signature"></samlsig:Transform> + </samlsig:Transforms> + <samlsig:DigestMethod Algorithm="https://www.w3.org/2000/09/xmldsig#sha256"></samlsig:DigestMethod> + <samlsig:DigestValue></samlsig:DigestValue> + </samlsig:Reference> + </samlsig:SignedInfo> + <samlsig:SignatureValue></samlsig:SignatureValue> + <samlsig:KeyInfo> + <samlsig:X509Data> + <samlsig:X509Certificate>MIIFmzCCA4OgAwIBAgIJAIusvV3gZIwiMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRIwEAYDVQQHDAlQYWxvIEFsdG8xEzARBgNVBAoMCk1hdHRlcm1vc3QxDzANBgNVBAsMBkRldk9wczEZMBcGA1UEAwwQYmFzZS5leGFtcGxlLmNvbTAeFw0xOTA2MDcxMjQ0MTdaFw0yOTA2MDQxMjQ0MTdaMGIxCzAJBgNVBAYTAlVTMRIwEAYDVQQHDAlQYWxvIEFsdG8xEzARBgNVBAoMCk1hdHRlcm1vc3QxDzANBgNVBAsMBkRldk9wczEZMBcGA1UEAwwQYmFzZS5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALAfDj+RyByszTOPRL4b+cilNF/3PB1I0CG3TNzgllgy5CwRGHLKn5/t8rPsJoWLKOUGenzVdXWuoVi3jyl5FZ1N60CBbXfmSWk20dSIkcYCcYEgs1BTBqKKYFw2dV4M0oppzNtlq7A0Glpg/gpaR/2TXEPAhOsUfORC2qAdJt9ev0AQjp5V0TkIKMZz8oo33Coi38TG5r/LG+ihRbpWzO7j9Rc2S5I6bczvG4wOg7nVKG+B5XBvuU9PjSqgxpd/F/fYf+ggAEru58E+VM4veCRV8vSPbBqDG4FMPV6DiA+tH/70n6zuPCS3soxX00kjKtP80QD6UgzvM2NN7PHiNlf0Zj6VCU3VdjEnypg7dzlHJuyyaAaTD5nSfkecamEoJpq7kaUB7uTmBHELRUhOOy24f54HnP72vnxicZL8cWsOkJwQAqIGzBxQ7J0uX4Os71WrV2YIur8QVk6KN6MBPxfiCh3xO/R+cycgx0aMrWZoyzOzP7NCTM5MNE41C48xeGviyCtUID4xiBow+xo6IDUaiCoUVJhz579ore8ic70a19DD0qHy4SpBvrUwCO54kvkgn6HjYlLC/k8nFM9F9W9wVAQD/QwIjd7EtLZLGgbU61Jv3q4kZxxq270hogCRY0lmI3RxkedGHhetF7kaizrikW5zJQEeido/ir37HhX5AgMBAAGjVDBSMBIGA1UdEwEB/wQIMAYBAf8CAQAwPAYDVR0RBDUwM4IQbG9ncy5leGFtcGxlLmNvbYITbWV0cmljcy5leGFtcGxlLmNvbYcEwKgAAYcEfwAAATANBgkqhkiG9w0BAQsFAAOCAgEAH1O91BABHXZjrU7v1OwG+GbU/4TYZqBXXNxax++OFSRCkEEoNKGg49R6J7lY4lrm12zBlw+oGSyjIOerzi39/dcxDkKpzyhGvEN4mExbDlybmdCVrHPeWgZl7uwqn4Bj1xiu97M6eMthgxJE7KVNDGDHthGL0/fTlONIh3qS7Far33hLHJJKy3+lC1MDB8cNltV3mf/ctHCx5Wa0bfZId0MJgd/seP0WU1HCf3kIxhnhsnOYs32xu7EGiM4/lgnquVd/q/f99ueSaDSHrep373/w2ce9iF3U0qcLd2iP8ayF/daGeW1dVPL9R10Oe4BpRjMkjlLwhZdjJeKSg9GBa2GXUEn1Ru9vpSw/C10no3Qx/6ZHweYbSmJ6hBg4T0nDBp6iVS1eQULNXxDuDWb26U0ESOO5jK8ATywuc45o0bqdvD1XOrGYGfGnofx7ofRWwKHWfltvxurnbsyo2vH6nM6K41K2DpVdyQOKAGvKe/oCWfdi+WyBQJGWcIp2OTC1XyWHv7JsY3lo04+islkHEcqJyd8Rf8GWmRHdXz0WzGiZbxWzAuvRRWnzM31VAws8kQBHTBwIJlJoGX4AXfEvPi+NTxkntf8cQdJucK9ZZbP4ycXHULO4LneyJoJ9Q7nxX11xWv7BDWxxclOXy6tyUkg9Fjb7pQ/HCVvGhRzilVU=</samlsig:X509Certificate> + </samlsig:X509Data> + </samlsig:KeyInfo> + </samlsig:Signature> +</samlp:AuthnRequest> +``` + +## SAML responses + +There are different types of SAML responses sent by the IdP to the SP. The response contains the Assertion with the NameID and attributes of a user. + +Below is a table of the different types of responses. Each response type is fully supported except when the SAML assertion is signed while the SAML response itself is not: + +<table> +<thead> +<tr> +<th>Signed SAML Response</th> +<th>Signed SAML Assertion</th> +<th>Encrypted SAML Assertion</th> +<th>Supported by Mattermost</th> +</tr> +</thead> +<tbody> +<tr> +<td>Yes</td> +<td>Yes</td> +<td>Yes</td> +<td>Yes</td> +</tr> +<tr> +<td>Yes</td> +<td>Yes</td> +<td>No</td> +<td>Yes</td> +</tr> +<tr> +<td>Yes</td> +<td>No</td> +<td>Yes</td> +<td>Yes</td> +</tr> +<tr> +<td>Yes</td> +<td>No</td> +<td>No</td> +<td>Yes</td> +</tr> +<tr> +<td>No</td> +<td>Yes</td> +<td>Yes</td> +<td>Partially, validation of assertion signature not supported</td> +</tr> +<tr> +<td>No</td> +<td>Yes</td> +<td>No</td> +<td>Partially, validation of assertion signature not supported</td> +</tr> +<tr> +<td>No</td> +<td>No</td> +<td>Yes</td> +<td>Yes</td> +</tr> +<tr> +<td>No</td> +<td>No</td> +<td>No</td> +<td>Yes</td> +</tr> +</tbody> +</table> + +For example XML responses for each type, see the [OneLogin SAML response examples](https://www.samltool.com/generic_sso_res.php). + +## Technical description of SAML synchronization with AD/LDAP + +When enabled, SAML synchronization with AD/LDAP occurs in phases: + +1. Get all the current LDAP users from the Mattermost database who have `Users.AuthService` set to `ldap`. This is a SQL query issued against the Mattermost database: `SELECT * FROM Users WHERE AuthService = 'ldap'`. +2. Get all the current SAML users from the Mattermost database who have `Users.AuthService` set to `saml`. This is a SQL query issued against the Mattermost database: `SELECT * FROM Users WHERE AuthService = 'saml'`. +3. Get all the current LDAP users from the LDAP server as defined by `LdapSettings.UserFilter`. This is an [LDAP query](https://github.com/mattermost/mattermost/blob/master/server/scripts/ldap-check.sh) issued against the LDAP server. Users are retrieved in batches as defined by `LdapSettings.MaxPageSize`. +4. Update LDAP attributes. For each existing Mattermost user retrieved in step 1, attempt to find a match against the list of LDAP users from step 3. To find matches, `Users.AuthData` field of the Mattermost user is compared against the `LdapSettings.IdAttribute` LDAP setting. + +> - If any attribute of the user has changed, that attribute is copied from the LDAP server and the user is marked as updated. +> - If the corresponding `LdapSettings.IdAttribute` is not found, the user is assumed to be deleted from the LDAP server, and deactivated from Mattermost by setting the `Users.DeleteAt` field to a valid timestamp. + +5. Update SAML attributes. For each existing Mattermost user retrieved in step 2, attempt to find a match against the list of LDAP users from step 3. To find matches, `SamlSettings.Email` is compared against the `LdapSettings.EmailAttribute` LDAP setting. + +> - If any attribute of the user has changed, that attribute is copied from the LDAP server and the user is marked as updated. +> - If the corresponding `LdapSettings.EmailAttribute` is not found, the user is assumed to be deleted from the LDAP server, and deactivated from Mattermost by setting the `Users.DeleteAt` field to a valid timestamp. + +## Frequently Asked Questions + +### How can I obtain a SAML metadata XML file consumed by Mattermost? + +You can obtain the XML file by calling the Mattermost RESTful API endpoint at `/api/v4/saml/metadata`. + +For other useful SAML API calls, see the [API reference](https://api.mattermost.com/#tag/SAML). + +### Can I update user attributes using the API? + +No. When Mattermost is configured to use SAML for user authentication, the following user attribute changes can't be made through the API: first name, last name, position, nickname, email, profile image, or username. SAML must be the authoritative source for these user attributes. + +### Why does the ObjectGUID of a user in Mattermost differ from what I'm seeing in ADFS? + +The Active Directory Object-Guid attribute (LDAP display name `objectGUID`) is a 16 byte array which can be displayed in different ways. However, only Microsoft changes the encoding of the ObjectGUID. All the others keep it the same except for the different base (octal, decimal, hex), as follows: + +1. The `ldapsearch` linux command displays it as base 64: `Hrz/HqNKnU+lCNTYHx9Ycw==`. This is also the format used in LDIF files. +2. The [LDAP Golang package Mattermost uses](https://github.com/go-ldap/ldap) emits the value as hexidecimal (base 16) array, with each byte separated by a backslash: `\1e\bc\ff\1e\a3\4a\9d\4f\a5\08\d4\d8\1f\1f\58\73` + +> - You can remove the backslashes (`1ebcff1ea34a9d4fa508d4d81f1f5873`) and parse it with [Golang like this](https://go.dev/play/p/9b8iDPuz0Nm). The snippets prints the base 10 representation of each value: `[30 188 255 30 163 74 157 79 165 8 212 216 31 31 88 115]` + +3. Windows Powershell displays the value like this: `1effbc1e-4aa3-4f9d-a508-d4d81f1f5873` + +### Does `relaystate` need to be passed back to the client from the identity provider? + +Yes. If you're integrating Mattermost with a provider that doesn't already do so by default, ensure that `relaystate` is enabled. See the PingIdentity [SAML RelayState](https://support.pingidentity.com/s/article/SAML-RelayState-and-PingFederate#:~:text=RelayState%20is%20an%20optional%20parameter,the%20SAML%202.0%20bindings%20specification) documentation for details. + +### How can I troubleshoot the SAML logon process? + +The most useful tool that we've found for troubleshooting SAML connection issues is the [SAML Chrome Panel](https://chromewebstore.google.com/detail/paijfdbeoenhembfhkhllainmocckace?utm_source=item-share-cp) Chrome extension. We're not aware of similar tools for other browsers, but this tool justifies installing Chrome! diff --git a/docs/main/administration-guide/onboard/sso-saml.mdx b/docs/main/administration-guide/onboard/sso-saml.mdx new file mode 100644 index 000000000000..90d3d822537f --- /dev/null +++ b/docs/main/administration-guide/onboard/sso-saml.mdx @@ -0,0 +1,86 @@ +--- +title: "SAML Single Sign-On" +--- +<PlanAvailability slug="all-commercial" /> + +Single sign-on (SSO) is a way for users to log into multiple applications with a single user ID and password without having to re-enter their credentials. The SAML standard allows identity providers to pass credentials to service providers. Mattermost can be configured to act as a SAML 2.0 Service Provider. + +Mattermost can be configured to act as a SAML 2.0 Service Provider, and Mattermost officially supports Okta, OneLogin, and Microsoft ADFS as the identity providers (IDPs), please see links below for more details on how to configure SAML with these providers. + +In addition to the officially supported identity providers, you can also configure SAML for a custom IdP. For instance, customers have successfully set up miniOrange, Azure AD, DUO, PingFederate, Keycloak, and SimpleSAMLphp as custom IdPs. Because we do not test against these identity providers, it is important that you test new versions of Mattermost in a staging environment to confirm it will work with your identity provider. You can also set up MFA on top of your SAML provider for additional security. + +The SAML Single sign-on integration offers the following benefits: + +- **Single sign-on.** Users can log in to Mattermost with their SAML credentials. +- **Centralized identity management.** Mattermost accounts automatically pull user attributes from SAML upon login, such as full name, email, and username. +- **Automatic account provisioning.** Mattermost user accounts are automatically created the first time a user signs in with their SAML credentials on the Mattermost server. +- **Sync groups to predefined roles in Mattermost.** Assign team and channel roles to groups via LDAP Group Sync. +- **Compliance alignment with administrator management.** Manage Administrator access to Mattermost in the System Console using SAML attributes. + +<Important> + +\- SAML Single sign-on itself does not support periodic updates of user attributes nor automatic deprovisioning. However, SAML with AD/LDAP sync can be configured to support these use cases. - Account creation and updates is influenced by the attributes configured for identification. + +- If the email address is used as the unique identifier and it changes, Mattermost might interpret this as a new user. If an ID attribute is not set, or if it's set to use the email address, a new account may be created in Mattermost when the email address changes. +- If an ID attribute that doesn't change, such as employeeID, is configured, then Mattermost can use this consistent ID to recognize and match the user account. This allows for updates to other attributes, such as email, without creating a new account. The user details are updated based on the non-changing ID attribute, ensuring continuity and correct user identification without duplicate accounts. +- If configuring Mattermost to use the EU-Login system for authentication, please be aware that their <code>issuerURI</code> field is what Mattermost calls "Service Provider Identifier". +- For more information about SAML, see [this article from Varonis](https://www.varonis.com/blog/what-is-saml/), and [this conceptual example from DUO](https://duo.com/blog/the-beer-drinkers-guide-to-saml). +- See the encryption options documentation for details on what [encryption methods](/deployment-guide/encryption-options#saml-encryption-support) Mattermost supports for SAML. + +</Important> + +## Using SAML attributes to apply roles + +You can use attributes to assign roles to specified users on login. To access the SAML attribute settings navigate to **System Console \> SAML 2.0**. + +### Username attribute + +(Optional) Enter a SAML assertion filter to use when searching for users. + +1. Navigate to **System Console \> Authentication \> SAML 2.0** (or **System Console \> SAML** in versions prior to 5.12). +2. Complete the **Username Attribute** field. +3. Choose **Save**. + +When the user accesses the Mattermost URL, they log in with same username and password that they use for organizational logins. + +### Guest attribute + +When enabled, the `guest` attribute in Mattermost identifies external users whose SAML assertion is guest and who are invited to join your Mattermost server. These users will have the guest role applied immediately upon first login instead of the default member user role. This eliminates having to manually assign the role in the System Console. + +If a Mattermost guest user has the guest role removed in the SAML system, the synchronization processes will not automatically promote them to a member user role. This is done manually via **System Console \> User Management**. If a member user has the `guest` attribute added, the synchronization processes will automatically demote the member user to the guest role. + +1. Enable Guest Access via **System Console \> SAML 2.0**. +2. Navigate to **System Console \> Authentication \> SAML 2.0**. +3. Complete the Guest Attribute field. +4. Choose **Save**. + +When a guest logs in for the first time they are presented with a default landing page until they are added to channels. + +See the [Guest accounts documentation](/administration-guide/onboard/guest-accounts) for more information about this feature. + +### Admin attribute + +(Optional) The attribute in the SAML Assertion for designating system admins. The users selected by the query will have access to your Mattermost server as system admins. By default, system admins have complete access to the Mattermost System Console. + +Existing members that are identified by this attribute will be promoted from member to system admin upon next login. The next login is based upon Session lengths set in **System Console \> Session Lengths**. It is recommended that users are manually demoted to members in **System Console \> User Management** to ensure access is restricted immediately. + +1. Navigate to **System Console \> Authentication \> SAML 2.0**. +2. Set **Enable Admin Attribute** to `true`. +3. Complete the **Admin Attribute** field. +4. Choose **Save**. + +<Note> + +If the `admin` attribute is set to `false` the member's role as system admin is retained. However if the attribute is removed/changed, system admins that were promoted via the attribute will be demoted to members and will not retain access to the System Console. When this attribute is not in use, system admins can be manually promoted/demoted in **System Console \> User Management**. + +</Note> + +## Configuration assistance + +We are open to providing assistance when configuring your custom IdP by answering Mattermost technical configuration questions and working with your IdP provider in support of resolving issues as they relate to Mattermost SAML configuration settings. However, we cannot guarantee your connection will work with Mattermost. + +For technical documentation on SAML, see [sso saml technical](/sso-saml-technical). + +To assist with the process of getting a user file for your custom IdP, see this [documentation](https://github.com/icelander/mattermost_generate_user_file). + +Please note that we may not be able to guarantee that your connection will work with Mattermost, however we will consider improvements to our feature as we are able. You can see more information on getting support [here](https://mattermost.com/support/) and submit requests for official support of a particular provider on our [feature idea portal](https://portal.productboard.com/mattermost/33-what-matters-to-you). diff --git a/docs/main/administration-guide/onboard/user-provisioning-workflows.mdx b/docs/main/administration-guide/onboard/user-provisioning-workflows.mdx new file mode 100644 index 000000000000..acf24420634f --- /dev/null +++ b/docs/main/administration-guide/onboard/user-provisioning-workflows.mdx @@ -0,0 +1,39 @@ +--- +title: "Provisioning workflows" +--- +<PlanAvailability slug="all-commercial" /> + +This document provides an overview of user provisioning and deprovisioning workflows in Mattermost. + +There are currently 3 recommended user provisioning workflows in Mattermost: + +1. **On demand:** If user accounts are not pre-provisioned using one of the methods described below, then a new user account will be provisioned when the user first logs in. When the user logs in, they are asked to select a public team to join (all users must belong to at least one team) and then they are added automatically to the Town Square channel. Mattermost also has a [default channel setting](/administration-guide/configure/experimental-configuration-settings#default-channels) that enables system admins to add everyone to additional channels specified by the organization. +2. **Pre-provisioned via bulk import:** Mattermost features a [bulk data loading tool](/administration-guide/onboard/bulk-loading-data) that can be used for pre-provisioning new users by adding them to teams and channels before their first login to Mattermost. This tool automates the creation of Teams, Channels, Users, and Posts (with file attachments). It can also be used to migrate users and content from an existing system. +3. **Mattermost API:** The Mattermost [RESTful API](https://api.mattermost.com) can be used to pre-provision new user accounts as well as add and remove them from teams and channels. This model is commonly used by enterprises that have central account provisioning applications. + +## Mattermost user identifier + +The user identifier used to uniquely identify users in Mattermost depends on the method of authentication: + +- **Email/password**: Email address or username. Created by the user or previously described account pre-provisioning process. +- **AD/LDAP**: Configure a unique and unchanging ID Attribute from the AD/LDAP server to be used in Mattermost. If a user's ID Attribute changes, it will create a new Mattermost account unassociated with their old one. +- **SAML 2.0**: Selected during configuration. You may use an Id Attribute instead of email to bind the user. We recommend choosing an ID that is unique and will not change over time. + +### User deprovisioning + +Users in Mattermost can be deactivated in the following ways: + +- **AD/LDAP Synchronization**: AD/LDAP users can be deactivated in Mattermost based on their status in the directory server via synchronization. Learn more in [AD/LDAP documentation](/administration-guide/onboard/ad-ldap#how-do-i-deactivate-users). +- **System Console**: User management screen in **System Console \> Users** allows system admins to deactiveate users with email/password login. See the [Deactivate users](/administration-guide/configure/user-management-configuration-settings#deactivate-users) documentation for details. +- **RESTful API** The Mattermost API can be used to deactivate users. See [API documentation to learn more](https://api.mattermost.com/#operation/DeleteUser). +- **Command Line Interface**: You can use the Mattermost [mmctl user deactivate](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-deactivate) command to deactivate users. + +Once deactivated, users still exist in the Mattermost database and their messages can still be viewed in Mattermost. You can use the [mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-delete) tools to delete a user and all of their content. + +From Mattermost v10.10, when a user is deactivated, the account's [availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability) is automatically set to offline. + +<Note> + +As long as the ID attribute selected via AD/LDAP or SAML 2.0 is a unique identifier, the user’s email address or name (along with other attributes) can be updated without breaking the user’s account. + +</Note> diff --git a/docs/main/administration-guide/scale/additional-ha-considerations.mdx b/docs/main/administration-guide/scale/additional-ha-considerations.mdx new file mode 100644 index 000000000000..241d71aa2273 --- /dev/null +++ b/docs/main/administration-guide/scale/additional-ha-considerations.mdx @@ -0,0 +1,5 @@ +--- +--- +[Elasticsearch](https://www.elastic.co) provides enterprise-scale deployments with optimized search performance and prevents performance degradation and timeouts. Elasticsearch allows you to search large volumes of data quickly, in near real-time, by creating and managing an index of post data. Mattermost’s implementation uses [Elasticsearch](https://www.elastic.co) as a distributed, RESTful search engine supporting highly efficient database searches in a [cluster environment](/administration-guide/scale/high-availability-cluster-based-deployment). Visit the [Mattermost Elasticsearch product documentation](/administration-guide/scale/elasticsearch-setup) for deployment and configuration details. + +Performance monitoring support enables a Mattermost server to track system health for large Enterprise deployments through integrations with [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/). These integrations support data collection from several Mattermost servers, which is particularly useful if you’re running Mattermost [in high availability mode](/administration-guide/scale/high-availability-cluster-based-deployment). Once you’re tracking system health, you can [set up performance alerts](/administration-guide/scale/performance-alerting) on your Grafana dashboard. Visit the [Mattermost Performance Monitoring product documentation](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) for installation details. diff --git a/docs/main/administration-guide/scale/backing-storage-benchmarks.mdx b/docs/main/administration-guide/scale/backing-storage-benchmarks.mdx new file mode 100644 index 000000000000..a5bb4b056901 --- /dev/null +++ b/docs/main/administration-guide/scale/backing-storage-benchmarks.mdx @@ -0,0 +1,157 @@ +--- +title: "Backing storage benchmarks" +draft: true +--- +Understanding the performance characteristics of your backing storage is critical for optimizing your Mattermost deployment. These benchmarks offer insights into the relative performance of each storage option, helping you make informed decisions based on your use case and infrastructure needs. + +This page provides detailed write and read benchmark results for supported storage options including [local file system (EBS, gp3)](#local), [network file system (EFS)](#efs), and [object storage (S3)](#s3). + +## Write operations + +<table style={{width: '73%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<thead> +<tr> +<th>File Size</th> +<th>Local (EBS)</th> +<th>EFS</th> +<th>S3</th> +</tr> +</thead> +<tbody> +<tr> +<td>100KB</td> +<td>0.57 ms (±0.26 ms, p50: 0.63 ms)</td> +<td>34.47 ms (±6.33 ms, p50: 32.57 ms)</td> +<td>181.59 ms (±39.05 ms, p50: 174.83 ms)</td> +</tr> +<tr> +<td>1MB</td> +<td>2.08 ms (±0.92 ms, p50: 2.28 ms)</td> +<td>57.43 ms (±7.32 ms, p50: 58.16 ms)</td> +<td>277.13 ms (±49.95 ms, p50: 279.36 ms)</td> +</tr> +<tr> +<td>10MB</td> +<td>18.15 ms (±5.31 ms, p50: 18.23 ms)</td> +<td>180.58 ms (±97.95 ms, p50: 150.35 ms)</td> +<td>469.29 ms (±166.32 ms, p50: 462.12 ms)</td> +</tr> +<tr> +<td>100MB</td> +<td>585.14 ms (±274.38 ms, p50: 795.78 ms)</td> +<td>390.87 ms (±166.32 ms, p50: 339.20 ms)</td> +<td>1.09 s (±0.04 s, p50: 1.09 s)</td> +</tr> +<tr> +<td>1GB</td> +<td>7.42 s (±2.13 s, p50: 7.99 s)</td> +<td>3.05 s (±1.09 s, p50: 2.93 s)</td> +<td>10.65 s (±0.82 s, p50: 10.44 s)</td> +</tr> +<tr> +<td>10GB</td> +<td>70.66 s (±7.05 s, p50: 80.50 s)</td> +<td>26.54 s (±2.47 s, p50: 26.86 s)</td> +<td>109.05 s (±12.47 s, p50: 105.13 s)</td> +</tr> +</tbody> +</table> + +<Note> + +**Write Performance**: Local EBS storage is fastest for small files (100KB - 10MB), while EFS performs better for larger files (100MB - 10GB). S3 is consistently the slowest for writes across all file sizes. + +</Note> + +## Read operations + +<table style={{width: '74%'}}> +<colgroup> +<col style={{width: '10%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '20%'}} /> +<col style={{width: '22%'}} /> +</colgroup> +<thead> +<tr> +<th>File Size</th> +<th>Local (EBS)</th> +<th>EFS</th> +<th>S3</th> +</tr> +</thead> +<tbody> +<tr> +<td>100KB</td> +<td>0.05 ms (±0.02 ms, p50: 0.04 ms)</td> +<td>0.66 ms (±0.17 ms, p50: 0.60 ms)</td> +<td>28.55 ms (±4.12 ms, p50: 27.63 ms)</td> +</tr> +<tr> +<td>1MB</td> +<td>0.18 ms (±0.06 ms, p50: 0.18 ms)</td> +<td>0.82 ms (±0.19 ms, p50: 0.72 ms)</td> +<td>27.03 ms (±4.28 ms, p50: 27.54 ms)</td> +</tr> +<tr> +<td>10MB</td> +<td>1.27 ms (±0.27 ms, p50: 1.16 ms)</td> +<td>7.83 ms (±18.12 ms, p50: 1.68 ms)</td> +<td>108.24 ms (±0.56 ms, p50: 108.18 ms)</td> +</tr> +<tr> +<td>100MB</td> +<td>16.50 ms (±0.95 ms, p50: 16.16 ms)</td> +<td>73.53 ms (±182.32 ms, p50: 16.91 ms)</td> +<td>1.05 s (±0.00 s, p50: 1.05 s)</td> +</tr> +<tr> +<td>1GB</td> +<td>167.89 ms (±2.19 ms, p50: 167.72 ms)</td> +<td>773.41 ms (±1768.89 ms p50: 168.17 ms)</td> +<td>10.49 s (±0.02 s, p50: 10.49 s)</td> +</tr> +<tr> +<td>10GB</td> +<td>1.57 s (±0.03 s, p50: 1.56 s)</td> +<td>1.56 s (±0.02 s, p50: 1.55 s)</td> +<td>150.66 s (±33.47 s, p50: 146.51 s)</td> +</tr> +</tbody> +</table> + +<Note> + +- **Read Performance**: Local and EFS have comparable read performance for very large files (10GB), but local storage outperforms for smaller files. S3 read performance is significantly slower, especially for large files (150.66s versus ~1.56s for 10GB files). +- **Consistency**: Local storage shows the most consistent performance (lower standard deviations) for small files, while EFS shows more consistent performance for large files. S3 generally has higher variability across all metrics. +- **Median vs Average**: The median (p50) values generally align with the averages, but in some cases (particularly EFS read operations), the median reveals that outliers significantly affect the average. For example, EFS read performance for 100MB and 1GB files shows much better median values than averages. + +</Note> + +![Read and Write Performance](/images/read-write-storage-performance.png) + +## Testing notes + +- For S3 tests, [Amazon S3 exported upload part size](/administration-guide/configure/environment-configuration-settings#amazon-s3-upload-part-size) was set to the default value (100MB). +- Local EBS storage is the stock gp3 (3000 IOPS) provided by EC2 instances. +- Both EBS and EFS solutions tested are considered `local` storage options from the application's perspective, where the [file storage system](/administration-guide/configure/environment-configuration-settings#file-storage-system) is set to `local` in both cases. EFS is essentially AWS's managed NFS, which enables it to serve as a potential alternative to S3 by allowing multiple Mattermost nodes in a high-availability (HA) deployment to share a common file system. In such HA scenarios, the standard local file storage (e.g., an EBS volume attached to a single instance) [is not suitable, as it can't be shared across multiple nodes](/administration-guide/scale/high-availability-cluster-based-deployment#file-storage-configuration). EFS is a good alternative in this case, but EFS is not a block storage solution like EBS. + +## Supported storage options + +### Local + +The local file system of the Mattermost server. If running in a cloud environment like AWS, this often utilizes Elastic Block Storage (EBS), which provides block-level storage attached directly to the instances. This setup typically offers high performance with low latency since the storage is local to the server. This option is often the fastest for small files due to low latency. + +### EFS + +Amazon Elastic File System, a managed file storage solution that supports shared access across multiple instances. EFS supports shared access across multiple instances but adds network overhead, which can impact performance compared to local storage options. EFS is generally slower than local storage but can be beneficial for certain use cases requiring shared access. + +### S3 + +Amazon Simple Storage Service, an object storage solution that provides high durability and scalability. While S3 is great for storing large amounts of data reliably, it introduces higher latency and slower performance due to network-based access and its nature as object storage rather than block or file storage. diff --git a/docs/main/administration-guide/scale/collect-performance-metrics.mdx b/docs/main/administration-guide/scale/collect-performance-metrics.mdx new file mode 100644 index 000000000000..829bdcd5be4c --- /dev/null +++ b/docs/main/administration-guide/scale/collect-performance-metrics.mdx @@ -0,0 +1,67 @@ +--- +title: "Collect performance metrics" +--- +<PlanAvailability slug="entry-ent" /> + +System admins can collect and store the [same performance monitoring metrics](/administration-guide/scale/performance-monitoring-metrics) as Prometheus, without having to deploy these third-party tools. Data is collected every minute and is stored in a path you configure. The data is synchronized to either a cloud-based or local file store every hour, and retained for 15 days. + +Download and share the collected data with Mattermost to understand application performance, troubleshoot system stability and performance, as well as inform route cause analysis. + +<Tip> + +Already have Prometheus and Grafana deployed? You can [use these tools to monitor performance of your Mattermost deployment](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). + +</Tip> + +## Mattermost configuration + +<Note> + +For Mattermost Cloud deployments, no setup is required. See the [usage](#usage) section below for details on collecting performance metrics. + +</Note> + +For a self-hosted Mattermost deployment, a Mattermost system admin must perform the following steps in Mattermost. + +1. Log in to your Mattermost [workspace](/end-user-guide/end-user-guide-index) as a system admin. +2. From Mattermost v10.1, you can install the Metrics plugin from the in-product Mattermost Marketplace by selecting the **Product** <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> icon and selecting **App Marketplace**. Search for **Metrics** and select **Install**. +3. Go to **System Console \> Plugins \> Plugin Management**. In the **Installed Plugins** section, scroll to **Mattermost Metrics Plugin**, and select **Enable Plugin**. +4. Specify the path of the time-series database, and select **Save**. +5. Go to **System Console \> Environment \> Performance Monitoring**, and set **Enable Performance Monitoring** to **true**. Select **Save**. +6. Go to **System Console \> Environment \> Performance Monitoring**, and set **Enable Client Performance Monitoring** to **true**. This setting is required for the system administrator's performance monitoring product experience. Select **Save**. + +<Note> + +For Mattermost deployments prior to v10.1, you must download the latest version of [the plugin binary release](https://github.com/mattermost/mattermost-plugin-metrics/releases), compatible with Mattermost v8.0.1 and later. Go to **System Console \> Plugins \> Plugin Management \> Upload Plugin**, and upload the plugin binary you downloaded. + +</Note> + +## Upgrade + +We recommend upgrading this feature as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-metrics/releases) for the latest release, available releases, and compatibiilty considerations. + +## Usage + +You need to be a Mattermost system admin to collect performance metrics. Select **Create Dump** to generate dump files. + +To use the generated dump file, you can simply clone the [Dockprom](https://github.com/stefanprodan/dockprom) repository. Change the Prometheus data volume to point to the dump that you just downloaded. The downloaded file is compressed, so to be able to use it, you need to decompress it first. + +The volume configuration for Prometheus should look like the code below in the `docker-compose.yml` file: + +``` yaml +volumes: + - ./prometheus:/etc/prometheus + - /Path/To/Dump/Directory:/prometheus/data +``` + +Once you set this up, run `docker-compose` as described in [Dockprom Repository](https://github.com/stefanprodan/dockprom?tab=readme-ov-file#install). + +You can also use our [Mattermost Performance Monitoring v2](https://grafana.com/grafana/dashboards/15582-mattermost-performance-monitoring-v2/) dashboard by simply importing it into Grafana. + +1. Open Grafana (`<localhost>:3000` by default) and then log into it. +2. Once you log in, go to the **Plus** <img src="/img/ui/plus_F0415.svg" alt="The Plus icon provides access to channel and direct message functionality." className="theme-icon" /> icon on the left sidebar, and then select **Import**. +3. Enter the dashboard ID (`15582`) in the **Grafana.com Dashboard** field, and then select **Load** to fetch the dashboard. + +## What's collected? + +Mattermost provides [custom metrics](/administration-guide/scale/performance-monitoring-metrics#custom-mattermost-metrics) and [standard Go metrics](/administration-guide/scale/performance-monitoring-metrics#standard-go-metrics) that can be used to monitor your system's performance. Additionally Enterprise customers can use the Metrics plugin to collect [host/system metrics](/administration-guide/scale/performance-monitoring-metrics#host-system-metrics) from [node exporter](https://github.com/prometheus/node_exporter) targets to monitor network-related panels for Mattermost Calls. diff --git a/docs/main/administration-guide/scale/common-configure-mattermost-for-enterprise-search.mdx b/docs/main/administration-guide/scale/common-configure-mattermost-for-enterprise-search.mdx new file mode 100644 index 000000000000..558959d2dd76 --- /dev/null +++ b/docs/main/administration-guide/scale/common-configure-mattermost-for-enterprise-search.mdx @@ -0,0 +1,51 @@ +--- +title: "Set server connection details" +--- +1. (Optional) Enter **Server Username** used to access the enterprise search server. +2. (Optional) Enter **Server Password** associated with the username. +3. Set **Enable Cluster Sniffing** (Optional). Sniffing finds and connects to all data nodes in your cluster automatically. + +<Warning> + +Do not enable cluster sniffing when using cloud-hosted search providers such as Elastic Cloud or Amazon OpenSearch Service. Cloud providers typically hide search cluster nodes behind a proxy, so sniffed node addresses may be unreachable from your network. The provider handles connection pooling for you, making sniffing unnecessary and potentially disruptive. + +</Warning> + +4. Optional CA and client certificate configuration settings are available for use with basic authentication credentials or to replace them. See the [Enterprise search configuration settings](/administration-guide/configure/environment-configuration-settings#enterprise-search) documentation for details. +5. Select **Test Connection** and then select **Save**. If the server connection is unsuccessful you won't be able to save the configuration or enable searching with Elasticsearch or AWS OpenSearch. + +<Note> + +From Mattermost v11, enterprise search server connections are tested during [Support Packet generation](/administration-guide/manage/admin/generating-support-packet). Any connection errors encountered during Support Packet generation are automatically included in the packet to help diagnose configuration issues. + +</Note> + +# Build the post index of existing messages + +Select **Index Now**. This process can take up to a few hours depending on the size of the post database and number of messages. The progress percentage can be seen as the index is created. To avoid downtime, set **Enable Elasticsearch for search queries** to `false` so that database search is available during the indexing process. + +# Enable enterprise search + +Ensure bulk indexing is complete before enabling enterprise search, otherwise search results will be incomplete. + +Set **Enable Elasticsearch for search queries** to `true`, and setting **Enable Elasticsearch for autocomplete** to `true`. Save your configuration updates and restart the Mattermost server. + +<Note> + +For high post volume deployments, we strongly encourage you to read and properly configure the Mattermost [LiveIndexingBatchSize](/administration-guide/configure/environment-configuration-settings#live-indexing-batch-size) configuration setting. + +</Note> + +<Warning> + +For high post volume deployments, we also strongly recommend *disabling* Database Search once Elasticsearch or AWS OpenSearch is fully configured and running. The Mattermost Server will fall back on Database search if ElasticSearch or OpenSearch are unavailable which can lead to performance degradation on high post volume deployments. + +</Warning> + +Once the configuration is saved, new posts made to the database are automatically indexed on the Elasticsearch or AWS OpenSearch server. + +## Enterprise search limitations + +1. Elasticsearch and AWS OpenSearch uses a standard selection of "stop words" to keep search results relevant. Results for the following words will not be returned: "a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", and "with". +2. Searching stop words in quotes returns more results than just the searched terms ([ticket](https://mattermost.atlassian.net/browse/MM-7216)). +3. By default, search results are limited to a user's team and channel membership. This is enforced by the Mattermost server. The entities are indexed in Elasticsearch or AWS OpenSearch in a way that allows Mattermost to filter them when querying, so the Mattermost server narrows down the results on every Elasticsearch or AWS OpenSearch request applying those filters. From Mattermost v11.6, admins can [allow searching public channels without membership](/administration-guide/configure/environment-configuration-settings#allow-searching-public-channels-without-membership) so that users can find messages in public channels they haven't joined, scoped to teams they belong to. diff --git a/docs/main/administration-guide/scale/deploy-grafana-loki-for-centralized-logging.mdx b/docs/main/administration-guide/scale/deploy-grafana-loki-for-centralized-logging.mdx new file mode 100644 index 000000000000..3ad76be7868d --- /dev/null +++ b/docs/main/administration-guide/scale/deploy-grafana-loki-for-centralized-logging.mdx @@ -0,0 +1,445 @@ +--- +title: "Deploy Grafana Loki for centralized logging" +--- +<PlanAvailability slug="entry-ent" /> + +This guide extends your existing [Prometheus and Grafana performance monitoring deployment](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) by adding [Grafana Loki](https://grafana.com/oss/loki/) for centralized log aggregation. While Prometheus collects **metrics** (CPU, request latency, goroutine counts), Loki collects **logs** — giving your operations team the ability to search, filter, and correlate Mattermost application logs across all servers from a single Grafana interface. + +With Loki in place you can: + +- Search Mattermost logs across all application servers from Grafana. +- Filter by log level, HTTP status code, or free-text search. +- Identify the top recurring errors and warnings. +- Correlate log events with Prometheus metric spikes on the same timeline. +- Optionally collect PostgreSQL database logs alongside application logs. + +<Tip> + +This guide assumes you have already deployed Prometheus and Grafana by following the [performance monitoring guide](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). Loki and the OpenTelemetry Collector will be added to that existing infrastructure. + +</Tip> + +## Architecture overview + +The deployment adds two components to your monitoring stack: + +- **Loki** — the log aggregation engine, installed on your existing Grafana/Prometheus monitoring server. +- **OpenTelemetry Collector** — a versatile, industry-standard agent installed on each Mattermost application server to ship logs. + +``` text +┌──────────────────────┐ ┌──────────────────────┐ +│ Mattermost App 01 │ │ Mattermost App 02 │ +│ │ │ │ +│ /opt/mattermost/ │ │ /opt/mattermost/ │ +│ logs/mattermost.log│ │ logs/mattermost.log│ +│ │ │ │ │ │ +│ [ OTel Col ] │ │ [ OTel Col ] │ +└─────────┬────────────┘ └─────────┬────────────┘ + │ push (:3100/otlp) │ + ▼ ▼ +┌─────────────────────────────────────────────────────┐ +│ Monitoring Server │ +│ │ +│ [ Prometheus :9090 ] [ Loki :3100 ] │ +│ │ │ │ +│ └──────┬──────────────┘ │ +│ ▼ │ +│ [ Grafana :3000 ] │ +│ Metrics + Logs │ +└─────────────────────────────────────────────────────┘ + +Optional: Add the OpenTelemetry Collector on your PostgreSQL server to also +ship database logs to Loki. +``` + +## Prerequisites + +Before starting, confirm the following: + +- Prometheus and Grafana are deployed and collecting Mattermost metrics per the [performance monitoring guide](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). +- You have **SSH access** with sudo privileges to the monitoring server and each Mattermost application server. +- Mattermost is installed at `/opt/mattermost` (the default location). If your installation path differs, substitute your path wherever `/opt/mattermost` appears. +- **Network connectivity**: Each Mattermost server can reach the monitoring server on **TCP port 3100** (Loki's HTTP API). + +## Step 1: Verify Mattermost JSON logging + +Mattermost must be writing JSON-formatted file logs for Loki queries to work. This is the default on all plans — verify it on each application server: + +``` bash +tail -1 /opt/mattermost/logs/mattermost.log +``` + +A JSON-formatted line looks like: + +``` json +{"timestamp":"2025-01-15T14:32:01.123Z","level":"info","msg":"Server is listening on [::]:8065","caller":"app/server.go:482"} +``` + +If you see plain-text output instead, go to **System Console \> Environment \> Logging** and set **Output file logs as JSON** to `true`, then restart Mattermost: + +``` bash +sudo systemctl restart mattermost +``` + +## Step 2: Install Loki on the monitoring server + +Install Loki on the same server that runs Grafana and Prometheus. All commands in this section are run **on the monitoring server**. + +<Important> + +The commands below use Loki version **3.4.2**. Check the [Loki releases page](https://github.com/grafana/loki/releases) for the latest version and substitute the version number as needed. + +</Important> + +1. Create the Loki user, directories, and download the binary: + + ``` bash + # Create a dedicated system user + sudo useradd --system --no-create-home --shell /bin/false loki + + # Create directories + sudo mkdir -p /opt/loki/data /opt/loki/bin + + # Download and extract Loki + sudo apt-get install -y unzip + cd /tmp + curl -LO https://github.com/grafana/loki/releases/download/v3.4.2/loki-linux-amd64.zip + unzip loki-linux-amd64.zip + sudo mv loki-linux-amd64 /opt/loki/bin/loki + sudo chmod +x /opt/loki/bin/loki + ``` + +2. Download and install the production configuration file: + + - [Download loki-config.yaml](/samples/loki/loki-config.yaml) + + ``` bash + sudo cp loki-config.yaml /opt/loki/loki-config.yaml + ``` + + <div class="tip"> + + <div class="title"> + + Tip + + </div> + + **Log retention** is set to **14 days** by default. To change this, edit `/opt/loki/loki-config.yaml` and update the `retention_period` value under `limits_config`. Loki requires this value in hours — common values: + + - `336h` = 14 days (default) + - `720h` = 30 days + - `2160h` = 90 days + - `8760h` = 365 days + + Longer retention increases disk usage. As a rough guide, expect 1–3 GB per day for a moderately active Mattermost deployment (varies with log volume). Monitor `/opt/loki/data/` after the first week to project storage needs. The `compactor.retention_enabled` setting must remain `true` for retention enforcement to work. + + </div> + +3. Set ownership: + + ``` bash + sudo chown -R loki:loki /opt/loki + ``` + +4. Create a systemd service file: + + ``` bash + sudo tee /etc/systemd/system/loki.service > /dev/null <<'EOF' + [Unit] + Description=Grafana Loki Log Aggregation + Documentation=https://grafana.com/docs/loki/latest/ + After=network-online.target + Wants=network-online.target + + [Service] + Type=simple + User=loki + Group=loki + ExecStart=/opt/loki/bin/loki -config.file=/opt/loki/loki-config.yaml + Restart=on-failure + RestartSec=5 + LimitNOFILE=65536 + StandardOutput=journal + StandardError=journal + + [Install] + WantedBy=multi-user.target + EOF + ``` + +5. Start Loki: + + ``` bash + sudo systemctl daemon-reload + sudo systemctl enable --now loki + ``` + +6. Verify Loki is running: + + ``` bash + sudo systemctl status loki + curl -s http://localhost:3100/ready + ``` + + The `/ready` endpoint should return `ready`. Loki may take 15–20 seconds after startup before it reports ready — this warmup delay is normal. + +## Step 3: Install OpenTelemetry Collector on each Mattermost server + +The OpenTelemetry (OTel) Collector runs on each Mattermost application server and pushes logs to Loki. Repeat these steps on **every Mattermost application server**. + +<Important> + +Replace `<LOKI_HOST>` with the IP address or hostname of your monitoring server, `<HOSTNAME>` with this server's hostname (e.g., `mm-app-01`), and `<SERVICE_NAME>` with the service type (e.g., `mattermost` or `postgres`). + +</Important> + +1. Install the OTel Collector Contrib distribution: + + ``` bash + # Add OTel Collector repository and install + # Commands below are for Ubuntu/Debian + wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.145.0/otelcol-contrib_0.145.0_linux_amd64.deb + sudo dpkg -i otelcol-contrib_0.145.0_linux_amd64.deb + ``` + + <div class="note"> + + <div class="title"> + + Note + + </div> + + The installation process automatically creates a system user and group named `otelcol-contrib`. + + </div> + +2. Download and edit the OpenTelemetry Collector configuration: + + - [Download otel-collector-config-mattermost.yaml](/samples/loki/otel-collector-config-mattermost.yaml) + + ``` bash + sudo cp otel-collector-config-mattermost.yaml /etc/otelcol-contrib/config.yaml + ``` + + Edit `/etc/otelcol-contrib/config.yaml` and replace the placeholders: + + - Replace `<LOKI_HOST>` with your monitoring server's address. + - Replace `<HOSTNAME>` with this server's hostname. + - Replace `<SERVICE_NAME>` with the service type (e.g., `mattermost`). + + ``` bash + sudo vi /etc/otelcol-contrib/config.yaml + ``` + +3. Grant the collector read access to the Mattermost log directory: + + ``` bash + # Grant the collector access to read Mattermost logs. + # Substitute 'mattermost' for the group that owns your log file. + sudo usermod -aG mattermost otelcol-contrib + + # Ensure logs are group-readable + sudo chmod 640 /opt/mattermost/logs/mattermost.log + sudo chmod g+rx /opt/mattermost/logs + ``` + +4. Restart the service: + + ``` bash + sudo systemctl restart otelcol-contrib + sudo systemctl enable otelcol-contrib + ``` + +5. Verify the collector is running and shipping logs: + + ``` bash + sudo systemctl status otelcol-contrib + sudo journalctl -u otelcol-contrib -f + ``` + +## Step 4: Add Loki as a data source in Grafana + +1. Log in to Grafana (default: `http://<monitoring-server>:3000`). +2. Navigate to **Administration \> Data Sources \> Add data source**. +3. Select **Loki** from the list. +4. Configure the connection: + - **Name**: `Loki` + - **URL**: `http://localhost:3100` (since Loki is colocated with Grafana) +5. Select **Save & test**. Grafana should confirm the data source is working. + +## Step 5: Import the Mattermost Loki dashboard + +A pre-built Grafana dashboard is recommended for monitoring your logs. This dashboard is provided as a basic example: + +- [Download the Mattermost Loki Logs dashboard JSON](/samples/grafana-dashboards/mattermost-loki-logs.json) + +<Note> + +While the dashboard provides a useful starting point, users can gain full query flexibility using the **Explore** tab in Grafana to build custom LogQL queries on the fly. + +</Note> + +The dashboard provides: + +- **Log Volume by Level** — stacked bar chart showing log rates by severity. +- **Error / Warning / Total counters** — stat panels for the selected time range. +- **HTTP 4xx/5xx count** — quick visibility into application-level HTTP errors. +- **Error Rate Over Time** — time series per instance for spotting error spikes. +- **Top Error Messages** — table ranking the most frequent errors. +- **Log Browser** — searchable, filterable log panel with level and free-text variables. + +To import the dashboard: + +1. In Grafana, go to **Dashboards \> New \> Import**. +2. Select **Upload JSON file** and choose the downloaded `mattermost-loki-logs.json` file. +3. On the import screen, select your **Loki** data source from the dropdown. +4. Select **Import**. + +## Step 6: Useful LogQL queries + +You can run these queries directly in **Grafana Explore** (select the Loki data source) or use them to build additional dashboard panels. + +**Search all Mattermost logs:** + +``` text +{service_name="mattermost"} +``` + +**Filter by log level:** + +``` text +{service_name="mattermost"} | json | detected_level="error" +``` + +**Search for all HTTP 4xx responses:** + +``` text +{service_name="mattermost"} | json | status_code >= 400 +``` + +**Search for all HTTP 5xx responses:** + +``` text +{service_name="mattermost"} | json | status_code >= 500 +``` + +**Top 5 error messages over 5-minute windows:** + +``` text +topk(5, sum(count_over_time({service_name="mattermost"} | json | detected_level="error" [5m])) by (msg)) +``` + +**Count errors by message over 5-minute windows:** + +``` text +sum(count_over_time({service_name="mattermost"} | json | detected_level="error" [5m])) by (msg) +``` + +**Free-text search (e.g., plugin errors):** + +``` text +{service_name="mattermost"} |~ "plugin" +``` + +**Authentication-related log lines:** + +``` text +{service_name="mattermost"} |~ "(?i)(auth|login|token|session)" +``` + +**Logs from a specific server instance:** + +``` text +{service_name="mattermost", service_instance_id="mm-app-01"} +``` + +<Tip> + +For a full LogQL reference, see the [Grafana Loki LogQL documentation](https://grafana.com/docs/loki/latest/query/). + +</Tip> + +## Optional: Add PostgreSQL log collection + +If your PostgreSQL database runs on a dedicated server (not RDS), you can ship its logs to Loki as well. This is useful for correlating slow queries or database errors with Mattermost application events. + +<Note> + +A separate configuration file is provided for PostgreSQL log collection. Install the OpenTelemetry Collector on the PostgreSQL server using the same steps from **Step 3**, then use this configuration file instead of the Mattermost one: + +- [Download otel-collector-config-postgres.yaml](/samples/loki/otel-collector-config-postgres.yaml) + +The PostgreSQL configuration handles common Ubuntu/Debian JSON log paths (`/var/log/postgresql/*.json`). Replace the same `<LOKI_HOST>`, `<HOSTNAME>`, and `<SERVICE_NAME>` placeholders as described in Step 3. + +</Note> + +Once running, PostgreSQL logs appear in Grafana under the label `{service_name="postgres"}`: + +``` text +{service_name="postgres"} | json | detected_level="error" +``` + +## Verification and troubleshooting + +**End-to-end verification checklist:** + +1. Loki is healthy: + + ``` bash + curl -s http://<monitoring-server>:3100/ready + # Expected: "ready" + ``` + +2. OpenTelemetry Collector is shipping logs (run on each Mattermost server): + + ``` bash + sudo journalctl -u otelcol-contrib -n 100 + # Look for export successful messages or lack of errors + ``` + +3. Logs are visible in Grafana: Go to **Explore**, select the **Loki** data source, and run `{service_name="mattermost"}`. You should see recent log lines. + +4. The dashboard loads: Open the **Mattermost Log Aggregation** dashboard and confirm panels are populated. (Note: You may need to update dashboard queries to use <code>service_name</code> and <code>service_instance_id</code>). + +**Common issues:** + +<table> +<colgroup> +<col style={{width: '40%'}} /> +<col style={{width: '60%'}} /> +</colgroup> +<thead> +<tr> +<th>Symptom</th> +<th>Resolution</th> +</tr> +</thead> +<tbody> +<tr> +<td>OTel Col target shows errors</td> +<td>Verify the file paths in the config match the actual log file location. Check file permissions (<code>otelcol-contrib</code> user must be able to read the file).</td> +</tr> +<tr> +<td><code>connection refused</code> on port 3100</td> +<td>Ensure Loki is running (<code>systemctl status loki</code>). Check firewall rules: <code>sudo iptables -L -n | grep 3100</code> or check your AWS security group allows TCP 3100 from the Mattermost servers.</td> +</tr> +<tr> +<td>Logs appear in Loki but fields aren't parsed</td> +<td>Confirm Mattermost is writing JSON-formatted logs (see Step 1). Check that the <code>json_parser</code> operator (for Postgres) or OTel processors are correctly configured.</td> +</tr> +<tr> +<td><code>/ready</code> returns an error</td> +<td>Check Loki logs: <code>sudo journalctl -u loki -f</code>. Common cause: permissions on <code>/opt/loki/data/</code> — ensure the <code>loki</code> user owns the directory.</td> +</tr> +<tr> +<td>Old logs are not being deleted</td> +<td>Verify <code>compactor.retention_enabled: true</code> and <code>limits_config.retention_period</code> are both set in the Loki config. The compactor runs on the <code>compaction_interval</code> (default: 10 minutes) and applies a <code>retention_delete_delay</code> (default: 2 hours) before actually removing data.</td> +</tr> +<tr> +<td>High disk usage on the monitoring server</td> +<td>Review the retention period in the configuration. Consider reducing it or adding more disk. Check <code>du -sh /opt/loki/data/</code> to see current usage.</td> +</tr> +</tbody> +</table> diff --git a/docs/main/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.mdx b/docs/main/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.mdx new file mode 100644 index 000000000000..abc5ba57ba97 --- /dev/null +++ b/docs/main/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.mdx @@ -0,0 +1,137 @@ +--- +title: "Deploy Prometheus and Grafana for performance monitoring" +--- +<PlanAvailability slug="entry-ent" /> + +Performance monitoring support enables admins to track system health for large Enterprise deployments through integrations with [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/). These integrations support data collection from several Mattermost servers, which is particularly useful if you're running Mattermost [in high availability mode](/administration-guide/scale/high-availability-cluster-based-deployment). Once you're tracking system health, you can [set up performance alerts](/administration-guide/scale/performance-alerting) on your Grafana dashboard. + +Admins can collect and store various data points from the Mattermost application in an [OpenMetrics](https://openmetrics.io) format by [deploying Prometheus](#install-prometheus) and [Grafana](#install-grafana). + +<Tip> + +Don't want to deploy Prometheus and Grafana? You can also [collect performance metrics using the Mattermost Metrics plugin](/administration-guide/scale/collect-performance-metrics). + +</Tip> + +## Install Prometheus + +<Important> + +While Prometheus and Grafana may be installed on the same server as Mattermost, we recommend installing these integrations on separate servers, and configure Prometheus to pull all metrics from Mattermost and other connected servers. + +</Important> + +1. [Download a precompiled binary for Prometheus](https://prometheus.io/download/). Binaries are provided for many popular distributions, including Darwin, Linux, and Windows. For installation instructions, see the [Prometheus install guides](https://prometheus.io/docs/prometheus/latest/getting_started/). + +2. The following settings are recommended in the Prometheus configuration file named `prometheus.yml`: + + ``` yaml + # my global config + global: + scrape_interval: 5s # Set to 5 seconds for optimal performance monitoring. + evaluation_interval: 5s # Set to 5 seconds for optimal performance monitoring. + # scrape_timeout is set to the global default (10s). + + # Attach these labels to any time series or alerts when communicating with + # external systems (federation, remote storage, Alertmanager). + external_labels: + monitor: 'mattermost-monitor' + + # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. + rule_files: + # - "first.rules" + # - "second.rules" + + # A scrape configuration containing exactly one endpoint to scrape: + # Here it's Prometheus itself. + scrape_configs: + # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. + - job_name: 'prometheus' + + # The scrape_interval can be overridden per job if needed (5s matches the global default). + # scrape_interval: 5s + + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + static_configs: + - targets: ["<hostname1>:<port>", "<hostname2>:<port>"] + ``` + +3. Replace the `<hostname1>:<port>` parameter with your Mattermost host IP address and port to scrape the data. It connects to `/metrics` using HTTP. + +4. In the Mattermost System Console, go to **Environment \> Performance Monitoring** to set **Enable Performance Monitoring** to **true**, then specify the **Listen Address** (port-only, e.g., `8067`), and select **Save**. See our [Configuration Settings](/administration-guide/configure/environment-configuration-settings#performance-monitoring) documentation for details. + + ![Enable performance monitoring options in the System Console by going to Environment \> Performance Monitoring, then specifying a listen address.](/images/perf_monitoring_system_console.png) + +5. To test that the server is running, go to `<ip>:<port>/metrics`. + +<Note> + +A Mattermost Enterprise license is required to connect to `/metrics` using HTTP. + +</Note> + +6. Finally, run `vi prometheus.yml` to finish configuring Prometheus. For starting the Prometheus service, read the [comprehensive guides provided by Prometheus](https://prometheus.io/docs/prometheus/latest/getting_started/). +7. Once the service has started, you can access the data in `<localhost>:<port>/graph`. While you can use the Prometheus service to create graphs, we'll focus on creating metric and analytics dashboards in Grafana. + +<Tip> + +For troubleshooting advice, check the [Prometheus FAQ page](https://prometheus.io/docs/introduction/faq/). + +</Tip> + +## Install Grafana + +<Important> + +While Prometheus and Grafana may be installed on the same server as Mattermost, we recommend installing these integrations on separate servers, and configure Prometheus to pull all metrics from Mattermost and other connected servers. + +</Important> + +1. [Download a precompiled binary for Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/) on Ubuntu or Debian. Binaries are also available for other distributions, including Redhat, Windows and Mac. For install instructions, see [Grafana install guides](https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/) + +2. The Grafana package is installed as a service, so it is easy to start the server. See their [install guides](https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/) to learn more. + +3. The default HTTP port is `3000` and default username and password are `admin`. + +4. Add a Mattermost data source with the following settings as defined in the screenshot below + + ![Mattermost data source configuration settings for a Grafana installation.](/images/mattermost_datasource.png) + +<Tip> + +- For troubleshooting advice, check the [Grafana Troubleshooting page](https://grafana.com/docs/grafana/latest/troubleshooting/). +- For user guides and tutorials, check the [Grafana documentation to learn more](https://grafana.com/docs/grafana/latest/). + +</Tip> + +## Getting started + +To help you get started, you can download three sample dashboards shared in Grafana: + +<Tip> + +See [this Grafana guide](https://grafana.com/docs/grafana/v7.5/dashboards/export-import/) to learn how to import Grafana dashboards either from the UI or from the HTTP API. + +</Tip> + +- [Mattermost Performance Monitoring v2](https://grafana.com/grafana/dashboards/15582-mattermost-performance-monitoring-v2/), which contains detailed charts for performance monitoring including application, cluster, job server, and system metrics. +- [Mattermost Notification Health Monitoring](https://grafana.com/grafana/dashboards/21305-mattermost-notification-health/), which can be used to track different types of notifications sent from Mattermost. Accessing and enabling Mattermost Notification Health Monitoring requires the feature flag `NotificationMonitoring` to be set to `true`. System admins can [disable notification monitoring data collection](/administration-guide/configure/site-configuration-settings#enable-notification-monitoring) through the System Console. +- [Mattermost Web App Performance Metrics](https://grafana.com/grafana/dashboards/21460-web-app-metrics/), which contains detailed metrics for client-side performance, including web vitals and Mattermost-specifc metrics. +- [Mattermost Desktop App Performance Metrics](https://grafana.com/grafana/dashboards/22736-desktop-app-metrics/), which contains detailed metrics for client-side desktop performance, including CPU and memory usage metrics. +- [Mattermost Mobile App Performance Metrics](https://grafana.com/grafana/dashboards/21695-mobile-performance-metrics/), which contains detailed metrics for client-side mobile performance, including web vitals and Mattermost-specifc metrics. +- [Mattermost Threaded Discussion Metrics](https://grafana.com/grafana/dashboards/15581-collapsed-reply-threads-performance/), which contains detailed metrics on the queries involved in our threaded discussions feature. +- [Mattermost Performance KPI Metrics](https://grafana.com/grafana/dashboards/2539-mattermost-performance-kpi-metrics/), which contains key metrics for monitoring performance and system health. +- [Mattermost Performance Monitoring (Bonus Metrics)](https://grafana.com/grafana/dashboards/2545-mattermost-performance-monitoring-bonus-metrics/), which contains additional metrics such as emails sent or files uploaded, which may be important to monitor in some deployments. + +## What's collected? + +Mattermost provides [custom metrics](/administration-guide/scale/performance-monitoring-metrics#custom-mattermost-metrics) and [standard Go metrics](/administration-guide/scale/performance-monitoring-metrics#standard-go-metrics) that can be used to monitor your system's performance. + +## Next steps + +Once you've set up performance monitoring, you may want to: + +- [Set up performance alerts](/administration-guide/scale/performance-alerting) to be notified when metrics exceed thresholds. +- [Deploy Grafana Loki for centralized logging](/administration-guide/scale/deploy-grafana-loki-for-centralized-logging) to search and correlate logs with metric spikes. diff --git a/docs/main/administration-guide/scale/elasticsearch-setup.mdx b/docs/main/administration-guide/scale/elasticsearch-setup.mdx new file mode 100644 index 000000000000..d32c429dcc6f --- /dev/null +++ b/docs/main/administration-guide/scale/elasticsearch-setup.mdx @@ -0,0 +1,110 @@ +--- +title: "Elasticsearch server setup" +--- +import Inc0_common_configure_mattermost_for_enterprise_search from './common-configure-mattermost-for-enterprise-search.mdx'; + +<PlanAvailability slug="ent-plus" /> + +Elasticsearch allows you to search large volumes of data quickly, in near real-time, by creating and managing an index of post data. The indexing process can be managed from the System Console after setting up and connecting an Elasticsearch server. The post index is stored on the Elasticsearch server and updated constantly after new posts are made. In order to index existing posts, a bulk index of the entire post database must be generated. + +Deploying Elasticsearch includes the following two steps: [setting up Elasticsearch](#set-up-elasticsearch), and [configuring Mattermost](#configure-mattermost). + +## Set up Elasticsearch + +We highly recommend that you set up Elasticsearch server on a dedicated machine separate from the Mattermost Server. + +1. Download and install the latest release of [Elasticsearch v8](https://www.elastic.co/guide/en/elasticsearch/reference/8.15/install-elasticsearch.html), or [Elasticsearch v7.17+](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/install-elasticsearch.html). See the Elasticsearch documentation for installation details. +2. Set up Elasticsearch with `systemd` by running the following commands: + +> ``` sh +> sudo /bin/systemctl daemon-reload +> sudo /bin/systemctl enable elasticsearch.service +> sudo systemctl start elasticsearch.service +> ``` + +3. Confirm Elasticsearch is working on the server by running the following command: + +> ``` sh +> curl localhost:9200 +> ``` + +4. Get your network interface name by running the following command: + +> ``` sh +> ip addr +> ``` + +5. Edit the Elasticsearch configuration file in `vi` by running the following command: + +> ``` sh +> vi /etc/elasticsearch/elasticsearch.yml +> ``` + +6. In this file, replace the `network.host` value of `_eth0_` with your network interface name, and save your changes. +7. When using Elasticsearch v8, ensure you set `action.destructive_requires_name` to `false` in `elasticsearch.yml` to allow for wildcard operations to work. +8. Restart Elasticsearch by running the following commands: + +> ``` sh +> sudo systemctl stop elasticsearch +> sudo systemctl start elasticsearch +> ``` + +9. Confirm the ports are listenings by running the following command: + +> ``` sh +> netstat -plnt +> ``` +> +> You should see the following ports, including the ones listening on ports 9200 and 9300. Confirm these are listening on your server's IP address. + +10. Create an Elasticsearch directory and give it the proper permissions. +11. Install the [icu-analyzer plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-icu.html) to the `/usr/share/elasticsearch/plugins` directory by running the following command: + +> ``` sh +> sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu +> ``` +> +> **(Optional) CJK language analyzer plugins**: To improve search for Korean, Japanese, or Chinese content, install one or more of the following language-specific analyzer plugins: `analysis-nori` (Korean), `analysis-kuromoji` (Japanese), and `analysis-smartcn` (Chinese). +> +> ``` sh +> sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-nori +> sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji +> sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-smartcn +> ``` +> +> After installing the CJK plugins, restart Elasticsearch to load them: +> +> ``` sh +> sudo systemctl restart elasticsearch +> ``` +> +> Then enable the [EnableCJKAnalyzers](/administration-guide/configure/environment-configuration-settings#enable-cjk-analyzers) configuration setting. See [Enabling Chinese, Japanese, and Korean Search](/administration-guide/configure/enabling-chinese-japanese-korean-search) for additional CJK search configuration options. +> +> <div class="important"> +> +> <div class="title"> +> +> Important +> +> </div> +> +> If you enable CJK analyzers on a server with existing indexed content, you must purge and rebuild the search index in **System Console \> Environment \> Elasticsearch** for the CJK analyzers to take effect on existing posts. +> +> </div> + +12. Test the connection from Mattermost to Elasticsearch by running the following command: + +> ``` sh +> curl 172.31.80.220:9200 +> ``` + +## Configure Mattermost + +Follow these steps to configure Mattermost to use your Elasticsearch server and to generate the post index: + +1. Go to **System Console \> Environment \> Elasticsearch**. +2. Set **Enable Elasticsearch Indexing** to `true` to enable the other the settings on the page. Once the configuration is saved, new posts made to the database are automatically indexed on the Elasticsearch server. +3. Ensure **Backend type** is set to `elasticsearch`. + +<Inc0_common_configure_mattermost_for_enterprise_search /> +:start-after: :nosearch: diff --git a/docs/main/administration-guide/scale/ensuring-releases-perform-at-scale.mdx b/docs/main/administration-guide/scale/ensuring-releases-perform-at-scale.mdx new file mode 100644 index 000000000000..05d720fe6e91 --- /dev/null +++ b/docs/main/administration-guide/scale/ensuring-releases-perform-at-scale.mdx @@ -0,0 +1,40 @@ +--- +title: "Ensuring Releases Perform at Scale" +--- +<PlanAvailability slug="entry-ent" /> + +To ensure each release of Mattermost upholds our high standards for performance at scale, the Mattermost Engineering team performs thorough load testing, develops features with scale in mind, and follows strict guidelines for database schema migrations. + +## Monthly release load tests + +Each month, before being approved for distribution, a release candidate of Mattermost is load tested via a comprehensive and mature set of [load test tooling](https://github.com/mattermost/mattermost-load-test-ng) using simulated data that matches real-world, high-scale usage patterns. + +Multiple tests covering different configurations are run against highly-available deployments of Mattermost with thousands of users and millions of posts. Both PostgreSQL and MySQL are tested, although MySQL tests will be dropped when [MySQL goes out of support with Mattermost v11](/product-overview/deprecated-features#mattermost-server-v10-0-0). + +The load tests generate a report detailing average API request times, database I/O, memory usage, concurrency, requests per second, and more. This performance report on the release candidate is then compared to the report of the latest previous stable version. Any deviations are investigated and remedied before the release candidate is promoted to the final release. + +Each report, along with analysis, is posted into the public [Developers: Performance](https://community.mattermost.com/core/channels/developers-performance) channel. + +## Developing scalable features and systems + +Scale is a major consideration during the development of new features and systems, and it's included in technical specifications from the beginning of the software design process. + +As a part of implementation, the load test agent is updated to include coverage for the feature or system. A load test is then run with results being compared to baselines. + +The code changes are then reviewed by at least two developers and a SDET/QA analyst before being merged. + +Once merged, a new build is created and deployed the next day to the [Mattermost Community Server](https://community.mattermost.com) where any impacts on performance are monitored for 3-4 weeks before the changes are included in a release candidate. + +## Database schema changes + +Database schema changes are kept to a minimum to reduce risk on upgrades and impact on performance. When a change in schema is required, Mattermost follows [strict migration guidelines](https://developers.mattermost.com/contribute/more-info/server/schema-migration-guide/) that minimize risk and prevents performance impact during and after migrations. + +If a more involved migration is required, detailed analysis is performed and published with guidance. An example analysis is the [Mattermost v6.0 schema migration](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055). + +Additionally, all database schema changes are load tested as a part of our monthly release process. + +## Monitoring post-release + +After a new version of Mattermost is released, it is rolled out to Mattermost Cloud customers over a multi-week period. During roll out, performance and error rate metrics are monitored for any unexpected changes. If any user-impacting changes are observed, the release is reverted and the deviations are investigated with any fixes being delivered as a part of patch release. + +In addition, Mattermost channels, user forums, and support tickets are closely monitored for reports of any issues. Any reports are investigated and resolved appropriately. diff --git a/docs/main/administration-guide/scale/enterprise-search.mdx b/docs/main/administration-guide/scale/enterprise-search.mdx new file mode 100644 index 000000000000..34d18fa5cda4 --- /dev/null +++ b/docs/main/administration-guide/scale/enterprise-search.mdx @@ -0,0 +1,179 @@ +--- +title: "Enterprise search" +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost database search starts to show performance degradation at around 2 million posts, on a server with 32 GB RAM and 4 CPUs. If you anticipate your Mattermost server reaching more than 2.5 million posts, we recommend enabling [Elasticsearch](#elasticsearch) or [AWS OpenSearch Service](#aws-opensearch-service) for optimum search performance **before** reaching 3 million posts. Both tools are highly capable and can handle enterprise-scale workloads. The choice between them depends on the following factors: + +- **Licensing and cost**: AWS OpenSearch may be preferable for organizations avoiding proprietary licensing or opting for cost-effective solutions. +- **Feature requirements**: Elasticsearch's proprietary features (e.g., advanced analytics, security suites) may be preferred by organizations needing powerful out-of-the-box functionality. +- **Infrastructure alignment**: AWS OpenSearch aligns well with AWS-centric environments, while Elasticsearch offers broader integrations. + +## Elasticsearch + +Elasticsearch is a well-established and widely used search engine with a large ecosystem and community support that provides enterprise-scale deployments with optimized search performance, dedicated indexing, and usage resourcing via cluster support for fast, predicable search results. + +Mattermost's implementation uses [Elasticsearch](https://www.elastic.co) as a distributed, RESTful search engine supporting highly efficient database searches in a [cluster environment](/administration-guide/scale/high-availability-cluster-based-deployment). Learn more about [setting up and configuring Mattermost for an Elasticsearch server](/administration-guide/scale/elasticsearch-setup). + +## AWS OpenSearch Service + +AWS OpenSearch Service is the official path forward from Elasticsearch v7.10.x for AWS customers. It's a fully managed service that makes it easy to deploy, operate, and scale OpenSearch clusters in the AWS Cloud to provide a simple and cost-effective way to search, analyze, and visualize data in real time. + +The AWS OpenSearch Service is built on the open-source OpenSearch project, which is a community-driven fork of Elasticsearch. Learn more about [setting up and configuring Mattermost for an OpenSearch server](/administration-guide/scale/opensearch-setup). + +## Supported paths + +Review the following support paths for enterprise search based on the version you're using: + +<div class="tab"> + +Elasticsearch v8 + +[Elasticsearch v8](https://www.elastic.co/guide/en/elasticsearch/reference/current/elasticsearch-intro.html) is supported from Mattermost v9.11. While Mattermost supports Elasticsearch v7.17+, we recommend upgrading your Elasticsearch v7 instance to v8.x. See the [Elasticsearch upgrade](https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html) documentation for upgrade details, and see the [Elasticsearch setup](/administration-guide/scale/elasticsearch-setup) documentation for details on configuring your Mattermost deployment to use Elasticsearch. + +</div> + +<div class="tab"> + +AWS OpenSearch Service + +AWS OpenSearch Service is the official path forward from Elasticsearch v7.10.x for AWS customers to provide a simple and cost-effective way to search, analyze, and visual data in real time. It's essentially a continuation of Elasticsearch v7.10.x but maintained as open source by AWS. It provides long-term support, active development, and compatibility with AWS clients, libraries, and managed services. + +See the **AWS Elasticsearch v7.10.x** tab on this page for details on upgrading to AWS OpenSearch, and see the [AWS OpenSearch setup](/administration-guide/scale/opensearch-setup) documentation for details on configuring your Mattermost deployment to use AWS OpenSearch. + +</div> + +<div class="tab"> + +AWS Elasticsearch v7.10.x + +If you're using Elasticsearch v7.10.x under AWS’s managed services, you can't use newer Elasticsearch clients like the v8 client without changing backend infrastructure. If you're using AWS Elasticsearch v7.10.x, you must [upgrade to AWS OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/version-migration.html) for future compatibility. + +The migration path from Elasticsearch v7.10.x to OpenSearch has been designed to be straightforward, minimizing effort: + +1. Disable "compatibility mode" in OpenSearch. +2. Upgrade Mattermost server. +3. Update the Mattermost `ElasticsearchSettings.Backend` configuration setting value from `elasticsearch` to `` `opensearch ``<code> manually or using \`mmctl \<mm-ref:administration-guide%2Fmanage%2Fmmctl-command-line-tool%3Ammctl%20config%20set\></code>\_\_. This value cannot be changed using the System Console. See the Mattermost search [backend type](/administration-guide/configure/environment-configuration-settings#backend-type) configuration setting documentation for additional details. +4. Restart the Mattermost server. + +</div> + +## Frequently asked questions (FAQ) + +### Do I need to use Elasticsearch or AWS OpenSearch? + +No. Enterprise search engines are designed for large Enterprise deployments to run highly efficient database searches in a cluster environment. The default Mattermost database search starts to show performance degradation at around 2.5 million posts, depending on the specifications for the database server. If you expect your Mattermost server to have more than 2.5 million posts, we recommend using Elasticsearch or AWS OpenSearch for optimum search performance. + +### Should I install Elasticsearch or OpenSearch on the same machine as Mattermost Server? + +No. We strongly recommend that you install Elasticsearch or AWS OpenSearch on a dedicated machine that's separate from the Mattermost server. + +### What types of indexes are created? + +Mattermost creates three types of indexes: users, channels, and posts. Users and channels have one index each. Posts are aggregated by date, into multiple indexes. + +### Can I pause an search indexing job? + +Yes. From Mattermost v6.7, the search indexing job is resumable. Stopping a server while the search indexing job is running puts the job in pending status. The job resumes when the server restarts. System admins can cancel an indexing job through the System Console. + +### Can an index rollover policy be defined? + +The [AggregatePostsAfterDays](/administration-guide/configure/environment-configuration-settings#aggregate-search-indexes) configuration setting defines a cutoff value. All posts preceding this value are reindexed and aggregated into new and bigger indexes. The default setting is 365 days. + +### Are there any new search features offered with Elasticsearch? + +The current implementation of Elasticsearch matches the search features currently available with database search. The Mattermost team is working on extending the Elasticsearch feature set with file name and content search, date filters, and operators and modifiers. + +### Are my files stored in Elasticsearch or OpenSearch? + +No, files and attachments are not stored. + +### How do I monitor system health of an Elasticsearch server? + +You can use this Prometheus exporter to monitor [various metrics](https://github.com/justwatchcom/elasticsearch_exporter#metrics) about Elasticsearch: [justwatchcom/elasticsearch_exporter](https://github.com/justwatchcom/elasticsearch_exporter). + +You can also refer to this [article about Elasticsearch performance monitoring](https://www.datadoghq.com/blog/monitor-elasticsearch-performance-metrics/#key-elasticsearch-performance-metrics-to-monitor). It's not written specifically for Prometheus, which [Mattermost's performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) system uses, but has several tips and best practices. + +### What form of data is sent to Elasticsearch or OpenSearch? + +Mattermost communicates with Elasticsearch or OpenSearch through its REST API using JSON messages for indexing and querying entities. + +### How much data is sent to Elasticsearch or OpenSearch and when? + +Every time a message is published, a channel is created, or a user changes, (either because their properties change e.g.: change of the first name or because they join/leave a channel), the data associated with that event is sent to Elasticsearch or OpenSearch. + +If search via Elasticsearch or OpenSearch is enabled, every search will generate a query. If autocompletion is enabled, every user or channel autocompletion associated with writing a message or user search will generate a query. + +### How do I know if a search job fails? + +Mattermost provides the status of each Elasticsearch or OpenSearch indexing job in **System Console \> Environment \> Elasticsearch**. Here you can see if the job succeeded or failed, including the details of the error. + +Failures are returned in the server logs. The error log begins with the string `Failed job` and includes a job_id key/value pair. Search job failures are identified with worker name `EnterpriseElasticsearchAggregator` and `EnterpriseElasticsearchIndexer`. You can optionally create a script that programmatically queries for such failures and notifies the appropriate system. + +### How do I diagnose enterprise search connection issues? + +From Mattermost v11, [Support Packet generation](/administration-guide/manage/admin/generating-support-packet) automatically tests the connection to your configured Elasticsearch or AWS OpenSearch server and includes any connection errors in the Support Packet. This provides valuable diagnostic information including server version, installed plugins, and specific error details if the connection fails. + +The enterprise search connection test results appear in the Support Packet and can help identify configuration issues such as network connectivity problems, authentication failures, or server availability issues. If connection errors are present, they will be clearly documented with specific error messages to aid in troubleshooting. + +### My search indexes won't complete, what should I do? + +If you have an search indexing job that's paused, it's likely your Elasticsearch or OpenSearch server has restarted. If you restart that server, you must also restart Mattermost to ensure jobs are completed. If restarting the Mattermost server does not resolve the issue, [customers with a Mattermost subscription can contact Mattermost Support](https://mattermost.com/support/) for assistance. + +### Do I need to purge first then bulk index each time? + +Yes. Every time you choose to remove old data (purge), you must follow it up with a bulk index operation to repopulate them with new data. When you purge (delete) indices, you are removing the existing data from Elasticsearch. After purging, if you want to repopulate the indices with fresh data, you perform a bulk index operation to rebuild the indices efficiently. The bulk API allows for indexing, deleting, or updating multiple documents in a single request, which is faster and more efficient than processing documents one by one. + +## Required Permissions For Mattermost Service Account + +In "least privilege" environments you may need to further constrain the service account permissions to limit the access your Elasticsearch or AWS OpenSearch service account has. + +The following JSON provides an example of a "least privilege" permission set that allows Mattermost to operate correctly with Elasticsearch or AWS OpenSearch: + +> ``` json +> { +> "cluster_permissions": [ +> "cluster:monitor/*", +> "indices:admin/template/put", +> "indices:data/write/bulk" +> ], +> "index_permissions": [ +> { +> "index_patterns": [ +> "\<IndexPrefix\>*" +> ], +> "allowed_actions": [ +> "indices:admin/get", +> "indices:admin/create", +> "indices:admin/delete", +> "indices:admin/mapping/put", +> "indices:admin/mappings/fields/get*", +> "indices:data/read*", +> "indices:data/write*" +> ] +> } +> ] +> } +> ``` + +A simpler, more flexible, and resilient variant of the above would be: + +``` json +{ + "cluster_permissions": [ + "cluster:monitor/*", + "indices:admin/template/put", + "indices:data/write/bulk" + ], + "index_permissions": [ + { + "index_patterns": [ + "\<IndexPrefix\>*" + ], + "allowed_actions": [ + "indices:*" + ] + } + ] +} +``` diff --git a/docs/main/administration-guide/scale/estimated-storage-per-user-per-month.mdx b/docs/main/administration-guide/scale/estimated-storage-per-user-per-month.mdx new file mode 100644 index 000000000000..4cb27309572f --- /dev/null +++ b/docs/main/administration-guide/scale/estimated-storage-per-user-per-month.mdx @@ -0,0 +1,15 @@ +--- +--- +File usage per user varies significantly across industries. The below benchmarks are recommended: + +- **Low usage teams** (1-5 MB/user/month) + +> - Primarily using text messages and links to communicate. Examples would include software development teams that heavily use web-based document creation and management tools, and therefore rarely upload files to the server. + +- **Medium usage teams** (5-25 MB/user/month) + +> - Using a mix of text messages as well as shared documents and images to communicate. Examples might include business teams that may commonly drag and drop screenshots, PDFs and Microsoft Office documents into Mattermost for sharing and review. + +- **High usage teams** (25-100 MB/user/month) + +> - Heaviest utilization comes from teams uploading a high number of large files into Mattermost on a regular basis. Examples include creative teams who share and store artwork and media with tags and commentary in a pipeline production process. diff --git a/docs/main/administration-guide/scale/high-availability-cluster-based-deployment.mdx b/docs/main/administration-guide/scale/high-availability-cluster-based-deployment.mdx new file mode 100644 index 000000000000..c06cada02d02 --- /dev/null +++ b/docs/main/administration-guide/scale/high-availability-cluster-based-deployment.mdx @@ -0,0 +1,634 @@ +--- +title: "High availability cluster-based deployment" +--- +<PlanAvailability slug="ent-plus" /> + +A high availability cluster-based deployment enables a Mattermost system to maintain service during outages and hardware failures through the use of redundant infrastructure. + +High availability in Mattermost consists of running redundant Mattermost application servers, redundant database servers, and redundant load balancers. The failure of any one of these components does not interrupt operation of the system. + +Mattermost Enterprise supports: + +1. Clustered Mattermost servers, which minimize latency by: + +- Storing static assets over a global CDN. +- Deploying multiple Mattermost servers to host API communication closer to the location of end users. + +They can also be used to handle scale and failure handoffs in disaster recovery scenarios. + +2. Database read replicas, where replicas can be: + +- Configured as a redundant backup to the active database server. +- Used to scale up the number of concurrent users. +- Deployed closer to the location of end users, reducing latency. + +Moreover, search replicas are also supported to handle search queries. + +![image](/images/architecture_high_availability.png) + +## Deployment guide + +Set up and maintain a high availability cluster-based deployment on your Mattermost servers. This document doesn't cover the configuration of databases in terms of disaster recovery, however, you can refer to the [frequently asked questions (FAQ)](#frequently-asked-questions-faq) section for our recommendations. + +To ensure your instance and configuration are compatible with a high availability cluster-based deployment, please review the [configuration and compatibility](#configuration-and-compatibility) section. + +<Note> + +Back up your Mattermost database and file storage locations before configuring high availability. For more information about backing up, see [backup disaster recovery](/deployment-guide/backup-disaster-recovery). + +</Note> + +1. Set up a new Mattermost server by following one of our **Install Guides**. This server must use an identical copy of the configuration file, `config.json`. Verify the servers are functioning by hitting each independent server through its private IP address. +2. Modify the `config.json` files on both servers to add `ClusterSettings`. See the [high availability cluster-based deployment configuration settings](/administration-guide/configure/environment-configuration-settings#high-availability) documentation for details. +3. Verify the configuration files are identical on both servers then restart each machine in the cluster. +4. Modify your NGINX setup so that it proxies to both servers. For more information about this, see [proxy server configuration](#proxy-server-configuration). +5. Open **System Console \> Environment \> High Availability** to verify that each machine in the cluster is communicating as expected with green status indicators. If not, investigate the log files for any extra information. + +### Add a server to the cluster + +1. Back up your Mattermost database and the file storage location. See the [backup](/deployment-guide/backup-disaster-recovery) documentation for details. +2. Set up a new Mattermost server. This server must use an identical copy of the configuration file, `config.json`. Verify the server is functioning by hitting the private IP address. +3. Modify your NGINX setup to add the new server. +4. Open **System Console \> Environment \> High Availability** to verify that all the machines in the cluster are communicating as expected with green status indicators. If not, investigate the log files for any extra information. + +### Remove a server from the cluster + +1. Back up your Mattermost database and the file storage location. See the [backup](/deployment-guide/backup-disaster-recovery) documentation for details. +2. Modify your NGINX setup to remove the server. For information about this, see [proxy server configuration](/deployment-guide/server/setup-nginx-proxy#manage-the-nginx-process) documentation for details. +3. Open **System Console \> Environment \> High Availability** to verify that all the machines remaining in the cluster are communicating as expected with green status indicators. If not, investigate the log files for any extra information. + +## Configuration and compatibility + +Details on configuring your system for High Availability. + +### Mattermost Server configuration + +#### Configuration settings + +1. High availability is configured in the `ClusterSettings` section of `config.json` and the settings are viewable in the System Console. When high availability is enabled, the System Console is set to read-only mode to ensure all the `config.json` files on the Mattermost servers are always identical. However, for testing and validating a high availability setup, you can set `ReadOnlyConfig` to `false`, which allows changes made in the System Console to be saved back to the configuration file. + +> ``` json +> "ClusterSettings": { +> "Enable": false, +> "ClusterName": "production", +> "OverrideHostname": "", +> "UseIpAddress": true, +> "ReadOnlyConfig": true, +> "GossipPort": 8074 +> } +> ``` +> +> For more details on these settings, see the [high availability configuration settings](/administration-guide/configure/environment-configuration-settings#high-availability) documentation. + +2. Change the process limit to 8192 and the maximum number of open files to 65536. + +> Modify `/etc/security/limits.conf` on each machine that hosts a Mattermost server by adding the following lines: +> +> ``` text +> * soft nofile 65536 +> * hard nofile 65536 +> * soft nproc 8192 +> * hard nproc 8192 +> ``` + +3. Increase the number of WebSocket connections: + +> Modify `/etc/sysctl.conf` on each machine that hosts a Mattermost server by adding the following lines: +> +> ``` text +> # Extending default port range to handle lots of concurrent connections. +> net.ipv4.ip_local_port_range = 1025 65000 +> +> # Lowering the timeout to faster recycle connections in the FIN-WAIT-2 state. +> net.ipv4.tcp_fin_timeout = 30 +> +> # Reuse TIME-WAIT sockets for new outgoing connections. +> net.ipv4.tcp_tw_reuse = 1 +> +> # Bumping the limit of a listen() backlog. +> # This is maximum number of established sockets (with an ACK) +> # waiting to be accepted by the listening process. +> net.core.somaxconn = 4096 +> +> # Increasing the maximum number of connection requests which have +> # not received an acknowledgment from the client. +> # This is helpful to handle sudden bursts of new incoming connections. +> net.ipv4.tcp_max_syn_backlog = 8192 +> +> # This is tuned to be 2% of the available memory. +> vm.min_free_kbytes = 167772 +> +> # Disabling slow start helps increasing overall throughput +> # and performance of persistent single connections. +> net.ipv4.tcp_slow_start_after_idle = 0 +> +> # These show a good performance improvement over defaults. +> # More info at https://blog.cloudflare.com/http-2-prioritization-with-nginx/ +> net.ipv4.tcp_congestion_control = bbr +> net.core.default_qdisc = fq +> net.ipv4.tcp_notsent_lowat = 16384 +> +> # TCP buffer sizes are tuned for 10Gbit/s bandwidth and 0.5ms RTT (as measured intra EC2 cluster). +> # This gives a BDP (bandwidth-delay-product) of 625000 bytes. +> # The maximum socket buffer size for kernel autotuning is set to be 4x the BDP (2500000). +> # The default socket buffer size is set to 1/4 BDP (156250). +> net.ipv4.tcp_rmem = 4096 156250 2500000 +> net.ipv4.tcp_wmem = 4096 156250 2500000 +> +> # Bumping the theoretical maximum buffer size of receiving/sending sockets, +> # either UDP, or TCP not using autotuning (i.e. using SO_RCVBUF) +> net.core.rmem_max = 16777216 +> net.core.wmem_max = 16777216 +> ``` + +You can do the same for the proxy server. + +#### Cluster discovery + +If you have non-standard (i.e. complex) network configurations, then you may need to use the [Override Hostname](/administration-guide/configure/environment-configuration-settings#override-hostname) setting to help the cluster nodes discover each other. The cluster settings in the config are removed from the config file hash for this reason, meaning you can have `config.json` files that are slightly different in high availability mode. The Override Hostname is intended to be different for each clustered node in `config.json` if you need to force discovery. + +If `UseIpAddress` is set to `true`, it attempts to obtain the IP address by searching for the first non-local IP address (non-loop-back, non-localunicast, non-localmulticast network interface). It enumerates the network interfaces using the built-in go function [net.InterfaceAddrs()](https://pkg.go.dev/net#InterfaceAddrs). Otherwise it tries to get the hostname using the [os.Hostname()](https://pkg.go.dev/os#Hostname) built-in go function. + +You can also run `SELECT * FROM ClusterDiscovery` against your database to see how it has filled in the **Hostname** field. That field will be the hostname or IP address the server will use to attempt contact with other nodes in the cluster. We attempt to make a connection to the `url Hostname:Port` and `Hostname:PortGossipPort`. You must also make sure you have all the correct ports open so the cluster can gossip correctly. These ports are under `ClusterSettings` in your configuration. + +In short, you should use: + +1. IP address discovery if the first non-local address can be seen from the other machines. +2. Override Hostname on the operating system so that it's a proper discoverable name for the other nodes in the cluster. +3. Override Hostname in `config.json` if the above steps do not work. You can put an IP address in this field if needed. The `config.json` will be different for each cluster node. + +#### Time synchronization + +Each server in the cluster must have the Network Time Protocol daemon `ntpd` running so that messages are posted in the correct order. + +#### State + +The Mattermost server is designed to have very little state to allow for horizontal scaling. The items in state considered for scaling Mattermost are listed below: + +- In memory session cache for quick validation and channel access. +- In memory online/offline cache for quick response. +- System configuration file that is loaded and stored in memory. +- WebSocket connections from clients used to send messages. + +When the Mattermost server is configured for high availability, the servers use an inter-node communication protocol on a different listening address to keep the state in sync. When a state changes it is written back to the database and an inter-node message is sent to notify the other servers of the state change. The true state of the items can always be read from the database. Mattermost also uses inter-node communication to forward WebSocket messages to the other servers in the cluster for real-time messages such as “\[User X\] is typing.” + +#### Proxy server configuration + +The proxy server exposes the cluster of Mattermost servers to the outside world. The Mattermost servers are designed for use with a proxy server such as NGINX, a hardware load balancer, or a cloud service like Amazon Elastic Load Balancer. + +If you want to monitor the server with a health check you can use `http://10.10.10.2/api/v4/system/ping` and check the response for `Status 200`, indicating success. Use this health check route to mark the server *in-service* or *out-of-service*. + +A sample configuration for NGINX is provided below. It assumes that you have two Mattermost servers running on private IP addresses of `10.10.10.2` and `10.10.10.4`. + +``` text +upstream backend { + server 10.10.10.2:8065; + server 10.10.10.4:8065; + keepalive 256; +} + +proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:50m max_size=16g inactive=60m use_temp_path=off; + +server { + listen 80 reuseport; + server_name mattermost.example.com; + + location ~ /api/v[0-9]+/(users/)?websocket$ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + client_max_body_size 100M; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + client_body_timeout 60s; + send_timeout 300s; + lingering_timeout 5s; + proxy_connect_timeout 30s; + proxy_send_timeout 90s; + proxy_read_timeout 90s; + proxy_http_version 1.1; + proxy_pass http://backend; + } + + location / { + proxy_set_header Connection ""; + client_max_body_size 100M; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + client_body_timeout 60s; + send_timeout 300s; + lingering_timeout 5s; + proxy_connect_timeout 30s; + proxy_send_timeout 90s; + proxy_read_timeout 90s; + proxy_http_version 1.1; + proxy_pass http://backend; + proxy_cache mattermost_cache; + proxy_cache_revalidate on; + proxy_cache_min_uses 2; + proxy_cache_use_stale timeout; + proxy_cache_lock on; + } +} +``` + +You can use multiple proxy servers to limit a single point of failure, but that is beyond the scope of this documentation. + +#### File storage configuration + +<Note> + +1. File storage is assumed to be shared between all the machines that are using services such as NAS or Amazon S3. +2. If `"DriverName": "local"` is used then the directory at `"FileSettings":` `"Directory": "./data/"` is expected to be a NAS location mapped as a local directory, otherwise high availability will not function correctly and may corrupt your file storage. +3. If you're using Amazon S3 or another S3-compatible service for file storage then no other configuration is required. + +</Note> + +If you’re using the Compliance Reports feature in Mattermost Enterprise, you need to configure the `"ComplianceSettings":` `"Directory": "./data/",` to share between all machines or the reports will only be available from the System Console on the local Mattermost server. + +Migrating to NAS or S3 from local storage is beyond the scope of this document. + +#### Database configuration + +<Tip> + +Specifying configuration setting values using Mattermost environment variables ensure that they always take precedent over any other configuration settings. + +</Tip> + +For an AWS High Availability RDS cluster deployment, point the [datasource](/administration-guide/configure/environment-configuration-settings#data-source) configuration setting to the write/read endpoint at the **cluster** level to benefit from the AWS failover handling. AWS takes care of promoting different database nodes to be the writer node. Mattermost doesn't need to manage this. + +Use the [read replica](/administration-guide/configure/environment-configuration-settings#read-replicas) feature to scale the database. The Mattermost server can be set up to use one master database and one or more read replica databases. + +<Note> + +For an AWS High Availability RDS cluster deployment, don't hard-code the IP addresses. Point this configuration setting to the write/read endpoint at the **cluster** level. This will benefit from the AWS failover handling where AWS takes care of promoting different database nodes to be the writer node. Mattermost doesn't need to manage this. + +</Note> + +On large deployments, also consider using the [search replicas](/administration-guide/configure/environment-configuration-settings#search-replicas) feature to isolate search queries onto one or more search replicas. A search replica is similar to a read replica, but is used only for handling search queries. + +<Note> + +For an AWS High Availability RDS cluster deployment, don't hard-code the IP addresses. Point this configuration setting directly to the underlying read-only node endpoints within the RDS cluster. We recommend circumventing the failover/load balancing that AWS/RDS takes care of (except for the write traffic), and populating the `DataSourceReplicas` array with the RDS reader node endpoints. Mattermost has its own method of balancing the read-only connections, and can also balance those queries to the DataSource/write+read connection should those nodes fail. + +</Note> + +Mattermost distributes queries as follows: + +- All write requests, and some specific read requests, are sent to the master. +- All other read requests (excluding those specific queries that go to the master) are distributed among the available read replicas. If no read replicas are available, these are sent to the master instead. +- Search requests are distributed among the available search replicas. If no search replicas are available, these are sent to the read replicas instead (or, if no read replicas are available, to the master). + +##### Size the databases + +For information about sizing database servers, see [hardware-sizing-for-enterprise](#hardware-sizing-for-enterprise). + +In a master/slave environment, make sure to size the slave machine to take 100% of the load in the event that the master machine goes down and you need to fail over. + +##### Deploy a multi-database configuration + +To configure a multi-database Mattermost server: + +1. Update the `DataSource` setting in `config.json` with a connection string to your master database server. +2. Update the `DataSourceReplicas` setting in `config.json` with a series of connection strings to your database read replica servers in the format `["readreplica1", "readreplica2"]`. Each connection should also be compatible with the `DriverName` setting. + +Here's an example `SqlSettings` block for one master and two read replicas: + +``` json +"SqlSettings": { + "DriverName": "mysql", + "DataSource": "master_user:master_password@tcp(master.server)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s", + "DataSourceReplicas": ["slave_user:slave_password@tcp(replica1.server)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s","slave_user:slave_password@tcp(replica2.server)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s"], + "DataSourceSearchReplicas": [], + "MaxIdleConns": 50, + "MaxOpenConns": 100, + "Trace": false, + "AtRestEncryptKey": "", + "QueryTimeout": 30 + } +``` + +The new settings can be applied by either stopping and starting the server, or by loading the configuration settings as described in the next section. + +Once loaded, database write requests are sent to the master database and read requests are distributed among the other databases in the list. + +##### Load a multi-database configuration onto an active server + +After a multi-database configuration has been defined in `config.json`, the following procedure can be used to apply the settings without shutting down the Mattermost server: + +1. Go to **System Console \> Environment \> Web Server**, then select **Reload Configuration from Disk** to reload configuration settings for the Mattermost server from `config.json`. +2. Go to **System Console \> Environment \> Database**, then select **Recycle Database Connections** to take down existing database connections and set up new connections in the multi-database configuration. + +While the connection settings are changing, there might be a brief moment when writes to the master database are unsuccessful. The process waits for all existing connections to finish and starts serving new requests with the new connections. End users attempting to send messages while the switch is happening will have an experience similar to losing connection to the Mattermost server. + +##### Manual failover for master database + +If the need arises to switch from the current master database - for example, if it is running out of disk space, or requires maintenance updates, or for other reasons - you can switch Mattermost server to use one of its read replicas as a master database by updating `DataSource` in `config.json`. + +To apply the settings without shutting down the Mattermost server: + +1. Go to **System Console \> Environment \> Web Server**, then select **Reload Configuration from Disk** to reload configuration settings for the Mattermost server from `config.json`. +2. Go to **System Console \> Environment \> Database**, then select **Recycle Database Connections** to take down existing database connections and set up new connections in the multi-database configuration. + +While the connection settings are changing, there might be a brief moment when writes to the master database are unsuccessful. The process waits for all existing connections to finish and starts serving new requests with the new connections. End users attempting to send messages while the switch is happening can have an experience similar to losing connection to the Mattermost server. + +##### Transparent failover + +The database can be configured for high availability and transparent failover use the existing database technologies. We recommend PostgreSQL Clustering or Amazon Aurora. Database transparent failover is beyond the scope of this documentation. + +##### Recommended configuration settings for PostgreSQL + +For the Postgres service we recommend the following configuration optimizations on your Mattermost server. These configurations were tested on an AWS Aurora r5.xlarge instance. There are also some general optimizations mentioned which requires servers with higher specifications. + +**Config for Postgres Primary or Writer node** + +``` sh +# If the instance is lower capacity than r5.xlarge, then set it to a lower number. +# Also tune the "MaxOpenConns" setting under the "SqlSettings" of the Mattermost app accordingly. +# Note that "MaxOpenConns" on Mattermost is per data source name. +# Recommended: MaxOpenConns: 100, MaxIdleConns: 50 (2:1 ratio) +max_connections = 1024 + +# Set it to 1.1, unless the DB is using spinning disks. +random_page_cost = 1.1 + +# This should be 32MB if using read replicas, or 16MB if using a single PostgreSQL instance. +# If the instance is of a lower capacity than r5.xlarge, then set it to a lower number. +work_mem = 32MB + +# Set both of the below settings to 65% of total memory. For a 32 GB instance, it should be 21 GB. +# If on a smaller server, set this to 20% or less total RAM. +# ex: 512MB would work for a 4GB RAM server +effective_cache_size = 21GB +shared_buffers = 21GB + +# If you are using pgbouncer, or any similar connection pooling proxy, +# in front of your DB, then apply the keepalive settings to the proxy instead, +# and revert the keepalive settings for the DB back to defaults. +tcp_keepalives_idle = 5 +tcp_keepalives_interval = 1 +tcp_keepalives_count = 5 + +# 1GB (reduce this to 512MB if your server has less than 32GB of RAM) +maintenance_work_mem = 512MB + +autovacuum_max_workers = 4 +autovacuum_vacuum_cost_limit = 500 + +# If you have more than 32 CPUs on your database server, please set the following options to utilize more CPU for your server: +max_worker_processes = 12 +max_parallel_workers_per_gather = 4 +max_parallel_workers = 12 +max_parallel_maintenance_workers = 4 +``` + +**Config for Postgres Replica node** + +Copy all the above settings to the read replica, and modify or add only the below. + +``` sh +# If the instance is lower capacity than r5.xlarge, then set it to a lower number. +# Also tune the "MaxOpenConns" setting under the "SqlSettings" of the Mattermost app accordingly. +# Note that "MaxOpenConns" on Mattermost is per data source name. +# Recommended: MaxOpenConns: 100, MaxIdleConns: 50 (2:1 ratio) +max_connections = 1024 + +# This setting should be 16MB on read nodes, and 32MB on writer nodes +work_mem = 16MB + +# The below settings allow the reader to return query results even when the primary has a write process running, a query conflict. +# This is set to on because of the high volume of write traffic that can prevent the reader from returning query results within the timeout. +# https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT +hot_standby = on +hot_standby_feedback = on +``` + +**A note on vacuuming** + +Performance of a Postgres database is particularly sensitive to [vacuuming and analyzing](https://www.postgresql.org/docs/current/sql-vacuum.html). A good way to check how frequently tables are vacuumed is with this query: + +``` sql +SELECT relname, n_tup_ins as inserts,n_tup_upd as updates,n_tup_del as deletes, n_live_tup as live_tuples, n_dead_tup as dead_tuples, n_mod_since_analyze, last_autovacuum, last_autoanalyze, autovacuum_count, autoanalyze_count FROM pg_stat_user_tables order by dead_tuples desc LIMIT 10; +``` + +The output of this query will indicate which tables have accumulated the most dead tuples. You can also look at the `last_autovacuum` and `last_autoanalyze` columns to see when the last autovacuum or autoanalyze ran. + +Depending on those values, you can choose to tune table-specific values for autovacuum or autoanalyze thresholds. For example, if you see more than 50,000 dead tuples on a table, and it hasn't been vacuumed or analyzed in the last 6 months, there's a good chance that it would benefit from more aggressive vacuuming. In that case, you can run this to tune your tables: + +``` sql +ALTER TABLE <table> SET ( + autovacuum_vacuum_scale_factor = 0.1, -- default is 0.2 + autovacuum_analyze_scale_factor = 0.05, -- default is 0.1 + autovacuum_vacuum_cost_limit = 1000 -- default is 200 +); +``` + +Feel free to choose different values as necessary. Refer to [https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM) for more information on how does Postgres calculate when to run vacuuming. Re-run the initial SQL query from time to time and adjust values accordingly. + +#### Leader election + +A cluster leader election process assigns any scheduled task such as LDAP sync to run on a single node in a multi-node cluster environment. + +The process is based on a widely used [bully leader election algorithm](https://en.wikipedia.org/wiki/Bully_algorithm) where the process with the lowest node ID number from amongst the non-failed processes is selected as the leader. + +<Note> + +From Mattermost v11.4, debug-level log messages help identify which node is executing specific Recurring Tasks (Scheduled Posts, Post Reminders, and DND Status Reset). Non-leader nodes log messages like `Skipping scheduled posts job startup since this is not the leader node` to indicate they are correctly deferring execution of these Recurring Tasks to the leader. These are normal operational messages, not errors. These debug messages do not apply to other job types such as Elasticsearch indexing, SAML sync, or LDAP sync. See [Cluster job execution debug messages](/administration-guide/manage/logging#cluster-job-execution-debug-messages) for details. + +</Note> + +#### Job server + +Mattermost runs periodic tasks via the [job server](/administration-guide/configure/experimental-configuration-settings#experimental-job-configuration-settings). These tasks include: + +- LDAP sync +- Data retention +- Compliance exports +- Elasticsearch indexing +- Scheduled posts +- DND status reset +- Post reminders + +Make sure you have set `JobSettings.RunScheduler` to `true` in `config.json` for all app and job servers in the cluster. The cluster leader will then be responsible for scheduling recurring jobs. + +<Note> + +- We strongly recommend not changing this setting from the default setting of `true` as this prevents the `ClusterLeader` from being able to run the scheduler. As a result, recurring jobs such as LDAP sync, Compliance Export, and data retention will no longer be scheduled. In previous Mattermost Server versions, and this documentation, the instructions stated to run the Job Server with `RunScheduler: false`. The cluster design has evolved and this is no longer the case. +- From Mattermost v11.4, you can verify that Recurring Tasks (Scheduled Posts, Post Reminders, and DND Status Reset) are running on the correct node by enabling debug logging. Non-leader nodes will log messages indicating they are skipping execution of these specific Recurring Tasks, which is expected behavior. These debug messages don't apply to other job types. See [Cluster job execution debug messages](/administration-guide/manage/logging#cluster-job-execution-debug-messages) for more information. + +</Note> + +#### Plugins and High Availability + +When you install or upgrade a plugin, it's propagated across the servers in the cluster automatically. File storage is assumed to be shared between all the servers, using services such as NAS or Amazon S3. + +If `"DriverName": "local"` is used then the directory at `"FileSettings":` `"Directory": "./data/"` is expected to be a NAS location mapped as a local directory. If this is not the case High Availability will not function correctly and may corrupt your file storage. + +When you reinstall a plugin in v5.14, the previous **Enabled** or **Disabled** state is retained. As of v5.15, a reinstalled plugin's initial state is **Disabled**. + +#### CLI and High Availability + +The CLI is run in a single node which bypasses the mechanisms that a [high availability environment](/administration-guide/scale/high-availability-cluster-based-deployment) uses to perform actions across all nodes in the cluster. As a result, when running [CLI commands](/administration-guide/manage/command-line-tools) in a High Availability environment, tasks such as updating and deleting users or changing configuration settings require a server restart. + +We recommend using [mmctl](/administration-guide/manage/mmctl-command-line-tool) in a high availability environment instead since a server restart is not required. These changes are made through the API layer, so the node receiving the change request notifies all other nodes in the cluster. + +## Upgrade guide + +An update is an incremental change to Mattermost server that fixes bugs or performance issues. An upgrade adds new or improved functionality to the server. + +<Tip> + +To learn how to safely upgrade your deployment in Kubernetes for High Availability and Active/Active support, see the [Upgrading Mattermost in Kubernetes and High Availability Environments](/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha) documenation. + +</Tip> + +### Update configuration changes while operating continuously + +A service interruption is not required for most configuration updates. See the section below for details on upgrades requiring service interruption. You can apply updates during a period of low load, but if your high availability cluster-based deployment is sized correctly, you can do it at any time. The system downtime is brief, and depends on the number of Mattermost servers in your cluster. Note that you are not restarting the machines, only the Mattermost server applications. A Mattermost server restart generally takes about five seconds. + +<Note> + +Don't modify configuration settings through the System Console, otherwise you'll have two servers with different `config.json` files in a high availability cluster-based deployment causing a refresh every time a user connects to a different app server. + +</Note> + +1. Make a backup of your existing `config.json` file. +2. For one of the Mattermost servers, make the configuration changes to `config.json` and save the file. Do not reload the file yet. +3. Copy the `config.json` file to the other servers. +4. Shut down Mattermost on all but one server. +5. Reload the configuration file on the server that is still running. Go to **System Console \> Environment \> Web Server**, then select **Reload Configuration from Disk**. +6. Start the other servers. + +### Update the Server version while operating continuously + +A service interruption is not required for security patch dot releases of Mattermost Server. You can apply updates during a period when the anticipated load is small enough that one server can carry the full load of the system during the update. + +<Note> + +Mattermost supports one minor version difference between the server versions when performing a rolling upgrade (for example v5.27.1 + v5.27.2 or v5.26.4 + v5.27.1 is supported, whereas v5.25.5 + v5.27.0 is not supported). Running two different versions of Mattermost in your cluster should not be done outside of an upgrade scenario. + +</Note> + +When restarting, you aren't restarting the machines, only the Mattermost server applications. A Mattermost server restart generally takes about five seconds. + +1. Review the upgrade procedure in the *Upgrade Enterprise Edition* section of [upgrading mattermost server](/administration-guide/upgrade/upgrading-mattermost-server). +2. Make a backup of your existing `config.json` file. +3. Set your proxy to move all new requests to a single server. If you are using NGINX and it's configured with an upstream backend section in `/etc/nginx/sites-available/mattermost` then comment out all but the one server that you intend to update first, and reload NGINX. +4. Shut down Mattermost on each server except the one that you are updating first. +5. Update each Mattermost instance that is shut down. +6. On each server, replace the new `config.json` file with your backed up copy. +7. Start the Mattermost servers. +8. Repeat the update procedure for the server that was left running. + +### Server upgrades requiring service interruption + +A service interruption is required when the upgrade includes a change to the database schema or when a change to `config.json` requires a server restart, such as when making the following changes: + +- Default server language +- Rate limiting +- Webserver mode +- Database +- High availability + +If the upgrade includes a change to the database schema, the database is upgraded by the first server that starts. + +Apply upgrades during a period of low load. The system downtime is brief, and depends on the number of Mattermost servers in your cluster. Note that you are not restarting the machines, only the Mattermost server applications. + +1. Review the upgrade procedure in the *Upgrade Enterprise Edition* section of [upgrading mattermost server](/administration-guide/upgrade/upgrading-mattermost-server). +2. Make a backup of your existing `config.json` file. +3. Stop NGINX. +4. Upgrade each Mattermost instance. +5. On each server, replace the new `config.json` file with your backed up copy. +6. Start one of the Mattermost servers. +7. When the server is running, start the other servers. +8. Restart NGINX. + +### All cluster nodes must use a single protocol + +All cluster traffic uses the gossip protocol. [Gossip clustering can no longer be disabled](/administration-guide/configure/deprecated-configuration-settings#use-gossip). + +When upgrading a high availability cluster-based deployment, you can't upgrade other nodes in the cluster when one node isn't using the gossip protocol. You must use gossip to complete this type of upgrade. Alternatively you can shut down all nodes and bring them all up individually following an upgrade. + +## Requirements for continuous operation + +To enable continuous operation at all times, including during server updates and server upgrades, you must make sure that the redundant components are properly sized and that you follow the correct sequence for updating each of the system's components. + +Redundancy at anticipated scale +Upon failure of one component, the remaining application servers, database servers, and load balancers must be sized and configured to carry the full load of the system. If this requirement is not met, an outage of one component can result in an overload of the remaining components, causing a complete system outage. + +Update sequence for continuous operation +You can apply most configuration changes and dot release security updates without interrupting service, provided that you update the system components in the correct sequence. See the [upgrade guide](#upgrade-guide) for instructions on how to do this. + +**Exception:** Changes to configuration settings that require a server restart, and server version upgrades that involve a change to the database schema, require a short period of downtime. Downtime for a server restart is around five seconds. For a database schema update, downtime can be up to 30 seconds. + +<Important> + +Mattermost does not support high availability deployments spanning multiple datacenters. All nodes in a high availability cluster must reside within the same datacenter to ensure proper functionality and performance. + +</Important> + +## Frequently asked questions (FAQ) + +### Does Mattermost support multi-region high availability cluster-based deployment? + +Yes. Although not officially tested, you can set up a cluster across AWS regions, for example, and it should work without issues. + +### What does Mattermost recommend for disaster recovery of the databases? + +When deploying Mattermost in a high availability configuration, we recommend using a database load balancer between Mattermost and your database. Depending on your deployment this needs more or less consideration. + +For example, if you're deploying Mattermost on AWS with Amazon Aurora we recommend utilizing multiple Availability Zones. If you're deploying Mattermost on your own cluster please consult with your IT team for a solution best suited for your existing architecture. + +### How to find the hostname of the connected websocket? + +From Mattermost v10.4, Enterprise customers running self-hosted deployments can go to the **Product** menu <img src="/img/ui/products_E82F.svg" alt="Navigate between Channels, collaborative playbooks, and boards using the product menu icon." className="theme-icon" /> and select **About Mattermost** to see the hostname of the node in the cluster running Mattermost. + +## Troubleshooting + +### Capture high availability troubleshooting data + +When deploying Mattermost in a high availability configuration, we recommend that you keep Prometheus and Grafana metrics as well as cluster server logs for as long as possible - and at minimum two weeks. + +You may be asked to provide this data to Mattermost for analysis and troubleshooting purposes. + +<Note> + +- Ensure that server log files are being created. You can find more on working with Mattermost logs [here](/deployment-guide/server/troubleshooting#review-mattermost-logs). +- When investigating and replicating issues, we recommend opening **System Console \> Environment \> Logging** and setting **File Log Level** to **DEBUG** for more complete logs. Make sure to revert to **INFO** after troubleshooting to save disk space. +- Each server has its own server log file, so make sure to provide server logs for all servers in your High Availability cluster-based deployment. + +</Note> + +### Red server status + +When high availability mode is enabled, the System Console displays the server status as red or green, indicating if the servers are communicating correctly with the cluster. The servers use inter-node communication to ping the other machines in the cluster, and once a ping is established the servers exchange information, such as server version and configuration files. + +A server status of red can occur for the following reasons: + +- **Configuration file mismatch:** Mattermost will still attempt the inter-node communication, but the System Console will show a red status for the server since the high availability mode feature assumes the same configuration file to function properly. +- **Server version mismatch:** Mattermost will still attempt the inter-node communication, but the System Console will show a red status for the server since the high availability mode feature assumes the same version of Mattermost is installed on each server in the cluster. It is recommended to use the [latest version of Mattermost](https://mattermost.com/download/) on all servers. Follow the upgrade procedure in [upgrading mattermost server](/administration-guide/upgrade/upgrading-mattermost-server) for any server that needs to be upgraded. +- **Server is down:** If an inter-node communication fails to send a message it makes another attempt in 15 seconds. If the second attempt fails, the server is assumed to be down. An error message is written to the logs and the System Console shows a status of red for that server. The inter-node communication continues to ping the down server in 15 second intervals. When the server comes back up, any new messages are sent to it. + +### WebSocket disconnect + +When a client WebSocket receives a disconnect it will automatically attempt to re-establish a connection every three seconds with a backoff. After the connection is established, the client attempts to receive any messages that were sent while it was disconnected. + +### App refreshes continuously + +When configuration settings are modified through the System Console, the client refreshes every time a user connects to a different app server. This occurs because the servers have different `config.json` files in a high availability cluster-based deployment. + +Modify configuration settings directly through `config.json` [following these steps](/administration-guide/scale/high-availability-cluster-based-deployment#update-configuration-changes-while-operating-continuously). + +### Messages do not post until after reloading + +When running in high availability mode, make sure all Mattermost application servers are running the same version of Mattermost. If they are running different versions, it can lead to a state where the lower version app server cannot handle a request and the request will not be sent until the frontend application is refreshed and sent to a server with a valid Mattermost version. Symptoms to look for include requests failing seemingly at random or a single application server having a drastic rise in goroutines and API errors. diff --git a/docs/main/administration-guide/scale/lifetime-storage.mdx b/docs/main/administration-guide/scale/lifetime-storage.mdx new file mode 100644 index 000000000000..f889f3725704 --- /dev/null +++ b/docs/main/administration-guide/scale/lifetime-storage.mdx @@ -0,0 +1,7 @@ +--- +--- +To forecast your own storage usage, begin with a Mattermost server approximately 600 MB to 800 MB in size including operating system and database, then add the multiplied product of: + +- Estimated storage per user per month (see below), multiplied by 12 months in a year +- Estimated mean average number of users in a year +- A 1-2x safety factor diff --git a/docs/main/administration-guide/scale/opensearch-setup.mdx b/docs/main/administration-guide/scale/opensearch-setup.mdx new file mode 100644 index 000000000000..1fded5f23fe6 --- /dev/null +++ b/docs/main/administration-guide/scale/opensearch-setup.mdx @@ -0,0 +1,321 @@ +--- +title: "AWS OpenSearch server setup" +--- +import Inc0_common_configure_mattermost_for_enterprise_search from './common-configure-mattermost-for-enterprise-search.mdx'; + +<PlanAvailability slug="ent-plus" /> + +AWS OpenSearch Service allows you to search large volumes of data quickly, in near real-time, by creating and managing an index of post data. The indexing process can be managed from the System Console after setting up and connecting an OpenSearch server. The post index is stored on the OpenSearch server and updated constantly after new posts are made. In order to index existing posts, a bulk index of the entire post database must be generated. + +Deploying AWS OpenSearch includes the following two steps: [setting up AWS OpenSearch](#set-up-aws-opensearch), and [configuring Mattermost](#configure-mattermost). + +## Set up AWS OpenSearch + +From Mattermost v9.11, beta support is available for [AWS OpenSearch v1.x and v2.x](https://opensearch.org/). This document covers both on‑premises and AWS OpenSearch setup, including manual steps and Terraform examples. + +We highly recommend that you set up an AWS OpenSearch server on a separate machine from the Mattermost server. + +<div class="tab" parse-titles=""> + +On-Premises OpenSearch + +1. To install on-premise OpenSearch, provision a dedicated server (e.g. Ubuntu 22.04 LTS). +2. Install Java (OpenSearch requires Java 11+): + +> ``` sh +> sudo apt update +> sudo apt install -y openjdk-11-jdk +> java -version +> ``` + +3. Download & extract OpenSearch 2.x: + +> ``` sh +> wget https://artifacts.opensearch.org/releases/bundle/opensearch/2.9.0/opensearch-2.9.0-linux-x64.tar.gz +> tar -xzf opensearch-2.9.0-linux-x64.tar.gz +> sudo mv opensearch-2.9.0 /usr/share/opensearch +> ``` + +4. Create a dedicated user & set permissions: + +> ``` sh +> sudo useradd --no-create-home --shell /bin/false opensearch +> sudo chown -R opensearch:opensearch /usr/share/opensearch +> ``` + +5. Configure systemd: + +> ``` sh +> [Unit] +> Description=OpenSearch +> Wants=network-online.target +> After=network-online.target +> +> [Service] +> Type=notify +> User=opensearch +> Group=opensearch +> ExecStart=/usr/share/opensearch/bin/opensearch +> Restart=on-failure +> LimitNOFILE=65536 +> LimitNPROC=4096 +> +> [Install] +> WantedBy=multi-user.target +> ``` + +6. Edit `opensearch.yml` to include the following: + +> ``` yaml +> cluster.name: mattermost-cluster +> node.name: node-1 +> path.data: /var/lib/opensearch +> path.logs: /var/log/opensearch +> network.host: 0.0.0.0 +> discovery.seed_hosts: ["<other-node-ip>"] +> cluster.initial_master_nodes: ["node-1", "node-2"] +> ``` +> +> <div class="note"> +> +> <div class="title"> +> +> Note +> +> </div> +> +> Ensure `path.data` and `path.logs` directories exist and are owned by the `opensearch` user before starting the service: +> +> ``` sh +> sudo mkdir -p /var/lib/opensearch /var/log/opensearch +> sudo chown -R opensearch:opensearch /var/lib/opensearch /var/log/opensearch +> ``` +> +> </div> + +7. Enable & start OpenSearch: + +> ``` sh +> sudo systemctl daemon-reload +> sudo systemctl enable opensearch +> sudo systemctl start opensearch +> sudo systemctl status opensearch +> ``` + +8. Install the [icu-analyzer plugin](https://docs.opensearch.org/latest/install-and-configure/additional-plugins/index/) to the `/usr/share/opensearch/plugins` directory by running the following command: + +> ``` sh +> sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-icu +> ``` + +**(Optional) CJK language analyzer plugins**: To improve search for Korean, Japanese, or Chinese content, install one or more of the following language-specific analyzer plugins: `analysis-nori` (Korean), `analysis-kuromoji` (Japanese), and `analysis-smartcn` (Chinese). + +> ``` sh +> sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-nori +> sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-kuromoji +> sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-smartcn +> ``` + +After installing the CJK plugins, restart OpenSearch to load them: + +> ``` sh +> sudo systemctl restart opensearch +> ``` + +Then enable the [EnableCJKAnalyzers](/administration-guide/configure/environment-configuration-settings#enable-cjk-analyzers) configuration setting. See [Enabling Chinese, Japanese, and Korean Search](/administration-guide/configure/enabling-chinese-japanese-korean-search) for additional CJK search configuration options. + +<Important> + +If you enable CJK analyzers on a server with existing indexed content, you must purge and rebuild the search index in **System Console \> Environment \> Elasticsearch** for the CJK analyzers to take effect on existing posts. + +</Important> + +## Terraform (Docker) Example + +``` sh +provider "docker" { + host = "unix:///var/run/docker.sock" +} + +resource "docker_image" "opensearch" { + name = "opensearchproject/opensearch:2.9.0" +} + +resource "docker_container" "opensearch" { + name = "opensearch" + image = docker_image.opensearch.latest + + ports { + internal = 9200 + external = 9200 + } + ports { + internal = 9600 + external = 9600 + } + + env = [ + "cluster.name=mattermost-cluster", + "network.host=0.0.0.0", + "discovery.type=single-node", # remove for multi-node + ] + + restart = "unless-stopped" +} + +resource "null_resource" "install_icu_plugin" { + depends_on = [docker_container.opensearch] + + provisioner "local-exec" { + command = "docker exec opensearch /usr/share/opensearch/bin/opensearch-plugin install analysis-icu && docker restart opensearch" + } +} +``` + +</div> + +<div class="tab" parse-titles=""> + +AWS OpenSearch Console Setup + +1. To install AWS OpenSearch, open the **AWS Console \> OpenSearch Service**. +2. Create a domain, where: + +> - Domain name: `mattermost-os` +> - Engine version: `OpenSearch 2.x`. + +3. Configure the cluster, where: + +> - instance type: `r6g.xlarge.search` +> - data nodes: 2 +> - master nodes: 2 +> - storage: EBS gp3 (1536 GiB, 4608 IOPS, 250 MiB/s) + +4. Specify the network for: VPC with 2 subnets, and a security group allowing Mattermost IPs on port `443`. + +<Note> + +Port 9200 is commonly used for local or on-premise OpenSearch. The AWS OpenSearch domain only supports HTTPS over port 443. + +</Note> + +5. Configure the access policy (JSON): + +> ``` sh +> { +> "Version": "2012-10-17", +> "Statement": [{ +> "Effect": "Allow", +> "Principal": { "AWS": +> "arn:aws:iam::123456789012:role/MattermostAppRole" }, +> "Action": "es:*", +> "Resource": "arn:aws:es:us-east-1:123456789012:domain/mattermost-os/*" }] +> } +> ``` + +6. Configure the following advanced settings (JSON): + +> ``` sh +> { +> "action.destructive_requires_name": "false", +> "rest.action.multi.allow_explicit_index": "true", +> "indices.query.bool.max_clause_count": "1024", +> "indices.fielddata.cache.size": "20" +> } +> ``` + +7. Configure the automated snapshot start hour as 23 (UTC), enforce HTTPS, then review & create. +8. To test, run the following command: + +> ``` sh +> curl https://mattermost-os-xxxxxxxxxxx.us-east-1.es.amazonaws.com +> ``` + +## AWS Terraform Example + +> ``` sh +> provider "aws" { +> region = "us-east-1" +> } +> +> resource "aws_iam_role" "os_service_role" { +> name = "OSServiceRole" +> assume_role_policy = <<EOF +> { +> "Version": "2012-10-17", +> "Statement": [{ +> "Action": "sts:AssumeRole", +> "Effect": "Allow", +> "Principal": { "Service": "es.amazonaws.com" } +> }] +> } +> EOF +> } +> +> resource "aws_opensearch_domain" "mattermost" { +> domain_name = "mattermost-os" +> engine_version = "OpenSearch_2.9" +> cluster_config { +> instance_type = "r6g.xlarge.search" +> instance_count = 2 +> dedicated_master_enabled = true +> dedicated_master_type = "r6g.xlarge.search" +> dedicated_master_count = 2 +> zone_awareness_enabled = true +> } +> +> ebs_options { +> ebs_enabled = true +> volume_type = "gp3" +> volume_size = 1536 +> iops = 4608 +> } +> +> vpc_options { +> subnet_ids = ["subnet-blah1", "subnet-blah2"] +> security_group_ids = ["sg-1234567890"] +> } +> +> advanced_options = { +> "rest.action.multi.allow_explicit_index" = "true" +> "indices.query.bool.max_clause_count" = "1024" +> "indices.fielddata.cache.size" = "20" +> "action.destructive_requires_name" = "false" +> } +> +> access_policies = <<POLICY +> { +> "Version": "2012-10-17", +> "Statement": [{ +> "Effect": "Allow", +> "Principal": { +> "AWS": "arn:aws:iam::123456789012:role/MattermostAppRole" +> }, +> "Action": "es:*", +> "Resource": "arn:aws:es:us-east-1:123456789012:domain/mattermost-os/*" +> }] +> } +> POLICY +> service_software_options { +> automated_snapshot_start_hour = 23 +> } +> +> domain_endpoint_options { +> enforce_https = true +> } +> } +> ``` + +</div> + +## Configure Mattermost + +Follow these steps to configure Mattermost to use your AWS OpenSearch server and to generate the post index: + +1. Go to **System Console \> Environment \> Elasticsearch**. +2. Set **Enable Elasticsearch Indexing** to `true` to enable the other the settings on the page. +3. Ensure **Backend type** is set to `opensearch`. +4. Set the **Server Connection Address** to your Elasticsearch or OpenSearch cluster endpoint. +5. Monitor cluster health: `curl https://mattermost-os-xxxxx.us-east-1.es.amazonaws.com/_cluster/health` + +<Inc0_common_configure_mattermost_for_enterprise_search /> diff --git a/docs/main/administration-guide/scale/performance-alerting.mdx b/docs/main/administration-guide/scale/performance-alerting.mdx new file mode 100644 index 000000000000..55ff741f0304 --- /dev/null +++ b/docs/main/administration-guide/scale/performance-alerting.mdx @@ -0,0 +1,158 @@ +--- +title: "Mattermost performance alerting guide" +--- +<PlanAvailability slug="entry-ent" /> + +Mattermost recommends using [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) to track performance metrics of the Mattermost application servers. The purpose of this guide is to help you set up alerts on your Grafana dashboard once you've [set up system health tracking](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). + +<Note> + +We highly recommend setting up performance alerting for deployments above 5,000 users, where additional servers have been added for performance load-balancing. + +</Note> + +## Prerequisites + +Set up performance monitoring for Mattermost. See our [Performance Monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) documentation to learn more. + +To get alerts, first set up a Notification Channel in Grafana. Here’s how you can set it up to automatically post alerts in Mattermost: + +1. In Mattermost: + +> 1. Create an Alerts channel. +> 2. Create an [incoming webhook](https://developers.mattermost.com/integrate/webhooks/incoming/) for the Alerts channel and copy the URL. + +2. In Grafana: + +> 1. Under the alert icon in the sidebar, select **Contact points**. +> 2. Select **Create contact point**. +> 3. Enter **Mattermost Alerts Channel** as the name. +> 4. For type, select **Slack**. +> 5. Paste your webhook URL into the URL field. +> 6. Include an @ mention in the mention field, if you want to send mentions when an alert is posted to Mattermost. +> 7. Press **Send Test** to test the alert. + +If you would also like to get email alerts, you can follow [these instructions](https://grafana.com/docs/grafana/latest/alerting/) to set that up. + +## Configure alerts + +The [Mattermost dashboards](https://grafana.com/grafana/dashboards/?search=mattermost) for Grafana come with some partially pre-configured alerts on the following charts: + +- CPU Utilization Rate +- Memory Usage +- Number of Goroutines +- Number of API Errors per Second +- Mean API Request Time + +To configure alerts, set an appropriate threshold and enable notifications. Enabling notifications is the same for each chart, but setting the correct threshold can have some variances that are better handled on a per-chart basis. + +1. For each chart, select the chart name, then select **Edit**: + +![Configure Grafana dashboard alerts for each chart by selecting the chart name then selecting Edit.](/images/perf-1.png) + +2. Select the **Alert** tab: + +![Switch to the Alert tab to access and configure Grafana dashboard alerts for the current chart.](/images/perf-2.png) + +3. The alert threshold, which will be discussed in the sections below, is the last field under **Conditions** (the one set to 600 in the screenshot above). + +See the sections below for how to set the threshold for each individual chart. If you would like to add your own custom alert conditions, configure them here. + +![When configuring Grafana dashboard alerts, set custom threshold conditions in the Conditions section of the screen.](/images/perf-3.png) + +4. To enable the notifications for any alerts, select the **Notification** tab on the left, then select **Mattermost Alerts Channel** under **Send to**: + +![When configuring Grafana dashboard alerts, set notifications for any alerts by switching to the Notification tab, selecting Send to, then selecting by Mattermost Alerts Channel.](/images/perf-4.png) + +Enter a message if you would like to add more context to the alert. + +By default, the alerts are configured to check the average of a chart over the last minute to see if that value is above a threshold. If it’s above the threshold, the alert will be triggered. Since it’s an average over the last minute, small spikes that go past the threshold won’t necessarily cause an alert. This helps prevent false positives that would result from natural spikes in usage. The alert state for each chart is evaluated every minute. + +## Available charts + +The sections below describe each chart in more detail. + +### CPU utilization rate + +CPU Utilization Rate is fairly straightforward. CPU Utilization Rate tracks the CPU usage of the app servers as a percentage. The maximum percentage is based on the number of CPU cores or vCPUs your app server has. For example, if you have four CPU cores and your app server was at 100% utilization rate on all four cores, the graph would show 400% for that app server. + +It’s best to set the alert threshold based on your average CPU utilization and how many cores/vCPUs your app servers have. Take a look at the chart over the last seven days. You’ll want to set the threshold somewhere between your maximum CPU usage (cores \* 100) and the CPU usage you see. The lower you set the threshold, the more alerts, and therefore the more false positives, you will get. Set the threshold too high and you may not receive an alert for an incident until it’s gotten worse. The same principle applies to all alerts, regardless of the chart. + +For example, on our community server, we have the threshold set to 15%: + +![Example CPU utilization rate metrics for the Mattermost Community Server, where the threshold is set to 15%. System admins should set the threshold between the maximum CPU usage and the CPU usage observed in metrics.](/images/perf-5.png) + +This value is below our maximum CPU usage and above our average usage at peak times. Therefore, we will get alerts if we begin experiencing unusually high CPU usage. + +### Memory usage + +Memory Usage tracks the megabytes of RAM that your app servers are using. Set the threshold similar to the CPU Utilization Rate: below maximum available memory and above your average usage during peak times. + +Here’s how we have the alert set on our Community server: + +![Example memory usage metrics for the Mattermost Community Server, where the threshold is configured similarly to the CPU utilization rate.](/images/perf-6.png) + +### Number of Goroutines + +Goroutines are functions or methods that run concurrently with other functions and methods. Goroutines are like lightweight threads with low-creation costs. A rising number of goroutines can be a good measure of the performance of your app servers. A continuous increase indicates your app server can't keep up and is creating goroutines faster than they can complete their tasks and stop. + +Set the threshold somewhere above the average number of goroutines you see during peak load times. Small spikes are usually nothing to worry about. It’s the uncontrolled climbing of goroutines that you want to watch out for. + +Here’s how we have it set on our Community server: + +![Example Goroutines metrics for the Mattermost Community Server, where the threshold is configured above the average number of Goroutines observed during peak load times.](/images/perf-7.png) + +### Number of API errors per second + +Any 4xx or 5xx HTTP response status codes are counted as a REST API error. API errors themselves are not necessarily a problem. There are many legitimate reasons for an API error to occur, such as users’ sessions expiring or clients requesting to see if a resource exists and is being given a `404 Not Found` response. It is normal to have some API errors that scale with your installation base. + +That said, errors against the REST API can be indicative of deployment and other issues. For example, if one of your app servers did not deploy correctly for whatever reason, it may begin returning a high number of API errors. Another example would be a rogue bot spamming the API with bad requests. Alerts on API errors per second would help catch these and other issues. + +Here’s how it’s set on our Community server: + +![Example metrics of the number of API errors per second for the Mattermost Community Server, where it's normal to have some API errors that scale with an installation base, but that can be indicative of deployment issues or other issues.](/images/perf-8.png) + +### Mean API request time + +The Mean API Request Time is the average amount of time a REST API request to the Mattermost app server takes to complete. If an app server starts to perform poorly, you’ll likely see a rise in the mean request time as it takes longer to complete requests. This could also happen if your database can’t sustain the load from the app servers. It may also be indicative of an issue between the app servers and your proxy. + +You’ll want to set the alert threshold a little above what the mean request time is during your peak load times. + +Here’s how it’s set on our community server: + +![Example mean API request time metrics for the Mattermost Community Server, where the alert threshold is configured a bit above the mean request time during peak load times.](/images/perf-9-b.png) + +### Plugin hooks + +You can trace hooks and plugin API calls with Prometheus. Below are some examples of hooks and API Prometheus metrics that you may want to be aware of when troubleshooting or monitoring your server's performance. + +``` text +# HELP mattermost_plugin_hook_time Time to execute plugin hook handler in seconds. +# TYPE mattermost_plugin_hook_time histogram +mattermost_plugin_hook_time_bucket{hook_name="ChannelHasBeenCreated",plugin_id="com.mattermost.demo-plugin",success="true",le="0.005"} 0 +mattermost_plugin_hook_time_bucket{hook_name="ChannelHasBeenCreated",plugin_id="com.mattermost.demo-plugin",success="true",le="0.01"} 0 +``` + +``` text +# HELP mattermost_plugin_multi_hook_time Time to execute multiple plugin hook handler in seconds. +# TYPE mattermost_plugin_multi_hook_time histogram +mattermost_plugin_multi_hook_time_bucket{plugin_id="com.mattermost.custom-attributes",le="0.005"} 100 +mattermost_plugin_multi_hook_time_bucket{plugin_id="com.mattermost.custom-attributes",le="0.01"} 100 +``` + +``` text +# HELP mattermost_plugin_multi_hook_server_time Time for the server to execute multiple plugin hook handlers in seconds. +# TYPE mattermost_plugin_multi_hook_server_time histogram +mattermost_plugin_multi_hook_server_time_bucket{le="0.005"} 1043 +``` + +``` text +# HELP mattermost_plugin_api_time Time to execute plugin API handlers in seconds. +# TYPE mattermost_plugin_api_time histogram +mattermost_plugin_api_time_bucket{api_name="AddUserToChannel",plugin_id="com.mattermost.plugin-incident-response",success="true",le="0.005"} 0 +mattermost_plugin_api_time_bucket{api_name="AddUserToChannel",plugin_id="com.mattermost.plugin-incident-response",success="true",le="0.01"} 0 +``` + +## Other alerts + +If you want more alerts, you can set them up on any of the Grafana charts you'd like. We recommend reviewing custom metrics listed on our [Performance Monitoring feature documentation](/administration-guide/scale/performance-monitoring-metrics). diff --git a/docs/main/administration-guide/scale/performance-monitoring-metrics.mdx b/docs/main/administration-guide/scale/performance-monitoring-metrics.mdx new file mode 100644 index 000000000000..673b69c801b8 --- /dev/null +++ b/docs/main/administration-guide/scale/performance-monitoring-metrics.mdx @@ -0,0 +1,256 @@ +--- +title: "Performance monitoring metrics" +--- +<PlanAvailability slug="entry-ent" /> + +Mattermost provides the following performance monitoring statistics to integrate with Prometheus and Grafana. + +## Custom Mattermost metrics + +The following is a list of custom Mattermost metrics that can be used to monitor your system's performance: + +### API metrics + +- `mattermost_api_time`: The total time in seconds to execute a given API handler. + +### Caching metrics + +- `mattermost_cache_etag_hit_total`: The total number of ETag cache hits for a specific cache. +- `mattermost_cache_etag_miss_total`: The total number of ETag cache misses for an API call. +- `mattermost_cache_mem_hit_total`: The total number of memory cache hits for a specific cache. +- `mattermost_cache_mem_invalidation_total`: The total number of memory cache invalidations for a specific cache. +- `mattermost_cache_mem_miss_total`: The total number of cache misses for a specific cache. + +The above metrics can be used to calculate ETag and memory cache hit rates over time. + +![Example caching metrics, including Etag hit rate and mem cache hit rate, in a self-hosted Mattermost deployment.](/images/perf_monitoring_caching_metrics.png) + +### Cluster metrics + +- `mattermost_cluster_cluster_request_duration_seconds`: The total duration in seconds of the inter-node cluster requests. +- `mattermost_cluster_cluster_health_score`: A score that gives an idea of how well it is meeting the soft-real time requirements of the gossip protocol. +- `mattermost_cluster_cluster_requests_total`: The total number of inter-node requests. +- `mattermost_cluster_cluster_event_type_totals`: The total number of cluster requests sent for any type. + +### Database metrics + +- `mattermost_db_active_users`: The total number of active users. +- `mattermost_db_cache_time`: Time to execute the cache handler. +- `mattermost_db_master_connections_total`: The total number of connections to the master database. +- `mattermost_db_read_replica_connections_total`: The total number of connections to all the read replica databases. +- `mattermost_db_search_replica_connections_total`: The total number of connections to all the search replica databases. +- `mattermost_db_store_time`: The total time in seconds to execute a given database store method. +- `mattermost_db_replica_lag_abs`: Absolute lag time based on binlog distance/transaction queue length. +- `mattermost_db_replica_lag_time`: The time taken for the replica to catch up. + +### Database connection metrics + +- `go_sql_max_open_connections`: Maximum number of open connections to the database. +- `go_sql_open_connections`: The number of established connections both in use and idle. +- `go_sql_in_use_connections`: The number of connections currently in use. +- `go_sql_idle_connections`: The number of idle connections. +- `go_sql_wait_count_total`: The total number of connections waited for. +- `go_sql_wait_duration_seconds_total`: The total time blocked waiting for a new connection. +- `go_sql_max_idle_closed_total`: The total number of connections closed due to SetMaxIdleConns. +- `go_sql_max_idle_time_closed_total`: The total number of connections closed due to SetConnMaxIdleTime. +- `go_sql_max_lifetime_closed_total`: The total number of connections closed due to SetConnMaxLifetime. + +### HTTP metrics + +- `mattermost_http_errors_total`: The total number of http API errors. +- `mattermost_http_requests_total`: The total number of http API requests. +- `mattermost_http_websockets_total`: The total number of websocket connections to this server. + +<Note> + +From Mattermost version v9.9, this value includes any potentially unauthenticated connections. Furthermore, this metric comes with an `origin_client` label that can be used to see the distribution of connections from different client types (i.e. web, mobile, and desktop). + +</Note> + +![Example HTTP metrics, including number of API errors per minute, number of API requests per minute, and mean request time per minute, in a self-hosted Mattermost deployment.](/images/perf_monitoring_http_metrics.png) + +### Login and session metrics + +- `mattermost_login_logins_fail_total`: The total number of failed logins. +- `mattermost_login_logins_total`: The total number of successful logins. + +### Mattermost channels metrics + +- `mattermost_post_broadcasts_total`: The total number of websocket broadcasts sent because a post was created. +- `mattermost_post_emails_sent_total`: The total number of emails sent because a post was created. +- `mattermost_post_file_attachments_total`: The total number of file attachments created because a post was created. +- `mattermost_post_pushes_sent_total`: The total number of mobile push notifications sent because a post was created. +- `mattermost_post_total`: The total number of posts created. +- `mattermost_post_webhooks_total`: Total number of webhook posts created. + +![Example Mattermost channels metrics, including messages per minute, broadcasts per minute, emails sent per minute, mobile push notifications per minute, and number of file attachments per minute, in a self-hosted Mattermost deployment.](/images/perf_monitoring_messaging_metrics.png) + +### Process metrics + +- `mattermost_process_cpu_seconds_total`: Total user and system CPU time spent in seconds. +- `mattermost_process_max_fds`: Maximum number of open file descriptors. +- `mattermost_process_open_fds`: Number of open file descriptors. +- `mattermost_process_resident_memory_bytes`: Resident memory size in bytes. +- `mattermost_process_start_time_seconds`: Start time of the process since unix epoch in seconds. +- `mattermost_process_virtual_memory_bytes`: Virtual memory size in bytes. +- `mattermost_process_virtual_memory_max_bytes`: Maximum amount of virtual memory available in bytes. + +### Search metrics + +- `mattermost_search_posts_searches_duration_seconds`: The total duration in seconds of post searches. +- `mattermost_search_channel_index_total`: The total number of channel indexes carried out. +- `mattermost_search_file_index_total`: The total number of files indexes carried out. +- `mattermost_search_files_searches_duration_seconds`: The total duration in seconds of file searches. +- `mattermost_search_files_searches_total`: The total number of file searches carried out. +- `mattermost_search_post_index_total`: The total number of posts indexes carried out. +- `mattermost_search_posts_searches_total`: The total number of post searches carried out. +- `mattermost_search_user_index_total`: The total number of user indexes carried out. + +### WebSocket metrics + +- `mattermost_websocket_broadcast_buffer_size`: Number of events in the websocket broadcasts buffer waiting to be processed. +- `mattermost_websocket_broadcast_buffer_users_registered`: Number of users registered in a broadcast buffer hub. +- `mattermost_websocket_broadcasts_total`: The total number of websocket broadcasts sent for any type. +- `mattermost_websocket_event_total`: Total number of websocket events. +- `mattermost_websocket_reconnects_total`: Total number of websocket reconnect attempts. + +### Logging metrics + +- `mattermost_logging_logger_queue_used`: Number of records in log target queue. +- `mattermost_logging_logger_logged_total`: The total number of records logged. +- `mattermost_logging_logger_error_total`: The total number of logger errors. +- `mattermost_logging_logger_dropped_total`: The total number of dropped log records. +- `mattermost_logging_logger_blocked_total`: The total number of log records that were blocked/delayed. + +### Debugging metrics - system + +- `mattermost_system_server_start_time`: The time the server started. + +Use `mattermost_system_server_start_time` to dynamically add an annotation corresponding to the event. + +![Example debugging metrics, including number of messages per second, in a self-hosted Mattermost deployment.](/images/mattermost_system_server_start_time.png) + +### Debugging metrics - jobs + +- `mattermost_jobs_active`: Number of active jobs. + +Use `mattermost_jobs_active` to display an active jobs chart. + +![Example debugging metrics, including active jobs, in a self-hosted Mattermost deployment.](/images/mattermost_active_jobs_chart.png) + +Or, use `mattermost_jobs_active` to dynamically add a range annotation corresponding to jobs being active. + +![Example debugging metrics, including number of messages per second, in a self-hosted Mattermost deployment.](/images/mattermost_dynamic_range_annotation.png) + +Use annotations to streamline analysis when a job is long running, such as an LDAP synchronization job. + +<Note> + +Jobs where the runtime is less than the Prometheus polling interval are unlikely to be visible because Grafana is performing range queries over the raw Prometheus timeseries data, and rendering an event each time the value changes. + +</Note> + +### Plugin metrics + +- `mattermost_plugin_api_time`: Time to execute plugin API handlers in seconds. +- `mattermost_plugin_hook_time`: Time to execute plugin hook handler in seconds. +- `mattermost_plugin_multi_hook_server_time`: Time for the server to execute multiple plugin hook handlers in seconds. +- `mattermost_plugin_multi_hook_time`: Time to execute multiple plugin hook handler in seconds. + +### Shared metrics + +- `mattermost_shared_channels_sync_collection_duration_seconds`: Duration tasks spend collecting sync data (seconds). +- `mattermost_shared_channels_sync_collection_step_duration_seconds`: Duration tasks spend in each step collecting data (seconds). +- `mattermost_shared_channels_sync_count`: Count of sync events processed for each remote. +- `mattermost_shared_channels_sync_send_duration_seconds`: Duration tasks spend sending sync data (seconds). +- `mattermost_shared_channels_sync_send_step_duration_seconds`: Duration tasks spend in each step sending data (seconds). +- `mattermost_shared_channels_task_in_queue_duration_seconds`: Duration tasks spend in queue (seconds). +- `mattermost_shared_channels_task_queue_size`: Current number of tasks in queue. + +### Remote cluster metrics + +- `mattermost_remote_cluster_clock_skew`: An approximated value for clock skew between clusters. +- `mattermost_remote_cluster_conn_state_change_total`: Total number of connection state changes. +- `mattermost_remote_cluster_msg_errors_total`: Total number of message errors. +- `mattermost_remote_cluster_msg_received_total`: Total number of messages received from the remote cluster. +- `mattermost_remote_cluster_msg_sent_total`: Total number of messages sent to the remote cluster. +- `mattermost_remote_cluster_ping_time`: The ping roundtrip times to the remote cluster. + +### Notification metrics + +- `mattermost_notifications_error`: Total number of errors that stop the notification flow. +- `mattermost_notifications_not_sent`: Total number of notifications the system deliberately did not send. +- `mattermost_notifications_success`: Total number of successfully sent notifications. +- `mattermost_notifications_total`: Total number of notification events. +- `mattermost_notifications_total_ack`: Total number of notification events acknowledged. +- `mattermost_notifications_unsupported`: Total number of untrackable notifications due to an unsupported app version. + +### Mobile app metrics + +- `mattermost_mobileapp_mobile_channel_switch`: Duration of the time taken from when a user clicks on a channel name, and the full channel sreen is loaded (seconds). +- `mattermost_mobileapp_mobile_load`: Duration of the time taken from when a user opens the app and the app finally loads all relevant information (seconds). +- `mattermost_mobileapp_mobile_team_switch`: Duration of the time taken from when a user clicks on a team, and the full categories screen is loaded (seconds). + +### Web app metrics + +- `mattermost_webapp_channel_switch`: Duration of the time taken from when a user clicks on a channel in the LHS to when posts in that channel become visible (seconds). +- `mattermost_webapp_cumulative_layout_shift`: Measure of how much a page's content shifts unexpectedly. +- `mattermost_webapp_first_contentful_paint`: Duration of how long it takes for any content to be displayed on screen to a user (seconds). +- `mattermost_webapp_global_threads_load`: Duration of the time taken from when a user clicks to open Threads in the LHS until when the global threads view becomes visible (milliseconds). +- `mattermost_webapp_interaction_to_next_paint`: Measure of how long it takes for a user to see the effects of clicking with a mouse, tapping with a touchscreen, or pressing a key on the keyboard (seconds). +- `mattermost_webapp_largest_contentful_paint`: Duration of how long it takes for large content to be displayed on screen to a user (seconds). +- `mattermost_webapp_long_tasks`: Counter of the number of times that the browser's main UI thread is blocked for more than 50ms by a single task. +- `mattermost_webapp_page_load`: The amount of time from when the browser starts loading the web app until when the web app's load event has finished (seconds). +- `mattermost_webapp_rhs_load`: Duration of the time taken from when a user clicks to open a thread in the RHS until when posts in that thread become visible (seconds). +- `mattermost_webapp_team_switch`: Duration of the time taken from when a user clicks on a team in the LHS to when posts in that team become visible (seconds). +- `mattermost_webapp_time_to_first_byte`: Duration from when a browser starts to request a page from a server until when it starts to receive data in response (seconds). + +## Standard Go metrics + +<PlanAvailability slug="all-commercial" /> + +The performance monitoring feature provides standard Go metrics for HTTP server runtime profiling data and system monitoring, such as: + +- `go_memstats_alloc_bytes` for memory usage +- `go_goroutines` for number of goroutines +- `go_gc_duration_seconds` for garbage collection duration +- `go_memstats_heap_objects` for object tracking on the heap + +To learn how to set up runtime profiling, see the [pprof package Go documentation](https://pkg.go.dev/net/http/pprof). You can also visit the `ip:port` page for a complete list of metrics with descriptions. + +<Note> + +A Mattermost Enterprise license is required to connect to `/metrics` using HTTP. + +</Note> + +If enabled, you can run the profiler by + +`go tool pprof http://localhost:<port>/debug/pprof/profile?seconds=<duration>` + +where you can replace `localhost` with the server name. The profiling reports are available at `<ip>:<port>`, which include: + +- `/debug/pprof/profile?seconds=30` for CPU profiling +- `/debug/pprof/cmdline` for command line profiling +- `/debug/pprof/symbol` for symbol profiling +- `/debug/pprof/trace` for trace profiling +- `/debug/pprof/goroutine` for Go routine profiling +- `/debug/pprof/heap` for heap profiling +- `/debug/pprof/threadcreate` for threads profiling +- `/debug/pprof/block` for block profiling +- `/debug/pprof/allocs` for past memory allocations +- `/debug/pprof/mutex` for logs of the holders of contended mutexes + +![Example Go metrics for HTTP server runtime profiling data and system monitoring, including memory usage, Go routines, and garbage collection duration, in a self-hosted Mattermost deployment.](/images/perf_monitoring_go_metrics.png) + +## Host/system metrics + +From Metrics Plugin v0.7.0, you can pull metrics from [node exporter](https://github.com/prometheus/node_exporter) targets to access network-related panels for Mattermost Calls. + +## Frequently asked questions + +### Why are chart labels difficult to distinguish? + +The chart labels used in server filters and legends are based on the hostname of your machines. If the hostnames are similar, then it will be difficult to distinguish the labels. + +You can either set more descriptive hostnames for your machines or change the display name with a `relabel_config` in [Prometheus configuration](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config). diff --git a/docs/main/administration-guide/scale/push-notification-health-targets.mdx b/docs/main/administration-guide/scale/push-notification-health-targets.mdx new file mode 100644 index 000000000000..ba65de7b85ba --- /dev/null +++ b/docs/main/administration-guide/scale/push-notification-health-targets.mdx @@ -0,0 +1,74 @@ +--- +title: "Push notification health targets" +--- +<PlanAvailability slug="entry-ent" /> + +When using the [Mattermost Notification Health](https://grafana.com/grafana/dashboards/21305-mattermost-notification-health) Grafana dashboard to track different types of notifications sent from Mattermost, we recommend adhering to the following mobile push notification health targets to ensure a performant production deployment of Mattermost. + +<Note> + +- Accessing and enabling Mattermost Notification Health Monitoring requires `MetricsSettings.Enable` set to `true`, and the feature flag `NotificationMonitoring` set to `true`. +- `MetricsSettings.EnableNotificationMetrics` must be enabled in the [Performance Monitoring](/administration-guide/configure/environment-configuration-settings#enable-notification-monitoring) configuration. +- System admins can [disable notification monitoring data collection](/administration-guide/configure/site-configuration-settings#enable-notification-monitoring) through the System Console. + +</Note> + +## Push Proxy Delivery Rate + +The **Push Proxy Delivery Rate** panel indicates the percentage of push notifications that have been successfully delivered to the Push Notification Service (i.e., Apple Push Notification service (APNs) or Firebase Cloud Messaging (FCM)) out of the total number of push notifications sent. + +Monitor this delivery rate to ensure that users are receiving their notifications in a timely manner. This value should always be 100%. Anything below 99% should be investigated further to identify issues with the push notification configuration, connectivity problems, or possible service interruptions with the push proxy provider. + +![The Push Notifications Errors by Reason panel provides admins with a breakdown of the errors encountered when sending push notifications, categorized by the specific reason for each error.](/images/push-proxy-delivery-rate.png) + +## Push Notifications Errors by Reason + +The **Push Notifications Errors by Reason** panel is a critical tool for maintaining the reliability and effectiveness of the push notification system. These values provide a breakdown of the errors encountered when sending push notifications, categorized by the specific reason for each error. + +This information helps admins to pinpoint common problems affecting push notification delivery, diagnose and fix issues more efficiently, detect patterns and trends, identify intermittent issues before they become more serious, and enhance the overall user experience with the Mattermost platform. + +Missing profile errors are generally safe to ignore. However, if you see occurences of this error increase, verify logs for `push_proxy_send_error`. + +## Push Notifications Not Sent Distribution + +The **Push Notifications Not Sent Distribution** panel helps admins ensure the robustness and reliability of the push notification system by providing detailed insights into the specific reasons why notifications weren't sent. + +This information helps admins understand the reasons why push notifications may not be sent, (i.e., the channel is muted), identify underlying system or configuration problems that need attention, prioritize areas for troubleshooting and improvement by focusing on the most significant issues affecting notification delivery rates, and monitor any trends or spikes in push notifications not sent, resulting in proactive maintenance and quicker resolution of issues as they arise. + +![The Push Notifications Not Sent Distribution panel provides admins with detailed insights into the specific reasons for notification delivery failures.](/images/push-notifications-not-sent-distribution.png) + +## Push Notifications Stats + +The **Push Notifications Stats** panel provides a high-level view of the number of notifications sent and acknowledged. + +An acknowledged push notification indicates successful communication between the service and the device because the recipient's mobile device successfully received the push notification, and sent back a confirmation of delivery to the push notification service. + +When a push notification isn't acknowledged, this indicates that the notification wasn't received, or that the device didn't send back a confirmation to the push notification service. + +Closer alignment between the send and acknowledge lines in this graph indicates better performance. + +![The Push Notifications Stats panel provides admins with a high-level view of the number of notifications sent and acknowledged.](/images/push-notification-stats.png) + +## Total Acked Push Notifications + +The **Total Acked Push Notifications** value indicates the total number of push notifications that have been acknowledged by mobile devices. This metric helps admins understand how many push notifications sent from the Mattermost server were successfully received and acknowledged by mobile devices. It's an important indicator of the reliability and effectiveness of the push notification system, as it ensures that messages are being delivered and received as intended. Any value over 80% is considered normal. + +![The Total Acked Push Notifications value helps admins understand how many push notifications sent from the Mattermost server were successfully received and acknowledged by mobile devices.](/images/total-acked-push-notifications.png) + +There are several scenarios where notifications may not be acknowledged which cover the remaining ~10-20% of notifications, as follows: + +Servers removed without users logging out + +- When a server is removed from the mobile app, and you can no longer contact the server using the mobile app, the server never logs the user session out. Therefore, Mattermost continues to send notifications to the mobile device. These sent notifications, can't be acknowledged because Mattermost would be missing the information about the server URL. + +iOS notifications are disabled + +- When notifications are disabled on iOS devices, notifications aren't processed by the mobile app. Therefore, we cannot acknowledge those notifications. Mattermost tracks whether the device has notifications disabled, but this information is only updated when the app starts. So any change without re-starting the app can lead to notifications not being acknowledged. + +Notifications are dropped at the Push Notification Service + +- APNs and FCM can drop notifications in several circumstances, especially when the mobile device doesn't have a connection. The notifications are marked as sent to the Push Proxy, but are never sent to the devices from the Push Notification Service. Therefore, the mobile device cannot acknowledge the notification. + +Extreme battery save mode + +- On Android, users can activate an extreme battery save mode. In this mode, notifications are not acknowledged. diff --git a/docs/main/administration-guide/scale/redis.mdx b/docs/main/administration-guide/scale/redis.mdx new file mode 100644 index 000000000000..3c9291b50bf1 --- /dev/null +++ b/docs/main/administration-guide/scale/redis.mdx @@ -0,0 +1,99 @@ +--- +title: "Redis" +--- +<PlanAvailability slug="ent-adv" /> + +Redis is an open-source, in-memory data structure store used as a database, cache, message broker, and streaming engine. Mattermost uses Redis as an external cache to improve performance at scale. When properly configured, Redis can help support Mattermost installations with more than 100,000 users by providing improved performance through efficient caching. + +## Deployment guide + +Deploying Redis with Mattermost includes the following 2 steps: [setting up the Redis server](#set-up-a-redis-server), and [configuring Redis in Mattermost](#configure-redis-in-mattermost). + +### Set up a Redis server + +1. Download and install the latest release of [Redis 7.x](https://redis.io/download/). See the Redis documentation for installation details specific to your operating system. +2. Configure Redis appropriately for your environment. Ensure that Redis is secured and accessible only by trusted systems. +3. For high availability deployments, consider setting up Redis in a cluster configuration for improved reliability and performance. + +### Configure Redis in Mattermost + +Follow these steps to configure Mattermost to use your Redis server: + +1. Go to **System Console \> Environment \> Cache**. +2. Set **Cache Type** to `redis` to enable the Redis-specific settings. +3. Set the Redis server connection details: + +> 1. Enter **Redis Address** for the Redis server you set up earlier (e.g., `redis.example.com:6379`). +> 2. (Optional) Enter **Redis Password** if your Redis server requires authentication. +> 3. (Optional) Enter **Redis Database** to specify which Redis database to use (-1 by default, which uses Redis's default database). + +4. Save your configuration and restart the Mattermost server. + +Alternatively, you can configure Redis in the `config.json` file: + +``` json +"CacheSettings": { + "CacheType": "redis", + "RedisAddress": "redis.example.com:6379", + "RedisPassword": "", + "RedisCachePrefix": "", + "RedisDB": -1, + "DisableClientCache": false +} +``` + +## Deploy with AWS ElastiCache + +For enterprise-scale deployments, AWS ElastiCache for Redis provides a fully managed Redis service that simplifies deployment, operation, and scaling. + +When deploying Mattermost with AWS ElastiCache: + +1. Create an ElastiCache for Redis instance, choosing Redis OSS version 7.1 or later. +2. Based on load testing results, we recommend starting with a `cache.m7g.2xlarge` instance for deployments supporting over 100,000 users. +3. Configure your Mattermost server to connect to the ElastiCache endpoint. +4. Monitor CPU utilization closely, as Redis is single-threaded and performance bottlenecks are typically CPU-bound rather than memory-bound. + +### Performance considerations + +When using Redis with Mattermost, consider the following performance insights: + +- Current load tests indicate that memory usage of Redis is relatively low, with CPU being the primary bottleneck because Redis is single-threaded. +- When planning your Redis deployment, use CPU utilization as the primary metric for scaling decisions. + +## Implementation details + +Mattermost uses the [rueidis](https://github.com/redis/rueidis) library instead of the more popular [go-redis](https://github.com/redis/go-redis), primarily because rueidis offers more performance optimizations out of the box, including: + +- Automatic pipelining of concurrent queries +- Client-side caching +- Additional performance tuning options like MaxFlushDelay + +The primary implementation files include: + +- `platform/services/cache/provider.go` - Contains the library initialization code +- `platform/services/cache/redis.go` - Contains the cache interface implementation + +## Frequently asked questions (FAQ) + +### Do I need to use Redis? + +While Redis is not required for smaller Mattermost deployments, it is highly recommended for large-scale installations. - If your installation has more than 100K users, Redis is highly recommended. Redis significantly improves performance by reducing database load and optimizing common operations. - If your installation has less than 100K users, Redis is not recommended. + +It is suggested to keep an eye on the `sum(rate(mattermost_cache_mem_invalidation_total[5m]))` metric which indicates the rate of cache invalidations happening. A single cache invalidation will send a message across your HA cluster to all nodes, leading to database calls from all of them. So the metric, combined with the number of nodes in your cluster should be used to determine when is the right time to use Redis. + +For example, if you have more than 10 nodes in your cluster, and the rate of invalidations goes beyond 10, then you should definitely start considering adding Redis. + +### Should I install Redis on the same machine as Mattermost Server? + +For production deployments, we recommend running Redis on a separate machine from the Mattermost server. This separation allows for better resource allocation and improved system reliability. + +### What Redis metrics should I monitor? + +When running Redis with Mattermost, monitor the following metrics: + +- CPU utilization (primary bottleneck) +- Memory usage +- Connected clients +- Cache hit ratio +- Operation latency +- Mattermost's `mattermost_db_cache_time` Grafana metric with labels of `cache_name` and `operation`, which can be used to further monitor the performance of Redis diff --git a/docs/main/administration-guide/scale/scale-to-100000-users.mdx b/docs/main/administration-guide/scale/scale-to-100000-users.mdx new file mode 100644 index 000000000000..fdd22a8c138e --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-100000-users.mdx @@ -0,0 +1,127 @@ +--- +title: "Scale Mattermost up to 100000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 100000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +\- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. - From Mattermost v10.4, Mattermost Enterprise customers can configure [Redis](https://redis.io/) (Remote Dictionary Server) as an alternative cache backend. Using Redis can help ensure that Mattermost remains performant and efficient, even under heavy usage. See the [Redis cache backend](/administration-guide/configure/environment-configuration-settings#redis-cache-backend) configuration settings documentation for details. - While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>6</td> +<td>16/32</td> +<td>c7i.4xlarge</td> +<td>F16s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>5</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 100000-person team with medium usage (with a safety factor of 2x) would require between 10.56TB <sup>1</sup> and 52.8TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 100000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 100000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-15000-users.mdx b/docs/main/administration-guide/scale/scale-to-15000-users.mdx new file mode 100644 index 000000000000..35e97f98bbd2 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-15000-users.mdx @@ -0,0 +1,146 @@ +--- +title: "Scale Mattermost up to 15000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 15000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, reader + +<Note> + +Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, +.scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + vertical-align: top; + word-wrap: break-word !important; + overflow-wrap: break-word !important; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; + text-align: left; +} +.scale-requirements-table th:nth-child(1) { width: 25%; } +.scale-requirements-table th:nth-child(2) { width: 10%; } +.scale-requirements-table th:nth-child(3) { width: 18%; } +.scale-requirements-table th:nth-child(4) { width: 23%; } +.scale-requirements-table th:nth-child(5) { width: 24%; } + +/* Dark mode support */ +body:not([data-custom-theme="light"]) .scale-requirements-table { + background-color: #2d3748; +} +body:not([data-custom-theme="light"]) .scale-requirements-table th { + background-color: #4a5568 !important; + color: #fff; + border-color: #718096 !important; +} +body:not([data-custom-theme="light"]) .scale-requirements-table td { + color: #e2e8f0; + border-color: #718096 !important; +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .scale-requirements-table { + font-size: 0.8em; + } + .scale-requirements-table th, + .scale-requirements-table td { + padding: 6px 4px; + } +} +</style> + +<table class="scale-requirements-table"> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/ Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>2</td> +<td>4/8</td> +<td>c7i.xlarge</td> +<td>F4s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>4/32</td> +<td>db.r7g.xlarge</td> +<td>E4as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>1</td> +<td>4/32</td> +<td>db.r7g.xlarge</td> +<td>E4as v6</td> +</tr> +<tr> +<td>Elasticsearch Node</td> +<td>2</td> +<td>4/32</td> +<td>r6g.xlarge.search</td> +<td>E4ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 15000-person team with medium usage (with a safety factor of 2x) would require between 1.8TB <sup>1</sup> and 9TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 15000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 15000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-200-users.mdx b/docs/main/administration-guide/scale/scale-to-200-users.mdx new file mode 100644 index 000000000000..863e5a81f510 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-200-users.mdx @@ -0,0 +1,143 @@ +--- +title: "Scale Mattermost up to 200 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; + +This page describes the Mattermost reference architecture designed for the load of up to 200 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Not required +- **Database Configuration**: Single + +<Note> + +Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, +.scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + vertical-align: top; + word-wrap: break-word !important; + overflow-wrap: break-word !important; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; + text-align: left; +} +.scale-requirements-table th:nth-child(1) { width: 25%; } +.scale-requirements-table th:nth-child(2) { width: 10%; } +.scale-requirements-table th:nth-child(3) { width: 18%; } +.scale-requirements-table th:nth-child(4) { width: 23%; } +.scale-requirements-table th:nth-child(5) { width: 24%; } + +/* Dark mode support */ +body:not([data-custom-theme="light"]) .scale-requirements-table { + background-color: #2d3748; +} +body:not([data-custom-theme="light"]) .scale-requirements-table th { + background-color: #4a5568 !important; + color: #fff; + border-color: #718096 !important; +} +body:not([data-custom-theme="light"]) .scale-requirements-table td { + color: #e2e8f0; + border-color: #718096 !important; +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .scale-requirements-table { + font-size: 0.8em; + } + .scale-requirements-table th, + .scale-requirements-table td { + padding: 6px 4px; + } +} +</style> + +<table class="scale-requirements-table"> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/ Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>1</td> +<td>2/4</td> +<td>c7i.large</td> +<td>F2s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>2/16</td> +<td>db.r7g.large</td> +<td>E2as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>0</td> +<td>2/16</td> +<td>db.r7g.large</td> +<td>E2as v6</td> +</tr> +<tr> +<td>Elasticsearch Node</td> +<td>0</td> +<td>4/32</td> +<td>r6g.xlarge.search</td> +<td>E4ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 200-person team with medium usage (with a safety factor of 2x) would require between 12GB <sup>1</sup> and 60GB <sup>2</sup> of free space per annum. + +<sup>1</sup> 200 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 200 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +Smaller deployments will need an increase in resources due to the fact the database is hosted on the same server as the Mattermost application. diff --git a/docs/main/administration-guide/scale/scale-to-2000-users.mdx b/docs/main/administration-guide/scale/scale-to-2000-users.mdx new file mode 100644 index 000000000000..40833ba87107 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-2000-users.mdx @@ -0,0 +1,146 @@ +--- +title: "Scale Mattermost up to 2000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for a minimum load of 100 concurrent users and up to 2000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, reader + +<Note> + +Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, +.scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + vertical-align: top; + word-wrap: break-word !important; + overflow-wrap: break-word !important; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; + text-align: left; +} +.scale-requirements-table th:nth-child(1) { width: 25%; } +.scale-requirements-table th:nth-child(2) { width: 10%; } +.scale-requirements-table th:nth-child(3) { width: 18%; } +.scale-requirements-table th:nth-child(4) { width: 23%; } +.scale-requirements-table th:nth-child(5) { width: 24%; } + +/* Dark mode support */ +body:not([data-custom-theme="light"]) .scale-requirements-table { + background-color: #2d3748; +} +body:not([data-custom-theme="light"]) .scale-requirements-table th { + background-color: #4a5568 !important; + color: #fff; + border-color: #718096 !important; +} +body:not([data-custom-theme="light"]) .scale-requirements-table td { + color: #e2e8f0; + border-color: #718096 !important; +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .scale-requirements-table { + font-size: 0.8em; + } + .scale-requirements-table th, + .scale-requirements-table td { + padding: 6px 4px; + } +} +</style> + +<table class="scale-requirements-table"> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/ Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>2</td> +<td>2/4</td> +<td>c7i.large</td> +<td>F2s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>2/16</td> +<td>db.r7g.large</td> +<td>E2as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>1</td> +<td>2/16</td> +<td>db.r7g.large</td> +<td>E2as v6</td> +</tr> +<tr> +<td>Elasticsearch Node</td> +<td>2</td> +<td>4/32</td> +<td>r6g.xlarge.search</td> +<td>E4ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 2000-person team with medium usage (with a safety factor of 2x) would require between 120GB <sup>1</sup> and 600GB <sup>2</sup> of free space per annum. + +<sup>1</sup> 2000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 2000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-200000-users.mdx b/docs/main/administration-guide/scale/scale-to-200000-users.mdx new file mode 100644 index 000000000000..f38c28b9b73d --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-200000-users.mdx @@ -0,0 +1,142 @@ +--- +title: "Scale Mattermost up to 200000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-adv" /> + +This page describes the Mattermost reference architecture designed for the load of up to 200000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +\- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. - From Mattermost v10.4, Mattermost Enterprise customers can configure [Redis](https://redis.io/) (Remote Dictionary Server) as an alternative cache backend. Using Redis can help ensure that Mattermost remains performant and efficient, even under heavy usage. See the [Redis cache backend](/administration-guide/configure/environment-configuration-settings#redis-cache-backend) configuration settings documentation for details. - While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## User login scalability + +Tests across all architectures were conducted at a rate of 4 user logins per second (14,400 users per hour). For this architecture, we performed additional testing at higher rates, reaching up to 30 user logins per second. + +Results show that this architecture supports logging in up to 150,000 users within 1.5 hours at the higher rate. Beyond this 150,000-user mark, the only available data is at the base rate of 4 logins per second, and no conclusive performance data exists at larger rates. + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>14</td> +<td>16/32</td> +<td>c7i.4xlarge</td> +<td>F16s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>6</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>4</td> +<td>32/128</td> +<td>m6in.8xlarge</td> +<td>D32s v6</td> +</tr> +<tr> +<td>Redis</td> +<td>1</td> +<td>8/32</td> +<td>cache.m7g.2xlarge</td> +<td>Azure Cache Redis P3</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 200000-person team with medium usage (with a safety factor of 2x) would require between 21.12TB <sup>1</sup> and 105.6TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 200000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 200000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/scale/scale-to-30000-users.mdx b/docs/main/administration-guide/scale/scale-to-30000-users.mdx new file mode 100644 index 000000000000..354eb27d35d8 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-30000-users.mdx @@ -0,0 +1,128 @@ +--- +title: "Scale Mattermost up to 30000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 30000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. +- While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>2</td> +<td>8/16</td> +<td>c7i.2xlarge</td> +<td>F8s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>8/64</td> +<td>db.r7g.2xlarge</td> +<td>E8as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>1</td> +<td>8/64</td> +<td>db.r7g.2xlarge</td> +<td>E8as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 30000-person team with medium usage (with a safety factor of 2x) would require between 3TB <sup>1</sup> and 15TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 30000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 30000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-50000-users.mdx b/docs/main/administration-guide/scale/scale-to-50000-users.mdx new file mode 100644 index 000000000000..43c5e975481c --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-50000-users.mdx @@ -0,0 +1,128 @@ +--- +title: "Scale Mattermost up to 50000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 50000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. +- While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>5</td> +<td>8/16</td> +<td>c7i.2xlarge</td> +<td>F8s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>8/64</td> +<td>db.r7g.2xlarge</td> +<td>E8as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>4</td> +<td>8/64</td> +<td>db.r7g.2xlarge</td> +<td>E8as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 50000-person team with medium usage (with a safety factor of 2x) would require between 6TB <sup>1</sup> and 30TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 50000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 50000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-80000-users.mdx b/docs/main/administration-guide/scale/scale-to-80000-users.mdx new file mode 100644 index 000000000000..eecbd678e028 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-80000-users.mdx @@ -0,0 +1,128 @@ +--- +title: "Scale Mattermost up to 80000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 80000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. +- While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>4</td> +<td>16/32</td> +<td>c7i.4xlarge</td> +<td>F16s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>3</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 80000-person team with medium usage (with a safety factor of 2x) would require between 10.56TB <sup>1</sup> and 52.8TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 80000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 80000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scale-to-90000-users.mdx b/docs/main/administration-guide/scale/scale-to-90000-users.mdx new file mode 100644 index 000000000000..f13bac9dfe27 --- /dev/null +++ b/docs/main/administration-guide/scale/scale-to-90000-users.mdx @@ -0,0 +1,128 @@ +--- +title: "Scale Mattermost up to 90000 users" +--- +import Inc0_lifetime_storage from './lifetime-storage.mdx'; +import Inc1_estimated_storage_per_user_per_month from './estimated-storage-per-user-per-month.mdx'; +import Inc2_additional_ha_considerations from './additional-ha-considerations.mdx'; + +<PlanAvailability slug="ent-plus" /> + +This page describes the Mattermost reference architecture designed for the load of up to 90000 concurrent users. Unsure which reference architecture to use? See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for details. + +- **High Availability**: Required +- **Database Configuration**: writer, multiple readers + +<Note> + +- Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. +- While the following Elasticsearch specifications may be more than sufficient for some use cases, we have not extensively tested configurations with lower resource allocations for this user scale. If cost optimization is a priority, admins may choose to experiment with smaller configurations, but we recommend starting with the tested specifications to ensure system stability and performance. Keep in mind that under-provisioning can lead to degraded user experience and additional troubleshooting effort. + +</Note> + +## Requirements + +<style> +.scale-requirements-table { + width: 100% !important; + table-layout: fixed !important; + border-collapse: collapse; + font-size: 0.9em; + overflow-wrap: break-word !important; + word-wrap: break-word !important; +} +.scale-requirements-table th, .scale-requirements-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + vertical-align: top; + word-wrap: break-word; + overflow-wrap: break-word; +} +.scale-requirements-table th { + background-color: #f8f9fa; + font-weight: bold; +} +.scale-requirements-table col:nth-child(1) { width: 25%; } +.scale-requirements-table col:nth-child(2) { width: 10%; } +.scale-requirements-table col:nth-child(3) { width: 18%; } +.scale-requirements-table col:nth-child(4) { width: 23%; } +.scale-requirements-table col:nth-child(5) { width: 24%; } +</style> + +<table class="scale-requirements-table"> +<colgroup> +<col style={{width: '25%'}} /> +<col style={{width: '10%'}} /> +<col style={{width: '18%'}} /> +<col style={{width: '23%'}} /> +<col style={{width: '24%'}} /> +</colgroup> +<thead> +<tr> +<th>Resource Type</th> +<th>Nodes</th> +<th>vCPU/Memory (GiB)</th> +<th>AWS Instance</th> +<th>Azure Instance</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mattermost Application</td> +<td>5</td> +<td>16/32</td> +<td>c7i.4xlarge</td> +<td>F16s v2</td> +</tr> +<tr> +<td>RDS Writer</td> +<td>1</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>RDS Reader</td> +<td>4</td> +<td>16/128</td> +<td>db.r7g.4xlarge</td> +<td>E16as v6</td> +</tr> +<tr> +<td>Elasticsearch cluster</td> +<td>4</td> +<td>8/64</td> +<td>r6g.2xlarge.search</td> +<td>E8ads v6</td> +</tr> +<tr> +<td>Proxy</td> +<td>1</td> +<td>16/64</td> +<td>m7i.4xlarge</td> +<td>D16s v6</td> +</tr> +</tbody> +</table> + +## Lifetime storage + +<Inc0_lifetime_storage /> + +### Estimated storage per user, per month + +<Inc1_estimated_storage_per_user_per_month /> + +### Example + +A 90000-person team with medium usage (with a safety factor of 2x) would require between 10.56TB <sup>1</sup> and 52.8TB <sup>2</sup> of free space per annum. + +<sup>1</sup> 90000 users \* 5 MB \* 12 months \* 2x safety factor + +<sup>2</sup> 90000 users \* 25 MB \* 12 months \* 2x safety factor + +We strongly recommend that you review storage utilization at least quarterly to ensure adequate free space is available. + +## Additional considerations + +<Inc2_additional_ha_considerations /> diff --git a/docs/main/administration-guide/scale/scaling-for-enterprise.mdx b/docs/main/administration-guide/scale/scaling-for-enterprise.mdx new file mode 100644 index 000000000000..b1a7f8826161 --- /dev/null +++ b/docs/main/administration-guide/scale/scaling-for-enterprise.mdx @@ -0,0 +1,82 @@ +--- +title: "Scaling for Enterprise" +--- +<PlanAvailability slug="ent-plus" /> + +Mattermost is designed to scale from small teams hosted on a single server to large enterprises running in cluster-based, highly available deployment configurations. + +- Mattermost supports any 64-bit x86 processor architecture +- **Databases supported**: PostgreSQL, Amazon RDS for PostgreSQL +- **Storage supported**: Amazon S3 or a local filestore + +Server requirements vary based on usage and we highly recommend that you run a pilot before an enterprise-wide deployment in order to estimate full scale usage based on your specific organizational needs. + +## Backing storage + +Review detailed [write and read storage benchmark results](/administration-guide/scale/backing-storage-benchmarks) for supported storage options including local file system (EBS, gp3), network file system (EFS), and object storage (S3) to make informed decisions based on your use case and infrastructure needs. + +## Enterprise search + +We highly recommend a dedicated server for large enterprise deployments to run highly efficient database searches in a cluster environment. + +For deployments with over 5 million posts, [Enterprise search](/administration-guide/scale/enterprise-search) using [Elasticsearch](/administration-guide/scale/enterprise-search#elasticsearch) or [AWS OpenSearch Service](/administration-guide/scale/enterprise-search#aws-opensearch-service) is required for optimized search performance, dedicated indexing and usage resourcing via cluster support without performance degradation and timeouts, resulting in faster, more predicable search results. + +## High availability + +A [high availability cluster-based deployment](/administration-guide/scale/high-availability-cluster-based-deployment) enables a Mattermost system to maintain service during outages and hardware failures through the use of redundant infrastructure. + +## Redis + +[Redis](/administration-guide/scale/redis) is an in-memory data structure store that can be used as a database, cache, and message broker. Mattermost uses Redis as an external cache to improve performance at scale. When properly configured, Redis can help support Mattermost installations with more than 100,000 users by providing improved performance through efficient caching. + +## Available reference architectures + +The following reference architectures are available as recommended starting points for your self-hosted Mattermost deployment, where user counts refer to the number of concurrent users for a given deployment. The number of concurrent numbers is commonly lower than the total number of user accounts. + +- [Scale up to 200 users](/administration-guide/scale/scale-to-200-users) - Learn how to scale Mattermost to up to 200 users. +- [Scale up to 2000 users](/administration-guide/scale/scale-to-2000-users) - Learn how to scale Mattermost to up to 2000 users. +- [Scale up to 15000 users](/administration-guide/scale/scale-to-15000-users) - Learn how to scale Mattermost to up to 15000 users. +- [Scale up to 30000 users](/administration-guide/scale/scale-to-30000-users) - Learn how to scale Mattermost to up to 30000 users. +- [Scale up to 50000 users](/administration-guide/scale/scale-to-50000-users) - Learn how to scale Mattermost to up to 50000 users. +- [Scale up to 80000 users](/administration-guide/scale/scale-to-80000-users) - Learn how to scale Mattermost to up to 80000 users. +- [Scale up to 90000 users](/administration-guide/scale/scale-to-90000-users) - Learn how to scale Mattermost to up to 90000 users. +- [Scale up to 100000 users](/administration-guide/scale/scale-to-100000-users) - Learn how to scale Mattermost to up to 100000 users. +- [Scale up to 200000 users](/administration-guide/scale/scale-to-200000-users) - Learn how to scale Mattermost to up to 200000 users. + +<Important> + +Due to constraints in testing, the proxy instance specifications were fixed for all the scaling tests from which we derived these reference architectures. This was done to avoid a combinatorial explosion of variables in tests, but it resulted in minor gaps in our understandings of certain aspects of the reference architectures. In particular, the proxy instance is overspecified for the smaller user counts. + +</Important> + +## Testing methodology and updates + +All tests were executed with the custom load test tool built by the Mattermost development teams to determine supported users for each deployment size. Over time, this guide will be updated with new deployment sizes, deployment architectures, and newer versions of the Mattermost Server will be tested using an ESR. + +At a high level, each deployment size was fixed (Mattermost server node count/sizing, database reader/writer count/sizing), and unbounded tests were used to report the maximum numbers of concurrent users the deployment can support. Each test included populated PostgreSQL v14 databases and a post table history of 100 million posts, ~200000 users, 20 teams, and ~720000 channels to provide a test simulation of a production Mattermost deployment. + +Tests were defined by configuration of the actions executed by each simulated user (and the frequency of these actions) where the coordinator metrics define a health system under load. Tests were performed using the Mattermost v9.5 Extended Support Release (ESR). Job servers weren't used. All tests with more than a single app node had an NGINX proxy running in front of them. + +For the last test of 200K users, further infrastructure changes were made. Elasticsearch nodes were added. A Redis instance was added, and multiple NGINX proxies were used to distribute traffic evenly across all nodes in the cluster. More details can be found on the [scale to 200000 users](/administration-guide/scale/scale-to-200000-users) documentation page. + +Full testing methodology, configuration, and setup is available, incluidng a [fixed database dump with 100 million posts](https://us-east-1.console.aws.amazon.com/backup/home?region=us-east-1#/resources/arn%3Aaws%3Ards%3Aus-east-1%3A729462591288%3Acluster%3Adb-pg-100m-posts-v9-5-5). Visit the [Mattermost Community](https://community.mattermost.com/) and join the [Developers: Performance channel](https://community.mattermost.com/core/channels/developers-performance) for details. + +The performance specifications and user capacities provided in these reference architectures are based on extensive testing conducted in AWS environments. + +For Azure deployments, the instance specifications have been extrapolated using equivalent configurations, drawing upon AWS performance data and industry expertise. While these configurations are designed to meet the stated requirements, we have not yet conducted formal testing in Azure environments to validate performance under load. Azure Blob Storage support is in active development, and not yet natively supported by Mattermost. + +## Mattermost load testing tools + +Mattermost provides a set of tools written in Go to help profiling Mattermost under heavy load, simulating real-world usage of a server installation at scale. The [Mattermost Load Test Tool](https://github.com/mattermost/mattermost-load-test-ng) estimates the maximum number of concurrently active users the target system supports, and enables you to control the load to generate. + +Visit the [Mattermost Load Test Tool](https://github.com/mattermost/mattermost-load-test-ng/tree/master/docs) documentation on GitHub for details on getting started with the tools, and visit [the Go documentation](https://pkg.go.dev/github.com/mattermost/mattermost-load-test-ng) for code-specific documentation details. + +<Important> + +- The Mattermost Load Test Tool was designed by and is used by our performance engineers to compare and benchmark the performance of the service from month to month to prepare for new releases. It's also used extensively in developing our recommended hardware sizing. +- We recommend deploying [Prometheus and Grafana](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) with our [dashboards](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring#getting-started) for ongoing monitoring and scale guidance. +- If you encounter performance concerns, we recommend [collecting performance metrics](/administration-guide/scale/collect-performance-metrics) and sharing them with us as a first troubleshooting step. + +</Important> + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/administration-guide/scale/server-architecture.mdx b/docs/main/administration-guide/scale/server-architecture.mdx new file mode 100644 index 000000000000..494eb4dda8ee --- /dev/null +++ b/docs/main/administration-guide/scale/server-architecture.mdx @@ -0,0 +1,113 @@ +--- +title: "Deployment Architecture at Scale" +--- +The following diagrams detail suggested architecture configurations of [high availability Mattermost deployments](/administration-guide/scale/high-availability-cluster-based-deployment#deployment-guide) at different scales. Hardware and infrastructure requirements will vary significantly based on usage and policies. See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for reference architecture guidance at scale, including hardware and infrastructure requirements. + +High availability in Mattermost consists of running redundant Mattermost application servers, redundant database servers, and redundant load balancers so that failure of any one of these components does not interrupt operation of the system. Upon failure of one component, the remaining application servers, database servers, and load balancers must be sized and configured to carry the full load of the system. If this requirement is not met, an outage of one component can result in an overload of the remaining components, causing a complete system outage. + +<Important> + +Mattermost does not support high availability deployments spanning multiple datacenters. All nodes in a high availability cluster must reside within the same datacenter to ensure proper functionality and performance. + +</Important> + +You can apply most configuration changes and dot release security updates without interrupting service, provided that you update the system components in the correct sequence. Changes to configuration settings that require a server restart, and server version upgrades that involve a change to the database schema, require a short period of downtime. Downtime for a server restart is around 5 seconds. For a database schema update, downtime can be up to 30 seconds. + +## Designed for scale + +Mattermost is designed to be able to handle a large number of concurrent users, and the architecture can be scaled up or down as needed. The architecture is also designed to be flexible, allowing for the addition of new components or services as needed. The following diagrams show the recommended architecture for Mattermost deployments at 5,000, 10,000, 25,000, and 50,000 users. The diagrams are organized by user count and include a general diagram and AWS and Azure versions of each diagram. See the [scaling for enterprise](/administration-guide/scale/scaling-for-enterprise) documentation for more information on scaling Mattermost deployments. + +- Each generalized diagram represents a full High Availability deployment across all critical components. The proxy, database, file storage, and Elasticsearch layers can be replaced by cloud services. +- Each AWS diagram represents a full High Availability deployment on Amazon Web Services making full use of the available services. +- Each Azure diagram represents a full High Availability deployment on Microsoft Azure making full use of the available services. +- Push proxy can be replaced by the Mattermost [hosted push notification service](/administration-guide/configure/environment-configuration-settings#hosted-push-notifications-service-hpns)). + +<div class="tab"> + +AWS + +<div class="tab"> + +5,000 users + +<img src="/images/MattermostDeployment5kaws.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +10,000 users + +<img src="/images/MattermostDeployment10kaws.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +25,000 users + +<img src="/images/MattermostDeployment25kaws.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +50,000 users + +<img src="/images/MattermostDeployment50kaws.png" class="bg-white" alt="image" /> + +</div> + +</div> + +<div class="tab"> + +Azure + +<div class="tab"> + +5,000 users + +<img src="/images/MattermostDeployment5kAzure.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +10,000 users + +<img src="/images/MattermostDeployment10kAzure.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +25,000 users + +<img src="/images/MattermostDeployment25kAzure.png" class="bg-white" alt="image" /> + +</div> + +<div class="tab"> + +50,000 users + +<img src="/images/MattermostDeployment50kAzure.png" class="bg-white" alt="image" /> + +</div> + +</div> + +<div class="tab"> + +Oracle + +<div class="tab"> + +5,000 users + +<img src="/images/MattermostDeployment5kOracle.png" class="bg-white" alt="image" /> + +</div> + +</div> diff --git a/docs/main/administration-guide/upgrade-mattermost.mdx b/docs/main/administration-guide/upgrade-mattermost.mdx new file mode 100644 index 000000000000..a2db11c14c66 --- /dev/null +++ b/docs/main/administration-guide/upgrade-mattermost.mdx @@ -0,0 +1,19 @@ +--- +title: "Upgrade Mattermost" +--- +<PlanAvailability slug="all-commercial" /> + +Stay up to date with the latest features and improvements. + +- [Important upgrade notes](/administration-guide/upgrade/important-upgrade-notes) - Find version-specific upgrade considerations. +- [Prepare to upgrade Mattermost](/administration-guide/upgrade/prepare-to-upgrade-mattermost) - Learn how to prepare for a Mattermost upgrade. +- [Communicate scheduled maintenance best practices](/administration-guide/upgrade/communicate-scheduled-maintenance) - Learn best practices for communicating scheduled server maintenance in advance of a service maintenance window. +- [Upgrade Mattermost Server](/administration-guide/upgrade/upgrading-mattermost-server) - Learn the basics of upgrading your Mattermost server to the latest version. +- [Upgrade Mattermost in Kubernetes and High Availability environments](/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha) - Learn how to upgrade Mattermost in Kubernetes and High Availability environments. +- [Upgrade PostgreSQL](/administration-guide/upgrade/upgrading-postgres) - Learn how to upgrade your PostgreSQL database server. +- [Upgrade Team Edition to Enterprise Edition](/administration-guide/upgrade/enterprise-install-upgrade) - Learn how to upgrade your Mattermost Team Edition server to Enterprise Edition. +- [Administrator onboarding tasks](/administration-guide/upgrade/admin-onboarding-tasks) - Learn about the onboarding tasks for administrators after an upgrade. +- [Enterprise roll-out-checklist](/administration-guide/upgrade/enterprise-roll-out-checklist) - Learn about the roll-out checklist for enterprise users. +- [Welcome email to end users](/administration-guide/upgrade/welcome-email-to-end-users) - Learn how to send a welcome email to end users after an upgrade. +- [Downgrade Mattermost Server](/administration-guide/upgrade/downgrading-mattermost-server) - Find out how to roll back to older versions of Mattermost. +- [Open source components](/administration-guide/upgrade/open-source-components) - Find out about the open source components used in Mattermost. diff --git a/docs/main/administration-guide/upgrade/admin-onboarding-tasks.mdx b/docs/main/administration-guide/upgrade/admin-onboarding-tasks.mdx new file mode 100644 index 000000000000..98df5f8baae0 --- /dev/null +++ b/docs/main/administration-guide/upgrade/admin-onboarding-tasks.mdx @@ -0,0 +1,144 @@ +--- +title: "Administrator onboarding tasks" +--- +<PlanAvailability slug="all-commercial" /> + +This document provides instructions for common administrator tasks, including some recommendations on tasks to prepare your Mattermost deployment to onboard users. + +## Getting started tasks + +1. Once you've installed and deployed Mattermost, ensure all configuration settings are appropriately set under **System Console \> Environment** including: + +> - Web server +> - Database +> - File storage +> - SMTP +> - Push Notification server + +These settings can also be set in the `config.json` file. Please see our [configuration settings documentation](/administration-guide/configure/configuration-settings) for a full listing of all configuration settings. + +2. Adjust settings under **System Console \> Site Configuration** to brand and customize how users will interact with the site. Be sure to update the Support Email and Help Link in Mattermost under **System Console \> Site Configuration \> Customization** to provide your users a resource for password resets or questions on their Mattermost account. + +> - The Support email is used on email notifications and during tutorial for users to ask support questions. +> - The Help Link is on the Mattermost login page, sign-up pages, and Main Menu and can be used to to link to your help desk ticketing system. + +These settings can also be set in the `config.json` file. Please see our [configuration settings documentation](/administration-guide/configure/configuration-settings) for a full listing of all configuration settings. + +3. Begin to onboard users by enabling account creation or by connecting an authentication service to assist with user provisioning. + +- Users can be pre-provisioned with migration and bulk loading data processes based on prior collaboration systems. Please see our [migration guide](/administration-guide/onboard/migrating-to-mattermost#migration-guide) and [bulk loading documentation](/administration-guide/onboard/bulk-loading-data) for additional details. +- [AD/LDAP authentication](/administration-guide/onboard/ad-ldap) and [SAML authentication](/administration-guide/onboard/sso-saml) are available for some subscription plans, providing identity management, single sign-on, and automatic account provisioning. + +If your organization requires more structure and project management artifacts for the implementation of Mattermost, please see our [Enterprise roll out checklist](/administration-guide/upgrade/enterprise-roll-out-checklist). + +## Important administration notes + +**DO NOT manipulate the Mattermost database** + +- In particular, DO NOT manually delete data from the database directly. Mattermost is designed as a continuous archive and cannot be supported after manual manipulation. +- If you need to permanently delete a team or user, use the [mmctl user delete](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-delete) command or the [mmctl user deletall](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-deleteall) command. + +## Common tasks + +**Creating System admin account from the command line** + +- If the System admin leaves the organization or is otherwise unavailable, you can use the [mmctl roles](/administration-guide/manage/mmctl-command-line-tool#mmctl-roles) commands to assign the *system_admin* role to an existing user. +- The user needs to log out and log back in before the *system_admin* role is applied. + +**Migrating to AD/LDAP or SAML from email-based authentication** + +- If you have a Mattermost Enterprise or Professional plan, you can migrate from email authentication to Active Directory/LDAP or to SAML Single Sign-on. To set up Active Directory/LDAP, see [Active Directory/LDAP Setup](/administration-guide/onboard/ad-ldap). To set up SAML Single Sign-on, see [SAML Single-Sign-On](/administration-guide/onboard/sso-saml). +- After the new authentication method is enabled, existing users cannot use the new method until they go to **Settings \> Security \> Sign-in method** and select **Switch to using AD/LDAP** or **Switch to using SAML Single Sign-on**. After they have switched, they can no longer use their email and password to log in. + +**Deactivating a user** + +- System admins can go to **System Console \> Users** for a list of all users on the server. The list can be searched and filtered to make finding the user easier. Click the user's role and in the menu that opens, click **Deactivate**. +- To preserve audit history, users are typically never deleted from the system. If permanently deleting a user is necessary (e.g. for the purposes of [GDPR](https://gdpr-info.eu/)), an [mmctl command](/administration-guide/manage/mmctl-command-line-tool) can be used to do so. +- Note that AD/LDAP user accounts cannot be deactivated from Mattermost; they must be deactivated from your Active Directory. + +**Checking for a valid license in Enterprise Edition without logging in** + +- Open the log file `mattermost.log`. It's usually in the `mattermost/logs/` directory but might be elsewhere on your system. Find the last occurrence of a log entry that starts with the text `[INFO] License key`. If the license key is valid, the complete line should be similar to the following example: + +``` text +[2017/05/19 16:51:40 UTC] [INFO] License key valid unlocking enterprise features. +``` + +## User experience optimizations + +We highly recommend the following best practices, configuration options, and features for an optimal Mattermost user experience. + +**1. Upgrade your Mattermost server** + +When you upgrade your Mattermost server frequently, your users can access new features, improved user experiences, bug fixes, security fixes, and mobile app compatibility. + +Mattermost releases regular updates to [Mattermost Team Edition](https://mattermost.com/) and [Mattermost Enterprise Edition](https://mattermost.com/pricing/). See the [release life cycle](/product-overview/releases-lifecycle) documentation for component life cycle details details. + +Upgrading your Mattermost server only takes a few minutes. See the [Upgrade Guide](/administration-guide/upgrade/upgrading-mattermost-server) for step-by-step instructions. + +**2. Install plugins** + +You can enable plugins and integrations to connect your team's workflows and toolsets into Mattermost. Plugins and integrations customize and extend the Mattermost platform. + +**Install and manage plugins** + +To enable and manage plugins, go to **System Console \> Plugins**. Next, install plugins from **Product menu \> Marketplace**. See the [Marketplace](https://developers.mattermost.com/integrate/admin-guide/admin-plugins-beta/#marketplace) documentation for details. + +Consider installing, configuring, and enabling the following community integrations for your users: +- Create polls with [Matterpoll](https://mattermost.com/marketplace/matterpoll/). +- Share GIFs with [GIF Commands](https://mattermost.com/marketplace/giphy-plugin/). +- Create and share memes with [Memes](https://mattermost.com/marketplace/memes-plugin/). +- Set personal reminders with [Remind](https://mattermost.com/marketplace/remind-plugin/). +- Create and share to do items with [Todo](https://github.com/mattermost/mattermost-plugin-todo). +- Customize welcome messages for new users with [WelcomeBot](https://mattermost.com/marketplace/welcomebot-plugin/). + +Explore all plugins and integrations available in the [Mattermost Marketplace](https://mattermost.com/marketplace/). + +**Enable and manage integrations** + +To enable integrations such as webhooks, slash commands, OAuth2.0, and bots, to go **System Console \> Integrations**. More information on these integrations can be found [here](https://developers.mattermost.com/integrate/other-integrations/). + +**3. Enable automatically extended sessions** + +Keep your desktop and mobile users logged in and [extend user sessions automatically](https://mattermost.com/blog/session-expiry-experience/) by setting **System Console \> Sessions \> Extend session length with activity** to **true**. See the [Extend session length with activity](/administration-guide/configure/environment-configuration-settings#extend-session-length-with-activity) configuration settings documentation for details. + +**4. Enable full content push notifications** + +Enable push notifications on mobile devices to deliver messages in real time by setting **System Console \> Push Notification Server \> Enable Push Notifications** to **Use TPNS**. See the [Push notification server](/administration-guide/configure/environment-configuration-settings#push-notification-server) configuration settings documentation for details. + +Enable full content push notifications, including the sender’s name, the channel name, and the message text, by setting **System Console \> Notifications \> Push Notification Contents** to **Full message contents**. See the [Push notification contents](/administration-guide/configure/site-configuration-settings#push-notification-contents) configuration settings documentation for details. + +<Note> + +- Mattermost subscription plans allow you to enable HPNS that includes production-level uptime SLAs. +- Mattermost Enterprise customers can [enable ID-Only push notifications](/administration-guide/configure/site-configuration-settings#push-notification-contents) so push notification content is not passed through Apple Push Notification Service (APNS) or Google Firebase Cloud Messaging (FCM) before reaching the device. The ID-only push notification setting [offers a high level of privacy](https://mattermost.com/blog/id-only-push-notifications/) while allowing team members to benefit from mobile push notifications. + +</Note> + +**5. Enable custom emoji** + +[Emojis](/end-user-guide/collaborate/react-with-emojis-gifs) enable users to express concepts such as emotions and physical gestures in messages. Enable the emoji picker by setting **System Console \> Emoji \> Enable Emoji Picker** to **true**. See the [Enable emoji picker](/administration-guide/configure/site-configuration-settings#enable-emoji-picker) configuration settings documentation for details. + +Empower users to create and share their own custom emojis by setting **System Console \> Emoji \> Enable Custom Emoji** to **true**. See the [Enable custom emoji](/administration-guide/configure/site-configuration-settings#enable-custom-emoji) configuration settings documentation for details. + +**6. Enable GIF picker** + +GIFs are animated images that can make messaging more fun and engaging. Enable users to access the Mattermost GIF picker from the message draft area by setting **System Console \> GIF (Beta) \> Enable GIF Picker** to **true**. See the [Enable GIF picker](/administration-guide/configure/integrations-configuration-settings#enable-gif-picker) configuration settings documentation for details. + +**7. Enable link previews** + +Link previews provide a visual glimpse of relevant content for links shared in messages. Enable link previews by setting **System Console \> Posts \> Enable Link Previews** to **true**. See the [Enable link previews](/administration-guide/configure/site-configuration-settings#enable-website-link-previews) configuration settings documentation for details. + +**8. Enable batched email notifications** + +Email notifications can be batched together so users don’t get overwhelmed with too many emails. + +Enable email notifications first by setting **System Console \> Notifications \> Enable Email Notifications** to **true**. See the [Enable email notifications](/administration-guide/configure/site-configuration-settings#enable-email-notifications) configuration settings documentation for details. Note that email notifications require an [SMTP email server](/administration-guide/configure/environment-configuration-settings#smtp-server) to be configured. + +Then, enable batched email notifications by setting **System Console \> Notifications \> Enable Email Batching** to **true**. See the [Enable email batching](/administration-guide/configure/site-configuration-settings#enable-email-batching) configuration settings documentation for details. Note that email batching is not available if you are running your deployment in [High Availability](/administration-guide/scale/high-availability-cluster-based-deployment). + +**9. Enable Elasticsearch** + +Mattermost Enterprise customers can enable [enterprise search](/administration-guide/scale/enterprise-search) for optimized search performance at enterprise-scale. Both Elasticsearch and AWS OpenSearch solve many known issues with full text database search, such as dots, dashes, and email addresses returning unexpected results. + +Enable Elasticsearch by setting **System Console \> Elasticsearch \> Enable Indexing** to **true**. See the [Elasticsearch](/administration-guide/configure/environment-configuration-settings#enterprise-search) configuration settings documentation for details. Enabling Elasticsearch requires [setting up an Elasticsearch server](/administration-guide/scale/elasticsearch-setup#set-up-elasticsearch). diff --git a/docs/main/administration-guide/upgrade/communicate-scheduled-maintenance.mdx b/docs/main/administration-guide/upgrade/communicate-scheduled-maintenance.mdx new file mode 100644 index 000000000000..04851cf9c536 --- /dev/null +++ b/docs/main/administration-guide/upgrade/communicate-scheduled-maintenance.mdx @@ -0,0 +1,188 @@ +--- +title: "Communicate scheduled maintenance best practices" +--- +<PlanAvailability slug="all-commercial" /> + +Performing scheduled maintenance on a Mattermost server with 1,000 or more users requires advanced planning and a clear communication strategy to ensure minimal disruption and maximum transparency. + +This guide provides best practices for notifying users via email and Mattermost channels, updating the load balancer’s error message, and configuring a dismissable banner to inform users of the upcoming maintenance. + +## Communication strategy + +A well-defined communication strategy is essential for informing users before, during, and after maintenance. The key components of this strategy are: + +- Define a clear maintenance window in which the self-hosted Mattermost server will be unavailable. + + > - Mattermost Cloud deployments have predefined service windows scheduled from 8:00-10:00 UTC on Saturdays only (when applicable) unless an exception has been made and communicated to impacted customers. + +- [Email notifications](#email-templates): Send structured and consistent emails to users at intervals of 7 days, 3 days, and 1 day before the scheduled maintenance window. + +- [Channel-based reminders](#channel-reminder-templates): [Send messages](/end-user-guide/collaborate/send-messages) similar to the emails in relevant Mattermost channels at the same intervals as the email notifications. + +- [Mattermost Banner notification](#banner-notification): Set a [system-wide notification](/administration-guide/manage/system-wide-notifications) to display at the top of the Mattermost instance ahead of the maintenance window and outage. + +- [Display a load balancer message](#display-load-balancer-message): Update the load balancer to show a maintenance message during the scheduled maintenance window of downtime. + +## Notification templates + +### Email Templates + +#### 7-Day notice email + +**Email subject**: Scheduled Maintenance Notification: \[Date and Time\] + +``` none +Dear Mattermost Users, + +This is a notification that our Mattermost server will undergo scheduled +maintenance on [Date] from [Start Time] to [End Time] [Time Zone]. +During this time, the Mattermost instance will be unavailable. + +We apologize for any inconvenience this may cause and appreciate your +understanding as we work to improve our service. + +If you have any questions or concerns, please contact our +support team at [Support Email]. + +Thank you for your cooperation. + +Best regards, +[Your Name] +[Your Position] +``` + +#### 3-Day notice email + +**Email subject**: Reminder: Scheduled Maintenance on \[Date and Time\] + +``` none +Dear Mattermost Users, + +This is a reminder that our Mattermost server will undergo scheduled +maintenance on [Date] from [Start Time] to [End Time] [Time Zone]. +The Mattermost instance will be unavailable during this period. + +If you have any questions or concerns, please contact our +support team at [Support Email]. + +Thank you for your cooperation. + +Best regards, +[Your Name] +[Your Position] +``` + +#### 1-Day notice email + +**Email subject**: Final Reminder: Scheduled Maintenance Tomorrow on \[Date and Time\] + +``` none +Dear Mattermost Users, + +This is a final reminder that our Mattermost server will undergo scheduled +maintenance tomorrow, [Date], from [Start Time] to [End Time] [Time Zone]. +The Mattermost instance will be unavailable during this period. + +If you have any questions or concerns, please contact our +support team at [Support Email]. + +Thank you for your cooperation. + +Best regards, +[Your Name] +[Your Position] +``` + +### Channel reminder templates + +#### 7-Day channel reminder + +``` none +@all Please be advised that our Mattermost server will +undergo scheduled maintenance on [Date], +from [Start Time] to [End Time] [Time Zone]. +The instance will be unavailable during this time. We appreciate your understanding. +``` + +#### 3-Day channel reminder + +``` none +@all This is a reminder that our Mattermost server will +undergo scheduled maintenance on [Date], +from [Start Time] to [End Time] [Time Zone]. +Please plan accordingly. +``` + +#### 1-Day channel reminder + +``` none +@all Final reminder: Our Mattermost server will +undergo scheduled maintenance tomorrow, [Date], +from [Start Time] to [End Time] [Time Zone]. +Thank you for your cooperation. +``` + +### Banner notification + +Sample message: + +``` text +Heads up! Scheduled maintenance is planned for [Date], +between [Start Time] and [End Time] [Time Zone]. +The Mattermost instance will be unavailable during this time. +``` + +Users can dismiss the banner until they log in again, or until you update the banner. + +### Display load balancer message + +Configure the load balancer to display a notification message during the scheduled maintenance window of downtime. + +1. Identify the load balancer you are using (e.g., AWS, HAProxy). +2. Edit configuration. Adjust paths and configurations according to your specific environment. + +> - For AWS, navigate to the Load Balancer configurations in the EC2 console. +> - For HAProxy, edit the `haproxy.cfg` file. + +<Important> + +We strongly recommend adding headers, where needed in your infrastructure, to avoid outdated information being communicated to your users during and following server maintenance. + +</Important> + +See the sample message HTML below to use as a starting point: + +``` html +HTML Template +<!DOCTYPE html> +<html> +<head> + <title>Maintenance in Progress + + + +
+

Maintenance in Progress

+

Our Mattermost server is currently undergoing scheduled maintenance.

+

Estimated downtime: [Start Time] to [End Time] [Time Zone]

+

We apologize for any inconvenience and thank you for your understanding.

+

If you have any questions, please contact our support team at [Support Email].

+
+ + +``` diff --git a/docs/main/administration-guide/upgrade/downgrading-mattermost-server.mdx b/docs/main/administration-guide/upgrade/downgrading-mattermost-server.mdx new file mode 100644 index 000000000000..e6142b179131 --- /dev/null +++ b/docs/main/administration-guide/upgrade/downgrading-mattermost-server.mdx @@ -0,0 +1,47 @@ +--- +title: "Downgrade Mattermost Server" +--- + + +In most cases you can downgrade Mattermost Server using the same steps as [upgrading mattermost server](/upgrading-mattermost-server). Server binaries can be found in the [Mattermost server version archive](/product-overview/version-archive) documentation. + + + +- We don't recommend downgrading more than one major version back from your current installation. +- We strongly recommend testing the downgrade in a staging environment first to identify any potential issues. +- Ensure that your plugins and integrations are compatible with the downgraded version you're moving to. + + + +## Prepare for downgrade + +Before downgrading the Mattermost server, we strongly recommend the following preparation steps. + +1. Back up your data: Ensure you have a full backup of your database and Mattermost application files. This is crucial in case you need to revert any changes. + +> 1. Back up your database using your organization’s standard procedures for backing up the database. +> 2. Back up your application by copying into an archive folder (e.g. `mattermost-back-YYYY-MM-DD-HH-mm`). Ensure to copy your Mattermost configuration files and any other necessary application files. + +2. Carefully review the Mattermost changelog for the version you are downgrading to in order to understand any potential issues or incompatibilities. +3. Verify the current schema version of your database using the [mattermost db version --all](/administration-guide/manage/command-line-tools#mattermost-db-version) command. Also, if you aren't sure about the target schema, you can verify the target schema version (i.e., applied migrations) by checking the public [GitHub repository](https://github.com/mattermost/mattermost/blob/master/server/channels/db/migrations/migrations.list) (Select the tag for desired version). + +## Perform the downgrade + +1. Stop the Mattermost service to ensure that no data is being written to the database during the downgrade process. +2. If the database schema has changed between versions, you must downgrade the schema. Use the newer mattermost binary to perform the downgrade using the [mattermost db downgrade](/administration-guide/manage/command-line-tools#mattermost-db-downgrade) command. For example: `mattermost db downgrade 128,127,126` + + + +You can review downgrade changes before committing them if you have used the `--save-plan` option while upgrading Mattermost. It has both forwards and backwards SQL scripts. This option allows you to avoid specifying migrations to be downgraded, and allows you to use older versions of Mattermost to perform the downgrade. For example: `mattermost db downgrade migration_plan_128_127.json`. + + + +3. There may be changes in configuration settings between versions. Revert any necessary configuration changes in the `config.json` file to match the downgraded version's expectations and support. + +## After the downgrade + +Replace the current Mattermost application binary with the version you want to downgrade to. Make sure to use the binary of the target version. The newer Mattermost binary contains the downgrade SQL for the migrations to be rolled back. The newer binary version is used to perform the downgrade; then you start using the application binary of the version you want to downgrade to. + +1. Restart the Mattermost Server after completing the downgrade. +2. Check the logs and test the application to ensure that everything is functioning correctly. +3. Inform your users about the downgrade and any potential changes they might experience. diff --git a/docs/main/administration-guide/upgrade/enterprise-install-upgrade.mdx b/docs/main/administration-guide/upgrade/enterprise-install-upgrade.mdx new file mode 100644 index 000000000000..69430ea8f4a1 --- /dev/null +++ b/docs/main/administration-guide/upgrade/enterprise-install-upgrade.mdx @@ -0,0 +1,98 @@ +--- +title: "Upgrade Team Edition to Enterprise Edition" +--- +If you're evaluating Mattermost using Team Edition, you'll need to upgrade to Mattermost Enterprise Edition before you can start a trial or upload a license that enables Enterprise features. The open source Mattermost Team Edition is functionally identical to the commercial Enterprise Edition, but there is no ability to start a trial or unlock paid features. + +## Upgrade to Enterprise Edition + +### Check your edition and version + +Open **Product menu \> About Mattermost** to check your edition and version from the web or desktop interface. + +- **Mattermost Entry** indicates you're using the licensed edition of Mattermost without a paid license. +- **Mattermost Professional** indicates you're using the licensed edition of Mattermost with a paid professional license. +- **Mattermost Enterprise** indicates you're using the licensed edition of Mattermost with a paid enterprise license. +- **Mattermost Enterprise Advanced** indicates you're using the licensed edition of Mattermost with a paid enterprise advanced license. +- **Mattermost Team Edition** indicates you're using the open source version and need to upgrade to a licensed edition before a license key can be applied. + +### Upgrade via System Console (Recommended) + +Most standalone servers can upgrade Team Edition to Enterprise Edition in minutes using the built-in conversion tool in the System Console, and this is our recommended approach. + +Go to **Product menu \> System Console \> Edition and License** and select **Upgrade to Enterprise Edition**. + +During the upgrade process, the Mattermost Enterprise Edition binary file that matches your current server version is downloaded, decompressed, and extracted. The Team Edition binary is then replaced by the Enterprise Edition version. + + + +If you're using a modified version of Mattermost, using this tool will overwrite your changes and replace them with the official Enterprise Edition binary. + + + +Once this process is complete, you're prompted to restart your server. The Mattermost version listed in **Product menu \> System Console \> Edition and License** will change from **Team Edition** to **Mattermost Entry**, and you can now upload a professional, enterprise, or enterprise advanced license to unlock paid features. + +### Upgrade manually + +You can alternatively replace the Mattermost Team Edition binary with a Mattermost Enterprise Edition binary when running a regularly scheduled server upgrade via this [upgrade procedure](/administration-guide/upgrade/upgrading-mattermost-server). + +We recommend backing up Mattermost prior to upgrading. The [migration guide](/administration-guide/onboard/migrating-to-mattermost) documentation outlines the process required to back up and restore your database. + +## Upgrade to Enterprise Edition in GitLab Omnibus + +GitLab Omnibus runs the open source Mattermost Team Edition. To upgrade to Mattermost Enterprise Edition, follow these steps: + +1. Disable the built-in Mattermost instance on GitLab Omnibus by going to `/etc/gitlab/gitlab.rb` and setting the following line to `false`: + +> ``` text +> mattermost['enable'] = false +> ``` +> +> Then run the following command to apply the updated setting: +> +> ``` +> sudo gitlab-ctl reconfigure +> ``` + +2. Install Mattermost using one of the guides above. +3. Migrate the database used by GitLab Mattermost for your new Enterprise Edition instance. +4. (Optional) Set up [GitLab slash command integration](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html) with your Mattermost instance. + +## Troubleshooting + +### Permissions and limitations + +If you're using a package manager, such as Gitlab Omnibus, to manage your Mattermost installation, the Mattermost system user won't have sufficient permissions to perform the upgrade. If this is the case, you'll need to change the file permissions manually. + +Changing the permissions in this way doesn't affect your Mattermost deployment or impact any data. The permission change is done solely for the upgrade. + +To change the permissions using the command line on the Mattermost server, you need access to the command line tool as *mattermost* user: + +1. Open the command line tool on the Mattermost server and `cd` to the Mattermost installation directory. +2. Run the following commands, replacing `` with the appropriate path - typically `/opt/mattermost/bin/mattermost`) to change the ownership of the binary file to *mattermost* user and grant write access: + +> ``` sh +> chown mattermost +> chmod +w +> ``` + +3. In the Mattermost System Console, retry the upgrade. +4. When the upgrade is complete, return to the command prompt on the Mattermost server and run the following command to restore the file permissions, replacing `` with the appropriate value: + +> ``` sh +> chown +> chmod -w +> ``` + +### Mattermost has reverted to Team Edition + +On a managed deployment, if you upgraded Team Edition to Enterprise Edition, and then upgraded again, the upgrade will have overwritten Enterprise Edition with the latest version of Team Edition. + +You can convert to Enterprise Edition again by following the steps above. If you plan to use Mattermost Enterprise Edition permanently, we recommend migrating your server to a self-hosted deployment. + +### Incompatible system architecture + +This System Console tool is only compatible with Linux systems using x86-64 architecture. If you're running Mattermost on a different architecture, follow the [manual upgrade process](#upgrade-manually) instead. + +### Can't retrieve Enterprise Edition binary file + +If the upgrade fails due to file retrieval failure, unavailable binary, or connectivity error, please check your proxy settings and try again. If the problem persists, follow the [manual upgrade process](#upgrade-manually) instead. diff --git a/docs/main/administration-guide/upgrade/enterprise-roll-out-checklist.mdx b/docs/main/administration-guide/upgrade/enterprise-roll-out-checklist.mdx new file mode 100644 index 000000000000..2a7f3eb00590 --- /dev/null +++ b/docs/main/administration-guide/upgrade/enterprise-roll-out-checklist.mdx @@ -0,0 +1,371 @@ +--- +title: "Enterprise roll out checklist" +--- + + +This checklist is intended to serve as a guide to Enterprises who are rolling out Mattermost to thousands of users. + +## Checklist overview + +### Prepare for the roll out + +- [1. Define the roll out project](#define-the-roll-out-project) +- [2. Validate essential security and compliance requirements](#validate-essential-security-and-compliance-requirements) +- [3. Create development, staging, and production environments](#create-development-staging-and-production-environments) +- [4. Configure and customize your Mattermost site](#configure-and-customize-your-mattermost-site) +- [5. Test production performance and redundancy](#test-production-performance-and-redundancy) + +### Roll out Mattermost + +- [1. Define your team and channel strategy](#define-your-team-and-channel-strategy) +- [2. Enable key integrations](#enable-key-integrations) +- [3. Prepare for user onboarding](#prepare-for-user-onboarding) +- [4. Deploy client apps](#deploy-client-apps) +- [5. Roll out to groups of users](#roll-out-to-groups-of-users) +- [6. Drive adoption](#drive-adoption) + +### Review the roll out + +- [1. Review project charter success metrics](#review-project-charter-success-metrics) +- [2. Review and analyze usage](#review-and-analyze-usage) +- [3. Analyze system performance](#analyze-system-performance) +- [4. Harden security](#harden-security) +- [5. Perform maintenance tasks](#perform-maintenance-tasks) + +## Checklist details + +### Prepare for the roll out + +Much of the preparation work is focused on ensuring the environment is deployed and secured prior to onboarding users. + +#### 1. Define the roll out project + +- Define key stakeholders and project team members + +> - Example project team members: Project Manager, Network Administrator, Database Administrator, Corporate Directory Administrator, Security & Compliance Administrator(s), User Support, User Champions, User Trainers + +- Define use cases and requirements for teams, their workflows and their integrations + +> - Resource: [https://mattermost.com/blog/27-things-enterprises-can-learn-startups-increase-productivity/](https://mattermost.com/blog/27-things-enterprises-can-learn-startups-increase-productivity/) + +- Define success criteria, goals and metrics to measure success +- Create a Project Charter to document goals, tasks, deliverables, and decisions + +> - Get buy-in from project team members and key stakeholders on the project charter + +#### 2. Validate essential security and compliance requirements + +- Review Mattermost security features + +> - Resource: [https://docs.mattermost.com/security-guide/security-guide-index.html](https://docs.mattermost.com/security-guide/security-guide-index.html) + +- Determine monitoring requirements + +> - Database, network, storage, log integrity +> - Identify fields for log management tools (e.g. Splunk Enterprise event data) + +- Determine environment access policies + +> - Network access, physical access, group controlled access + +- Determine encryption policies + +> - Resource: [https://docs.mattermost.com/deployment-guide/encryption-options.html](https://docs.mattermost.com/deployment-guide/encryption-options.html) +> - Resource: [https://docs.mattermost.com/deployment-guide/transport-encryption.html](https://docs.mattermost.com/deployment-guide/transport-encryption.html) + +- Determine system administration access policies + +> - Identify the list of users or groups who need administrative access for Mattermost System Console, Command Line Tools, and API privileges + +- Define and configure authentication policies + +> - Resource: [https://docs.mattermost.com/product-overview/corporate-directory-integration.html](https://docs.mattermost.com/product-overview/corporate-directory-integration.html) + +- Determine requirements for multi-factor authentication + +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/multi-factor-authentication.html](https://docs.mattermost.com/administration-guide/onboard/multi-factor-authentication.html) + +- Configure and test SSO or Corporate Directory integration (SAML or AD/LDAP) + +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/sso-saml.html](https://docs.mattermost.com/administration-guide/onboard/sso-saml.html) +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/ad-ldap.html](https://docs.mattermost.com/administration-guide/onboard/ad-ldap.html) + +- Define your mobile usage policy + +> - Resource: [https://docs.mattermost.com/deployment-guide/mobile/mobile-app-deployment.html](https://docs.mattermost.com/deployment-guide/mobile/mobile-app-deployment.html) + +- Evaluate external network access requirements + +> - The [Mattermost Marketplace](https://mattermost.com/marketplace) is a service hosted by Mattermost that functions as a central place to store the current versions of available Mattermost integrations. See [Enable Remote Marketplace](/administration-guide/configure/plugins-configuration-settings#enable-remote-marketplace) documentation for details about required external network access. +> - Mattermost supports external GIF providers. See [GIF Commands](/administration-guide/configure/integrations-configuration-settings#enable-gif-picker) configuration documentation for details about required external network access. + +#### 3. Create development, staging, and production environments + +- Finalize production environment design basing hardware on expected usage and requirements for high availability + +> - Resource: [https://docs.mattermost.com/deployment-guide/reference-architecture/application-architecture.html](https://docs.mattermost.com/deployment-guide/reference-architecture/application-architecture.html) +> - Resource: [https://docs.mattermost.com/deployment-guide/deployment-guide-index.html](https://docs.mattermost.com/deployment-guide/deployment-guide-index.html) +> - Resource: [https://docs.mattermost.com/administration-guide/scale/scaling-for-enterprise.html](https://docs.mattermost.com/administration-guide/scale/scaling-for-enterprise.html) +> - Resource: [https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html](https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html) + +- Create development and staging environments + +> - Recommend using to test early configurations for database, authentication, file storage, Elasticsearch, prior to setting up high availability and load balancing +> - Recommend configuring staging to be an identical replication of your production environment + +- Create a production environment + +> - Install Mattermost +> +> > - Install the number of nodes based on your high availability requirements outlined in your production environment design +> > - Recommendation: Use Kubernetes and the Mattermost Operator, with external supported external database and file storage solutions. This will also provide blue/green deployment, rolling upgrades, and canary builds +> > +> > > - Resource: [https://docs.mattermost.com/deployment-guide/server/deploy-kubernetes.html](https://docs.mattermost.com/deployment-guide/server/deploy-kubernetes.html) +> +> - Install and configure database +> +> > - Install the number of read and search replicas based on your high availability requirements outlined in your production environment design +> > +> > > - Resource: [https://docs.mattermost.com/deployment-guide/reference-architecture/application-architecture.html](https://docs.mattermost.com/deployment-guide/reference-architecture/application-architecture.html) +> > +> > - (Optional) Set up configuration management via the database instead of a config file for high available environments +> > +> > > - Resource: [https://docs.mattermost.com/administration-guide/configure/configuration-in-your-database.html](https://docs.mattermost.com/administration-guide/configure/configuration-in-your-database.html) +> +> - Install and configure File Storage +> +> > - Resource: [https://docs.mattermost.com/deployment-guide/server/preparations.html#file-storage-preparation](https://docs.mattermost.com/deployment-guide/server/preparations.html#file-storage-preparation) +> +> - Install and configure proxy or load balancers +> +> > - Note: If running Kubernetes and the Mattermost Operator, proxies will be created automatically. +> > - Add SSL Cert +> > +> > > - Resource: [https://docs.mattermost.com/administration-guide/onboard/ssl-client-certificate.html](https://docs.mattermost.com/administration-guide/onboard/ssl-client-certificate.html) +> > > - Resource: [https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html#proxy-server-configuration](https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html#proxy-server-configuration) +> > +> > - (Optional) Set up certificate-based authentication (CBA) for user or device-based authentication with a digital certificate +> > +> > > - Resource: [https://docs.mattermost.com/administration-guide/onboard/certificate-based-authentication.html](https://docs.mattermost.com/administration-guide/onboard/certificate-based-authentication.html) +> +> - Configure SMTP for email notifications +> +> > - Resource: [https://docs.mattermost.com/administration-guide/configure/smtp-email.html](https://docs.mattermost.com/administration-guide/configure/smtp-email.html) +> +> - Set up Elasticsearch (highly recommended if your organization anticipates over two million posts) +> +> > - Resource: [https://docs.mattermost.com/administration-guide/scale/elasticsearch-setup.html](https://docs.mattermost.com/administration-guide/scale/elasticsearch-setup.html) + +- Document network configuration + +> - Example: [https://docs.mattermost.com/administration-guide/scale/backing-storage-benchmarks.html](https://docs.mattermost.com/administration-guide/scale/backing-storage-benchmarks.html) + +#### 4. Configure and customize your Mattermost site + +- Login to Mattermost and access the System Console to connect your environment to Mattermost + +> - Resource: [https://docs.mattermost.com/administration-guide/configure/configuration-settings.html#environment-variables](https://docs.mattermost.com/administration-guide/configure/configuration-settings.html#environment-variables) +> - Upload your valid Enterprise License under Edition and License +> - Ensure site URL is set appropriately for your production, dev and staging environments +> - Add your database configuration to **System Console \> Environment \> Database** +> - Add your Elasticsearch or AWS OpenSearch configuration to **System Console \> Environment \> Elasticsearch** +> - Add your file storage system configuration to **System Console \> Environment \> File Storage** +> - Add your proxy configuration to **System Console \> Environment \> Image Proxy** +> - Add your SMTP configuration to **System Console \> Environment \> SMTP** +> - Enable Push Notifications by adding your server to **System Console \> Environment \> Push Notification Server** +> - Add your cluster configuration to **System Console \> Environment \> High Availability** + +- Configure your site within the System Console + +> - Resource: [https://docs.mattermost.com/administration-guide/configure/configuration-settings.html#site-configuration](https://docs.mattermost.com/administration-guide/configure/configuration-settings.html#site-configuration) + +- Set site access policies including permissions for roles and guest access + +> - Permissions Resource: [https://docs.mattermost.com/administration-guide/onboard/advanced-permissions.html](https://docs.mattermost.com/administration-guide/onboard/advanced-permissions.html) +> - Guest Access Resource: [https://docs.mattermost.com/administration-guide/onboard/guest-accounts.html](https://docs.mattermost.com/administration-guide/onboard/guest-accounts.html) + +#### 5. Test production performance and redundancy + +- Define and test disaster recovery policy and processes + +> - Resource: [https://docs.mattermost.com/deployment-guide/server/deploy-kubernetes.html](https://docs.mattermost.com/deployment-guide/server/deploy-kubernetes.html) +> - Resource: [https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html#upgrade-guide](https://docs.mattermost.com/administration-guide/scale/high-availability-cluster-based-deployment.html#upgrade-guide) + +- Performance test production environment + +> - Load test production environment to verify that it will handle anticipated user load +> +> > - Resource: [https://github.com/mattermost/mattermost-load-test](https://github.com/mattermost/mattermost-load-test) +> +> - Set up Prometheus and Grafana to monitor performance +> +> > - Resource: [https://docs.mattermost.com/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.html](https://docs.mattermost.com/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.html) +> +> - Set up alerts in Grafana +> +> > - Resource: [https://docs.mattermost.com/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.html](https://docs.mattermost.com/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring.html) + +### Roll out Mattermost + +Now that you have an environment in place, we recommend working through the following items in an iterative process. You may need to cycle through each of these topics multiple times to make adjustments to suit your organization as you onboard groups of users. + +#### 1. Define your team and channel strategy + +- Determine and create a team structure for your environment + +> - Recommendation: Start with fewer teams in your early roll out +> - Resource: [https://docs.mattermost.com/end-user-guide/collaborate/channel-naming-conventions.html](https://docs.mattermost.com/end-user-guide/collaborate/channel-naming-conventions.html) + +- Determine and create key channels to support your users. A default Town Square channel is created automatically and available on every team. + +> - Recommendation: Add a “Support” channel for your users to escalate questions + +- (Optional) Migrate messages and channels from legacy systems + +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/migrating-to-mattermost.html](https://docs.mattermost.com/administration-guide/onboard/migrating-to-mattermost.html) + +#### 2. Enable key integrations + +- Build the list of key integrations and tools used by your teams + +> - Resource: [https://developers.mattermost.com/integrate/getting-started/](https://developers.mattermost.com/integrate/getting-started/) + +- Define use cases and requirements for plugins, bots, webhooks, slash commands + +> - Resource: [https://developers.mattermost.com/integrate/other-integrations/](https://developers.mattermost.com/integrate/other-integrations/) + +- Set up key integrations (or migrate from POC environments) + +> - Resource: [https://mattermost.com/marketplace/](https://mattermost.com/marketplace/) + +- Understand Mattermost API capabilities + +> - Resource: [https://api.mattermost.com/](https://api.mattermost.com/) + +#### 3. Prepare for user onboarding + +- Onboard champion users +- Onboard trainers and support team +- Create a training plan + +> - Resource: [https://academy.mattermost.com/](https://academy.mattermost.com/) + +- Define user escalation and support processes + +> - Ensure you have set the site’s support URL to your own support team under **System Console \> Site Configuration \> Customization** + +- Notify users in advance of roll out + +> - Sample email: [https://docs.mattermost.com/administration-guide/upgrade/welcome-email-to-end-users.html](https://docs.mattermost.com/administration-guide/upgrade/welcome-email-to-end-users.html) + +#### 4. Deploy client apps + +- Roll out desktop app + +> - Resource: [https://docs.mattermost.com/deployment-guide/desktop/desktop-app-deployment.html](https://docs.mattermost.com/deployment-guide/desktop/desktop-app-deployment.html) +> - (Optional) Use the MSI installer to install on Windows machines +> +> > - Resource: [https://docs.mattermost.com/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.html](https://docs.mattermost.com/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.html) + +- Roll out mobile app + +> - Resource: [https://docs.mattermost.com/deployment-guide/mobile/mobile-app-deployment.html](https://docs.mattermost.com/deployment-guide/mobile/mobile-app-deployment.html) +> - (Optional) Use an EMM provider +> +> > - Resource: [https://docs.mattermost.com/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider.html](https://docs.mattermost.com/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider.html) + +#### 5. Roll out to groups of users + +- Provision user accounts + +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/user-provisioning-workflows.html](https://docs.mattermost.com/administration-guide/onboard/user-provisioning-workflows.html) + +- (Optional) Bulk Load users + +> - Resource: [https://docs.mattermost.com/administration-guide/onboard/bulk-loading-data.html](https://docs.mattermost.com/administration-guide/onboard/bulk-loading-data.html) + +- Onboard users to teams and channels + +> - Recommendation: Use LDAP Group Sync to automate this process +> +> > - Resource: [https://docs.mattermost.com/administration-guide/onboard/ad-ldap-groups-synchronization.html](https://docs.mattermost.com/administration-guide/onboard/ad-ldap-groups-synchronization.html) + +- Implement your training plan to end users on how to use Mattermost + +> - Train on using Mattermost +> - Train on how to use integrations + +#### 6. Drive adoption + +- Incrementally roll out to additional user groups + +> - See “Roll Out to Groups of Users” + +- Manage support requests and product requests from your end users + +> - Resource: [https://mattermost.com/support/](https://mattermost.com/support/) +> - See the process below for escalating to Mattermost + +- Enable additional integrations and plugins to support user workflows + +> - Resource: [https://mattermost.com/marketplace/](https://mattermost.com/marketplace/) + +- Understand management tools available to support users + +> - mmctl Command Line Tool Resource: [https://docs.mattermost.com/administration-guide/manage/mmctl-command-line-tool.html](https://docs.mattermost.com/administration-guide/manage/mmctl-command-line-tool.html) +> - Command Line Tools Resource: [https://docs.mattermost.com/administration-guide/manage/command-line-tools.html](https://docs.mattermost.com/administration-guide/manage/command-line-tools.html) + +### Review the roll out + +We recommend that you review your rollout on a cadence that matches your iterative approach to rolling out to users. Below are some areas to consider. + +#### 1. Review project charter success metrics + +- Perform end-user surveys and measure satisfaction +- Verify use case fulfillment from original requirements gathering +- Measure your response time and resolution rate for user support issues +- Identify usage gaps and address or create a plan for addressing + +#### 2. Review and analyze usage + +- Review Project Charter success metrics - identify usage gaps and address or create a plan for addressing +- Monitor site and team statistics + +> - Resource: [https://docs.mattermost.com/administration-guide/manage/statistics.html](https://docs.mattermost.com/administration-guide/manage/statistics.html) +> - Review: Total posts, total teams, total channels, total group chats, total direct chats, top channels, top teams + +- Analyze usage by lines of business and peak usage times + +#### 3. Analyze system performance + +- Monitor trends in CPU/memory usage +- Review trends in database connections +- Review trends in Go routines +- Review trends in concurrent sessions + +#### 4. Harden security + +- Harden security controls around the web, desktop, and mobile security +- Harden configuration management +- Harden network security + +> - Identify additional tests and scans +> - (Optional) Enable Compliance Reporting +> +> > - Resource: [https://docs.mattermost.com/administration-guide/comply/compliance-export.html](https://docs.mattermost.com/administration-guide/comply/compliance-export.html) + +#### 5. Perform maintenance tasks + +- Monitor for security updates (or sign up for email updates) + +> - Resource: [https://mattermost.com/security-updates/](https://mattermost.com/security-updates/) + +- Perform the first upgrade + +> - Resource: [https://docs.mattermost.com/administration-guide/upgrade/upgrading-mattermost-server.html](https://docs.mattermost.com/administration-guide/upgrade/upgrading-mattermost-server.html) + +- Determine upgrade schedule based on Mattermost release schedules and life cycle + +> - Resource: [https://docs.mattermost.com/product-overview/releases-lifecycle.html](https://docs.mattermost.com/product-overview/releases-lifecycle.html) + +- Run System checks and either address or set address-by date diff --git a/docs/main/administration-guide/upgrade/important-upgrade-notes.mdx b/docs/main/administration-guide/upgrade/important-upgrade-notes.mdx new file mode 100644 index 000000000000..40f6b12090d7 --- /dev/null +++ b/docs/main/administration-guide/upgrade/important-upgrade-notes.mdx @@ -0,0 +1,1173 @@ +--- +title: "Important Upgrade Notes" +draft: true +--- +import Inc0_common_esr_support_rst from '../../product-overview/common-esr-support-rst.mdx'; + + + + + +We recommend reviewing the [additional upgrade notes](#additional-upgrade-notes) at the bottom of this page. + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

If you're upgrading from a version earlier than...

====================================================

v11.6

Then...

==================================================================================================================================================================

Single-channel guests are no longer counted toward the primary licensed seat count and are permitted free up to a 1:1 ratio with licensed seats. A new stat card, license row, and admin banner provide visibility into single-channel guest usage and overage warnings.

v11.5

Added a new column translations.state and a new index idx_translations_state to the translations table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

ALTER TABLE translationsADD COLUMN IF NOT EXISTS state varchar(20) NOT NULL;CREATE INDEX IF NOT EXISTS idx_translations_stateON translations(state)WHERE state IN ('processing');

Added a new column channelmembers.autotranslationdisabled to the channelmembers table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

ALTER TABLE channelmembers    ADD COLUMN IF NOT EXISTS autotranslationdisabled boolean NOT NULL DEFAULT false;

Modified the column translations.objectType and changed the primary key (objectId, dstLang) to (objectId, objectType, dstLang) in the translations table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

UPDATE translations SET objectType = 'post' WHERE objectType IS NULL;ALTER TABLE translations ALTER COLUMN objectType SET NOT NULL;ALTER TABLE translations DROP CONSTRAINT translations_pkey;ALTER TABLE translations ADD PRIMARY KEY (objectId, objectType, dstLang);

Added a new column translations.channelid to the translations table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

ALTER TABLE translations ADD COLUMN IF NOT EXISTS channelid varchar(26);

Added a new index idx_translations_channel_updateat to the translations table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

-- morph:nontransactionalCREATE INDEX CONCURRENTLY IF NOT EXISTS idx_translations_channel_updateat    ON translations(channelid, objectType, updateAt DESC, dstlang);

Dropped the index idx_translations_updateat from the translations table. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

-- morph:nontransactionalDROP INDEX CONCURRENTLY IF EXISTS idx_translations_updateat;
v11.4Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments.

Added two new tables, Recaps and RecapChannels. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

-- Recaps table: stores recap metadataCREATE TABLE IF NOT EXISTS Recaps (    Id VARCHAR(26) PRIMARY KEY,    UserId VARCHAR(26) NOT NULL,    Title VARCHAR(255) NOT NULL,    CreateAt BIGINT NOT NULL,    UpdateAt BIGINT NOT NULL,    DeleteAt BIGINT NOT NULL,    TotalMessageCount INT NOT NULL,    Status VARCHAR(32) NOT NULL,    ReadAt BIGINT DEFAULT 0 NOT NULL,    BotID VARCHAR(26) DEFAULT '' NOT NULL);CREATE INDEX IF NOT EXISTS idx_recaps_user_id ON Recaps(UserId);CREATE INDEX IF NOT EXISTS idx_recaps_create_at ON Recaps(CreateAt);CREATE INDEX IF NOT EXISTS idx_recaps_user_id_delete_at ON Recaps(UserId, DeleteAt);CREATE INDEX IF NOT EXISTS idx_recaps_user_id_read_at ON Recaps(UserId, ReadAt);CREATE INDEX IF NOT EXISTS idx_recaps_bot_id ON Recaps(BotID);-- RecapChannels table: stores per-channel summariesCREATE TABLE IF NOT EXISTS RecapChannels (    Id VARCHAR(26) PRIMARY KEY,    RecapId VARCHAR(26) NOT NULL,    ChannelId VARCHAR(26) NOT NULL,    ChannelName VARCHAR(64) NOT NULL,    Highlights TEXT,    ActionItems TEXT,    SourcePostIds TEXT,    CreateAt BIGINT NOT NULL,    FOREIGN KEY (RecapId) REFERENCES Recaps(Id) ON DELETE CASCADE);CREATE INDEX IF NOT EXISTS idx_recap_channels_recap_id ON RecapChannels(RecapId);CREATE INDEX IF NOT EXISTS idx_recap_channels_channel_id ON RecapChannels(ChannelId);
v11.3Starting in v11.3.1, photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments.

Added schema changes in the form of a new tables (ReadReceipts and TemporaryPosts) that aggregate user attributes into a separate table. Added Type field for both Drafts and ScheduledPosts. A previous version of Mattermost can run with the new schema changes. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are:

CREATE TABLE IF NOT EXISTS ReadReceipts (    PostId VARCHAR(26) NOT NULL,    UserId VARCHAR(26) NOT NULL,    ExpireAt bigint NOT NULL,    PRIMARY KEY (PostId, UserId));CREATE INDEX IF NOT EXISTS idx_read_receipts_post_id ON ReadReceipts(PostId);CREATE INDEX IF NOT EXISTS idx_read_receipts_user_id_post_id_expire_at ON ReadReceipts(UserId, PostId, ExpireAt);CREATE TABLE IF NOT EXISTS TemporaryPosts (    PostId VARCHAR(26) PRIMARY KEY,    Type VARCHAR(26) NOT NULL,    ExpireAt BIGINT NOT NULL,    Message VARCHAR(65535),    FileIds VARCHAR(300));CREATE INDEX IF NOT EXISTS idx_temporary_posts_expire_at ON TemporaryPosts(expireat);ALTER TABLE drafts ADD COLUMN IF NOT EXISTS Type text;ALTER TABLE scheduledposts ADD COLUMN IF NOT EXISTS Type text;

Added a new translations table, two new columns (channels.autotranslation, channelmembers.autotranslation), and four new indexes. The migrations are fully backwards-compatible and there are no table rewrites. < 1 second of downtime is required. Zero downtime is possible when using CREATE INDEX CONCURRENTLY before upgrading for true zero-downtime upgrade. Standard upgrade is safe for all instance sizes; no special manual steps required unless zero-downtime is critical. The SQL queries for absolute zero downtime are:

CREATE INDEX CONCURRENTLY IF NOT EXISTSidx_channelmembers_autotranslation_enabled   ON channelmembers (channelid)   WHERE autotranslation = true;CREATE INDEX CONCURRENTLY IF NOT EXISTSidx_channels_autotranslation_enabled   ON channels (id)   WHERE autotranslation = true;CREATE INDEX CONCURRENTLY IF NOT EXISTSidx_users_id_locale   ON users (id, locale);
Beginning in Mattermost v11.3, some plugins that register a Right Hand Sidebar (RHS) component using registerRightHandSidebarComponent will need to implement additional code to support RHS popouts if their RHS component relies on plugin-specific state. See this forum post for full details.
v11.2Starting in v11.2.3, photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments.

Added a new column to the OAuthApps table called isdynamicallyregistered. It has a default value of false. Also added three new columns to the OAuthAuthData table called resource, codechallenge and codechallengemethod. All columns default to ‘’. Also added a new column to the OAuthAccessData table called audience. It has a default value of ‘’. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The tables take an ACCESS EXCLUSIVE LOCK, however it is only to add/remove the metadata. The command returns instantly. The SQL queries included are:

ALTER TABLE oauthapps ADD COLUMN IF NOT EXISTS isdynamicallyregistered BOOLEAN DEFAULT FALSE;ALTER TABLE oauthauthdata ADD COLUMN IF NOT EXISTS codechallenge varchar(128) DEFAULT '';ALTER TABLE oauthauthdata ADD COLUMN IF NOT EXISTS codechallengemethod varchar(10) DEFAULT '';ALTER TABLE oauthaccessdata ADD COLUMN IF NOT EXISTS audience varchar(512) DEFAULT '';ALTER TABLE oauthauthdata ADD COLUMN IF NOT EXISTS resource varchar(512) DEFAULT '';
v11.1The version of React used by the Mattermost web app has been updated from React 17 to React 18. See more details in this forum post.

Added three new tables, ContentFlaggingCommonReviewers, ContentFlaggingTeamSettings, and ContentFlaggingTeamReviewers for storing Data Spillage settings. Added an index on ContentFlaggingTeamReviewers table to optimize fetching the team settings. The migrations are fully backwards-compatible. No table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

CREATE TABLE IF NOT EXISTS ContentFlaggingCommonReviewers (    UserId VARCHAR(26) PRIMARY KEY);CREATE TABLE IF NOT EXISTS ContentFlaggingTeamSettings (    TeamId VARCHAR(26) PRIMARY KEY,    Enabled BOOLEAN);CREATE TABLE IF NOT EXISTS ContentFlaggingTeamReviewers (    TeamId VARCHAR(26),    UserId VARCHAR(26),    PRIMARY KEY (TeamId, UserId));CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_contentflaggingteamreviewers_userid ON ContentFlaggingTeamReviewers (userid);
v11.0GitLab SSO has been deprecated from Team Edition. Deployments using GitLab SSO can remain on v10.11 ESR (with 12 months of security updates) while transitioning to our new free offering Mattermost Entry, or can explore commercial/nonprofit options. See more details in this forum post.
The TeamSettings.ExperimentalViewArchivedChannels setting has been deprecated. Archived channels will always be accessible, subject to normal channel membership. The server will fail to start if this setting is set to false. To deny access to archived channels, mark them as private and remove affected channel members. See more details in this forum post.
Playbooks has stopped working for Team Edition. Entry, Professional, Enterprise, and Enterprise Advanced plans are automatically upgraded to Playbooks v2 with no expected downtime. See more details in this forum post.
Experimental Bleve Search functionality has been retired. If Bleve is enabled, search will not work until DisableDatabaseSearch is set to false. See more details in this forum post.
Support for MySQL has ended. Our Migration Guide outlines the steps, tools and support available for migrating to PostgreSQL. See more details in this forum post.
The registerPostDropdownMenuComponent hook in the web app’s plugin API has been removed in favour of registerPostDropdownMenuAction. See more details in this forum post.
The web app is no longer exposing the Styled Components dependency for use by web app plugins. See more details in this forum post.
Omnibus support has been deprecated. The last mattermost-omnibus release was v10.12. See more details in this forum post.
Deprecated include_removed_members option in api/v4/ldap/sync has been removed. Admins can use the LDAP setting ReAddRemovedMembers.
Customers that have the NPS plugin enabled can remove it as it no longer sends the feedback over through telemetry.
Format query parameter requirement in the /api/v4/config/client endpoint has been deprecated.

Removed deprecated mmctl commands and flags:

  • channel add - use channel users add
  • channel remove - use channel users remove
  • channel restore - use channel unarchive
  • channel make-private - use channel modify --private
  • command delete - use command archive
  • permissions show - use permissions role show
  • mmctl user email - use mmctl user edit email
  • mmctl user username - use mmctl user edit username
Experimental certificate-based authentication feature has been removed. ExperimentalSettings.ClientSideCertEnable must be false to start the server.
Added logic to migrate the password hashing method from bcrypt to PBKDF2. The migration will happen progressively, migrating the password of a user as soon as they enter it; e.g. when logging in or when double-checking their password for any sensitive action. There is an edge case where users might get locked out of their account: if a server upgrades to v11 and user A logs in (i.e., they need to enter their password), and then the server downgrades to v10.12 or previous, user A will no longer be able to log in. In this case, admins will need to manually reset the password of such users, through the system console or through the mmctl user reset-password [users] command. The new password hashing method is more CPU-intensive. Admins of servers with password-based login should monitor the performance on periods where many users log in at the same time.
/api/v4/teams/{team_id}/channels/search_archived has been deprecated in favour of /api/v4/channels/search with the deleted parameter.
Changed default database connection pool settings: changed MaxOpenConns from 300 to 100 and MaxIdleConns from 20 to 50, establishing a healthier 2:1 ratio for better database connection management.

Separate notification log file has been deprecated. If admins want to continue using a separate log file for notification logs, they can use the AdvancedLoggingJSON configuration. An example configuration to use is:

{  "LogSettings": {    "AdvancedLoggingJSON": {      "notifications_file": {        "type": "file",        "format": "json",        "levels": [            {"id": 300, "name": "NotificationError"},            {"id": 301, "name": "NotificationWarn"},            {"id": 302, "name": "NotificationInfo"},            {"id": 303, "name": "NotificationDebug"},            {"id": 304, "name": "NotificationTrace"}        ],        "options": {            "filename": "notifications.log",            "max_size": 100,            "max_age": 0,            "max_backups": 0,            "compress": true        },        "maxqueuesize": 1000      }    }  }}
Stopped supporting manually installed plugins as per https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192.
Support for PostgreSQL v13 has been removed. The new minimum PostgreSQL version is v14+. See the PostgreSQL version policy documentation for details.
v10.12There are no important upgrade notes in v10.12 release.
v10.11Starting in v10.11.11, photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments.
Mattermost v10.11.4 introduces a new API endpoint /api/v4/users/login/sso/code-exchange as part of security enhancements to the SSO authentication flow. Customer using SSO (e.g. with SAML) should ensure network configurations allow traffic to this endpoint.
v10.10

Added a new column DefaultCategoryName to the Channels table. This is nullable and stores a category name to be added/created when new users join a channel. This is only used if the ExperimentalChannelCategorySetting is enabled. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

PostgreSQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000138_add_default_category_name_to_channel.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000138_add_default_category_name_to_channel.up.sql

MySQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000138_add_default_category_name_to_channel.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000138_add_default_category_name_to_channel.up.sql

Added new columns RemoteId and ChannelId to the PostAcknowledgements table. This is nullable, and stores the remote ID (if available) and channel ID to which the post was made when acknowledgements to posts were set. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

PostgreSQL: 000141_add_remoteid_channelid_to_post_acknowledgements.down.sql and 000141_add_remoteid_channelid_to_post_acknowledgements.up.sql

MySQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000141_add_remoteid_channelid_to_post_acknowledgements.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000141_add_remoteid_channelid_to_post_acknowledgements.up.sql

Added a new column LastMembersSyncAt to the SharedChannelRemotes table and added LastMembershipSyncAt to SharedChannelUsers. This is nullable, and stores the LastMembersSyncAt timestamp (if available) which tracks the last time channel membership data was synchronized between the local cluster and each remote cluster. LastMembershipSyncAt timestamp tracks the last time a specific user's channel membership status was synchronized with a specific remote cluster. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

PostgreSQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000140_add_lastmemberssyncat_to_sharedchannelremotes.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000140_add_lastmemberssyncat_to_sharedchannelremotes.up.sql

MySQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000140_add_lastmemberssyncat_to_sharedchannelremotes.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000140_add_lastmemberssyncat_to_sharedchannelremotes.up.sql

Added a new column LastGlobalUserSyncAt to the RemoteClusters table. This is nullable, and LastGlobalUserSyncAt tracks the timestamp of the last successful global user sync for each remote cluster, enabling incremental syncing. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

PostgreSQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000139_remoteclusters_add_last_global_user_sync_at.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/postgres/000139_remoteclusters_add_last_global_user_sync_at.up.sql

MySQL: https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000139_remoteclusters_add_last_global_user_sync_at.down.sql and https://github.com/mattermost/mattermost/blob/release-10.10/server/channels/db/migrations/mysql/000139_remoteclusters_add_last_global_user_sync_at.up.sql

v10.9

A new index to the CategoryId column in SidebarChannels table was added to improve query performance. No database downtime is expected for this upgrade. For PostgreSQL, it takes around 2s to add the index on a table with 1.2M rows with an instance size of 8 cores and 16GB RAM. For MySQL, it takes around 5s on a table with 300K rows on an instance size of 8 cores and 16GB RAM. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are:

PostgreSQL:

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_sidebarchannels_categoryid ON sidebarchannels(categoryid);

MySQL:

CREATE INDEX idx_sidebarchannels_categoryid ON SidebarChannels(CategoryId);

Schema changes in the form of a new materialized view (AttributeView) was added that aggregates user attributes into a separate table. No database downtime is expected for this upgrade. A previous version of Mattermost can run with the new schema changes. The SQL queries included in the schema changes are below:

PostgreSQL: https://github.com/mattermost/mattermost/blob/release-10.9/server/channels/db/migrations/postgres/000137_update_attribute_view.up.sql

MySQL: https://github.com/mattermost/mattermost/blob/release-10.9/server/channels/db/migrations/mysql/000136_create_attribute_view.up.sql

The objective of showing the SQL queries is not to reduce downtime, but to let the Admin make the schema changes without requiring to upgrade Mattermost. Then when they actually upgrade Mattermost, it becomes instantaneous since the changes are already made.

When SamlSettings.EnableSyncWithLdap is enabled, Mattermost will now check if a user exists on the connected LDAP server during login. If the user doesn't exist on the LDAP server, login will fail. Previously, users not present on the LDAP server could login, but would be deactivated on the next LDAP sync.
v10.8New tables AccessControlPolicies and AccessControlPolicyHistory will be created. The migration is fully backwards-compatible, non-locking, and zero downtime is expected.
Support for legacy SKUs E10 and E20 licenses was removed. If you need assistance, talk to a Mattermost expert.
v10.7

Added new column BannerInfo in the Channels table for storing metadata for an upcoming licensed feature. The migration is fully backwards-compatible, non-locking, and zero downtime is possible. Below are the SQL queries included in the schema changes:

PostgreSQL:

ALTER TABLE channels ADD COLUMN IF NOT EXISTS bannerinfo jsonb;

MySQL:

SET @preparedStatement = (SELECT IF(   NOT EXISTS(       SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS       WHERE table_name = 'Channels'       AND table_schema = DATABASE()       AND column_name = 'BannerInfo'   ),   'ALTER TABLE Channels ADD COLUMN BannerInfo json;',   'SELECT 1;'));PREPARE addColumnIfNotExists FROM @preparedStatement;EXECUTE addColumnIfNotExists;DEALLOCATE PREPARE addColumnIfNotExists;

Added support for cursor-based pagination on the property architecture tables, including SQL migration to create indices. The migration is fully backwards-compatible, non-locking, and zero downtime is possible. Below are the SQL queries included in the schema changes:

MySQL:

SET @preparedStatement = (SELECT IF(    (        SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS        WHERE table_name = 'PropertyValues'        AND table_schema = DATABASE()        AND index_name = 'idx_propertyvalues_create_at_id'    ) > 0,    'SELECT 1',    'CREATE INDEX idx_propertyvalues_create_at_id ON PropertyValues(CreateAt, ID);'));PREPARE createIndexIfNotExists FROM @preparedStatement;EXECUTE createIndexIfNotExists;DEALLOCATE PREPARE createIndexIfNotExists;
SET @preparedStatement = (SELECT IF(    (        SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS        WHERE table_name = 'PropertyFields'        AND table_schema = DATABASE()        AND index_name = 'idx_propertyfields_create_at_id'    ) > 0,    'SELECT 1',    'CREATE INDEX idx_propertyfields_create_at_id ON PropertyFields(CreateAt, ID);'));PREPARE createIndexIfNotExists FROM @preparedStatement;EXECUTE createIndexIfNotExists;DEALLOCATE PREPARE createIndexIfNotExists;

PostgreSQL:

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_propertyvalues_create_at_id ON PropertyValues(CreateAt, ID)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_propertyfields_create_at_id ON PropertyFields(CreateAt, ID)
v10.6Support for PostgreSQL v11 and v12 have been removed. The new minimum PostgreSQL version is v13+. | See the | minimum supported PostgreSQL version policy documentation | for details. |

System Console statistics now perform faster on PostgreSQL. The MaxUsersForStatistics configuration setting now only disables the User counts with posts chart, while all other stats remain unaffected. The other stats remain unaffected because that configuration value is no longer needed to disable the other queries since they are always fast now. Post and file counts update daily, so they may not always reflect real-time data. Advanced stats, such as line charts and plugin data, are now hidden until clicked, reducing load time. No performance improvements apply to MySQL since it's scheduled for full deprecation in v11. We recommend migrating to PostgreSQL for better performance and long-term support. Migration times: On a system with 12M posts, and 1M fileinfo entries, the migration takes 15s, but could take several minutes depending on the server's table sizes and database specs. This migration is non-locking. Note that there is no migration for MySQL deployments because this optimization is only applicable for PostgreSQL. Below are the SQL queries included in the schema changes:

CREATE MATERIALIZED VIEW IF NOT EXISTS posts_by_team_day asSELECT to_timestamp(p.createat/1000)::date as day, COUNT(*) as num, teamidFROM posts p JOIN channels c on p.channelid=c.idGROUP BY day, c.teamid;CREATE MATERIALIZED VIEW IF NOT EXISTS bot_posts_by_team_day asSELECT to_timestamp(p.createat/1000)::date as day, COUNT(*) as num, teamidFROM posts pJOIN Bots b ON p.UserId = b.UseridJOIN channels c on p.channelid=c.idGROUP BY day, c.teamid;CREATE MATERIALIZED VIEW IF NOT EXISTS file_stats asSELECT COUNT(*) as num, COALESCE(SUM(Size), 0) as usageFROM fileinfoWHERE DeleteAt = 0;
v10.5Mattermost versions v10.5.0 and v10.5.1 include a bundled Jira plugin (v4.2.0) that contains a bug which may cause plugin configuration settings to disappear. We strongly advise against upgrading to these versions to avoid potential disruption. If you have already upgraded to v10.5.0 or v10.5.1, we recommend updating the Jira plugin to version v4.2.1, or preferably, upgrading both Mattermost and the Jira plugin to their latest available versions.
The internal workings of the PluginLinkComponent in the web app have been changed to unmount link tooltips from the DOM by default, significantly improving performance. Plugins that register link tooltips using registerLinkTooltipComponent will experience changes in how tooltip components are managed—they are now only mounted when a link is hovered over or focused. As a result, plugins may need to update their components to properly handle mounting and unmounting scenarios. For example, changes were made in mattermost-plugin-jira, where componentDidUpdate lifecycle hook was replaced with componentDidMount. If your plugin’s tooltip component is a functional React component, there is a high chance that this behavior will be handled automatically, as it would be managed by useEffect with an empty dependency array.
The Mattermost server has stopped supporting manual plugin deployment. Plugins were deployed manually when an administrator or some deployment automation copies the contents of a plugin bundle into the server's working directory. If a manual or automated deployment workflow is still required, administrators can instead prepackage the plugin bundles. See this forum post for details.
Mattermost has stopped official Mattermost server builds for the Microsoft Windows operating system. Administrators should migrate existing Mattermost server installations to use the official Linux builds. See more details in this forum post.
v10.5 introduces updates to the Compliance Export functionality, which will modify how exported data is structured, stored and processed. These changes | primarily affect System Administrators and the main changes are outlined below. See more details in | the Compliance Export documentation. | | Output files and directories have changed - Previously we were exporting a single zip containing all the batch directories. Now we will export a single | directory, and under that directory each batch will be its own zip. | | Compliance exports performance improvements - Compliance exports should now be at least 50% faster, and possibly more. | | Logic improvements - We’ve made improvements and fixed bugs that we found. | | Changes specific to each Export Type - The export output formats have been changed. Some fields’ semantic meaning has been clarified, and there are a number of | new fields. Our goal was to maintain backwards compatibility while fixing the logic bugs. | | See the compliance export product documentation for details. |

As part of the Property System Architecture feature, Mattermost v10.5 is going to run a set of migrations to add new tables to the schema. This migration only creates new tables and indexes, so there is no impact on preexisting data.

New tables PropertyGroups, PropertyFields and PropertyValues are going to be created.

In the case of PostgreSQL, a new enum type property_field_type is going to be created, to be used in the Type column of the PropertyFields table.

The PropertyFields and PropertyValues tables have a unique constraint that will generate an index in MySQL, and in the case of PostgreSQL, they directly use a UNIQUE INDEX to enforce this constraint.

A new index idx_propertyvalues_targetid_groupid will be created for the PropertyValues table.

The migration is only creating new tables with no data. The migration is backwards-compatible, and a previous version of Mattermost can run with the new schema changes. No table locks or existing operations on the table are impacted by this upgrade. Zero downtime is possible when upgrading to this release.

Below are the SQL queries included in the schema changes:

MySQL:

CREATE TABLE IF NOT EXISTS PropertyGroups ( ID varchar(26) PRIMARY KEY, Name varchar(64) NOT NULL, UNIQUE(Name));CREATE TABLE IF NOT EXISTS PropertyFields ( ID varchar(26) PRIMARY KEY, GroupID varchar(26) NOT NULL, Name varchar(255) NOT NULL, Type enum('text', 'select', 'multiselect', 'date', 'user', 'multiuser'), Attrs json, TargetID varchar(255), TargetType varchar(255), CreateAt bigint(20), UpdateAt bigint(20), DeleteAt bigint(20), UNIQUE(GroupID, TargetID, Name, DeleteAt));CREATE TABLE IF NOT EXISTS PropertyValues ( ID varchar(26) PRIMARY KEY, TargetID varchar(255) NOT NULL, TargetType varchar(255) NOT NULL, GroupID varchar(26) NOT NULL, FieldID varchar(26) NOT NULL, Value json, CreateAt bigint(20), UpdateAt bigint(20), DeleteAt bigint(20), UNIQUE(GroupID, TargetID, FieldID, DeleteAt));SET @preparedStatement = (SELECT IF( (    SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS    WHERE table_name = 'PropertyValues'    AND table_schema = DATABASE()    AND index_name = 'idx_propertyvalues_targetid_groupid' ) > 0, 'SELECT 1', 'CREATE INDEX idx_propertyvalues_targetid_groupid ON PropertyValues (TargetID, GroupID);'));PREPARE createIndexIfNotExists FROM @preparedStatement;EXECUTE createIndexIfNotExists;DEALLOCATE PREPARE createIndexIfNotExists;

PostgreSQL:

CREATE TABLE IF NOT EXISTS PropertyGroups ( ID varchar(26) PRIMARY KEY, Name varchar(64) NOT NULL, UNIQUE(Name));DOBEGIN  IF NOT EXISTS (SELECT * FROM pg_type typ                        INNER JOIN pg_namespace nsp ON nsp.oid = typ.typnamespace                    WHERE nsp.nspname = current_schema()                        AND typ.typname = 'property_field_type') THEN CREATE TYPE property_field_type AS ENUM (    'text',    'select',    'multiselect',    'date',    'user',    'multiuser' );  END IF;END;LANGUAGE plpgsql;CREATE TABLE IF NOT EXISTS PropertyFields ( ID varchar(26) PRIMARY KEY, GroupID varchar(26) NOT NULL, Name varchar(255) NOT NULL, Type property_field_type, Attrs jsonb, TargetID varchar(255), TargetType varchar(255), CreateAt bigint NOT NULL, UpdateAt bigint NOT NULL, DeleteAt bigint NOT NULL);CREATE UNIQUE INDEX IF NOT EXISTS idx_propertyfields_unique ON PropertyFields (GroupID, TargetID, Name) WHERE DeleteAt = 0;CREATE TABLE IF NOT EXISTS PropertyValues ( ID varchar(26) PRIMARY KEY, TargetID varchar(255) NOT NULL, TargetType varchar(255) NOT NULL, GroupID varchar(26) NOT NULL, FieldID varchar(26) NOT NULL, Value jsonb NOT NULL, CreateAt bigint NOT NULL, UpdateAt bigint NOT NULL, DeleteAt bigint NOT NULL);CREATE UNIQUE INDEX IF NOT EXISTS idx_propertyvalues_unique ON PropertyValues (GroupID, TargetID, FieldID) WHERE DeleteAt = 0;CREATE INDEX IF NOT EXISTS idx_propertyvalues_targetid_groupid ON PropertyValues (TargetID, GroupID);    ``
v10.4There are no important upgrade notes in v10.4 release.
v10.3The Classic Mobile App has been phased out. Please download the new v2 Mobile App from the Apple App Store or Google Play Store. See more details in the classic mobile app deprecation Mattermost forum post.
v10.2Docker Content Trust (DCT) for signing Docker image artifacts has been replaced by Sigstore Cosign in v10.2 (November, 2024). If you rely on artifact verification using DCT, please transition to using Cosign. See the upcoming DCT deprecation Mattermost forum post for more details.
v10.1There are no important upgrade notes in v10.1 release.
v10.0We no longer support new installations using MySQL starting in v10. All new customers and/or deployments will only be supported with the minimum supported version of the PostgreSQL database. End of support for MySQL is targeted for Mattermost v11.
Apps Framework is deprecated for new installs. Please extend Mattermost using webhooks, slash commands, OAuth2 apps, and plugins.
Mattermost v10 introduces Playbooks v2 for all Enterprise licensed customers. Professional SKU customers may continue to use Playbooks v1 uninterrupted which will be maintained and supported until September 2025, followed by an appropriate grandfathering strategy. More detailed information and the discussion are available on our forums here.
Renamed Channel Moderation to Advanced Access Control in the channel management section in the System Console.
Renamed announcement banner feature to “system-wide notifications”.
Renamed “Collapsed Reply Threads” to “Threaded Discussions” in the System Console.
Renamed “System Roles” to “Delegated Granular Administration” in the System Console.
Renamed "Office 365" to "Entra ID" for SSO logins.
Fully deprecated the /api/v4/image endpoint when the image proxy is disabled.
Pre-packaged Calls plugin v1.0.1. This includes breaking changes including the removal of group calls from unlicensed servers in order to focus supportability and quality on licensed servers. Unlicensed servers can continue to use Calls in direct message channels, which represent the majority of activity.
Removed deprecated Config.ProductSettings, LdapSettings.Trace, and AdvancedLoggingConfig configuration fields.
Removed deprecated pageSize query parameter from most API endpoints.
Deprecated the experimental Strict CSRF token enforcement. This feature will be fully removed in Mattermost v11.
v9.11Added support for Elasticsearch v8. Also added Beta support for OpenSearch v1.x and v2.x. A new config setting ElasticsearchSettings.Backend has been | added to differentiate between Elasticsearch and OpenSearch. The default value is elasticsearch which breaks support for AWS Elasticsearch v7.10.x | since the official v8 client only works from Elasticsearch v7.11+ versions. | | .. note:: | | - For AWS customers on OpenSearch, you must modify Mattermost configuration from elasticsearch to opensearch and disable compatibility mode. | See the OpenSearch documentation for details on upgrading. | - After upgrading the Mattermost server, use mmctl or edit the config manually, | then restart the Mattermost server. | - If you are using OpenSearch, you must set the backend to opensearch. Otherwise Mattermost will not work. | | If you are using Elasticsearch v8, be sure to set action.destructive_requires_name to false in elasticsearch.yml to allow for wildcard operations to | work. |
v9.10There are no important upgrade notes in v9.10 release.
v9.9There are no important upgrade notes in v9.9 release.
v9.8There are no important upgrade notes in v9.8 release.
v9.7There are no important upgrade notes in v9.7 release.
v9.6There are no important upgrade notes in v9.6 release.
v9.5We have stopped supporting MySQL v5.7 since it's at the end of life. We urge customers to upgrade their MySQL instance at their earliest convenience.
Added safety limit error message in compiled Team Edition and Enterprise Edition deployments when enterprise scale and access control automation features are | unavailable and count of users who are registered and not deactivated exceeds 10,000. | ERROR_SAFETY_LIMITS_EXCEEDED. |
v9.4There are no important upgrade notes in v9.4 release.
v9.3There are no important upgrade notes in v9.3 release.
v9.2Fixed data retention policies to run jobs when any custom retention policy is enabled even when the global retention policy is set to "keep-forever". Before this fix, the enabled custom data retention policies wouldn't run as long as the global data retention policy was set to "keep-forever" or was disabled. After the fix, the custom data retention policies will run automatically even when the global data retention policy is set to "keep-forever". Once the server is upgraded, posts may unintentionally be deleted. Admins should make sure to disable all custom data retention policies before upgrading, and then re-enable them again after upgrading.
v9.1Minimum supported Desktop App version is now v5.3. OAuth/SAML flows were modified to include desktop_login which makes earlier versions incompatible.
v9.0Removed the deprecated Insights feature.
Mattermost Boards and various other plugins have transitioned to being fully community supported. See this forum post for more details.
The channel_viewed websocket event was changed to multiple_channels_viewed, and is now only triggered for channels that actually have unread messages.
v8.1

In v8.1.2, improved performance on data retention DeleteOrphanedRows queries.

New migration for a new table:

MySQL:

CREATE TABLEIF NOT EXISTS  RetentionIdsForDeletion(Id    VARCHAR(26) NOT NULL,    TableName VARCHAR(64),    Ids json, PRIMARY KEY (Id      ), KEY    idx_retentionidsfordeletion_tablename    (TableName)) ENGINE =  InnoDB DEFAULT CHARSET =  utf8mb4;  ``

PostgreSQL:

CREATE TABLEIF NOT EXISTS  retentionidsfordeletion(id    VARCHAR(26) PRIMARY KEY,    tablename VARCHAR(64),    ids VARCHAR(26) []);  CREATE INDEXIF NOT EXISTS  idx_retentionidsfordeletion_tablename  ON retentionidsfordeletion(    tablename);  ``

Hard deleting a user or a channel will now also clean up associated reactions.

Removed feature flag DataRetentionConcurrencyEnabled. Data retention now runs without concurrency in order to avoid any performance degradation.

Added a new configuration setting DataRetentionSettings.RetentionIdsBatchSize, which allows admins to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100.

v8.0Insights has been deprecated for all new instances and for existing servers that upgrade to v8.0. See more details in this forum post on why Insights has been deprecated.
The Focalboard plugin is now disabled by default for all new instances and can be enabled in the System Console > Plugin settings.
The Channel Export and Apps plugins are now disabled by default.
Apps Bar is now enabled by default for on-prem servers. ExperimentalSettings.EnableAppBar was also renamed to ExperimentalSettings.DisableAppBar. See the :ref: configuration settings <administration-guide/configure/experimental-configuration-settings:disable-apps-bar> documentation, and this forum article for details.
In the main server package, the Go module path has changed from github.com/mattermost/mattermost-server/server/v8 to github.com/mattermost/mattermost/server/v8. But with the introduction of the public submodule, it should no longer be necessary for third-party code to import this server package.
Introduced the public submodule, housing the familiar model and plugin packages, but now discretely versioned from the server. It is no longer necessary to go get a particular commit hash, as Go programs and plugins can now opt-in to importing github.com/mattermost/mattermost-server/server/public and managing versions idiomatically. While this submodule has not yet shipped a v1 and will introduce breaking changes before stabilizing the API, it remains both forwards and backwards compatible with the Mattermost server itself.
As part of the public submodule above, a context.Context is now passed to model.Client4 methods.
Removed support for PostgreSQL v10. The new minimum PostgreSQL version is now v11.
The Mattermost public API for Go is now available as a distinctly versioned package. Instead of pinning a particular commit hash, use idiomatic Go to add this package as a dependency: go get github.com/mattermost/mattermost-server/server/public. This relocated Go API maintains backwards compatibility with Mattermost v7. Furthermore, the existing Go API previously at github.com/mattermost/mattermost-server/v6/model remains forward compatible with Mattermost v8, but may not contain newer features. Plugins do not need to be recompiled, but developers may opt in to using the new package to simplify their build process. The new public package is shipping alongside Mattermost v8 as version 0.5.0 to allow for some additional code refactoring before releasing as v1 later this year.
Three configuration fields have been added, LogSettings.AdvancedLoggingJSON, ExperimentalAuditSettings.AdvancedLoggingJSON, and NotificationLogSettings.AdvancedLoggingJSON which support multi-line JSON, escaped JSON as a string, or a filename that points to a file containing JSON. The AdvancedLoggingConfig fields have been deprecated.
The Go MySQL driver has changed the maxAllowedPacket size from 4MiB to 64MiB. This is to make it consistent with the change in the server side default value from MySQL 5.7 to MySQL 8.0. If your max_allowed_packet setting is not 64MiB, then please update the MySQL config DSN with an additional param of maxAllowedPacket to match with the server side value. Alternatively, a value of 0 can be set to to automatically fetch the server side value, on every new connection, which has a performance overhead.

Removed ExperimentalSettings.PatchPluginsReactDOM. If this setting was previously enabled, confirm that:

  1. All Mattermost-supported plugins are updated to the latest versions.
  2. Any other plugins have been updated to support React 17. See the section for v7.7 release for more information.
Removed deprecated PermissionUseSlashCommands.
Removed deprecated model.CommandArgs.Session.
For servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the ServiceSettings.AllowCorsFrom | configuration setting. Also ensure that | the siteURL is set correctly. |
In v8.0 release, the following repositories are merged into one: mattermost-server, mattermost-webapp and mmctl. Developers should read the updated Developer Guide for details.
Fixed an issue caused by a migration in the previous release. Query takes around 11ms on a PostgreSQL 14 DB t3.medium RDS instance. Locks on the preferences table will only be acquired if there are rows to delete, but the time taken is negligible.
Fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in PostgreSQL: Execution time: 58.11 sec, DELETE 2766690. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec).
For servers wanting to allow websockets to connect from other origins, please set the ServiceSettings.AllowCorsFrom config setting.

The file info stats query is now optimized by denormalizing the channelID column into the table itself. This will speed up the query to get the file count for a channel when selecting the right-hand pane. Migration times:

On a PostgreSQL 12.14 DB with 1731 rows in FileInfo and 11M posts, it took around 0.27s

On a MySQL 8.0.31 DB with 1405 rows in FileInfo and 11M posts, it took around 0.3s

v7.10In v7.10.1, fixed an issue caused by a migration in the previous release. Query takes around 11ms on a PostgreSQL 14 DB t3.medium RDS instance. Locks on the preferences table will only be acquired if there are rows to delete, but the time taken is negligible.
In v7.10.1, fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690.
In v7.10.3, for servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the | ServiceSettings.AllowCorsFrom | configuration setting. Also ensure that | the siteURL is set correctly. |
v7.9

Added a new index on Posts(OriginalId). For a database with 11.8 million posts, on a machine with a i7-11800H CPU (8 cores, 16 threads), 32GiB of RAM and SSD, the index creation takes 98.51s on MYSQL and 2.6s on PostgreSQL.

  • In PostgreSQL databases, the Posts table will be locked during index creation. To avoid locking this table, admins can create the index manually before performing the upgrade using the following non-blocking query: CREATE INDEX CONCURRENTLY idx_posts_original_id ON Posts(OriginalId);.
  • Admins managing PostgreSQL deployments containing fewer posts may prefer that the migration process creates the index, and accept that Posts table will remain locked until the migration is complete.
In v7.9.4, fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690.

In v7.9.4, backported a fix related Oauth 2. Query times depend on if you have rows to delete or not.

With no rows to delete:

  • MySQL v5.7.12: 9ms
  • PostgreSQL v10: 21ms

4 rows:

  • MySQL v5.7.12: 17.2ms
  • PostgreSQL v10: 9.9ms

Those times are based off the following table sizes:

  • Preferences: 2 million records
  • oauthaccessdata and sessions: 10 records

You can assess the number of impacted rows by running the following:

PostgreSQL:

SELECT count(o.*)FROM oauthaccessdata o WHERE NOT EXISTS (    SELECT p.*    FROM preferences p    WHERE o.clientid = p.name      AND o.userid = p.      userid      AND p.category =      'oauth_app'    );

MySQL:

SELECT COUNT(o.`Token`)FROM OAuthAccessData oLEFT JOIN Preferences p ON o.  clientid = p.name  AND o.userid = p.userid  AND p.category = 'oauth_app'INNER JOIN Sessions s ON o.token = s  .tokenWHERE p.name IS NULL;

Locks on the oauthaccessdata and sessions table will only be acquired if there are rows to delete.

In v7.9.5, for servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the | ServiceSettings.AllowCorsFrom | configuration setting. Also ensure that | the siteURL is set correctly. |
v7.8Message Priority & Acknowledgement is now enabled by default | for all instances. You may disable this feature in the System Console by going to Posts > Message Priority or via the config PostPriority setting. |
In v7.8.5, fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690.

In v7.8.5, backported a fix related Oauth 2. Query times depend on if you have rows to delete or not.

With no rows to delete:

  • MySQL v5.7.12: 9ms
  • PostgreSQL v10: 21ms

4 rows:

  • MySQL v5.7.12: 17.2ms
  • PostgreSQL v10: 9.9ms

Those times are based off the following table sizes:

  • Preferences: 2 million records
  • oauthaccessdata and sessions: 10 records

You can assess the number of impacted rows by running the following:

PostgreSQL:

SELECT count(o.*) FROM oauthaccessdata o WHERE NOT EXISTS (    SELECT p.*    FROM preferences p    WHERE o.clientid = p.name      AND o.userid = p.      userid      AND p.category =      'oauth_app'    );

MySQL:

SELECT COUNT(o.`Token`)FROM OAuthAccessData oLEFT JOIN Preferences p ON o.  clientid = p.name  AND o.userid = p.userid  AND p.category = 'oauth_app'INNER JOIN Sessions s ON o.token = s  .tokenWHERE p.name IS NULL;

Locks on the oauthaccessdata and sessions table will only be acquired if there are rows to delete.

In v7.8.7, for servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the | ServiceSettings.AllowCorsFrom | configuration setting. Also ensure that | the siteURL is set correctly. |

In v7.8.11, improved performance on data retention DeleteOrphanedRows queries.

New migration for a new table:

MySQL:

CREATE TABLEIF NOT EXISTS  RetentionIdsForDeletion(Id    VARCHAR(26) NOT NULL,    TableName VARCHAR(64),    Ids json, PRIMARY KEY (Id      ), KEY    idx_retentionidsfordeletion_tablename    (TableName)) ENGINE =  InnoDB DEFAULT CHARSET =  utf8mb4;  ``

PostgreSQL:

CREATE TABLEIF NOT EXISTS  retentionidsfordeletion(id    VARCHAR(26) PRIMARY KEY,    tablename VARCHAR(64),    ids VARCHAR(26) []);  CREATE INDEXIF NOT EXISTS  idx_retentionidsfordeletion_tablename  ON retentionidsfordeletion(    tablename);  ``

Hard deleting a user or a channel will now also clean up associated reactions.

Removed feature flag DataRetentionConcurrencyEnabled. Data retention now runs without concurrency in order to avoid any performance degradation.

Added a new configuration setting DataRetentionSettings.RetentionIdsBatchSize, which allows admins to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100.

v7.7

Plugins with a webapp component may need to be updated to work with Mattermost v7.7 release and the updated React v17 dependency.

This is to avoid plugins crashing with an error about findDOMNode being called on an unmounted component. While our starter template depended on an external version of React, it did not do the same for ReactDOM. Plugins need to update their webpack.config.js directives to externalize ReactDOM. For reference, see https://github.com/mattermost/mattermost-plugin-playbooks/pull/1489. Server-side only plugins are unaffected. This change can be done for existing plugins any time prior to upgrading to Mattermost v7.7 and is backwards compatible with older versions of Mattermost. If you run into issues, you can either enable ExperimentalSettings.PatchPluginsReactDOM or just disable the affected plugin while it's updated.

Denormalized Threads table by adding the ThreadTeamId column. Even though it denormalizes the schema, we gain performance by removing the unnessesary joins.

Test results for schema changes are outlined below:

instance: db.r5.large

size of Threads table: 846313 rows

number of posts: 12 million

number of reactions: 2.5 million

MySQL:

-- Drop any existing TeamId column from 000094_threads_teamid.up.sqlSET @preparedStatement = (SELECT IF(    EXISTS(``        SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS        WHERE table_name = 'Threads'        AND table_schema = DATABASE()        AND column_name = 'TeamId'    ),    'ALTER TABLE Threads DROP COLUMN TeamId;',    'SELECT 1;'));PREPARE removeColumnIfExists FROM @preparedStatement;EXECUTE removeColumnIfExists;DEALLOCATE PREPARE removeColumnIfExists;SET @preparedStatement = (SELECT IF(    NOT EXISTS(        SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS        WHERE table_name = 'Threads'        AND table_schema = DATABASE()        AND column_name = 'ThreadTeamId'    ),    'ALTER TABLE Threads ADD COLUMN ThreadTeamId varchar(26) DEFAULT NULL;',    'SELECT 1;'));PREPARE addColumnIfNotExists FROM @preparedStatement;EXECUTE addColumnIfNotExists;DEALLOCATE PREPARE addColumnIfNotExists;Query OK, 0 rows affected (7.71 sec)UPDATE Threads, ChannelsSET Threads.ThreadTeamId = Channels.TeamIdWHERE Channels.Id = Threads.ChannelIdAND Threads.ThreadTeamId IS NULL;Query OK, 846313 rows affected (51.32 sec)Rows matched: 846313 Changed: 846313 Warnings: 0

PostgreSQL:

-- Drop any existing TeamId column from 000094_threads_teamid.up.sqlALTER TABLE threads DROP COLUMN IF EXISTS teamid;ALTER TABLE threads ADD COLUMN IF NOT EXISTS threadteamid VARCHAR(26);ALTER TABLETime: 2.236 msUPDATE threadsSET threadteamid = channels.  teamidFROM channelsWHERE threads.threadteamid IS  NULL  AND channels.id = threads.  channelid;UPDATE 847646Time: 29744.608 ms (00:29.745)**Backwards-compatibility:**A previous version of Mattermost can run with the new schema changes**Table locks or impact to existing operations on the table:**Table locks - Threads table

Queries posted above can be run prior to upgrading Mattermost for both MySQL and PostgreSQL. After schema changes migration becomes instantaneous (0.78 sec).

Starting with the Calls version shipping with v7.7, there's now a minimum version requirement when using the external RTCD service. This means that if Calls is configured to use the external service, customers need to upgrade RTCD first to at least version 0.8.0 or the plugin will fail to start.
In v7.7.2, Message Priority & Acknowledgement is now enabled by | default for all instances. You may disable this feature in the System Console by going to Posts > Message Priority or via the config PostPriority | setting. |
v7.5Added a new schema migration to ensure ParentId column is dropped from the Posts table. Depending on the table size, if the column is not dropped before, a significant spike in database CPU usage is expected on MySQL databases. Writes to the table will be limited during the migration.
For PluginRegistry.registerCustomRoute, when you register a custom route component, you must specify a CSS grid-area in order for it to be placed properly into the root layout (recommended: grid-area: center).
v7.3Boards is moving from a channel-based to a role-based permissions system. The migration will happen automatically, but your administrator should perform a backup prior to the upgrade. We removed workspaces, so if you were a member of many boards prior to migration, they will now all appear under the same sidebar.
v7.2

Several schema changes impose additional database constraints to make the data more strict. All the commands listed below were tested on a 8 core, 16GB RAM machine. Here are the times recorded:

PostgreSQL (131869 channels, 2 teams):

  • CREATE TYPE channel_type AS ENUM ('P', 'G', 'O', 'D'); took 14.114 milliseconds
  • ALTER TABLE channels alter column type type channel_type using type::channel_type; took 3856.790 milliseconds (3.857 seconds)
  • CREATE TYPE team_type AS ENUM ('I', 'O'); took 4.191 milliseconds
  • ALTER TABLE teams alter column type type team_type using type::team_type; took 116.205 milliseconds
  • CREATE TYPE upload_session_type AS ENUM ('attachment', 'import'); took 4.266 milliseconds
  • ALTER TABLE uploadsessions alter column type type upload_session_type using type::upload_session_type; took 37.099 milliseconds

MySQL (270959 channels, 2 teams):

  • ALTER TABLE Channels MODIFY COLUMN Type ENUM("D", "O", "G", "P"); took 13.24 seconds
  • ALTER TABLE Teams MODIFY COLUMN Type ENUM("I", "O"); took 0.04 seconds
  • ALTER TABLE UploadSessions MODIFY COLUMN Type ENUM("attachment", "import"); took 0.03 seconds
v7.1A new configuration option MaxImageDecoderConcurrency indicates how many images can be decoded concurrently at once. The default is -1, and the value indicates the number of CPUs present. This affects the total memory consumption of the server. The maximum memory of a single image is dictated by MaxImageResolution * 24 bytes. Therefore, we recommend that MaxImageResolution * MaxImageDecoderConcurrency * 24 should be less than the allocated memory for image decoding.

Mattermost v7.1 introduces schema changes in the form of a new column and its index. Our test results for the schema changes are included below:

  • MySQL 12M Posts, 2.5M Reactions - ~1min 34s (instance: PC with 8 cores, 16GB RAM)
  • PostgreSQL 12M Posts, 2.5M Reactions - ~1min 18s (instance: db.r5.2xlarge)

You can run the following SQL queries before the upgrade to obtain a lock on Reactions table, so that users' reactions posted during this time won't be reflected in the database until the migrations are complete. This is fully backwards-compatible.

MySQL:

  • ALTER TABLE Reactions ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT "";
  • UPDATE Reactions SET ChannelId = COALESCE((select ChannelId from Posts where Posts.Id = Reactions.PostId), '') WHERE ChannelId="";
  • CREATE INDEX idx_reactions_channel_id ON Reactions(ChannelId) LOCK=NONE;

PostgreSQL:

  • ALTER TABLE reactions ADD COLUMN IF NOT EXISTS channelid varchar(26) NOT NULL DEFAULT '';
  • UPDATE reactions SET channelid = COALESCE((select channelid from posts where posts.id = reactions.postid), '') WHERE channelid='';
  • CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_reactions_channel_id on reactions (channelid);
v7.0

IMPORTANT: Session length configuration settings have changed from using a unit of days to hours. Instances using a config.json file or a database configuration for the following values should be automatically migrated to the new units, but instances using environment variables must make the following changes:

  1. replace MM_SERVICESETTINGS_SESSIONLENGTHWEBINDAYS with MM_SERVICESETTINGS_SESSIONLENGTHWEBINHOURS (x24 the value).
  2. replace MM_SERVICESETTINGS_SESSIONLENGTHMOBILEINDAYS with MM_SERVICESETTINGS_SESSIONLENGTHMOBILEINHOURS (x24 the value).
  3. replace MM_SERVICESETTINGS_SESSIONLENGTHSSOINDAYS with MM_SERVICESETTINGS_SESSIONLENGTHSSOINHOURS (x24 the value).
MySQL self-hosted customers may notice the migration taking longer than usual when having a large number of rows in FileInfo table. For MySQL, it takes around 19 seconds for a table of size 700,000 rows. The time required for PostgreSQL is negligible. The testing was performed on a machine with specifications of CPU - Intel i7 6-cores @ 2.6 GHz and Memory - 16 GB.
When a new configuration setting via System Console > Experimental > Features > Enable App Bar is enabled, all channel header icons registered by plugins will be moved to the new Apps Bar, even if they do not explicitly use the new registry function to render a component there. The setting for Apps Bar defaults to false for self-hosted deployments.
The value of ServiceSettings.TrustedProxyIPHeader defaults to empty from now on. A previous bug prevented this from happening in certain conditions. | Customers are requested to check for these values in their config and set them to nil if necessary. See more details | here. |
Collapsed Reply Threads is now generally available and enabled by default for new | Mattermost servers. For servers upgrading to v7.0 and later, please reference | this article for more information | and guidance on enabling the feature. |
v6.7

New schema changes were introduced in the form of a new index. The following summarizes the test results measuring how long it took for the database queries to run with these schema changes:

MySQL 7M Posts - ~17s (Instance: db.r5.xlarge)

MySQL 9M Posts - 2min 12s (Instance: db.r5.large)

Postgres 7M Posts - ~9s (Instance: db.r5.xlarge)

For customers wanting a zero downtime upgrade, they are encouraged to apply this index prior to doing the upgrade. This is fully backwards compatible and will not acquire any table lock or affect any existing operations on the table when run manually. Else, the queries will run during the upgrade process and will lock the table in non-MySQL environments. Run the following to apply this index:

For MySQL: CREATE INDEX idx_posts_create_at_id on Posts(CreateAt, Id) LOCK=NONE;

For Postgres: CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_posts_create_at_id on posts(createat, id);

In v6.7.1, the value of ServiceSettings.TrustedProxyIPHeader defaults to empty from now on. A previous bug prevented this from happening in certain | conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details | here. |
v6.6The Apps Framework protocol for binding/form submissions has changed, by separating the single call into separate submit, form, refresh and lookup calls. If any users have created their own Apps, they have to be updated to the new system.
Channel admins can now configure certain actions to be executed automatically based on trigger | conditions without writing any code. Users running an older Playbooks release need to upgrade their Playbooks instance to at least v1.26 to take advantage of | the channel actions functionality. |
In v6.6.2, the value of ServiceSettings.TrustedProxyIPHeader defaults to empty from now on. A previous bug prevented this from happening in certain | conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details | here. |
v6.5The mattermost version CLI command does not interact with the database anymore. Therefore the database version is not going to be | printed. Also, the database migrations are not going to be applied with the version sub command. | A new db migrate sub command is added to enable administrators | to trigger migrations. |
In v6.5.2, the value of ServiceSettings.TrustedProxyIPHeader defaults to empty from now on. A previous bug prevented this from happening in certain | conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details | here. |
v6.4

A new schema migration system has been introduced, so we strongly recommend backing up the database before updating the server to this version. The new migration system will run through all existing migrations to record them to a new table. This will only happen for the first run in order to migrate the application to the new system. The table where the migration information is stored is called db_migrations. Additionally, a db_lock table is used to prevent multiple installations from running migrations in parallel. In case of an error while applying the migrations, please check this table first. Any downtime depends on how many records the database has and whether there are missing migrations in the schema. If you encounter an issue please file an Issue by including the failing migration name, database driver/version, and the server logs.

On MySQL, if you encounter an error "Failed to apply database migrations" when upgrading to v6.4.0, it means that there is a mismatch between the table collation and the default database collation. You can manually fix this by changing the database collation with ALTER DATABASE <YOUR_DB_NAME> COLLATE = 'utf8mb4_general_ci',. Then do the server upgrade again and the migration will be successful.

It has been commonly observed on MySQL 8+ systems to have an error Error 1267: Illegal mix of collations when upgrading due to changing the default collation. This is caused by the database and the tables having different collations. If you get this error, please change the collations to have the same value with, for example, ALTER DATABASE <db_name> COLLATE = '<collation>'.

The new migration system requires the MySQL database user to have additional EXECUTE, CREATE ROUTINE, ALTER ROUTINE and REFERENCES privileges to run schema migrations.
v6.3In v6.3.3, the default for ThreadAutoFollow has been changed to false. This does not affect existing configurations where this value is already set to true.
In v6.3.9, the value of ServiceSettings.TrustedProxyIPHeader defaults to empty from now on. A previous bug prevented this from happening in certain | conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details | here. |
v6.2Channel results in the channel autocomplete will include private channels. Customers using Bleve or | Elasticsearch for autocomplete will have to reindex their data to get the new results. Since this can | take a long time, we suggest disabling autocomplete and running indexing in the background. When this is complete, re-enable autocomplete. | | .. note:: | Only channel members see private channel names in autocomplete results. |
In v6.2.3, the default for ThreadAutoFollow has been changed to false. This does not affect existing configurations where this value is already set to true.
Mattermost Boards requires EnableReliableWebSockets setting to be manually set to true for real-time updates to appear correctly.
v6.1Please refer to the schema migration analysis when upgrading to v6.1.
The Bleve index has been updated to use the scorch index type. This new default index type features some efficiency improvements which means that the indexes use significantly less disk space. To use this new type of index, after upgrading the server version, run a purge operation and then a reindex from the Bleve section of the System Console. Bleve is still compatible with the old indexes, so the currently indexed data will work fine if the purge and reindex is not run.

A composite index has been added to the jobs table for better query performance. For some customers with a large jobs table, this can take a long time, so we recommend adding the index during off-hours, and then running the migration. A table with more than 1 million rows can be considered as large enough to be updated prior to the upgrade.

  • For PostgreSQL: create index concurrently idx_jobs_status_type on jobs (status,type);
  • For MySQL: create index idx_jobs_status_type on Jobs (Status,Type);
In v6.1.3, the default for ThreadAutoFollow has been changed to false. This does not affect existing configurations where this value is already set to true.
Mattermost Boards requires EnableReliableWebSockets setting to be manually set to true for real-time updates to appear correctly.
v6.0

Longer migration times can be expected.

  • See this document for the estimated upgrade times with datasets of 10+ million posts.
  • See this document for the estimated upgrade times with datasets of 70+ million posts.

The field type of Data in model.ClusterMessage was changed to []byte from string. A v6 server is incompatible to run along with a v5 server in a cluster. Customers upgrading from 5.x to 6.x cannot do a High Availability upgrade. While upgrading, it is required that no other v5 server runs when a v6 server is brought up. A v6 server will run significant database schema changes that can cause a large startup time depending on the dataset size. Zero downtime will not be possible, but depending on the efforts made during the migration process, it can be minimized to a large extent.

1. Low effort, long downtime - This is the usual process of starting a v6 server normally. This has two implications: during the migration process, various tables will be locked which will render those tables read-only during that period. Secondly, once the server finishes migration and starts the application, no other v5 server can run in the cluster.

2. Medium effort, medium downtime - This process will require SQL queries to be executed manually on the server. To avoid causing a table lock, a customer can choose to use the pt-online-schema-change tool for MySQL. For Postgres, the table locking is very minimal. The advantage is that since there are a lot of queries, the customer can take their own time to run individual queries during off-hours. All queries except #11 are safe to be executed this way. Then the usual method of (1) can be followed.

3. High effort, low downtime - This process requires everything of (2), plus it tries to minimize the impact of query #11. We can do this by following step 2, and then starting v6 along with a running v5 server, and then monitor the application logs. As soon as the v6 application starts up, we need to bring down a v5 node. This minimizes the downtime to only a few seconds.

It is recommended to start Mattermost directly and not through systemctl to avoid the server process getting killed during the migration. This can happen since the value of TimeoutStartSec in the provided systemctl service file is set to one hour.

Customers using the Mattermost Kubernetes operator should be aware of the above migration information and choose the path that is most appropriate for them. If (1) is acceptable, then the normal upgrade process using the operator will suffice. For minimum downtime, follow (2) before using the operator to update Mattermost following the normal upgrade process.

While trying to upgrade to a Mattermost version >= 6.0.x, you might encounter the following error: Failed to alter column type. It is likely you have invalid JSON values in the column. Please fix the values manually and run the migration again.

This means that the particular column has some invalid JSON values which need to be fixed manually. A common fix that is known to work is to wipe out all \u0000 characters.

Please follow these steps:

  1. Check the affected values by: SELECT COUNT(*) FROM <table> WHERE <column> LIKE '%\u0000%';
  2. If you get a count more than 0, check those values manually, and confirm they are okay to be removed.
  3. Remove them by UPDATE <table> SET <column> = regexp_replace(<column>, '\\u0000', '', 'g') where <column> like '%\u0000%';

Then try to start Mattermost again.

Please see unsupported legacy releases documentation for a list of deprecations in this release. |
Focalboard plugin has been renamed to Mattermost Boards, and v0.9.1 (released with Mattermost v6.0) is now enabled by default.
The advanced logging configuration schema changed. This is a breaking change relative to 5.x. See updated | documentation. |
The existing theme names and colors, including "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" have been updated to the new "Denim", | "Quartz", "Indigo", and "Onyx" theme names and colors, respectively. Anyone using the existing themes will see slightly modified theme colors after their | server or workspace is upgraded. The theme variables for the existing "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" themes will still be | accessible in our documentation. A custom theme can be created with these theme variables if desired. | Custom themes are unaffected by this change. |

Some breaking changes to plugins are included:

  • Support for left-hand side-specific bot icons was dropped.
  • Removed a deprecated "Backend" field from the plugin manifest.
  • Converted the "Executables" field in the plugin manifest to a map.
Mattermost Boards requires EnableReliableWebSockets setting to be manually set to true for real-time updates to appear correctly.
v5.38.0The “config watcher” (the mechanism that automatically reloads the config.json file) has been removed in favor of the mmctl config reload command, which must be run to apply configuration changes after they are made on disk. This change improves configuration performance and robustness.
v5.38 adds fixes for some of the incorrect mention counts and unreads around threads and channels since the introduction of Collapsed Reply Threads (Beta). This fix is done through a SQL migration, and it may take several minutes to complete for large databases. The fixCRTChannelMembershipCounts fix takes 1 minute and 20 seconds for a database containing approximately four million channel memberships and about 130,000 channels. The fixCRTThreadCountsAndUnreads fix takes about 3 minutes and 30 seconds for a database containing 56367 threads, 124587 thread memberships, and 220801 channel memberships. These are on MySQL v5.6.51.
Focalboard v0.8.2 (released with Mattermost v5.38.0) requires Mattermost v5.37+ due to the new database connection system.
v5.37.0The platform binary and “--platform” flag have been removed. If you are using the “--platform” flag or are using the platform binary directly to run the Mattermost server application via a systemd file or custom script, you will be required to use only the mattermost binary.
Collapsed Reply Threads are available as Beta in Mattermost Server | v5.37 and later. It’s expected that you may experience bugs as we stabilize the feature. In particular, please be aware of | the known issues documented here. |
v5.37 adds support for emoji standard v13.0. If you have added a custom emoji in the past that uses one of the new system names, then it is going to get overwritten by the system emoji. The workaround is to change the custom emoji name.
Parts of Incident Collaboration are now available to all Mattermost editions. As part of this update, Incident Collaboration will require a minimum server version of v5.37. To learn more about what is available in each edition, visit our pricing page.
In v5.37.8, the default for ThreadAutoFollow has been changed to false. This does not affect existing configurations where this value is already set to true.
v5.36.0

Gossip clustering mode is now in General Availability and is no longer available as an option. All cluster traffic will always use the gossip protocol. The config setting UseExperimentalGossip has no effect and has only been kept for compatibility purposes. The setting to use gossip has been removed from the System Console.

For High Availability upgrades, all nodes in the cluster must use a single protocol. If an existing system is not currently using gossip, one node in a cluster can't be upgraded while other nodes in the cluster use an older version. Customers must either use gossip for their High Availability upgrade, or customers must shut down all nodes, perform the upgrade, and then bring all nodes back up.

To enable Focalboard, open the Marketplace from the sidebar menu, install the Focalboard plugin, then click on Configure, enable it, and save. Update your NGINX or Apache web proxy config.
v5.35.0Due to the introduction of backend database architecture required for upcoming new features, Shared Channels and Collapsed Reply Threads, the performance of the migration process for the v5.35 release (May 16, 2021) has been noticeably affected. Depending on the size, type, and version of the database, longer than usual upgrade times should be expected. This can vary from a couple of minutes (average case) to hours (worst case, MySQL 5.x only). A moderate to significant spike in database CPU usage should also be expected during this process. More details on the performance impact of the migration and possible mitigation strategies are available.
The existing password generation logic used during the bulk user import process was comparatively weak. Hence it's advised for admins to immediately reset the passwords for all the users who were generated during the bulk import process and whose password has not been changed even once.
v5.35.0 introduces a new feature to search for files. Search results for files shared in the past may be incomplete until a | content extraction command is executed to extract | and index the content of files already in the database. Instances running Elasticsearch or Bleve search backends will also need to execute a Bulk Indexing after | the content extraction is complete. Please see more details in this blog post. |
v5.34.1

v5.34.1 fixes an issue where upgrading to v5.34.0 runs a migration that can cause timeouts on MySQL installations. Upgrading to v5.34.1 may also execute missing migrations that were scheduled for v5.32.0. These additions can be lengthy on very big MySQL (version 5.x) installations.

  • Altering of Posts.FileIds type (PostgreSQL only)
  • Added new column ThreadMemberships.UnreadMentions
  • Added new column Channels.Shared
  • Added new column Reactions.UpdateAt
  • Added new column Reactions.DeleteAt
v5.33.0Deleting a reaction is now a soft delete in the Reactions table. A schema update is required and may take up to 15 seconds on first run with large data sets.
WebSocket handshakes done with HTTP version lower than 1.1 will result in a warning, and the server will transparently upgrade the version to 1.1 to comply with the WebSocket RFC. This is done to work around incorrect Nginx (and other proxy) configs that do not set the proxy_http_version directive to 1.1. This facility will be removed in a future Mattermost version and it is strongly recommended to fix the proxy configuration to correctly use the WebSocket protocol.
v5.32.0ExperimentalChannelOrganization, EnableXToLeaveChannelsFromLHS, CloseUnusedDirectMessages, and ExperimentalHideTownSquareinLHS settings are only functional if the Legacy Sidebar (EnableLegacySidebar) is enabled since they are not compatible with the new sidebar experience. ExperimentalChannelSidebarOrganization has been deprecated, since the new sidebar is now enabled for all users.
Breaking changes to the Golang client API were introduced: GetPostThread, GetPostsForChannel, GetPostsSince, GetPostsAfter, GetPostsBefore, and GetPostsAroundLastUnread now require an additional collapsedThreads parameter to be passed. Any client making use of these functions will need to update them when upgrading its dependencies.
A breaking change was introduced when upgrading the Go version to v1.15.5 where user logins fail with AD/LDAP Sync when the certificate of the LDAP Server has no Subject Alternative Name (SAN) in it. Creating a new certificate on the AD/LDAP Server with the SAN inside fixes this.
TLS versions 1.0 and 1.1 have been deprecated by browser vendors. Starting in Mattermost Server v5.32 (February 16), mmctl returns an error when connected to Mattermost servers deployed with these TLS versions. System admins will need to explicitly add a flag in their commands to continue to use them. We recommend upgrading to TLS version 1.2 or higher.
v5.31.0For Mobile Apps v1.42.0+, the minimum server version is set to v5.31.3 as v5.31.3 fixed an issue where the server version was reported as v5.30.0.
v5.29.0A new configuration setting ThreadAutoFollow has been added to support Collapsed Reply Threads releasing in beta in Q1 2021. | This setting is enabled by default and may affect server performance. It is recommended to review our documentation on hardware requirements | to ensure your servers are appropriately scaled for the size of your user base. |
Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library.
v5.28.0

Now when the service crashes, it will generate a coredump instead of just dumping the stack trace to the console. This allows us to preserve the full information of the crash to help with debugging it.

For more information about coredumps, please see: https://man7.org/linux/man-pages/man5/core.5.html.

In-product notices have been introduced to keep system admins and end users informed of the latest product enhancements available in new server and desktop | versions. Learn more about in-product notices and how to disable them in our documentation. |
Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library.
v5.27.0Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library.
v5.26.0In v5.26, Elasticsearch indexes needed to be recreated. Admins should re-index Elasticsearch using the Purge index and then Index now button so that all the changes will be included in the index. Systems may be left with a limited search during the indexing, so it should be done during a time when there is little to no activity because it may take several hours.

An EnableExperimentalGossipEncryption option was added under ClusterSettings. If set to true, and UseExperimentalGossip is also true, all communication through the cluster using the gossip protocol will be encrypted. The encryption uses AES-256 by default, and it is not kept configurable by design. However, if one wishes, they can set the value in Systems table manually for the ClusterEncryptionKey row. A key is a byte array converted to base64. It should be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.

To update the key, one can execute: UPDATE Systems SET Value='<value>' WHERE Name='ClusterEncryptionKey'; in MySQL and UPDATE systems SET value='<value>' WHERE name='ClusterEncryptionKey' for PostgreSQL.

For any change in this config setting to take effect, the whole cluster must be shut down first. Then the config change made, and then restarted. In a cluster, all servers either will completely use encryption or not. There cannot be any partial usage.

SAML Setting "Use Improved SAML Library (Beta)" was forcefully disabled.
PostgreSQL ended long-term support for version 9.4 in February 2020. From v5.26 Mattermost officially supports PostgreSQL version 10 as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL 9.4. PostgreSQL 9.4 and all 9.x versions are now fully deprecated in our v5.30 release (December 16, 2020). Follow the Upgrading Section within the PostgreSQL documentation.
v5.25.0Some incorrect instructions regarding SAML setup with Active Directory ADFS for setting the “Relying Party Trust Identifier” were corrected. Although the | settings will continue to work, it is encouraged that you | modify those settings. |
Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library.
v5.24.0A new configuration setting, ExtendSessionLengthWithActivity automatically extends sessions to keep users logged in if they are active in their Mattermost apps. It is recommended to enable this setting to improve user experience if compliant with your organization's policies. Learn more here.

The mattermost_http_request_duration_seconds histogram metric (in Enterprise Edition) has been removed. This information was already captured by mattermost_api_time, which also contains the API handler name, HTTP method, and the response code.

As an example, if you are using rate(mattermost_http_request_duration_seconds_sum{server=~"$var"}[5m]) / rate(mattermost_http_request_duration_seconds_count{server=~"$var"}[5m]) to measure average call duration, it needs to be replaced with sum(rate(mattermost_api_time_sum{server=~"$var"}[5m])) by (instance) / sum(rate(mattermost_api_time_count{server=~"$var"}[5m])) by (instance).

Due to fixing performance issues related to emoji reactions, the performance of the upgrade has been affected in that the schema upgrade now takes more time in environments with lots of reactions in their database. These environments are recommended to perform the schema migration during low usage times and potentially in advance of the upgrade. Since this migration happens before the Mattermost server is fully launched, non-High Availability installs will be unreachable during this time.

The migration is a single line of SQL and can be applied directly to the database through the MySQL/PSQL command line clients if you prefer to decouple this from restarting the Mattermost server. It is fully backwards compatible so the schema change can be applied to any previous version of Mattermost without issue. During the time the schema change is running (~30s per million rows in the Reactions table), if end users attempt to react to posts, the emoji reactions will not load for end users.

MySQL: ALTER TABLE Reactions DROP PRIMARY KEY, ADD PRIMARY KEY (PostId, UserId, EmojiName);

PostgreSQL: ALTER TABLE reactions DROP CONSTRAINT reactions_pkey, ADD PRIMARY KEY (PostId, UserId, EmojiName);

On mobile apps, users will not be able to see LDAP group mentions (E20 feature) in the autocomplete dropdown. Users will still receive notifications if they are part of an LDAP group. However, the group mention keyword will not be highlighted.
SAML Setting "Use Improved SAML Library (Beta)" was forcefully disabled. Follow instructions at https://docs.mattermost.com/administration-guide/onboard/sso-saml.html for enabling SAML using the feature-equivalent xmlsec1 utility.
v5.22.0

Due to fixing performance issues related to emoji reactions, the performance of the upgrade has been affected in that the schema upgrade now takes more time in environments with lots of reactions in their database. These environments are recommended to perform the schema migration during low usage times and potentially in advance of the upgrade. Since this migration happens before the Mattermost server is fully launched, non-High Availability installs will be unreachable during this time.

The migration is a single line of SQL and can be applied directly to the database through the MySQL/PSQL command line clients if you prefer to decouple this from restarting the Mattermost server. It is fully backwards compatible so the schema change can be applied to any previous version of Mattermost without issue. During the time the schema change is running (~30s per million rows in the Reactions table), if end users attempt to react to posts, the emoji reactions will not load for end users.

MySQL: ALTER TABLE Reactions DROP PRIMARY KEY, ADD PRIMARY KEY (PostId, UserId, EmojiName);

Postgres: ALTER TABLE reactions DROP CONSTRAINT reactions_pkey, ADD PRIMARY KEY (PostId, UserId, EmojiName);

The Channel Moderation Settings feature is supported on mobile app versions v1.30 and later. In earlier versions of the mobile app, users who attempt to post or react to posts without proper permissions will see an error.
Direct access to the Props field in the model.Post structure has been deprecated. The available GetProps() and SetProps() methods should now be used. Also, direct copy of the model.Post structure must be avoided in favor of the provided Clone() method.
SAML Setting "Use Improved SAML Library (Beta)" was forcefully disabled. Follow instructions at https://docs.mattermost.com/administration-guide/onboard/sso-saml.html for enabling SAML using the feature-equivalent xmlsec1 utility.
v5.21.0Honour key value expiry in KVCompareAndSet, KVCompareAndDelete, and KVList. We also improved handling of plugin key value race conditions and deleted keys in Postgres.
SAML Setting "Use Improved SAML Library (Beta)" was forcefully disabled. Follow instructions at https://docs.mattermost.com/administration-guide/onboard/sso-saml.html for enabling SAML using the feature-equivalent xmlsec1 utility.
v5.20.0Any pre-packaged plugin that is not enabled in the config.json will no longer install automatically, but can continue to be installed via the Plugin Marketplace.
Boolean elements from interactive dialogs are no longer serialized as strings. While we try to avoid breaking changes, this change was necessary to allow both the web and mobile apps to work with the boolean elements introduced with v5.16.
v5.19.0LockTeammateNameDisplay setting was moved to Enterprise Edition E20 as it was erroneously available in Team Edition and Enterprise Edition E10.
v5.18.0Marking a post unread from the mobile app requires v1.26 or later. If using v5.18, but mobile is on v1.25 or earlier, marking a post unread from webapp/desktop will only be reflected on mobile the next time the app launches or is brought to the foreground.
The Go module path of mattermost-server was changed to comply with the Go module version specification. Developers using Go modules with mattermost-server as a dependency must change the module and import paths to github.com/mattermost/mattermost-server/v5 when upgrade this dependency to v5.18. See https://go.dev/blog/v2-go-modules for further information.
Removed Team.InviteId from the related Websocket event and sanitized it on all team API endpoints for users without invite permissions.
Removed the ability to change the type of a channel using the PUT /channels/{channel_id} API endpoint. The new PUT /channels/{channel_id}/privacy endpoint should be used for that purpose.
v5.16.0Support for Internet Explorer (IE11) is removed. See this forum post to learn more.
The Mattermost Desktop v4.3.0 release includes a change to how desktop notifications are sent sent from non-secure URLs http://. Organizations using non-secure Mattermost Servers http:// will need to update to Mattermost Server versions 5.16.0+, 5.15.1, 5.14.4 or 5.9.5 (ESR) to continue receiving desktop notifications when using Mattermost Desktop v4.3.0 or later.
When enabling Guest Accounts, all users who have the ability to invite users will be able to | invite guests by default. System admins will need to remove this permission on each role via System Console > Permissions Schemes. In Mattermost Server | version 5.17, the system admin will be the only role to automatically get the invite guest permission, however the fix will not be applicable in 5.16 due to | database migration processes. |
v5.14.0Webhooks are now only displayed if the user is the creator of the webhook or a system administrator.
With the update from Google+ to Google People, system admins need to ensure the GoogleSettings.Scope config.json setting is set to profile email and | UserAPIEndpoint setting should be set to https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata per | updated documentation. |
v5.12.0If your plugin uses the DeleteEphemeralMessage plugin API, update it to accept a postId string parameter. See documentation to learn more.
Image link and YouTube previews do not display unless System Console > Enable Link Previews is enabled. Please ensure that your Mattermost server is connected to the internet and has network access to the websites from which previews are expected to appear. Learn more here.
ExperimentalEnablePostMetadata setting was removed. Post metadata, including post dimensions, is now stored in the database to correct scroll position and eliminate scroll jumps as content loads in a channel.
Added the ability to enforce the administration of teams/channels with Group Sync. If Group Sync is enabled, all team and channel admin designations will be lost upon upgrade. It is highly recommended that prior to upgrading, Team and channel admins are added to admin-specific LDAP groups corresponding to their teams and channels. After upgrading, those groups will need to be role-synced to the Team or channel admin role.
v5.11.0

If your integration uses Update.Props == nil to clear Props, this will no longer work in 5.11+. Instead, use Update.Props == {} to clear properties.

This change was made because Update.Props == nil unintentionally cleared all Props, such as the profile picture, instead of preserving them.

v5.10.0SupportedTimezonesPath setting in config.json and changes to timezones in the UI based on the timezones.json file was removed. This was made to support | storing configurations in the database. |
v5.9.0If DisableLegacyMfa setting in config.json is set to true and | multi-factor authentication is enabled, ensure your users have upgraded to mobile app | version 1.17 or later. Otherwise, users who have MFA enabled may not be able to log in successfully. | | If the setting is not defined in the config.json file, the DisableLegacyMfa setting is set to false by default to ensure no breaking changes. | | We recommend setting DisableLegacyMfa to true for additional security hardening. |
The public IP of the Mattermost application server is considered a reserved IP for additional security hardening in the context of untrusted external requests | such as Open Graph metadata, webhooks, or slash commands. | See documentation for additional information. |
v5.8.0The local image proxy has been added, and images displayed within the client are now affected by the AllowUntrustedInternalConnections setting. | See documentation for more details if you have trouble loading images. |
v5.6.0Built-in WebRTC is removed. See here for more details.

If EnablePublicChannelsMaterialization setting in config.json is set to false, an offline migration prior to upgrade may be required to synchronize the materialized table for public channels to increase channel search performance in the channel switcher (CTRL/CMD+K), channel autocomplete (~), and elsewhere in the UI. Use the following steps:

  1. Shut down your application servers.
  2. Connect to your Mattermost database.
  3. Execute the following queries:
DELETE FROM PublicChannels;INSERT INTO PublicChannels    (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)SELECT    c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.PurposeFROM    Channels cWHERE    c.Type = 'O';

The queries above rebuild the materialized PublicChannels table without modifying the authoritative Channels table.

This migration is not required if the experimental PublicChannels feature was never disabled. This feature launched in Mattermost v5.4 with a temporary flag to disable should an issue arise, but nothing prompted doing so. If you did not modify this setting, there is no need to perform this migration.

v5.4.0Mattermost mobile app version 1.13+ is required. File uploads will fail on earlier mobile app versions.
In certain upgrade scenarios the new Allow Team Administrators to edit others posts setting under General then Users and Teams may be set to True while the Mattermost default in 5.1 and earlier and with new 5.4+ installations is False.
v5.3.0Those servers with Elasticsearch enabled will notice that hashtag search is case-sensitive.
v5.2.0Those servers upgrading from v4.1 - v4.4 directly to v5.2 or later and have Jira enabled will need to re-enable the Jira plugin after an upgrade.
v5.1.0mattermost export CLI command is renamed to mattermost export schedule. Make sure to update your scripts if you use this command.
v5.0.0All API v3 endpoints are removed. See documentation to learn how to migrate your integrations to API v4.
platform binary is renamed to mattermost for a clearer install and upgrade experience. You should point your systemd service file at the new mattermost binary. All command line tools, including the bulk loading tool and developer tools, are also be renamed from platform to mattermost.
A Mattermost user setting to configure desktop notification duration in Account Settings > Notifications > Desktop Notifications is removed.
Slash commands configured to receive a GET request will have the payload being encoded in the query string instead of receiving it in the body of the request, consistent with standard HTTP requests. Although unlikely, this could break custom slash commands that use GET requests incorrectly.
A new config.json setting to whitelist types of protocols for auto-linking will be added. If you rely on custom protocols auto-linking in Mattermost, whitelist them in config.json before upgrading.
A new config.json setting to disable the permanent APIv4 delete team parameter is added. The setting will be off by default for all new and existing installs, except those deployed on GitLab Omnibus. If you reply on the APIv4 parameter, enable the setting in config.json before upgrading.
An unused ExtraUpdateAt field will be removed from the channel modal.

This release includes support for post messages longer than the default of 4000 characters, but may require a manual database migration. This migration is entirely optional, and need only be done if you want to enable post messages up to 16383 characters. For many installations, no migration will be required, or the old limit remains sufficient.

To check your current post limit after upgrading to 5.0.0, look for a log message on startup:

[2018/03/27 09:08:00 EDT] [INFO] Post.Message supports at most 16383 characters (65535 bytes)

As of 5.0.0, the maximum post message size is 16383 (multi-byte) characters. If your logs show a number less than this limit and you want to enable longer post messages, you will need to manually migrate your database as described below. This migration can be slow for larger Posts tables, so it's best to schedule this upgrade during off-peak hours.

To migrate a MySQL database, connect to your database and run the following:

ALTER TABLE Posts MODIFY COLUMN Message TEXT;

To migrate a PostgreSQL database, connect to your database and run the following:

ALTER TABLE Posts ALTER COLUMN Message TYPE VARCHAR(65535);

Restart your Mattermost instances.

Deployments on Enterprise E20 will need to enable RunJobs in the config.json and allow the permissions migration to complete before using Team | Override Schemes. |
v4.10.0Old email invitation links will no longer work due to a bug fix where teams could be re-joined via the link. Team invite links copied from the Team Invite Link dialog, password reset links and email verification links are not affected and are still valid.
Server logs written to System Console > Logs and to the mattermost.log file specified in System Console > Logging > File Log Directory now use JSON formatting. If you have built a tool that parses the server logs and sends them to an external system, make sure it supports the JSON format.
Team icons with transparency will be filled with a white background in the Team sidebar.
Those servers with SAML authentication enabled should upgrade during non-peak hours. SAML email addresses are migrated to lowercase to prevent login issues, which could result in longer than usual upgrade time.
If you use PostgreSQL database and the password contains special characters (e.g. []), escape them in your password, e.g., xxx[]xxx will be xxx%5B%5Dxxx.
v4.9.0To improve the production use of Mattermost with Docker, the Docker image is now running a as non-root user and listening on port 8000. Please read the upgrade instructions for important changes to existing installations.

Several configuration settings have been migrated to roles in the database and changing their config.json values no longer takes effect. These permissions can still be modified by their respective System Console settings as before. The affected config.json settings are:

  • RestrictPublicChannelManagement,
  • RestrictPrivateChannelManagement,
  • RestrictPublicChannelCreation,
  • RestrictPrivateChannelCreation,
  • RestrictPublicChannelDeletion,
  • RestrictPrivateChannelDeletion,
  • RestrictPrivateChannelManageMembers,
  • EnableTeamCreation,
  • EnableOnlyAdminIntegrations,
  • RestrictPostDelete,
  • AllowEditPost,
  • RestrictTeamInvite,
  • RestrictCustomEmojiCreation.
The behavior of the config.json setting PostEditTimeLimit has been updated to accommodate the migration to a roles based permission system. When post editing is permitted, set "PostEditTimeLimit": -1 to allow editing anytime, or set "PostEditTimeLimit" to a positive integer to restrict editing time in seconds. If post editing is disabled, this setting does not apply.
If using Let's Encrypt without a proxy server, the server will fail to start with an error message unless the Forward80To443 | config.json setting is set to true.

If forwarding port 80 to 443, the server will fail to start with an error message unless the ListenAddress | config.json setting is set to listen on port 443. |

v4.6.2If using Let's Encrypt without a proxy server, forward port 80 through a firewall, with the Forward80To443 | config.json setting set to true to complete the Let's Encrypt certification. |
v4.4.0Composite database indexes were added to the Posts table. This may lead to longer upgrade times for servers with more than one million messages.
LDAP sync now depends on email. Make sure all users on your AD/LDAP server have an email address or that their account is deactivated in Mattermost.
v4.2.0Mattermost now handles multiple content types for integrations, including plaintext content type. If your integration suddenly prints the JSON payload data instead of rendering the generated message, make sure your integration is returning the application/json content-type to retain previous behavior.
By default, user-supplied URLs such as those used for Open Graph metadata, webhooks, or slash commands will no longer be allowed to connect to reserved IP | addresses including loopback or link-local addresses used for internal networks. | | This change may cause private integrations to break in testing environments, which may point to a URL such as http://127.0.0.1:1021/my-command. | | If you point private integrations to such URLs, you may whitelist such domains, IP addresses, or CIDR notations via the | Allowed Untrusted Internal Connections | configuration setting in your local environment. Although not recommended, you may also whitelist the addresses in your production environments. See | documentation to learn more. | | Push notification, OAuth 2.0 and WebRTC server URLs are trusted and not affected by this setting. |
Uploaded file attachments are now grouped by day and stored in /data/<date-of-upload-as-YYYYMMDD>/teams/... of your file storage system.
Mattermost /platform repo has been separated to /mattermost-webapp and /mattermost-server. This may affect you if you have a private fork of the /platform repo. `More details here <https://forum.mattermost.com/t/mattermost-separating-platform-into-two-repositories-on-september-6th/3708>__.
v4.0.0

(High Availability only)

You must manually add new items to the ClusterSettings section of your existing config.json.

v3.9.0Old email invitation links, password reset links, and email verification links will no longer work due to a security change. Team invite links copied from the Team Invite Link dialog are not affected and are still valid.
v3.8.0

A change is required in the proxy configuration. If you’re using NGINX:

  1. Open the NGINX configuration file as root. The file is usually /etc/nginx/sites-available/mattermost but might be different on your system.
  2. Locate the line: location /api/v3/users/websocket {
  3. Replace the line with location ~ /api/v[0-9]+/(users/)?websocket$ {

If you are using a proxy other than NGINX, make the equivalent change to that proxy's configuration.

You need to verify settings in the System Console due to a security-related change.

  1. Go to the the GENERAL section of the System Console
  2. Click Logging
  3. Make sure that the File Log Directory field is either empty or has a directory path only. It must not have a filename as part of the path.
Backwards compatibility with the old CLI tool was removed. If you have any scripts that rely on the old CLI, they must be revised to use the | new CLI. |
v3.6.0

Update the maximum number of files that can be open.

On RHEL6 and Ubuntu 14.04:
  • Verify that the line limit nofile 50000 50000 is included in the /etc/init/mattermost.conf file.
On RHEL7 and Ubuntu 16.04:
  • Verify that the line LimitNOFILE=49152 is included in the /etc/systemd/system/mattermost.service file.

(Enterprise Only)

Previous config.json values for restricting Public and Private channel management will be used as the default values for new settings for restricting Public and Private channel creation and deletion.

v3.4.0If public links are enabled, existing public links will no longer be valid. This is because in earlier versions, existing public links were not invalidated when the Public Link Salt was regenerated. You must update any place where you have published these links.
+ +## Additional upgrade notes + + + +- Upgrading the Microsoft Teams Calling plugin to v2.0.0 requires users to reconnect their accounts. +- Mattermost plugins built with Go versions 1.22.0 and 1.22.1 do not work. Plugin developers should use Go 1.22.2 or newer instead. +- Keybase has stopped serving Mattermost's Ubuntu repository signing key. If you were using it, update your installation scripts to retrieve the key as mentioned in our [Linux deployment documentation](/deployment-guide/server/deploy-linux). +- We recommend avoiding the use of MySQL 8.0.22 as it contains an [issue with JSON column types](https://bugs.mysql.com/bug.php?id=101284) changing string values to integers which is preventing Mattermost from working properly. +- When upgrading to Mattermost 7.x from a 5.x release, upgrade to 5.37.10 first before attempting the v7.x upgrade. +- SQL queries for related schema changes below are **automatically executed** during the Mattermost server upgrade process. **You don't need to run these queries manually**. These SQL queries are provided to help you understand what database changes will occur during the upgrade, and for cases where you prefer to reduce downtime by pre-applying schema changes. + + diff --git a/docs/main/administration-guide/upgrade/notify-admin.mdx b/docs/main/administration-guide/upgrade/notify-admin.mdx new file mode 100644 index 000000000000..34c3f7689628 --- /dev/null +++ b/docs/main/administration-guide/upgrade/notify-admin.mdx @@ -0,0 +1,22 @@ +--- +title: "Notify admin" +--- +Some Mattermost features are limited to specific plans. Users who want to access these unavailable features can request access through their system admin by sending a notification. + +If access to a feature requires a plan upgrade, system admins receive notifications of these requests in order to collect data before upgrading. For example, if only one end-user requests access to AD/LDAP, it probably isn't necessary to upgrade. However, if 20 users, including team and channel admins request it, you may want to consider upgrading to support this need. + +This feature is designed for informational purposes only, and no action is required unless you want to take action. Your Mattermost instance's functionality is not affected if you choose not to upgrade. + +## Notifications + +Notifications are triggered by users. The very first time a user sends a request to upgrade or start a trial, a bot message is sent to all system admins indicating the feature or functionality the user has requested that requires an upgrade or trial. This bot message is listed in the **Direct Messages** section of the channel sidebar. + +Subsequent request notifications are received by system admins at most every 14 days. When a notification is received by a system admin, a 14-day cool-off period begins. Any requests generated in the middle of the cool-off period will be held off until 14 days later, and then provided in a summarized format. + +## Take action + +You can take action on any of the requests sent using the options provided in the message. + +## Dismiss notifications + +You're not obligated to upgrade or change your plan. Once you've read the notification, it's marked as read and is filed in your list of direct messages. You can find the message at any time using the search bar. None of your existing Mattermost features and functions are affected negatively if you don't upgrade. diff --git a/docs/main/administration-guide/upgrade/open-source-components.mdx b/docs/main/administration-guide/upgrade/open-source-components.mdx new file mode 100644 index 000000000000..719cd644d4f1 --- /dev/null +++ b/docs/main/administration-guide/upgrade/open-source-components.mdx @@ -0,0 +1,249 @@ +--- +title: "Open Source Components" +--- + + +The following open source components are used to provide the full benefits of Mattermost Enterprise. + +## Desktop + +- Mattermost Desktop v6.1.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-6.1/NOTICE.txt). +- Mattermost Desktop v6.0.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-6.0/NOTICE.txt). +- Mattermost Desktop v5.13.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.13/NOTICE.txt). +- Mattermost Desktop v5.12.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.12/NOTICE.txt). +- Mattermost Desktop v5.11.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.11/NOTICE.txt). +- Mattermost Desktop v5.10.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.10/NOTICE.txt). +- Mattermost Desktop v5.9.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.9/NOTICE.txt). +- Mattermost Desktop v5.8.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.8/NOTICE.txt). +- Mattermost Desktop v5.7.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.7/NOTICE.txt). +- Mattermost Desktop v5.6.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.6/NOTICE.txt). +- Mattermost Desktop v5.5.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.5/NOTICE.txt). +- Mattermost Desktop v5.4.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.4/NOTICE.txt). +- Mattermost Desktop v5.3.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.3/NOTICE.txt). +- Mattermost Desktop v5.2.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.2/NOTICE.txt). +- Mattermost Desktop v5.1.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.1/NOTICE.txt). +- Mattermost Desktop v5.0.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-5.0/NOTICE.txt). +- Mattermost Desktop v4.7.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.7/NOTICE.txt). +- Mattermost Desktop v4.6.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.6/NOTICE.txt). +- Mattermost Desktop v4.5.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.5/NOTICE.txt). +- Mattermost Desktop v4.4.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.4/NOTICE.txt). +- Mattermost Desktop v4.3.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.3.0/NOTICE.txt). +- Mattermost Desktop v4.2.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.2/NOTICE.txt). +- Mattermost Desktop v4.1.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.1/NOTICE.txt). +- Mattermost Desktop v4.0.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-4.0/NOTICE.txt). +- Mattermost Desktop v3.7.0 - [View Open Source Components](https://github.com/mattermost/desktop/blob/release-3.7/NOTICE.txt). + +## Mobile + +- Mattermost Mobile v2.39.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.39/NOTICE.txt). +- Mattermost Mobile v2.38.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.38/NOTICE.txt). +- Mattermost Mobile v2.37.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.37/NOTICE.txt). +- Mattermost Mobile v2.36.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.36/NOTICE.txt). +- Mattermost Mobile v2.35.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.35/NOTICE.txt). +- Mattermost Mobile v2.34.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.34/NOTICE.txt). +- Mattermost Mobile v2.33.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.33/NOTICE.txt). +- Mattermost Mobile v2.32.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.32/NOTICE.txt). +- Mattermost Mobile v2.31.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.31/NOTICE.txt). +- Mattermost Mobile v2.30.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.30/NOTICE.txt). +- Mattermost Mobile v2.29.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.29/NOTICE.txt). +- Mattermost Mobile v2.28.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.28/NOTICE.txt). +- Mattermost Mobile v2.27.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.27/NOTICE.txt). +- Mattermost Mobile v2.26.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.26/NOTICE.txt). +- Mattermost Mobile v2.25.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.25/NOTICE.txt). +- Mattermost Mobile v2.24.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.24/NOTICE.txt). +- Mattermost Mobile v2.23.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.23/NOTICE.txt). +- Mattermost Mobile v2.22.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.22/NOTICE.txt). +- Mattermost Mobile v2.21.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.21/NOTICE.txt). +- Mattermost Mobile v2.20.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.20/NOTICE.txt). +- Mattermost Mobile v2.19.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.19/NOTICE.txt). +- Mattermost Mobile v2.18.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.18/NOTICE.txt). +- Mattermost Mobile v2.17.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.17/NOTICE.txt). +- Mattermost Mobile v2.16.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.16/NOTICE.txt). +- Mattermost Mobile v2.15.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.15/NOTICE.txt). +- Mattermost Mobile v2.14.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.14/NOTICE.txt). +- Mattermost Mobile v2.13.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.13/NOTICE.txt). +- Mattermost Mobile v2.12.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.12/NOTICE.txt). +- Mattermost Mobile v2.11.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.11/NOTICE.txt). +- Mattermost Mobile v2.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.10/NOTICE.txt). +- Mattermost Mobile v2.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.9/NOTICE.txt). +- Mattermost Mobile v2.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.8/NOTICE.txt). +- Mattermost Mobile v2.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.7/NOTICE.txt). +- Mattermost Mobile v2.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.6/NOTICE.txt). +- Mattermost Mobile v2.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.5/NOTICE.txt). +- Mattermost Mobile v2.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.4/NOTICE.txt). +- Mattermost Mobile v2.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.3/NOTICE.txt). +- Mattermost Mobile v2.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.2/NOTICE.txt). +- Mattermost Mobile v2.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.1/NOTICE.txt). +- Mattermost Mobile v2.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-2.0/NOTICE.txt). +- Mattermost Mobile v1.55.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.55/NOTICE.txt). +- Mattermost Mobile v1.54.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.54/NOTICE.txt). +- Mattermost Mobile v1.53.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.53/NOTICE.txt). +- Mattermost Mobile v1.52.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.52/NOTICE.txt). +- Mattermost Mobile v1.51.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.51/NOTICE.txt). +- Mattermost Mobile v1.50.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.50/NOTICE.txt). +- Mattermost Mobile v1.49.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.49/NOTICE.txt). +- Mattermost Mobile v1.48.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.48/NOTICE.txt). +- Mattermost Mobile v1.47.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.47/NOTICE.txt). +- Mattermost Mobile v1.46.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.46/NOTICE.txt). +- Mattermost Mobile v1.45.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.45/NOTICE.txt). +- Mattermost Mobile v1.44.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.44/NOTICE.txt). +- Mattermost Mobile v1.43.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.43/NOTICE.txt). +- Mattermost Mobile v1.42.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.42/NOTICE.txt). +- Mattermost Mobile v1.41.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.41/NOTICE.txt). +- Mattermost Mobile v1.40.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.40/NOTICE.txt). +- Mattermost Mobile v1.39.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.39/NOTICE.txt). +- Mattermost Mobile v1.38.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.38/NOTICE.txt). +- Mattermost Mobile v1.37.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.37/NOTICE.txt). +- Mattermost Mobile v1.36.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.36/NOTICE.txt). +- Mattermost Mobile v1.35.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.35/NOTICE.txt). +- Mattermost Mobile v1.34.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.34/NOTICE.txt). +- Mattermost Mobile v1.33.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.33/NOTICE.txt). +- Mattermost Mobile v1.32.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.32/NOTICE.txt). +- Mattermost Mobile v1.31.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.31/NOTICE.txt). +- Mattermost Mobile v1.30.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.30/NOTICE.txt). +- Mattermost Mobile v1.29.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.29/NOTICE.txt). +- Mattermost Mobile v1.28.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.28/NOTICE.txt). +- Mattermost Mobile v1.27.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.27/NOTICE.txt). +- Mattermost Mobile v1.26.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.26/NOTICE.txt). +- Mattermost Mobile v1.25.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.25/NOTICE.txt). +- Mattermost Mobile v1.24.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.24/NOTICE.txt). +- Mattermost Mobile v1.23.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.23/NOTICE.txt). +- Mattermost Mobile v1.22.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.22/NOTICE.txt). +- Mattermost Mobile v1.21.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.21/NOTICE.txt). +- Mattermost Mobile v1.20.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.20/NOTICE.txt). +- Mattermost Mobile v1.19.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.19/NOTICE.txt). +- Mattermost Mobile v1.18.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.18/NOTICE.txt). +- Mattermost Mobile v1.17.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.17/NOTICE.txt). +- Mattermost Mobile v1.16.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.16/NOTICE.txt). +- Mattermost Mobile v1.15.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.15/NOTICE.txt). +- Mattermost Mobile v1.14.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.14/NOTICE.txt). +- Mattermost Mobile v1.13.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.13/NOTICE.txt). +- Mattermost Mobile v1.12.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.12/NOTICE.txt). +- Mattermost Mobile v1.11.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.11/NOTICE.txt). +- Mattermost Mobile v1.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.10/NOTICE.txt). +- Mattermost Mobile v1.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.9/NOTICE.txt). +- Mattermost Mobile v1.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.8/NOTICE.txt). +- Mattermost Mobile v1.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.7/NOTICE.txt). +- Mattermost Mobile v1.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.6/NOTICE.txt). +- Mattermost Mobile v1.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.5/NOTICE.txt). +- Mattermost Mobile v1.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.4/NOTICE.txt). +- Mattermost Mobile v1.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.3/NOTICE.txt). +- Mattermost Mobile v1.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.2/NOTICE.txt). +- Mattermost Mobile v1.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.1/NOTICE.txt). +- Mattermost Mobile v1.0.1 - [View Open Source Components](https://github.com/mattermost/mattermost-mobile/blob/release-1.0.1/NOTICE.txt). + +## Server + +- Mattermost Enterprise Edition v11.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.6/NOTICE.txt). +- Mattermost Enterprise Edition v11.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.5/NOTICE.txt). +- Mattermost Enterprise Edition v11.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.4/NOTICE.txt). +- Mattermost Enterprise Edition v11.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.3/NOTICE.txt). +- Mattermost Enterprise Edition v11.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.2/NOTICE.txt). +- Mattermost Enterprise Edition v11.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.1/NOTICE.txt). +- Mattermost Enterprise Edition v11.0.2 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-11.0/NOTICE.txt). +- Mattermost Enterprise Edition v10.12.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.12/NOTICE.txt). +- Mattermost Enterprise Edition v10.11.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.11/NOTICE.txt). +- Mattermost Enterprise Edition v10.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.10/NOTICE.txt). +- Mattermost Enterprise Edition v10.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.9/NOTICE.txt). +- Mattermost Enterprise Edition v10.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.8/NOTICE.txt). +- Mattermost Enterprise Edition v10.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.7/NOTICE.txt). +- Mattermost Enterprise Edition v10.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.6/NOTICE.txt). +- Mattermost Enterprise Edition v10.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.5/NOTICE.txt). +- Mattermost Enterprise Edition v10.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.4/NOTICE.txt). +- Mattermost Enterprise Edition v10.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.3/NOTICE.txt). +- Mattermost Enterprise Edition v10.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.2/NOTICE.txt). +- Mattermost Enterprise Edition v10.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.1/NOTICE.txt). +- Mattermost Enterprise Edition v10.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-10.0/NOTICE.txt). +- Mattermost Enterprise Edition v9.11.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.11/NOTICE.txt). +- Mattermost Enterprise Edition v9.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.10/NOTICE.txt). +- Mattermost Enterprise Edition v9.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.9/NOTICE.txt). +- Mattermost Enterprise Edition v9.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.8/NOTICE.txt). +- Mattermost Enterprise Edition v9.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.7/NOTICE.txt). +- Mattermost Enterprise Edition v9.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.6/NOTICE.txt). +- Mattermost Enterprise Edition v9.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.5/NOTICE.txt). +- Mattermost Enterprise Edition v9.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.4/NOTICE.txt). +- Mattermost Enterprise Edition v9.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.3/NOTICE.txt). +- Mattermost Enterprise Edition v9.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.2/NOTICE.txt). +- Mattermost Enterprise Edition v9.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.1/NOTICE.txt). +- Mattermost Enterprise Edition v9.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-9.0/NOTICE.txt). +- Mattermost Enterprise Edition v8.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-8.1/NOTICE.txt). +- Mattermost Enterprise Edition v8.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-8.0/NOTICE.txt). +- Mattermost Enterprise Edition v7.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.10/NOTICE.txt). +- Mattermost Enterprise Edition v7.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.9/NOTICE.txt). +- Mattermost Enterprise Edition v7.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.8/NOTICE.txt). +- Mattermost Enterprise Edition v7.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.7/NOTICE.txt). +- Mattermost Enterprise Edition v7.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.5/NOTICE.txt). +- Mattermost Enterprise Edition v7.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.4/NOTICE.txt). +- Mattermost Enterprise Edition v7.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.3/NOTICE.txt). +- Mattermost Enterprise Edition v7.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.2/NOTICE.txt). +- Mattermost Enterprise Edition v7.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.1/NOTICE.txt). +- Mattermost Enterprise Edition v7.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-7.0/NOTICE.txt). +- Mattermost Enterprise Edition v6.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.7/NOTICE.txt). +- Mattermost Enterprise Edition v6.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.6/NOTICE.txt). +- Mattermost Enterprise Edition v6.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.5/NOTICE.txt). +- Mattermost Enterprise Edition v6.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.4/NOTICE.txt). +- Mattermost Enterprise Edition v6.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.3/NOTICE.txt). +- Mattermost Enterprise Edition v6.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.2/NOTICE.txt). +- Mattermost Enterprise Edition v6.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.1/NOTICE.txt). +- Mattermost Enterprise Edition v6.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-6.0/NOTICE.txt). +- Mattermost Enterprise Edition v5.39.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.39/NOTICE.txt). +- Mattermost Enterprise Edition v5.38.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.38/NOTICE.txt). +- Mattermost Enterprise Edition v5.37.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.37/NOTICE.txt). +- Mattermost Enterprise Edition v5.36.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.36/NOTICE.txt). +- Mattermost Enterprise Edition v5.35.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.35/NOTICE.txt). +- Mattermost Enterprise Edition v5.34.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.34/NOTICE.txt). +- Mattermost Enterprise Edition v5.33.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.33/NOTICE.txt). +- Mattermost Enterprise Edition v5.32.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.32/NOTICE.txt). +- Mattermost Enterprise Edition v5.31.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.31/NOTICE.txt). +- Mattermost Enterprise Edition v5.30.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.30/NOTICE.txt). +- Mattermost Enterprise Edition v5.29.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.29/NOTICE.txt). +- Mattermost Enterprise Edition v5.28.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.28/NOTICE.txt). +- Mattermost Enterprise Edition v5.27.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.27/NOTICE.txt). +- Mattermost Enterprise Edition v5.26.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.26/NOTICE.txt). +- Mattermost Enterprise Edition v5.25.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.25/NOTICE.txt). +- Mattermost Enterprise Edition v5.24.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.24/NOTICE.txt). +- Mattermost Enterprise Edition v5.23.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.23/NOTICE.txt). +- Mattermost Enterprise Edition v5.22.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.22/NOTICE.txt). +- Mattermost Enterprise Edition v5.21.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.21/NOTICE.txt). +- Mattermost Enterprise Edition v5.20.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.20/NOTICE.txt). +- Mattermost Enterprise Edition v5.19.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.19/NOTICE.txt). +- Mattermost Enterprise Edition v5.18.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.18/NOTICE.txt). +- Mattermost Enterprise Edition v5.17.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.17/NOTICE.txt). +- Mattermost Enterprise Edition v5.16.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.16/NOTICE.txt). +- Mattermost Enterprise Edition v5.15.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.15/NOTICE.txt). +- Mattermost Enterprise Edition v5.14.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.14/NOTICE.txt). +- Mattermost Enterprise Edition v5.13.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.13/NOTICE.txt). +- Mattermost Enterprise Edition v5.12.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.12/NOTICE.txt). +- Mattermost Enterprise Edition v5.11.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.11/NOTICE.txt). +- Mattermost Enterprise Edition v5.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.10/NOTICE.txt). +- Mattermost Enterprise Edition v5.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.9/NOTICE.txt). +- Mattermost Enterprise Edition v5.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.8/NOTICE.txt). +- Mattermost Enterprise Edition v5.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.7/NOTICE.txt). +- Mattermost Enterprise Edition v5.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.6/NOTICE.txt). +- Mattermost Enterprise Edition v5.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.5/NOTICE.txt). +- Mattermost Enterprise Edition v5.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.4/NOTICE.txt). +- Mattermost Enterprise Edition v5.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.3/NOTICE.txt). +- Mattermost Enterprise Edition v5.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.2/NOTICE.txt). +- Mattermost Enterprise Edition v5.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.1/NOTICE.txt). +- Mattermost Enterprise Edition v5.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-5.0/NOTICE.txt). +- Mattermost Enterprise Edition v4.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.10/NOTICE.txt). +- Mattermost Enterprise Edition v4.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.9/NOTICE.txt). +- Mattermost Enterprise Edition v4.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.8/NOTICE.txt). +- Mattermost Enterprise Edition v4.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.7/NOTICE.txt). +- Mattermost Enterprise Edition v4.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.6/NOTICE.txt). +- Mattermost Enterprise Edition v4.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.5/NOTICE.txt). +- Mattermost Enterprise Edition v4.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.4/NOTICE.txt). +- Mattermost Enterprise Edition v4.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.3/NOTICE.txt). +- Mattermost Enterprise Edition v4.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.2/NOTICE.txt). +- Mattermost Enterprise Edition v4.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.1/NOTICE.txt). +- Mattermost Enterprise Edition v4.0.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-4.0/NOTICE.txt). +- Mattermost Enterprise Edition v3.10.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.10/NOTICE.txt). +- Mattermost Enterprise Edition v3.9.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.9/NOTICE.txt). +- Mattermost Enterprise Edition v3.8.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.8/NOTICE.txt). +- Mattermost Enterprise Edition v3.7.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.7/NOTICE.txt). +- Mattermost Enterprise Edition v3.6.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.6/NOTICE.txt). +- Mattermost Enterprise Edition v3.5.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.5/NOTICE.txt). +- Mattermost Enterprise Edition v3.4.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.4/NOTICE.txt). +- Mattermost Enterprise Edition v3.3.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.3/NOTICE.txt). +- Mattermost Enterprise Edition v3.2.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.2/NOTICE.txt). +- Mattermost Enterprise Edition v3.1.0 - [View Open Source Components](https://github.com/mattermost/mattermost-server/blob/release-3.1/NOTICE.txt). diff --git a/docs/main/administration-guide/upgrade/prepare-to-upgrade-mattermost.mdx b/docs/main/administration-guide/upgrade/prepare-to-upgrade-mattermost.mdx new file mode 100644 index 000000000000..6e97035a2cf3 --- /dev/null +++ b/docs/main/administration-guide/upgrade/prepare-to-upgrade-mattermost.mdx @@ -0,0 +1,124 @@ +--- +title: "Prepare to upgrade Mattermost" +--- + + +In most cases, you can [upgrade Mattermost Server](/administration-guide/upgrade/upgrading-mattermost-server) in a few minutes. However, the upgrade can take longer depending on several factors, including the size and complexity of your installation, and the version that you're upgrading from. When planning an upgrade, it's worth confirming that your current database and operating system version are still supported. Details can be found on our [software and hardware requirements](/deployment-guide/software-hardware-requirements#server-software) page. + +## Upgrade Best Practices + +Mattermost will aim to have non-locking, backwards-compatible migrations in general. This backwards compatibility guarantee extends to only the last ESR version. For example, if there are three ESR versions ESR1, ESR2, and ESR3, upgrading from ESR1 to ESR2, and then ESR2 to ESR3 will ensure backwards compatibility, but not from ESR1 to ESR3 directly. + +In the case of delayed upgrades, we recommend upgrading to the closest ESR version first, and from there to the next ESR. Do not attempt to directly upgrade to the latest version as it might break backwards compatibility of the older nodes in the cluster during the upgrade. + +## Upgrade to Mattermost v7.1 + +Mattermost v7.1 introduces schema changes in the form of a new column and its index. Our test results for the schema changes include: + +- PostgreSQL 12M Posts, 2.5M Reactions - ~1min 18s (instance: db.r5.2xlarge) + +You can run the following SQL queries before the upgrade that obtains a lock on `Reactions` table. Users' reactions posted during this time won't be reflected in the database until the migrations are complete. This is fully backwards-compatible. + +If your connection collation and table collations are different, this can result in the error Illegal mix of collations. To resolve this error, set the same collation for both the connection and the table. There are different collations at different levels - connection, database, table, column, and database administrators may choose to set different collation levels for different objects. + +`ALTER TABLE reactions ADD COLUMN IF NOT EXISTS channelid varchar(26) NOT NULL DEFAULT '';` + +`UPDATE reactions SET channelid = COALESCE((select channelid from posts where posts.id = reactions.postid), '') WHERE channelid='';` + +`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_reactions_channel_id on reactions (channelid);` + +## Upgrade to Mattermost v6.7 + +Mattermost v6.7 introduces schema changes in the form of a new index. The following notes our test results for the schema changes: + +- Postgres 7M Posts - ~9s (instance: db.r5.xlarge) + +If you want a zero downtime upgrade, you can apply this index prior to doing the upgrade. + +`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_posts_create_at_id on posts(createat, id);` + +This is fully backwards-compatible and will not acquire any table lock or affect any existing operations on the table. + +## Upgrade to Mattermost v6.0 + +A Mattermost Server v6.0 upgrade will run significant database schema changes that can cause an extended startup time depending on the dataset size. Zero downtime won't be possible for v6.0, but depending on the efforts made during the migration process, it can be minimized to a large extent. + +Running queries prior to the upgrade can also save some downtime. However, some queries can still cause full table locking and require Mattermost to be in read-only mode for the duration of the query. + +We strongly recommend that you: + +- Set up a maintenance window outside of working hours to mitigate the migration impact. +- Keep a backup of your database to ensure you can load a previous database snapshot if necessary. +- Upgrade your instance of Mattermost to the latest [Extended Support Release (ESR)](/product-overview/mattermost-server-releases) first before attempting to run the Mattermost v6.0 upgrade. + + + +Support for Mattermost Server v10.5 [Extended Support Release](/product-overview/mattermost-server-releases) has come to the end of its life cycle on November 15, 2025. Upgrading to Mattermost Server v10.11 Extended Support Release or later is required. Upgrading from the previous Extended Support Release to the latest Extended Support Release is supported. Review the [important upgrade notes](/important-upgrade-notes) for all intermediate versions in between to ensure you’re aware of the possible migrations that could affect your upgrade. + + + +### v6.0 database schema migrations + +Mattermost v6.0 introduces several database schema changes to improve both database and application performance. The upgrade will run significant database schema changes that can cause an extended startup time depending on the dataset size. We've conducted extensive tests on supported PostgreSQL database drivers, using realistic datasets of more than 10 million posts and more than 72 million posts. + +The following query executed during the migration process will have a significant impact on database CPU usage and write operation restrictions for the duration of the query: + +`ALTER TABLE posts ALTER COLUMN props TYPE jsonb USING props::jsonb;` (~ 11 minutes) + +For a complete breakdown of PostgreSQL queries, as well as their impact and duration, see the [Mattermost v6.0 DB schema migrations analysis](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055#postgresql-1). + +## Upgrade from releases older than v5.35 + +Customers upgrading from a release older than Mattermost v5.35 should expect extended downtime when upgrading to v6.0 due to the introduction of backend database architecture introduced in v5.35. This upgrade path isn't recommended for large installations. We recommend upgrading to the latest [Extended Support Release (ESR)](/product-overview/mattermost-server-releases) first before upgrading to Mattermost v6.0. See the [unsupported legacy releases](/product-overview/unsupported-legacy-releases) documentation for additional details. + +If you're upgrading from a version prior to Mattermost v5.0, you can't upgrade directly to v6.0. Instead, we strongly recommend approaching the upgrade in phases, starting with an upgrade to the latest ESR first, followed by the upgrade to v6.0. During the first phase of updates, you must also modify your service file to work with the binary changes introduced with the v5.0 release. Your execution directory should point to the Mattermost base directory (i.e. `/opt/mattermost`), and your binary should point to the `mattermost` binary (i.e. `/opt/mattermost/bin/mattermost`). + +Ensure you review the [important upgrade notes](/important-upgrade-notes) for all intermediate release versions in between to ensure you’re aware of the possible migrations that could affect your upgrade. + + + +Customers upgrading from releases older than v5.35 following our recommended upgrade process may encounter the following error during the upgrade to v6.0: + +`Failed to alter column type. It is likely you have invalid JSON values in the column. Please fix the values manually and run the migration again.","caller":"sqlstore/store.go:854","error":"pq: unsupported Unicode escape sequence` + +To assist with troubleshooting, you can enable `SqlSettings.Trace` to narrow down what table and column are causing issues during the upgrade. The following queries change the columns to JSONB format in PostgreSQL. Run these against your v5.39 development database to find out which table and column has Unicode issues: + +``` sh +ALTER TABLE posts ALTER COLUMN props TYPE jsonb USING props::jsonb; +ALTER TABLE channelmembers ALTER COLUMN notifyprops TYPE jsonb USING notifyprops::jsonb; +ALTER TABLE jobs ALTER COLUMN data TYPE jsonb USING data::jsonb; +ALTER TABLE linkmetadata ALTER COLUMN data TYPE jsonb USING data::jsonb; +ALTER TABLE sessions ALTER COLUMN props TYPE jsonb USING props::jsonb; +ALTER TABLE threads ALTER COLUMN participants TYPE jsonb USING participants::jsonb; +ALTER TABLE users ALTER COLUMN props TYPE jsonb USING props::jsonb; +ALTER TABLE users ALTER COLUMN notifyprops TYPE jsonb USING notifyprops::jsonb; +ALTER TABLE users ALTER COLUMN timezone TYPE jsonb USING timezone::jsonb; +``` + +Once you've identified the table being affected, verify how many invalid occurrences of u0000 you have using the following SELECT query: + +``` sh +SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%\u0000%'; +``` + +Then select and fix the rows accordingly. If you prefer, you can also fix all occurrences at once in a given table or column using the following UPDATE query: + +``` sh +UPDATE TableName SET ColumnName = regexp_replace(ColumnName, '\\u0000', '', 'g') WHERE ColumnName LIKE '%\u0000%'; +``` + + + +## Upgrade high availability cluster-based deployments + +In [high availability cluster-based](/administration-guide/scale/high-availability-cluster-based-deployment) environments, you should expect to schedule downtime for the upgrade to v6.0. Based on your database size and setup, the migration to v6.0 can take a significant amount of time, and may even lock the tables for posts which will prevent your users from posting or receiving messages until the migration is complete. + +Ensure you review the [high availability cluster-based deployment upgrade guide](/administration-guide/scale/high-availability-cluster-based-deployment#upgrade-guide), as well as the [important upgrade notes](/important-upgrade-notes) to make sure you're aware of any actions you need to take before or after upgrading from your particular version. + + + +Running two different versions of Mattermost in your cluster should not be done outside of an upgrade scenario. Due to a fundamental change to the clustering code in v6.0, nodes from different versions cannot be run, as noted in the [important upgrade notes](/important-upgrade-notes) product documentation. + +The release of v6.0 also introduces database schema changes and longer migration times should be expected. + + diff --git a/docs/main/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha.mdx b/docs/main/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha.mdx new file mode 100644 index 000000000000..20501fa9ad41 --- /dev/null +++ b/docs/main/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha.mdx @@ -0,0 +1,239 @@ +--- +title: "Upgrade Mattermost in Kubernetes and High Availability environments" +--- + + +This guide provides a resilient and comprehensive strategy for upgrading Mattermost deployments managed via Kubernetes and the Mattermost Operator, including High Availability (HA) and optional Active/Active failover configurations. It outlines best practices to ensure zero downtime, minimize service risk, and provide robust fallback mechanisms. + +## Architecture overview + +### Kubernetes-based deployment + +Mattermost uses [Kubernetes](/deployment-guide/server/deploy-kubernetes) for container orchestration, deployed and managed via Helm charts and the [Mattermost Operator](#install-mattermost-operator). This model enables scalable, highly available, and automatically managed application lifecycles. + +The Mattermost Operator handles the upgrade process automatically, ensuring that pods are updated incrementally and that traffic is routed correctly throughout the upgrade. If an error occurs during the upgrade, the Operator will not apply any changes, allowing you to investigate and resolve the issue or manually roll back without impacting the live environment. See the [Downgrade Mattermost Server](/administration-guide/upgrade/downgrading-mattermost-server) documentation for rollback details. + +Health monitoring ensures that only healthy pods are replaced, and new pods are brought online only after passing health checks. New pods are deployed with the updated version, while old pods are gracefully terminated. + +### High Availability + +In [High Availability (HA) cluster-based deployments](/administration-guide/scale/high-availability-cluster-based-deployment), Mattermost runs multiple application servers in a cluster. This configuration ensures that if one server fails, others can continue to serve requests without downtime. User traffic load balancing is managed with services such as NGINX Ingress or HAProxy. [PostgreSQL](/deployment-guide/server/preparations#database-preparation) and [file storage](/deployment-guide/server/preparations#file-storage-preparation) are deployed with replication for redundancy and failover. + +### Active/Active deployments + +An Active/Active configuration is optional and consists of two or more Mattermost clusters running concurrently across geographically distributed regions or availability zones. Each cluster is capable of serving live user traffic and processing requests independently while remaining in sync with shared backend components such as the database and file storage. + +Key benefits for enterprise customers include: + +- **Resilience and uptime**: If a site becomes unavailable due to maintenance or an outage, another site can continue to serve users with minimal disruption. +- **Geographic distribution**: Users connect to the nearest cluster for lower latency and faster response times. +- **Load distribution**: Workload can be balanced between clusters to improve performance and system scalability. + +These deployments require careful configuration management and coordination to ensure data consistency, upgrade safety, and seamless traffic failover. These clusters must maintain configuration/data consistency and require coordinated upgrades. See the [Active/Active upgrade considerations](#active-active-upgrade-considerations) section for recommendations. + +## Step 1: Prepare + +This phase ensures your environment is healthy, backed up, and ready for an upgrade. Follow each step carefully to avoid disruptions and to ensure rollback readiness. + + + +- **Backup your data**: Always back up your database and file storage before starting an upgrade. This ensures you can restore to a previous state in case of issues during the upgrade process. +- **Upgrade safely**: The Mattermost Operator performs upgrade validation checks before rollout. If checks fail, the upgrade is blocked and no changes are applied. If checks pass, the Operator upgrades pods incrementally to maintain uptime. + + + +### Pre-upgrade checklist + +1. **Cluster health**: Ensure all nodes are in a ready state and all pods are running without errors. This step is crucial to avoid issues during the upgrade process. Use the following commands to check cluster health: + +> ``` bash +> kubectl get nodes +> kubectl get pods --all-namespaces +> ``` + +2. **Helm setup**: Verify that Helm is installed and configured correctly in your Kubernetes cluster. Ensure you have the latest version of the Mattermost Operator Helm chart. Use the following commands to check Helm setup: + +> ``` bash +> helm repo update +> helm upgrade mattermost-operator mattermost/mattermost-operator -n -f +> ``` + +3. **Confirm Mattermost Operator version**: Make sure the image version matches the latest supported release from the Helm repository. Use the following command to check the current image version of the Mattermost Operator: + +> ``` bash +> kubectl get deployment mattermost-operator -n mattermost -o=jsonpath='{.spec.template.spec.containers[0].image}' +> ``` + +4. **Verify available resources**: Ensure your Kubernetes cluster has sufficient CPU and memory resources to handle the upgrade process. Use the following commands to check resource availability: + +> ``` bash +> kubectl top nodes +> kubectl describe node | grep Allocatable +> ``` + +5. Back up database and file storage. + + > Use `pg_dump` or volume snapshots to create a full backup to a secure, external location (e.g., S3 or NFS). Validate the backup can be restored. See the [Backup and Disaster Recovery](/deployment-guide/backup-disaster-recovery) documentation for details. + +6. **Ensure configuration consistency**: Validate that `values.yaml`, secrets, and other configuration files are version-controlled and consistent across all clusters (required for [Active/Active deployments](#active-active-upgrade-considerations)). Use tools like GitOps or configuration management systems to ensure all clusters have the same configuration. + +7. We strongly recommend performing a dry run by testing the upgrade in a staging environment that mirrors production to catch misconfigurations early. + +## Step 2: Perform the upgrade + +This step involves updating the Mattermost Operator and Mattermost server to a new version. The Operator manages the upgrade process, ensuring that pods are updated incrementally and that traffic is routed correctly throughout the upgrade. + +We recommend having a separate Mattermost custom resource. See the [Deploy Mattermost on Kubernetes](/deployment-guide/server/deploy-kubernetes) documentation for details. + +1. In the separate resource, update the `version` field in your `mattermost-installation.yaml` file by replacing the `<new-version-tag>` with the specific version you are upgrading to: + +> ``` yaml +> apiVersion: installation.mattermost.com/v1beta1 +> kind: Mattermost +> metadata: +> name: +> spec: +> version: <new-version-tag> # Update this field +> ``` +> +> Alternatively, if you're using Helm `values.yaml` directly, update it with the desired Mattermost version: +> +> ``` yaml +> image: +> repository: mattermost/mattermost-enterprise-edition +> tag: <new-version-tag> +> ``` + +2. Apply the updated configuration: + +> For Mattermost custom resource deployments: +> +> ``` bash +> kubectl apply -f mattermost-installation.yaml +> ``` +> +> For Helm values deployments: +> +> ``` bash +> helm upgrade mattermost mattermost/mattermost-operator -f values.yaml +> ``` + +3. Monitor the rollout by tracking upgrade progress and logs with the following commands: + +> ``` bash +> kubectl get pods -n mattermost +> kubectl logs -f <pod-name> -n mattermost +> ``` + +New pods are started with the updated version. Old pods are gracefully terminated after health checks pass, and traffic remains uninterrupted due to rolling upgrade behavior. NGINX, HAProxy, or Ingress configurations continue routing traffic seamlessly during the upgrade process. + +## Step 3: Active/Active upgrade considerations + +When your deployment includes an Active/Active configuration with multi-cluster or multi-region deployments, you must ensure that all clusters are upgraded in a coordinated manner to maintain data consistency and service availability. + +For coordinated site upgrades, we recommend the following steps: + +- Use your global load balancer or DNS to route traffic away from the site being upgraded. +- Upgrade one site at a time while directing traffic to the other. This minimizes downtime and allows for validation of the upgrade process. +- Confirm replication health for databases and storage before proceeding to the next site. +- Monitor performance and logs before resuming traffic to the upgraded site. + +To prevent split-brain scenarios during upgrades and ensure data consistency: + +- Use a global load balancer or DNS to direct traffic exclusively to the active site. +- Disable writes on the site being upgraded until the upgrade is complete and validated. +- Confirm that only one site is actively writing data at any time. +- Monitor logs for signs of replication lag, file synchronization issues, or data divergence. +- Validate the health of data replication channels before and after each site upgrade. + +## Step 4: Validate + +After the upgrade: + +1. Confirm that all pods are healthy and running the expected version using the following command: + +> ``` bash +> kubectl get pods -n mattermost -o=jsonpath='{.items[*].spec.containers[*].image}' +> ``` + +3. Perform product smoke tests: + +> - Log in to the Mattermost web interface and navigate across teams and channels. +> - Test core functionalities such as posting messages and uploading files. +> - Verify that all integrations, webhooks, and plugins are functioning as expected. +> - Check for error messages in the logs. + +4. Use monitoring tools to confirm application health and performance. See the [Performance monitoring with Prometheus and Grafana](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) documentation or the [Metrics plugin](/administration-guide/scale/performance-monitoring-metrics) documentation for details on collecting and reviewing performance metrics. + +## Rollback strategy + +In case of upgrade issues, rollback should be performed by modifying the custom resource and setting the Mattermost version back to its original value. + +For Mattermost custom resource deployments, update the `version` field in your `mattermost-installation.yaml` file to the previous version: + +``` yaml +apiVersion: installation.mattermost.com/v1beta1 +kind: Mattermost +metadata: + name: +spec: + version: # Set back to previous version +``` + +Then apply the rollback: + +``` bash +kubectl apply -f mattermost-installation.yaml +``` + +Alternatively, for Helm values deployments, use Helm's rollback command: + +``` bash +helm rollback mattermost +``` + +Restore your PostgreSQL database and file store backups if needed. Refer to the [Backup and Disaster Recovery](/deployment-guide/backup-disaster-recovery) documentation for detailed guidance. + +## Frequently asked questions + +### How can I confirm an upgrade was successful? + +A successful upgrade is indicated by: + +- All pods running the expected image version +- No errors in pod logs +- Functional smoke tests passing (login, messaging, file upload, etc.) +- No anomalies in monitoring dashboards + +### What should I monitor post-upgrade? + +We recommend monitoring the following key metrics after an upgrade: + +- Pod health and restarts +- Application logs for errors or warnings +- Database replication health (if HA or Active/Active) +- Performance metrics (latency, error rate) via Prometheus/Grafana + +### How can I test upgrades without impacting production? + +We strongly recommend deploying a separate staging environment that mirrors production, and running a full end-to-end upgrade simulation before upgrading live production clusters. + +### Can I upgrade the Operator and Mattermost server at the same time? + +Upgrade the Operator first. Validate it’s stable before upgrading the Mattermost server version. + +### Do I need to upgrade the database separately? + +Mattermost does not upgrade the database schema by default. You must manually apply database schema updates if required by a newer Mattermost version. Review the [Mattermost Server changelog](/product-overview/mattermost-v10-changelog) for any migration steps. + +### What if my pods don’t become ready after the upgrade? + +Check the Operator logs and pod events using `kubectl` to identify and resolve issues. Look for common issues such as resource constraints, configuration errors, or network connectivity problems. + +### What version compatibility should I be aware of between the Mattermost Operator and the application server? + +Running an older Operator version may not support newer Mattermost features or upgrade flows. Always check the [Helm chart release notes](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-operator) for version compatibility between the Operator and the Mattermost server. + +### Can I automate this upgrade process using GitOps or CI/CD? + +Yes. You can manage upgrades using tools like ArgoCD or FluxCD to apply Helm changes from version-controlled `values.yaml` files. Ensure changes are peer-reviewed and validated in staging before promotion. diff --git a/docs/main/administration-guide/upgrade/upgrade-v11.mdx b/docs/main/administration-guide/upgrade/upgrade-v11.mdx new file mode 100644 index 000000000000..d39b2ee7766f --- /dev/null +++ b/docs/main/administration-guide/upgrade/upgrade-v11.mdx @@ -0,0 +1,44 @@ +--- +title: Upgrade Guide v11 +sidebar_position: 20 +description: Operator-facing upgrade procedure for moving a Mattermost cluster to v11. +slug: /upgrade-guide/upgrade-v11 +--- + + + + +# Upgrade Guide v11 + +Per-major-version upgrade guides give operators a single canonical procedure for moving a Mattermost cluster to that major version. They are paired with the corresponding [What's New in v11](../../product-overview/whats-new-in-v11.mdx) page (release-management facing) — both share the same source-of-truth for breaking changes, but this page focuses on the operator runbook. + +URL convention: `/upgrade-guide/upgrade-v{X.Y}/` (Grafana pattern). Predictable, deep-linkable, per-version. + +:::note Status +This page is a stub seeded by the IA redesign Phase 1 (see `docs/_redesign/proposed-ia.md` §6 in the repo). Content authored by the release-management + technical-writing team. +::: + +## Before you upgrade + +- Confirm the source version is within the supported upgrade matrix. See [Important Upgrade Notes](./important-upgrade-notes.mdx) for non-sequential upgrade paths. +- Read [Prepare to Upgrade Mattermost](./prepare-to-upgrade-mattermost.mdx). +- For air-gapped deployments, stage the v11 release artifacts following [Air-Gapped Quick-Start Runbook](../../deployment-guide/air-gapped-operations/quick-start-runbook) steps 1–3. + +## Procedure + +*Per-release, version-specific procedure authored by release-management team.* + +## Validation + +*Post-upgrade verification checklist.* + +## Rollback + +*Documented rollback procedure for this version, if any. See [Downgrading Mattermost Server](./downgrading-mattermost-server.mdx) for cross-version downgrade guidance.* + +## Related + +- [What's New in v11](../../product-overview/whats-new-in-v11.mdx) — feature and behavior changes. +- [v11 Changelog](../../product-overview/mattermost-v11-changelog.mdx) — commit-level release notes. +- [Important Upgrade Notes](./important-upgrade-notes.mdx) — version-by-version notes for non-sequential upgrades. +- [Upgrading Mattermost Server](./upgrading-mattermost-server.mdx) — general upgrade procedure (cross-version). diff --git a/docs/main/administration-guide/upgrade/upgrading-mattermost-server.mdx b/docs/main/administration-guide/upgrade/upgrading-mattermost-server.mdx new file mode 100644 index 000000000000..8901496b8997 --- /dev/null +++ b/docs/main/administration-guide/upgrade/upgrading-mattermost-server.mdx @@ -0,0 +1,266 @@ +--- +title: "Upgrade Mattermost Server" +--- + + +In most cases, you can upgrade Mattermost Server in a few minutes. However, the upgrade can take longer depending on several factors, including the size and complexity of your installation, and the version that you're upgrading from. + +If this is your first Mattermost upgrade, we recommend that you read the [comprehensive upgrade guide](#comprehensive-upgrade-guide) below. If you're an experienced system admin familiar with the upgrade process, see the [quick start checklist](#quick-start). + +## Quick start + +Experienced system admins looking for a quick overview of the Mattermost upgrade process can use the following 4-step checklist below: + +1. Ensure you have a complete backup of your system before proceeding, including database and application. +2. **System requirements**: Verify that your server and PostgreSQL version meets [Mattermost requirements](/deployment-guide/software-hardware-requirements). +3. **Preparation steps** + +> - Download the latest server version. +> - Extract the new files to a temporary location (`/tmp`) +> - Identify the current Mattermost directory (default: `/opt/mattermost`) + +4. **Upgrade process** + +> - Stop the Mattermost service: `sudo systemctl stop mattermost` +> - Remove old application files (preserve config, data, logs, plugins). +> - Copy new files to the install directory. +> - Change file ownership: `sudo chown -R mattermost:mattermost mattermost` +> - Set capabilities for low port usage if needed: `sudo setcap cap_net_bind_service=+ep ./mattermost/bin/mattermost` +> - Start the Mattermost service: `sudo systemctl start mattermost` +> - Remove temporary upgrade files. + +For detailed instructions and additional considerations, see the complete upgrade guide below. + +
+ + + +To learn how to safely upgrade your deployment in Kubernetes for High Availability and Active/Active support, see the [Upgrading Mattermost in Kubernetes and High Availability Environments](/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha) documenation. + + + +
+ +## Comprehensive upgrade guide + +### Before you begin + +**Read these instructions carefully from start to finish.** + + + +**Before upgrading to Mattermost v11.0**: If you're currently using Bleve search (found under **System Console \> Experimental \> Bleve**), ensure that `DisableDatabaseSearch` is set to `false` before upgrading, or search will become non-functional after the upgrade. Bleve search has been removed in v11.0. For enterprise search capabilities, consider migrating to [Elasticsearch](/administration-guide/scale/elasticsearch-setup) or [OpenSearch](/administration-guide/scale/opensearch-setup) for [enterprise search](/administration-guide/scale/enterprise-search) capabilities. + + + +Make sure that you understand how to [prepare for your upgrade](/administration-guide/upgrade/prepare-to-upgrade-mattermost), familiarize yourself with all [software and hardware requirements](/deployment-guide/software-hardware-requirements), read the [important upgrade notes](/administration-guide/upgrade/important-upgrade-notes) and that you understand each step of the upgrade process documented below before starting a Mattermost upgrade. If you have questions or concerns, you can ask on the Mattermost forum at [https://forum.mattermost.com/](https://forum.mattermost.com/). + +**Gather the following information before starting the upgrade:** + +- **Existing install directory - {install-path}**: If you don't know where Mattermost Server is installed, use the `whereis mattermost` command to find standard binary places and $PATH. + - This command won't return anything if `/opt/mattermost/bin` wasn't added to the PATH. + - Alternatively, you can use the `find / -executable -type f -iname mattermost 2> /dev/null` command to find the `mattermost` binary. + - The output should be similar to `/opt/mattermost/bin/mattermost`. + - The install directory is everything before the first occurrence of the string `/mattermost`. In this example, the `{install-path}` is `/opt`. + - If that command doesn't produce any results, it's likely because your version is older; try `whereis platform` instead. +- **Location and size of your local storage directory**: The local storage directory contains all the files that users have attached to their messages. + - If you don't know its location, open the System Console and go to **Environment \> File Storage**, then read the value in **Local Storage Directory**. + - Paths are relative to the `mattermost` directory. For example, if the local storage directory is `./data/` then the absolute path is `{install-path}/mattermost/data`. +- **Database disk space**: If you're upgrading a Mattermost deployment on the same server as your database, we recommend a minimum 2GB of free disk space to allow for extraction, copy, and cleanup, and a minimum of twice the size of your Mattermost installation available for the database. + + + +Consider generating a migration plan using the [mattermost db migrate --save-plan](/administration-guide/manage/command-line-tools#mattermost-db-migrate) CLI command when upgrading to have a detailed record of the changes that will be applied to your database. This can make it easier to revert those changes if you need to downgrade later. + + + +### Upgrade Mattermost Server + +1. In a terminal window on the server that hosts Mattermost, change to your home directory. Delete any files and directories that might still exist from a previous download. + + ``` sh + cd /tmp + ``` + +2. Download [the latest version of Mattermost Server](https://mattermost.com/download/) based on your Mattermost edition. + +>
+> +> Enterprise Edition +> +> In the following command, replace `X.X.X` with the version that you want to download: +> +> ``` sh +> wget https://releases.mattermost.com/X.X.X/mattermost-X.X.X-linux-amd64.tar.gz +> ``` +> +>
+> +>
+> +> Team Edition +> +> In the following command, replace `X.X.X` with the version that you want to download: +> +> ``` sh +> wget https://releases.mattermost.com/X.X.X/mattermost-team-X.X.X-linux-amd64.tar.gz +> ``` +> +>
+ +3. Confirm no other Mattermost zip folders exist in your `/tmp` directory. If another version's zip file does exist, delete or rename the file. + + ``` sh + ls -- mattermost*.gz + ``` + + If anything except the new release is returned above, rename this file or delete it completely. + +4. Extract the Mattermost Server files. + + ``` sh + tar -xf mattermost*.gz --transform='s,^[^/]\+,\0-upgrade,' + ``` + + The `transform` option adds a suffix to the topmost extracted directory so it does not conflict with the usual install directory. + +5. Stop your Mattermost server. + + ``` sh + sudo systemctl stop mattermost + ``` + +6. Back up your data and application. Make sure you've properly backed up your database before continuing with the upgrade. In case of an unexpected failure, you should be in a position to load a previous database snapshot. + + 1. Back up your database using your organization’s standard procedures for backing up the database. + + 2. Back up your application by copying into an archive folder (e.g. `mattermost-back-YYYY-MM-DD-HH-mm`). + + ``` sh + cd {install-path} + sudo cp -ra mattermost/ mattermost-back-$(date +'%F-%H-%M')/ + ``` + +7. Remove all files **except** data and custom directories from within the current `mattermost` directory. We strongly recommend reading the important note below before executing the following command. + + ``` sh + sudo find mattermost/ mattermost/client/ -mindepth 1 -maxdepth 1 \! \( -type d \( -path mattermost/client -o -path mattermost/client/plugins -o -path mattermost/config -o -path mattermost/logs -o -path mattermost/plugins -o -path mattermost/data \) -prune \) | sort | sudo xargs rm -r + ``` + +
+ +
+ + Important + +
+ + By default, the following subdirectories will be preserved on upgrade:`config`, `logs`, `plugins`, `client/plugins`, and `data`. Custom directories and ANY other directories that you've added to Mattermost are NOT preserved by default. Generally, these are TLS keys or other custom information, but can also include a different directories configured for local storage other than `data`, as well as custom directories used to store attachments. + + Before continuing with your upgrade, we strongly recommend that you: + + 1. Run `ls` on your Mattermost install directory to identify all default folders that exist prior to upgrading. + + A default Mattermost installation has the following files and directories: + + ``` sh + $ ls /opt/mattermost + ENTERPRISE-EDITION-LICENSE.txt README.md client data i18n manifest.txt prepackaged_plugins + NOTICE.txt bin config fonts logs plugins templates + ``` + + 2. Perform a dry run of deleting the contents of the `mattermost` folder and preserving only the specified directories and their contents by running the following command. It's the same command listed above, but it omits `sudo xargs rm -r`: + + ``` sh + sudo find mattermost/ mattermost/client/ -mindepth 1 -maxdepth 1 \! \( -type d \( -path mattermost/client -o -path mattermost/client/plugins -o -path mattermost/config -o -path mattermost/logs -o -path mattermost/plugins -o -path mattermost/data \) -prune \) | sort + ``` + + 3. If you store TLSCert/TLSKey files or other information within your `/opt/mattermost` folder, you need to append `-o -path mattermost/yourFolderHere` to the command above to avoid having to manually copy the TLSCert/TLSKey files from the backup into the new install. + + ``` sh + sudo find mattermost/ mattermost/client/ -mindepth 1 -maxdepth 1 \! \( -type d \( -path mattermost/client -o -path mattermost/client/plugins -o -path mattermost/config -o -path mattermost/logs -o -path mattermost/plugins -o -path mattermost/data -o -path mattermost/yourFolderHere \) -prune \) | sort + ``` + + 4. If you're using [Bleve search](/administration-guide/configure/bleve-search), and the directory exists *within* the `mattermost` directory, the index directory path won't be preserved using the command above. + + - You can either move the bleve index directory out from the `mattermost` directory before upgrading or, following an upgrade, you can copy the contents of the bleve index directory from the `backup` directory. + - You can then store that directory or re-index as preferred. + - The bleve indexes can be migrated without reindexing between Mattermost versions. See our [Configuration Settings](/administration-guide/configure/deprecated-configuration-settings#bleve-settings) documentation for details on configuring the bleve index directory. + + Once you've completed all of the steps above (where applicable), you're ready to execute the full command that includes `xargs rm -r` to delete the files. Note that the following example includes `-o -path mattermost/yourFolderHere`: + + ``` sh + sudo find mattermost/ mattermost/client/ -mindepth 1 -maxdepth 1 \! \( -type d \( -path mattermost/client -o -path mattermost/client/plugins -o -path mattermost/config -o -path mattermost/logs -o -path mattermost/plugins -o -path mattermost/data -o -path mattermost/yourFolderHere \) -prune \) | sort | sudo xargs rm -r + ``` + +
+ +8. Copy the new files to your install directory. + + ``` sh + sudo cp -an /tmp/mattermost-upgrade/. mattermost/ + ``` + +
+ +
+ + Note + +
+ + The `n` (no-clobber) flag and trailing `.` on source are very important. The `n` (no-clobber) flag preserves existing configurations and logs in your installation path. The trailing `.` on source ensures all installation files are copied. + +
+ +9. Change ownership of the new files after copying them. For example: + + ``` sh + sudo chown -R mattermost:mattermost mattermost + ``` + +
+ +
+ + Note + +
+ + - If you didn't use `mattermost` as the owner and group of the install directory, run `sudo chown -hR {owner}:{group} {install-path}/mattermost`. + - If you're uncertain what owner or group was defined, use the `ls -l {install-path}/mattermost/bin/mattermost` command to obtain them. + +
+ +10. If you want to use port 80 or 443 to serve your server, and/or if you have TLS set up on your Mattermost server, you **must** activate the `CAP_NET_BIND_SERVICE` capability to allow the new Mattermost binary to bind to ports lower than 1024. For example: + + ``` sh + sudo setcap cap_net_bind_service=+ep ./mattermost/bin/mattermost + ``` + +11. Start your Mattermost server. + + ``` sh + sudo systemctl start mattermost + ``` + +12. Remove the temporary files. + + ``` sh + sudo rm -r /tmp/mattermost-upgrade/ + sudo rm -i /tmp/mattermost*.gz + ``` + +13. If you're using a [high availability](/administration-guide/scale/high-availability-cluster-based-deployment) deployment, you need to apply the steps above on every node in your cluster. Once complete, the **Config File MD5** columns in the high availability section of the System Console should be green. If they're yellow, please ensure that all nodes have the same server version and the same configuration. + + If they continue to display as yellow, trigger a configuration propagation across the cluster by opening the System Console, changing a setting, and reverting it. This will enable the **Save** button for that page. Then, select **Save**. This will not change any configuration, but sends the existing configuration to all nodes in the cluster. + +After the server is upgraded, users might need to refresh their browsers to experience any new features. + +## Upgrade Team Edition to Enterprise Edition + +To upgrade from the Team Edition to the Enterprise Edition, follow the normal upgrade instructions provided above, making sure that you download the Enterprise Edition of Mattermost Server in Step 2. + +## Upload a license key + +When Enterprise Edition is running, open **System Console \> About \> Editions and License** and upload your license key. diff --git a/docs/main/administration-guide/upgrade/upgrading-postgres.mdx b/docs/main/administration-guide/upgrade/upgrading-postgres.mdx new file mode 100644 index 000000000000..1071bdaebaad --- /dev/null +++ b/docs/main/administration-guide/upgrade/upgrading-postgres.mdx @@ -0,0 +1,148 @@ +--- +title: "Upgrade PostgreSQL" +--- + + +Mattermost follows the [PostgreSQL community versioning policy](https://www.postgresql.org/support/versioning/), which provides 5 years of support per major version. When a PostgreSQL version reaches end-of-life, Mattermost drops support for it in a subsequent release. See the [software and hardware requirements](/deployment-guide/software-hardware-requirements) documentation for the currently supported PostgreSQL versions. + +When upgrading PostgreSQL, refer to the [official PostgreSQL upgrade documentation](https://www.postgresql.org/docs/current/upgrading.html) for comprehensive guidance. This page covers the steps specific to Mattermost deployments. + +## Before you begin + +1. **Back up your database.** Always take a full database backup before upgrading. See the [backup and disaster recovery](/deployment-guide/backup-disaster-recovery) documentation. +2. **Check supported versions.** Confirm the target PostgreSQL version is supported by your Mattermost release. See [software and hardware requirements](/deployment-guide/software-hardware-requirements). +3. **Stop Mattermost.** Shut down the Mattermost server before starting the database upgrade to prevent data writes during the process. + +## Upgrade a bare-metal PostgreSQL server + +There are two main approaches for upgrading PostgreSQL on a bare-metal or virtual machine: + +- **pg_upgrade** (in-place): Faster; upgrades the data directory without a full dump/restore cycle. Recommended for large databases. +- **pg_dump / pg_restore** (logical): Simpler and safer for cross-machine migrations or when in-place upgrade is not possible. + +### Using pg_upgrade + +`pg_upgrade` allows you to upgrade between major PostgreSQL versions without a full export. Both the old and new PostgreSQL versions must be installed side-by-side. + +1. Install the new PostgreSQL version alongside the existing one using your package manager. + +2. Stop the existing PostgreSQL service: + + ``` sh + sudo systemctl stop postgresql + ``` + +3. Run `pg_upgrade` as the `postgres` user, specifying the binary and data directories for both versions. Replace `` and `` with the appropriate version numbers (e.g. `15` and `16`): + + ``` sh + sudo -u postgres /usr/lib/postgresql//bin/pg_upgrade \ + --old-datadir /var/lib/postgresql//main \ + --new-datadir /var/lib/postgresql//main \ + --old-bindir /usr/lib/postgresql//bin \ + --new-bindir /usr/lib/postgresql//bin + ``` + +4. Update your system to start the new PostgreSQL version by default, then start the service: + + ``` sh + sudo systemctl start postgresql + ``` + +For full `pg_upgrade` reference, see the [official pg_upgrade documentation](https://www.postgresql.org/docs/current/pgupgrade.html). + +### Using pg_dump and pg_restore + +This approach exports the entire database, installs the new PostgreSQL version, and restores the data. It is simpler but requires downtime proportional to database size. + +1. Export the Mattermost database (replace `mattermost` with your database name and `mmuser` with your database user): + + ``` sh + pg_dump -U mmuser -Fc mattermost > mattermost_backup.dump + ``` + +2. Install the new PostgreSQL version and create the database user and database: + + ``` sh + sudo -u postgres psql -c "CREATE USER mmuser WITH PASSWORD 'your_password';" + sudo -u postgres psql -c "CREATE DATABASE mattermost OWNER mmuser;" + ``` + +3. Restore the database into the new PostgreSQL instance: + + ``` sh + pg_restore -U mmuser -d mattermost mattermost_backup.dump + ``` + +## Upgrade PostgreSQL in Docker + + + +The steps below are written for the official [Mattermost Docker deployment](https://github.com/mattermost/docker). If you are using a custom Docker setup, adapt the container and volume names accordingly. + + + +When running PostgreSQL in Docker, `pg_dump`/`pg_restore` is the recommended upgrade approach. In-place `pg_upgrade` is complex in containers because it requires both old and new binaries in the same container. + +1. Stop the Mattermost container: + + ``` sh + docker stop mattermost + ``` + +2. Dump the database from the running PostgreSQL container (replace `mattermost`, `mmuser`, and `db` with your database name, user, and container name): + + ``` sh + docker exec postgres pg_dump -U mmuser -Fc mattermost > mattermost_backup.dump + ``` + +3. Stop the existing PostgreSQL container: + + ``` sh + docker stop postgres + ``` + +4. Update `POSTGRES_IMAGE_TAG` in your `.env` file to the new version. For example: + + ``` text + POSTGRES_IMAGE_TAG=16-alpine + ``` + +5. Recreate the PostgreSQL container so the new image tag from `.env` is applied: + + ``` sh + docker compose up -d --force-recreate postgres + ``` + +
+ +
+ + Note + +
+ + If your volume already contains data from the old major version, PostgreSQL will refuse to start. In that case, create a new named volume for the new container, then restore from the dump in the next step. + +
+ +6. Recreate the database user and database in the new container, then restore: + + ``` sh + docker exec -i postgres psql -U postgres -c "CREATE USER mmuser WITH PASSWORD 'your_password';" + docker exec -i postgres psql -U postgres -c "CREATE DATABASE mattermost OWNER mmuser;" + docker exec -i postgres pg_restore -U mmuser -d mattermost < mattermost_backup.dump + ``` + +## After the upgrade + +After upgrading PostgreSQL, run `ANALYZE VERBOSE` on the Mattermost database. This re-populates the `pg_statistics` table used by PostgreSQL to generate optimal query plans. Skipping this step can result in degraded database performance. + +``` sh +sudo -u postgres psql -d mattermost -c "ANALYZE VERBOSE;" +``` + +Once complete, restart Mattermost: + +``` sh +sudo systemctl start mattermost +``` diff --git a/docs/main/administration-guide/upgrade/welcome-email-to-end-users.mdx b/docs/main/administration-guide/upgrade/welcome-email-to-end-users.mdx new file mode 100644 index 000000000000..a7686a128b24 --- /dev/null +++ b/docs/main/administration-guide/upgrade/welcome-email-to-end-users.mdx @@ -0,0 +1,43 @@ +--- +title: "Welcome email to end users" +--- + + +To make it easy for your end users to start using Mattermost right away, we created a sample email template that you can use. + +Remember to replace all the items below in bold with your information. + +## Email template + +From: **\[company name\]** IT Team + +To: End users + +Subject: New Collaboration Platform - Mattermost + +Hi all, + +As some of you already know, we are moving to Mattermost as our collaboration platform. Mattermost is collaboration software you can use to talk, share files, and collaborate on projects or initiatives. Mattermost also integrates with many of the apps that you use every day, like **\[add apps\]**. + +We are moving to Mattermost because it will host all our collaboration in one place, is instantly searchable and available from all your devices. + +Some of the major benefits of using Mattermost are: + +- Direct 1:1 and group messaging +- Channels for topic-based, group-based, or meeting-based chat +- Streamlined collaboration on projects +- Reduced email clutter +- Searching across messages and channels +- Sharing files + +To get started: + +1. Open a browser on your computer, go to **\[Mattermost URL\]** and log in with your **\[LDAP/AD, SAML, Google, etc\]** credentials. Remember to bookmark the URL so you can use it to log in next time. +2. [Download](https://mattermost.com/apps) the Mattermost apps for desktop and mobile. See the [Use Mattermost](/end-user-guide/end-user-guide-index) end user documentation for details on how to get up and running quickly. +3. Start messaging! + +Questions? If you have any questions, feel free to post in the **\[~Mattermost channel\]** or email us at **\[IT email\]**. + +Happy collaborating! + +**\[company name\]** IT Team diff --git a/docs/main/deployment-guide/air-gapped-operations/disable-phone-home-features.mdx b/docs/main/deployment-guide/air-gapped-operations/disable-phone-home-features.mdx new file mode 100644 index 000000000000..eb5b4423f750 --- /dev/null +++ b/docs/main/deployment-guide/air-gapped-operations/disable-phone-home-features.mdx @@ -0,0 +1,90 @@ +--- +title: Disable Phone-Home Features +sidebar_position: 4 +description: Complete inventory of outbound network calls Mattermost makes, and the settings to disable each one for air-gapped operation. +--- + + + + +# Disable Phone-Home Features + +Mattermost makes a small set of outbound network calls during normal operation. In an air-gapped enclave these calls fail silently — they do not affect functionality, but they pollute egress logs and may trigger boundary alerts. Disable each one explicitly so the cluster makes **zero** unexpected outbound connections. + +This page is the **single canonical inventory** of phone-home behavior. Every outbound call Mattermost initiates from the server process is listed below with its purpose, target, and the setting that disables it. + +:::important Use this list as a checklist +Run through every row of the table below as a Day-1 task. After the cluster is up, packet-capture at the enclave boundary should show no outbound connections to any of the targets listed. +::: + +## Outbound call inventory + +| Feature | Outbound target | Disable in `config.json` | +|---|---|---| +| Anonymous diagnostics telemetry | `telemetry.mattermost.com` | `LogSettings.EnableDiagnostics = false` | +| Security update notifications | `security.mattermost.com` | `ServiceSettings.EnableSecurityFixAlert = false` | +| Plugin Marketplace catalog | `api.integrations.mattermost.com` | `PluginSettings.EnableMarketplace = false` | +| Automated license utilization reporting | `customers.mattermost.com` | `ServiceSettings.EnableLicenseReporting = false` *(see [Offline License Activation](./offline-license-activation))* | +| In-product version check | `releases.mattermost.com` | `ServiceSettings.EnableLatestVersionCheck = false` | +| In-product notices feed | `notices.mattermost.com` | `AnnouncementSettings.AdminNoticesEnabled = false` and `AnnouncementSettings.UserNoticesEnabled = false` | +| Image proxy for inline images | varies (per-image origin) | `ImageProxySettings.Enable = false` *(in air-gapped mode, inline images from external URLs are blocked at the network layer anyway)* | +| Outbound webhooks / slash commands | per-integration URL | Disable individual integrations in **System Console → Integrations** | +| Apple Push Notification Service (APNs) | `api.push.apple.com` | Use mediated push proxy — *Push Notifications without Direct APNs / FCM Egress* (Phase 2) | +| Google Firebase Cloud Messaging (FCM) | `fcm.googleapis.com` | Use mediated push proxy — Phase 2 | +| Bleve search index download (first start) | `releases.mattermost.com` | Pre-stage Bleve index on internal mirror; see [Mirror Package Repositories](./mirror-package-repositories) | +| Plugin install from URL | per-plugin URL | Plugins must be installed via `mmctl plugin add` from local file system; do not use URL install | + +## Recommended `config.json` snippet + +```json +{ + "ServiceSettings": { + "EnableSecurityFixAlert": false, + "EnableLicenseReporting": false, + "EnableLatestVersionCheck": false + }, + "LogSettings": { + "EnableDiagnostics": false + }, + "PluginSettings": { + "EnableMarketplace": false + }, + "AnnouncementSettings": { + "AdminNoticesEnabled": false, + "UserNoticesEnabled": false + }, + "ImageProxySettings": { + "Enable": false + } +} +``` + +Apply this snippet via configuration management (Ansible, Salt, etc.) rather than editing `config.json` by hand. The Mattermost Operator (Kubernetes) accepts these settings via the `MattermostInstallation` CR's `mattermostConfig` field. + +## Cross-cutting concerns + +### What this does *not* disable + +These settings disable **Mattermost-initiated** outbound calls. They do **not** disable: + +- **OS-level callbacks** (NTP, DNS, distribution-package updaters). Manage these via your OS hardening profile, not Mattermost configuration. +- **User-initiated outbound calls** (link unfurling when a user pastes a public URL into a channel). Mattermost respects the enclave's network policy here — link unfurling will simply fail. +- **Plugin-initiated outbound calls**. Each plugin has its own outbound behavior. Audit each plugin you install. The Mattermost Calls plugin in particular requires careful egress configuration; see [Calls Deployment](../) (top-level Deployment Guide → Calls Deployment section, expanded in Phase 2). + +### Verification + +After applying the snippet and restarting Mattermost: + +1. Tail the server log for one hour during steady-state traffic. +2. Grep the log for any of the disabled targets: + ``` + grep -E '(telemetry|security|releases|notices|customers|api.integrations)\.mattermost\.com' mattermost.log + ``` + Expected output: **none**. +3. Run a packet capture at the enclave boundary for one hour. Confirm zero connections to any row of the table above. + +If any outbound call is observed despite the settings being applied, file a security issue at `security@mattermost.com`. In an air-gapped enclave, you may need to send this out-of-band via your security liaison. + +## Reference + +This page consolidates phone-home behavior previously scattered across multiple admin configuration pages. The canonical home for this inventory is here under Air-Gapped Operations because the Air-Gapped Operator persona (`docs/_redesign/personas.md` §4 in the repo) is the primary consumer. diff --git a/docs/main/deployment-guide/air-gapped-operations/index.mdx b/docs/main/deployment-guide/air-gapped-operations/index.mdx new file mode 100644 index 000000000000..3dfd1d8a7ebc --- /dev/null +++ b/docs/main/deployment-guide/air-gapped-operations/index.mdx @@ -0,0 +1,34 @@ +--- +title: Air-Gapped Operations +sidebar_position: 5 +description: Deploy and operate Mattermost in network-isolated enclaves — air-gapped, sovereign-cloud, and tactical-edge environments. +--- + + + + +# Air-Gapped Operations + +This section is for operators deploying Mattermost in **network-isolated enclaves** — environments with no egress to public networks, no DNS to public resolvers, no upstream package mirrors, and no telemetry. Typical contexts: DoD SIPRNet / JWICS, IL4 / IL5 enclaves, sovereign-cloud (AWS GovCloud, Azure Government), and forward-deployed tactical edges with DDIL (Disconnected, Intermittent, Limited bandwidth) connectivity. + +Mattermost runs fully in air-gapped mode. The procedure differs from a connected install in five ways: package mirroring, offline license activation, disabling phone-home features, push-notification mediation, and audit-log export topology. Each is documented below. + +:::note Persona scope +This sub-tree is the canonical home for the **Air-Gapped Operator** persona (see `docs/_redesign/personas.md` §4 in the repo). Companion pages for **Security Architects** live under Security & Compliance; compliance machinery for **Compliance Officers** lives under Administration Guide → Comply. +::: + +## In this section + +- [Quick-Start Runbook](./quick-start-runbook) — 12-step procedure to stand up a working air-gapped Mattermost cluster from scratch. +- [Mirror Package Repositories](./mirror-package-repositories) — internal Linux package + container registry topology and trust setup. +- [Offline License Activation](./offline-license-activation) — activate Enterprise / Enterprise Advanced licenses without phoning home to `mattermost.com`. +- [Disable Phone-Home Features](./disable-phone-home-features) — inventory of every outbound network call Mattermost makes and how to disable it in air-gapped mode. + +## Roadmap (Phase 2) + +Phase 2 of the IA redesign (see `docs/_redesign/proposed-ia.md` §6 in the repo) adds four more pages: + +- Push Notifications without Direct APNs / FCM Egress +- Air-Gapped Upgrade Procedure +- Audit Log Export to Air-Gapped SIEM +- Tactical Edge / DDIL Operations diff --git a/docs/main/deployment-guide/air-gapped-operations/mirror-package-repositories.mdx b/docs/main/deployment-guide/air-gapped-operations/mirror-package-repositories.mdx new file mode 100644 index 000000000000..2b999ca06fb5 --- /dev/null +++ b/docs/main/deployment-guide/air-gapped-operations/mirror-package-repositories.mdx @@ -0,0 +1,66 @@ +--- +title: Mirror Package Repositories +sidebar_position: 2 +description: Stand up internal Linux package mirrors and container registries that host Mattermost artifacts inside the enclave. +--- + + + + +# Mirror Package Repositories + +In an air-gapped enclave, every package and container image Mattermost depends on must come from a mirror inside the enclave. There is no fall-through to upstream registries. This page enumerates the artifacts that need mirroring and the trust topology that ties them together. + +## What needs mirroring + +### Linux distribution packages + +Mirror the upstream Linux package repositories for the OS image you run Mattermost on. Mattermost requires recent versions of `glibc`, `ca-certificates`, and (for plugins) `ImageMagick` and `xpdf-utils`. PostgreSQL is the only supported database for new installs. + +- **Ubuntu / Debian**: mirror the upstream `apt` repos for the release you use (e.g., `noble`, `jammy`). Tools: `apt-mirror`, `aptly`, internal Pulp 3. +- **RHEL / Rocky / Alma / SUSE**: mirror upstream `dnf` / `zypper` repos. Tools: `reposync`, Red Hat Satellite, Pulp. + +### Mattermost release artifacts + +Mattermost publishes three artifact families. Stage all three on your operator workstation, verify checksums and signatures, then transfer across the air gap. + +| Artifact | Source | Verification | +|---|---|---| +| Server tarball (`mattermost-VERSION-linux-amd64.tar.gz`) | `releases.mattermost.com` | SHA-256 + PGP signature | +| Container images (`mattermost/mattermost-enterprise-edition:VERSION`, `mattermost/mattermost-mobile-push-proxy:VERSION`) | Docker Hub | Image digest (`sha256:…`) | +| Mattermost Operator Helm chart | `chartmuseum.mattermost.com` | SHA-256 of `.tgz` | + +### Plugin and integration artifacts + +Pre-built plugins ship as signed `.tar.gz` files from the Mattermost Marketplace. Stage the bundle of plugins you intend to install (e.g., Channel Export, Legal Hold, Calls, AI Agents) before the air-gap transfer. + +:::important +The Mattermost Marketplace itself **cannot reach your enclave**. After air-gapped install, the Marketplace UI surface is disabled (see [Disable Phone-Home Features](./disable-phone-home-features)). Plugins are installed via `mmctl plugin add` from the local file system. +::: + +## Internal container registry + +For Kubernetes / container deployments, push the Mattermost container images to your internal registry (Harbor, Artifactory, Quay, GitLab Container Registry, AWS ECR inside GovCloud). Tag images with the same version strings you pulled upstream. + +Configure your Kubernetes cluster's `imagePullSecrets` to authenticate to the internal registry, and configure the Mattermost Operator Helm chart's `image.repository` value to point at the internal path (e.g., `registry.enclave.example/mattermost/mattermost-enterprise-edition`). + +## Trust topology + +The artifact-trust chain inside the enclave depends on: + +1. **Your internal CA** signing the TLS certificate served by the internal package mirror and container registry. +2. **The enclave OS trust store** including your internal CA. Without this, `apt update` / `dnf install` will fail with TLS errors. +3. **A verified signature chain** for the Mattermost artifacts themselves. The enclave operator should verify checksums and PGP signatures *before* publishing to the internal mirror. + +## Validation + +After mirroring is complete: + +- `apt update` (or distribution equivalent) succeeds against only the internal mirror. +- `docker pull registry.enclave.example/mattermost/mattermost-enterprise-edition:VERSION` succeeds. +- `helm pull oci://registry.enclave.example/charts/mattermost-operator --version VERSION` succeeds. +- Outbound traffic capture at the enclave boundary shows **no connections to `releases.mattermost.com`, `chartmuseum.mattermost.com`, or Docker Hub** during install. + +## Reference + +This page is a stub — Phase 2 will add per-distribution `apt-mirror` / `reposync` configuration examples and a Harbor + GovCloud ECR worked example. Tracked in `docs/_redesign/proposed-ia.md` §6 in the repo. diff --git a/docs/main/deployment-guide/air-gapped-operations/offline-license-activation.mdx b/docs/main/deployment-guide/air-gapped-operations/offline-license-activation.mdx new file mode 100644 index 000000000000..ea9ea890239c --- /dev/null +++ b/docs/main/deployment-guide/air-gapped-operations/offline-license-activation.mdx @@ -0,0 +1,64 @@ +--- +title: Offline License Activation +sidebar_position: 3 +description: Activate Mattermost Enterprise or Enterprise Advanced licenses inside an enclave without phoning home. +--- + + + + +# Offline License Activation + +In a connected install, Mattermost activates Enterprise licenses by contacting `customers.mattermost.com` and validating the license signature against Mattermost's signing key. In an air-gapped enclave, that callback is impossible. + +Offline activation produces a **license file** that is signed by Mattermost's customer-success team and validated locally by the Mattermost server using a pre-installed public key. No network access is required at activation time. + +## Procedure + +1. **Open a license request with Mattermost Customer Success** through your standard support channel. Provide: + - The Mattermost server version you'll install (e.g., `v10.5.0`). + - The expected user count (must match your purchased seat count). + - Your enclave's clock authority (so the license `IssuedAt` is sensible relative to your NTP source). + - Whether the deployment requires **FIPS mode** at activation (see [Configure FIPS at Install Time](../server/configure-fips-at-install-time)). +2. **Receive a signed `mattermost.license` file** out-of-band (typically encrypted email, customer portal download, or shipped on physical media for sovereign-cloud deployments). +3. **Transfer the license across the air gap** using your approved transfer mechanism. Verify the file SHA-256 hash on both sides. +4. **Install the license** on the running Mattermost server: + ``` + mmctl license upload /path/to/mattermost.license + ``` + Or via the System Console: **System Console → Edition and License → Upload Mattermost License File**. +5. **Verify activation**: + ``` + mmctl license status + ``` + The output should list the licensee, expiration, and active feature set. + +## License lifecycle in air-gapped mode + +| Event | Connected install | Air-gapped install | +|---|---|---| +| Initial activation | Online callback to `customers.mattermost.com` | Local validation of pre-signed `.license` file | +| Renewal | Automatic prompt 60 days before expiry | Manual: customer-success issues new file; operator re-uploads | +| Automated utilization reporting | Daily POST to `customers.mattermost.com` | **Disabled** — Mattermost does not contact `customers.mattermost.com` from inside the enclave. Reporting is done manually at renewal. | + +:::important Automated license utilization reporting must be disabled +The `EnableLicenseReporting` server setting must be set to `false` in `config.json`. Otherwise, Mattermost attempts (and silently fails) a daily POST to `customers.mattermost.com`. The failure does not affect functionality, but it pollutes egress logs and triggers boundary alerts. See [Disable Phone-Home Features](./disable-phone-home-features). +::: + +## License signature verification + +Mattermost server ships with the public key used to verify license signatures embedded in the binary. There is no need to import or trust an additional key. + +If license validation fails after upload, the server logs an explicit error message. Common causes: + +- **Clock skew**: enclave clock is more than 5 minutes off from the license `IssuedAt`. Fix your NTP source. +- **Version mismatch**: the license was issued for a different Mattermost major version than the one installed. Re-request from customer success. +- **Tampering**: SHA-256 hash of the license file changed during air-gap transfer. Re-transfer. + +## Renewal cadence + +Mattermost Enterprise licenses are typically 12-month terms. In air-gapped mode, plan for license renewal **60 days before expiry** to allow time for customer-success issuance + air-gap transfer. Expired licenses degrade Mattermost to free-tier features; they do not lock the server. + +## Reference + +This page is a stub — Phase 2 will add a worked example for sovereign-cloud (GovCloud) deployments where the license file is delivered via the customer portal rather than out-of-band. Tracked in `docs/_redesign/proposed-ia.md` §6 in the repo. diff --git a/docs/main/deployment-guide/air-gapped-operations/quick-start-runbook.mdx b/docs/main/deployment-guide/air-gapped-operations/quick-start-runbook.mdx new file mode 100644 index 000000000000..04b7c2ef8080 --- /dev/null +++ b/docs/main/deployment-guide/air-gapped-operations/quick-start-runbook.mdx @@ -0,0 +1,54 @@ +--- +title: Quick-Start Runbook +sidebar_position: 1 +description: 12-step procedure to stand up a working Mattermost cluster in an air-gapped enclave from scratch. +--- + + + + +# Air-Gapped Quick-Start Runbook + +This runbook brings a Mattermost cluster online inside a network-isolated enclave. It assumes you are the **deploying operator** with administrative access to the enclave's package mirror, container registry, certificate authority, and DNS. + +:::important Prerequisites +- An enclave with internal-only DNS, an internal package mirror (Linux distro repos), and an internal container registry (Harbor / Artifactory / equivalent). +- An offline-activatable Enterprise or Enterprise Advanced license — see [Offline License Activation](./offline-license-activation). +- A staged Mattermost Server release tarball + checksums verified out-of-band, and a Mattermost Operator Helm chart (Kubernetes) or Linux package (`.deb` / `.rpm`). +- A PostgreSQL database reachable from the Mattermost host(s) inside the enclave. +- An NTP source reachable from inside the enclave. +::: + +## The 12 steps + +1. **Stage the release artifacts on the operator workstation.** Download the Mattermost Server tarball, container images, Helm chart, and Vale + plugin assets from `releases.mattermost.com` on an internet-connected workstation. Verify SHA-256 checksums and PGP signatures against the published list. *Never* let a non-verified artifact cross the air gap. +2. **Transfer artifacts across the air gap.** Use the enclave's approved transfer mechanism (one-way diode, manual media, or cross-domain solution). Re-verify checksums on the enclave side before staging in the internal mirror. +3. **Publish artifacts to the internal package mirror and container registry.** Mirror the Linux package repos (Ubuntu, RHEL, SLES — whichever your hosts use) and push container images (e.g., `mattermost/mattermost-enterprise-edition`, `mattermost/mattermost-mobile-push-proxy`) to the internal registry. Tag images with the same version strings published upstream. +4. **Provision PostgreSQL.** Provision the database inside the enclave per [Reference Architecture](../reference-architecture/). Set `max_connections`, `shared_buffers`, and `effective_cache_size` per the [scale tier](../reference-architecture/) you're targeting. +5. **Configure DNS and TLS inside the enclave.** Create an internal DNS A record for the Mattermost host (e.g., `mattermost.enclave.example`). Issue a TLS certificate from your internal CA. Configure NGINX or your reverse proxy with [TLS](../setup-tls.mdx). +6. **Install the Mattermost binary.** Install on Linux ([deploy-linux](../server/deploy-linux.mdx)), Kubernetes via the Mattermost Operator ([deploy-kubernetes](../server/deploy-kubernetes.mdx)), or containers ([deploy-containers](../server/deploy-containers.mdx)). Point image references at your internal registry, not Docker Hub. +7. **Apply the air-gapped configuration profile.** See [Disable Phone-Home Features](./disable-phone-home-features) for the complete list. At minimum, disable: `EnableDiagnostics`, `EnableSecurityFixAlert`, `EnableMarketplace`, automated license utilization reporting, image proxy, and the in-product version check. +8. **Activate the license.** Apply the offline license file produced by the Customer Account team — see [Offline License Activation](./offline-license-activation). +9. **Mediate push notifications.** Apple APNs and Google FCM are reachable only from internet-connected networks. Deploy a mediated push proxy at your enclave boundary; see *Push Notifications without Direct APNs / FCM Egress* (Phase 2). +10. **Configure NTP.** Mattermost relies on accurate clocks for token validation, audit-log timestamps, and rate-limiting. Point hosts at the enclave's internal NTP source. +11. **Configure FIPS at install time** if required for the enclave (DoD IL4 / IL5, FedRAMP Moderate). FIPS cannot be enabled post-deploy. See [Configure FIPS at Install Time](../server/configure-fips-at-install-time). +12. **Verify and run smoke tests.** Confirm the cluster passes the [post-install verification checklist](../server/server-deployment-planning.mdx). Run a manual smoke: log in as system admin, create a team, send a message, install one bundled plugin, trigger an audit-log export. + +## Validation + +After completing all 12 steps, your air-gapped cluster should: + +- Reach the in-product login page over TLS from inside the enclave. +- Authenticate users against your internal directory (AD/LDAP, SAML, OIDC) — no public IdP. +- Make **no outbound DNS queries to public resolvers** during steady-state operation. Verify with packet capture at the enclave boundary. +- Show no "Mattermost installation telemetry" or "Marketplace pings" in egress logs. + +## What this runbook does *not* cover + +- **Hardening beyond the install procedure** — see [Security & Compliance → Hardening Guides](../../security-guide/security-guide-index.mdx). +- **Upgrade procedure for an already-installed air-gapped cluster** — see *Air-Gapped Upgrade Procedure* (Phase 2). +- **Tactical edge / DDIL operation** — for forward-deployed nodes that sync intermittently to a parent enclave, see *Tactical Edge / DDIL Operations* (Phase 2). + +## Reference + +This runbook is modelled on GitLab's [Offline GitLab Quick Start Guide](https://docs.gitlab.com/topics/offline/quick_start_guide/) and Red Hat OpenShift's [Disconnected installation chapter](https://docs.okd.io/4.18/installing/disconnected_install/index.html). Both treat air-gapped deployment as a first-class, runbook-shaped operation rather than a "contact sales" stub. diff --git a/docs/main/deployment-guide/backup-disaster-recovery.mdx b/docs/main/deployment-guide/backup-disaster-recovery.mdx new file mode 100644 index 000000000000..b9fb2e960b71 --- /dev/null +++ b/docs/main/deployment-guide/backup-disaster-recovery.mdx @@ -0,0 +1,90 @@ +--- +title: "Backup and disaster recovery" +--- + + +Options to protect your Mattermost server from different types of failures range from simple backups to sophisticated disaster recovery deployments and automation. + +## Backup + +The state of your Mattermost server is contained in multiple data stores that need to be backed up and restored separately to fully recover your system from failure. + +To back up your Mattermost server: + +1. Back up your Mattermost database using standard procedures depending on your database version. [PostgreSQL SQL Dump backup documentation](https://www.postgresql.org/docs/10/backup-dump.html) is available online. Use the navigation at the top of the page to select your PostgreSQL version. +2. Back up your server settings stored in `config/config.json`. If you are using SAML configuration for Mattermost, your SAML certificate files will be saved in the `config` directory. Therefore, we recommend backing up the entire directory. +3. Back up files stored by your users with one of the following options: + +> - If you use local storage using the default `./data` directory, back up this directory. +> - If you use local storage using a non-default directory specified in the `Directory` setting in `config.json`, back up files in that location. +> - If you store your files in S3, you can typically keep the files where they are located without backup. + + + +To make a clean backup, you must stop Mattermost during the duration of the backup, otherwise the database and files may become out of sync. + + + +To restore a Mattermost instance from backup, restore your database, `config.json` file, and optionally the locally stored user files into the locations from which they were backed up. + +## Disaster recovery + +An appropriate disaster recovery plan weighs the benefits of mitigating specific risks against the cost and complexity of setting up disaster recovery infrastructure and automation. + + + +**High availability (HA) vs. disaster recovery (DR)** + +HA and DR are distinct concepts that are often confused. HA refers to a clustered deployment within a single site that eliminates single points of failure and keeps Mattermost running through individual component outages (e.g., a failed app node or database replica). DR addresses the broader scenario of an entire site or region becoming unavailable, and typically requires a secondary deployment in a separate data center or cloud region. + +Mattermost supports active/passive DR, where a secondary site is kept in sync but only activated during a failover. Mattermost does not support active/active deployments, where both sites serve live traffic simultaneously. + + + +### Automated backup + +Automating backups for a Mattermost server provides a copy of the server's state at a particular point in time, which can be restored if a failure in the future leads to loss of data. Options include: + +- Automation to periodically back up the Mattermost server, which may include all the components listed above or a subset depending on what you choose to protect. +- Automation to restore a server from backup, or deploy a new server, to reduce recovery time. +- Automation to verify a backup has been successfully produced to protect against backup automation failures. +- Storing backups off-site, to protect against physical loss of onsite systems. + +Recovering from a failure using a backup is typically a manual process and will incur downtime. The alternative is to automate recovery using a high availability deployment. + +### Active/passive DR deployment + +For step-by-step instructions on setting up Mattermost in an active/passive DR configuration across two data centers, including how to replicate the database, file storage, and search indices, and how to perform a failover, see the platform-specific guide: + +### Failover from Single Sign-On outage + +When using Single Sign-on with Mattermost Enterprise Edition, an outage to your SSO provider can cause a partial outage on your Mattermost instance. + +**What happens during an SSO outage?** + +- **Most people can still log in.** By default, when a user logs in to Mattermost they receive a session token lasting 30 days (the duration can be configured in the System Console). During an SSO outage, users with valid session tokens can continue using Mattermost uninterrupted. +- **Some people can't log in.** During an SSO outage, there are two situations under which a user cannot log in: + - Users whose session token expires during the outage. + - Users trying to log in to new devices. + +In each case, the user cannot reach the SSO provider, and cannot log in. In either case, several mitigations are available: + +#### Configure your SSO provider for High Availability + +If you're using a self-hosted Single Sign-on provider, several options are available for [High Availability configurations that protect your system from unplanned outages](https://learn.microsoft.com/en-us/microsoft-identity-manager/pam/high-availability-disaster-recovery-considerations-bastion-environment). + +For SaaS-based authentication providers, while you still have a dependency on service uptime, you can set up redundancy in source systems from which data is being pulled. For example, with the OneLogin SaaS-based authentication service, you can set up High Availability LDAP connectivity to further reduce the chances of an outage. + +#### Set up your own IDP to provide an automated or manual SSO failover option + +Create a custom Identity Provider for SAML authentication that connects to both an active and a standby authentication option, that can be manually or automatically switched in case of an outage. + +In this configuration, security should be carefully reviewed to prevent the standby SSO option from weakening your authentication protocols. + +#### Set up a manual failover plan for SSO outages + +When users are unable to reach your organization's SSO provider during an outage, an error message directing them to contact your support link (defined in your System Console settings) is displayed. + +Once IT is contacted about an SSO outage, they can temporarily change a user's account from SSO to email-password using the System Console, and the end user can use their email and password to claim the account until the SSO outage is over and the account can be converted back to SSO. + +When the outage is over, it's critical to switch everyone back to SSO from email-password to maintain consistency and security. diff --git a/docs/main/deployment-guide/deployment-architecture.mdx b/docs/main/deployment-guide/deployment-architecture.mdx new file mode 100644 index 000000000000..72bb59307da5 --- /dev/null +++ b/docs/main/deployment-guide/deployment-architecture.mdx @@ -0,0 +1,32 @@ +--- +title: "Deployment Architecture" +sidebar_label: "Deployment Architecture" +description: Interactive deployment architecture builder. Pick a scale tier, deployment type, and hosting provider — get an architecture diagram and a bill of materials. +--- + +Pick your scale tier, deployment type, and hosting provider. The builder below renders a target architecture and a bill of materials sized to those choices. Sizing follows the [Mattermost scaling guide](/deployment-guide/reference-architecture/application-architecture); provider SKUs are illustrative — verify against current pricing and regional / compliance constraints before committing to a procurement decision. + + + +## How to use this page + +1. **Pick the scale tier** that fits your expected concurrent user count. Tiers correspond to the named bands in the scaling guide (Trial / Small / Medium / Large / Extra Large / Mega / Hyperscale). +2. **Pick a deployment type**: + - **Virtual machines** — Mattermost installed via the [Linux install paths](/deployment-guide/server/deploy-linux), with a separate VM per role (app, database, cache, search). Most common for self-hosted and private-cloud deployments. + - **Kubernetes** — Mattermost deployed via the [Mattermost Operator](/deployment-guide/server/deploy-kubernetes). The diagram and bill of materials swap the load balancer for an ingress controller and the app row for the Operator pattern. +3. **Pick a hosting provider** to see provider-specific SKU recommendations. **On-prem / Other** swaps managed services for self-managed equivalents (PostgreSQL on a VM, Redis on a VM, OpenSearch / Elasticsearch on a VM cluster, MinIO or NFS for object storage). + +## What's next + +Once you've sized the architecture: + +- For **air-gapped, sovereign-cloud, or DDIL** environments, also work through [Air-Gapped Operations](/deployment-guide/air-gapped-operations/quick-start-runbook). The architecture is the same; the install procedure and dependency-staging are different. +- For **regulated workloads** (FedRAMP, DoD IL, DISA STIG), see [Security & Compliance → Compliance Frameworks](/security-guide/compliance-frameworks) for the configuration overlay that goes on top of the architecture choices above. +- For **HA tuning** (clustering, Redis configuration, multi-AZ database topology), see [High Availability cluster-based deployment](/administration-guide/scale/high-availability-cluster-based-deployment). +- For **specific install paths**, jump to [Install on Linux](/deployment-guide/server/deploy-linux), [Install on Kubernetes](/deployment-guide/server/deploy-kubernetes), or [Install with Containers](/deployment-guide/server/deploy-containers). + +:::note[Want the planning context first?] + +If you haven't already, walk through [Deployment Scenarios](/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index) before sizing. Scenarios describe **what shape** of deployment fits your operational pattern (air-gapped, mission partner, DDIL, sovereign-Microsoft, out-of-band); this page sizes **the components** of whichever shape you pick. + +::: diff --git a/docs/main/deployment-guide/deployment-guide-index.mdx b/docs/main/deployment-guide/deployment-guide-index.mdx new file mode 100644 index 000000000000..fbd0ca13de93 --- /dev/null +++ b/docs/main/deployment-guide/deployment-guide-index.mdx @@ -0,0 +1,31 @@ +--- +title: "Deployment Guide" +--- +Welcome to deployment guidance for Mattermost. This guide is organized into sections based on application types and deployment scenarios to help you achieve a successful deployment of Mattermost across various platforms. + +Whether you're deploying the server application, desktop application, or mobile application, or troubleshooting deployments, this guide has you covered. Use the navigation below to access detailed information about each topic. + +- [Quick Start Evaluation](/deployment-guide/quick-start-evaluation) - A quick start guide to help you get started with Mattermost. +- [Reference Architecture](/deployment-guide/reference-architecture/reference-architecture-index) - Reference architectures for scaling Mattermost and specialized deployment scenarios. +- [Server deployment](/deployment-guide/server/server-deployment-planning) - Pre-deployment checks, security considerations, hardware recommendations, software prerequisites, and step-by-step guidance to deploying Mattermost server. +- [Calls Deployment Guide](/administration-guide/configure/calls-deployment-guide) - Deploy and operate Mattermost Calls infrastructure, including RTCD, recording services, and supporting network configuration. +- [Desktop deployment](/deployment-guide/desktop/desktop-app-deployment) - Installation procedures for Mattermost's desktop applications across Windows, macOS, and Linux, and large-scale, enterprise-wide deployments. +- [Mobile deployment](/deployment-guide/mobile/mobile-app-deployment) - How to set up push notifications using Mattermost's notification service and troubleshooting tips. +- [Deployment troubleshooting](/deployment-guide/deployment-troubleshooting) - Best practices for diagnosing and resolving common deployment issues. + +## How to use this guide + +Navigate through the sections using the headings above to find the deployment instructions and troubleshooting steps pertinent to your needs. Each section is designed to provide clear, actionable information to ensure a successful deployment and operation of Mattermost. + +If you are new to Mattermost, we recommend starting with the Application Architecture section to understand the prerequisites and get started, or alternatively use the Try Mattermost section to explore Mattermost before planning your production deployment. + + + +- If you encounter issues that aren't covered in this documentation: + - Customers with a Mattermost subscription: See the [Mattermost Support Knowledge Base](https://support.mattermost.com/hc/en-us), or [contact Mattermost Support](https://support.mattermost.com/hc/en-us/requests/new) for assistance. + - Community deployments: Reference the [Mattermost community forums](https://forum.mattermost.com/) + - For advanced customization or integrations, refer to the [Open source components](/administration-guide/upgrade/open-source-components) documentation for details about extending Mattermost functionality. + + + +Enjoy deploying Mattermost with confidence! diff --git a/docs/main/deployment-guide/deployment-troubleshooting.mdx b/docs/main/deployment-guide/deployment-troubleshooting.mdx new file mode 100644 index 000000000000..da712fc0b4ea --- /dev/null +++ b/docs/main/deployment-guide/deployment-troubleshooting.mdx @@ -0,0 +1,11 @@ +--- +title: "Deployment troubleshooting" +--- +These guides will help you troubleshoot aspects of your Mattermost deployment. + +- [General deployment troubleshooting](/deployment-guide/server/troubleshooting) +- [Docker deployment troubleshooting](/deployment-guide/server/docker-troubleshooting) +- [Desktop app installation troubleshooting](/deployment-guide/desktop/desktop-troubleshooting) +- [Mobile applications troubleshooting](/deployment-guide/mobile/mobile-troubleshooting) +- [PostgreSQL installation troubleshooting](/deployment-guide/server/trouble-postgres) +- [MySQL installation troubleshooting](/deployment-guide/server/trouble_mysql) diff --git a/docs/main/deployment-guide/desktop/desktop-app-deployment.mdx b/docs/main/deployment-guide/desktop/desktop-app-deployment.mdx new file mode 100644 index 000000000000..1e8255d32e2e --- /dev/null +++ b/docs/main/deployment-guide/desktop/desktop-app-deployment.mdx @@ -0,0 +1,63 @@ +--- +title: "Desktop App Deployment" +--- + + +The Mattermost desktop app is available for Windows, macOS, and Linux operating systems, and offers [additional functionality](/end-user-guide/preferences/customize-desktop-app-experience) beyond the web-based experience. + +Learn more about desktop app [software requirements](/deployment-guide/software-hardware-requirements#desktop-apps), [releases and server compatibility](/product-overview/mattermost-desktop-releases) as well as the [what's changed across releases](/product-overview/desktop-app-changelog). + +## Download + +Download and install the Mattermost desktop app from the [App Store (macOS)](https://www.apple.com/app-store/), [Microsoft Store (Windows)](https://apps.microsoft.com/home?hl=en-US&gl=US), or by [using a package manager (Linux)](/deployment-guide/desktop/linux-desktop-install). We strongly recommend installing the desktop app on a local drive. Network shares aren't supported. + +In Matermost, users are notified under **Downloads** when new desktop app releases become available. If managing the distribution of the Desktop app on behalf of users, you can recommend that your users disable desktop update notifications by going to **… \> File \> Settings** on Windows or **Mattermost \> Settings** on Mac and clearing the **Automatically check for updates** option. + +See additional deployment options below to manage distribution of the desktop app to your users. + +### Windows distribution channels + +From desktop v6.1, organizations deploying on Windows have 2 primary distribution options: + +- **Windows Store** (recommended): Provides automatic updates through the Microsoft Store infrastructure. This is the recommended option for most organizations seeking streamlined update management. +- **MSI packages**: Traditional deployment method with full control over installation timing. See the [MSI installer and group policy guide](/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install) documentation for details. + +The desktop v6.1 app includes in-app update notifications. All distribution channels (Windows Store, MSI, Mac App Store, Flathub, APT/RPM) release simultaneously to prevent notification and availability mismatches across deployment methods. + +## Deployment options + +Learn about installation, configuration, and management options for deploying the desktop app in your environment. + +- [Distribute a custom desktop app](/deployment-guide/desktop/distribute-a-custom-desktop-app) +- [Silent Windows desktop distribution](/deployment-guide/desktop/silent-windows-desktop-distribution) +- [MSI installer and group policy guide](/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install) +- [Custom dictionaries for Windows and Linux](/deployment-guide/desktop/desktop-custom-dictionaries) +- [Managed resources for the desktop app](/deployment-guide/desktop/desktop-app-managed-resources) +- [Desktop app troubleshooting](/deployment-guide/desktop/desktop-troubleshooting) + +## Privacy and data handling + +### Error reporting + +From Mattermost Desktop v6.1, the desktop app includes automatic error reporting to help identify and fix crashes and stability issues. + +**What information is sent** + +Error reports include: + +- Crash information and stack traces +- App version and platform details (OS type, architecture) +- Error messages and context + +**What is NOT sent** + +- Message content or user communications +- User credentials, passwords, or authentication tokens +- Personally identifiable information (PII) +- Server URLs or team names + +**Privacy and user control** + +Error reporting is **enabled by default**. Users can disable it at any time by going to **Settings \> Advanced \> Send error reports to help improve the app**. Restart the app to apply the change. + +Organizations with data handling policies should inform users about this feature and provide guidance on whether to disable it. For organizations building the Desktop app from source, error reporting can be disabled at build time by omitting the `MM_DESKTOP_BUILD_SENTRYDSN` environment variable. diff --git a/docs/main/deployment-guide/desktop/desktop-app-managed-resources.mdx b/docs/main/deployment-guide/desktop/desktop-app-managed-resources.mdx new file mode 100644 index 000000000000..50234519b7b0 --- /dev/null +++ b/docs/main/deployment-guide/desktop/desktop-app-managed-resources.mdx @@ -0,0 +1,37 @@ +--- +title: "Desktop managed resources" +--- + + +The Mattermost desktop app supports managed resources. A managed resource can be any service available on the same hostname using the same protocol as the Mattermost server. + + + +Using this feature requires a custom build of the Mattermost desktop app \. + + + +Add the path of a managed resource to your configuration file. When selected, it opens as a pop-up window in the Mattermost desktop app. + +In addition to customizing the Mattermost Desktop App, the [Managed Resource Paths](/administration-guide/configure/environment-configuration-settings#managed-resource-paths) setting on the Mattermost server must be configured. + +In the below example we add the managed resource `/video`. + +``` text +[...] +managedResources: ['trusted', 'video'], +[...] +``` + +Here are two example server URLs each with valid and invalid managed resource URLs: + +- Mattermost server: `https://mattermost.my.org` + - A valid video service: `https://mattermost.my.org/video` + - A valid conference service: `https://mattermost.my.org/conference` + - An invalid video service using a different protocol: `http://mattermost.my.org/video` + - An invalid conference service having a different origin: `https://conference.my.org` +- Mattermost server: `https://my.org/mattermost` + - A valid video service: `https://my.org/video` + - A valid conference service: `https://my.org/conference` + - An invalid video service using a different protocol: `http://my.org/video` + - An invalid conference service having a different origin: `https://conference.my.org` diff --git a/docs/main/deployment-guide/desktop/desktop-custom-dictionaries.mdx b/docs/main/deployment-guide/desktop/desktop-custom-dictionaries.mdx new file mode 100644 index 000000000000..daf7d536bf88 --- /dev/null +++ b/docs/main/deployment-guide/desktop/desktop-custom-dictionaries.mdx @@ -0,0 +1,27 @@ +--- +title: "Desktop App custom dictionaries" +--- + + +From Mattermost desktop app v4.7.1, custom dictionary definitions can be served through a URL on Windows and Linux. If custom dictionaries aren't specified, default dictionary definitions are obtained automatically from Chromium's CDNs (content delivery networks). On macOS, the Mattermost desktop app uses dictionary definitions provided by Apple that can't be customized. + +## Prepare custom dictionaries + +On Windows and Linux, the Mattermost desktop app uses [Hunspell Dictionary definitions](https://hunspell.github.io/) by default. You can download a copy of these dictionary definitions and modify them to fit specific needs. + +To access a copy of these dictionary definitions: + +1. Download a copy of `hunspell_dictionaries.zip` from the [latest electron release](https://github.com/electron/electron/releases/latest). +2. Extract the dictionary definitions from the ZIP file. +3. Convert the filenames to lowercase. (Chromium expects `en-us` rather than `en-US`). Once renamed, these definition files match the usage of using Chromium's CDN ones, and you can modify the definitions as needed. +4. Serve the extracted and converted files from a web server, and note the URL to the root folder of the dictionaries. Specify this URL as the **alternate dictionary URL** in the desktop app. + +## Configure the Desktop App + +1. In the Mattermost Desktop App, go to Settings by selecting Use the More icon in the top left corner to access Mattermost desktop apps customization settings. **\> File \> Settings**. +2. Under **App Options**, ensure that the **Check spelling** option is enabled. +3. Select **Use an alternative dictionary URL** to specify the URL to the root folder of your custom dictionaries, then select **Save**. + +## Remove custom dictionaries + +Select **Revert to default** to stop using the specified dictionary definitions, and revert to default dictionary definitions. diff --git a/docs/main/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.mdx b/docs/main/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.mdx new file mode 100644 index 000000000000..09b355531bb1 --- /dev/null +++ b/docs/main/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.mdx @@ -0,0 +1,237 @@ +--- +title: "Desktop MSI installer and group policy guide" +--- + + +This page provides guidance on installing the desktop app MSI and use Group Policies in Windows for Mattermost Enterprise or Professional. The MSI installer package can be downloaded [here](https://github.com/mattermost/desktop/releases/latest). + + + +**Per-machine installation from v6.1.0**: From Mattermost Desktop v6.1.0, the Windows MSI installer defaults to per-machine (system-wide) installation to meet enterprise compliance requirements. This changes deployment strategies and upgrade paths. See the [Deployment considerations for v6.1.0+](#deployment-considerations-for-v6-1-0) section below for details. + + + +## Windows distribution options + +From desktop v6.1, organizations deploying on Windows have 2 primary distribution options: + +- **Windows Store**: Primary option for automatic updates. Recommended for most users. The Windows Store version handles updates automatically through the Microsoft Store infrastructure. +- **MSI installer**: Direct download option for traditional deployment methods. This guide covers MSI deployment. + +The desktop v6.1 app includes in-app update notifications that check the Mattermost website for new versions. All distribution channels (Windows Store, MSI, Mac App Store, Flathub, APT/RPM) release simultaneously to ensure users receive consistent update notifications regardless of their installation method. + +## Upgrading to v6.1.0 with MSI installer + +Users upgrading from earlier Desktop app versions using the MSI installer may need to recreate taskbar shortcuts once after the upgrade. The v6.1.0 installer uses a more reliable method for shortcut icons that prevents shortcuts from breaking during future upgrades. This fixes a long-standing issue where shortcuts could break during MSI upgrades. This is a one-time action for the upgrade to v6.1.0. Future upgrades to v6.1.2 and later won't require shortcut recreation. Windows Store deployments aren't affected by this change. + +We recommend telling your users in advance that they may need to re-pin the taskbar shortcut after upgrading to desktop app v6.1. Desktop shortcuts are typically unaffected while taskbar shortcuts are most commonly impacted. + +If a user reports a broken shortcut after upgrading to v6.1.0, the user should: + +1. Right-click the broken shortcut on the taskbar and select **Unpin from taskbar**. +2. Launch Mattermost Desktop from the Start Menu. +3. Right-click the Mattermost icon in the taskbar. +4. Select **Pin to taskbar**. + +## Download group policy and MSI installer files + +1. Using a newly created Windows VM or dedicated Windows computer, make sure to use a Windows version that supports `Edit group policy` out of the box (i.e. Windows 10 Pro or Enterprise). + + ![When downloading group policy and MIS installer files, ensure to use a Windows version that supports Edit group policy.](/images/desktop/msi_gpo/msi_gpo_installation_test_00001.png) + +2. Navigate to the [Mattermost Desktop](https://github.com/mattermost/desktop) repository on [GitHub.com](https://github.com/). + + ![Go to the mattermost/desktop repository on GitHub.](/images/desktop/msi_gpo/msi_gpo_installation_test_00002.png) + +3. Navigate to the release page for [version v6.1.2](https://github.com/mattermost/desktop/releases/latest) and download the appropriate installer for your version of Windows (32-bit vs. 64-bit). + +4. Download the [source.zip](https://github.com/mattermost/desktop/archive/v6.1.2.zip) file as well to extract group policy files. + + ![In the mattermost/desktop repository on GitHub, go to the release page for the latest desktop release, then download the installer for your version of Windows. Download the source.zip file as well to extract group policy files.](/images/desktop/msi_gpo/msi_gpo_installation_test_00003.png) + +## Install group policy files locally + +The following group policies are available supporting a state option of Not Configured, Enabled, or Disabled: + +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +>
Group policyDescriptionMattermost releaseSetting
Enable Server ManagementIf disabled, management of servers in the app settings are disabled.v4.3 or laterEnableServerManagement
Default Server ListDefine one or more default, permanent servers.v4.3 or laterDefaultServerList
Update NotificationsIf disabled, in-app update notifications are not shown.v5.1 or laterEnableAutoUpdates
+ +1. Browse to the folder the above files were downloaded to and unzip the `desktop-6.1.2.zip` file in place. + + ![Go to the install download directory on your machine and unzip the ZIP file.](/images/desktop/msi_gpo/msi_gpo_installation_test_00004.png) + +2. Navigate to the unzipped `desktop-6.1.2\resources\windows\gpo` folder and copy the contents. + + ![Go to the \resources\windows\gpo directory and copy its contents.](/images/desktop/msi_gpo/msi_gpo_installation_test_00005.png) + +3. Navigate to the `C:\Windows\PolicyDefinitions` folder and paste the files copied in the last step. + + ![Go to the Windows\PolicyDefinitions directory and paste the files you copied in the previous step.](/images/desktop/msi_gpo/msi_gpo_installation_test_00006.png) + +4. Verify the `mattermost.admx` file is in the `C:\Windows\PolicyDefinitions` folder. + + ![Verify the mattermost.admx file is present in the Windows\PolicyDefinitions directory.](/images/desktop/msi_gpo/msi_gpo_installation_test_00007.png) + +5. Verify the `mattermost.adml` file is in the `C:\Windows\PolicyDefinitions\en-US` folder. + + ![Verify the mattermost.adml file is present in the Windows\PolicyDefinitions\en-US directory.](/images/desktop/msi_gpo/msi_gpo_installation_test_00008.png) + + + +- `\\FQDNDomain\sysvol\FQDNDomain\Policies\PolicyDefinitions` can be used instead of `C:\Windows\PolicyDefinitions` if available. +- `\\FQDNDomain\sysvol\FQDNDomain\Policies\PolicyDefinitions\en-US` can be used instead of `C:\Windows\PolicyDefinitions\en-US` if available. + + + +**Disable update notifications** + +Update notifications can be disabled by configuring the supported group policy. Changes to group policies require you to restart Mattermost for those changes to take effect. + +## Configure Mattermost using group policy settings + +1. Run the `Edit group policy` application by selecting **Start**, typing `gpedit` into the search field, then selecting the resulting **Edit group policy** search option. + + ![When configuring Mattermost using group policy settings, run the Edit group policy application by going to Start, typing gpedit into the search field, then selecting the resulting Edit group policy search option.](/images/desktop/msi_gpo/msi_gpo_installation_test_00009.png) + +2. In the **Edit group policy** window, navigate to `Local Computer Policy\Computer Configuration\Administrative Templates\Mattermost`. In this example, double-click on `DefaultServerList` to set one or more default servers that will appear on app launch. + + ![In the Edit group policy window, go to Local Computer Policy \> Computer Configuration \> Administrative Templates \> Mattermost. To set one or more default servers to appear on app launch, for example, double-click on DefaultServerList to begin.](/images/desktop/msi_gpo/msi_gpo_installation_test_00010.png) + +3. In the resulting window for **DefaultServerList**, select **Enabled** to turn the feature on, then select the **Show…** button in the **Options:** section of the window to add default servers. + + ![In the DefaultServerList window, enable the feature, then select Show..., located under Options, to add the default servers.](/images/desktop/msi_gpo/msi_gpo_installation_test_00011.png) + +4. In the resulting window, add desired Mattermost servers using a memorable name (i.e., Community) and the web URL of the Mattermost server (i.e., [https://community.mattermost.com](https://community.mattermost.com)). + +5. Select **OK** twice, then close the **Edit group policy** app. + + ![Add the default servers by name and by URL, then select OK twice to close the Edit group policy application.](/images/desktop/msi_gpo/msi_gpo_installation_test_00012.png) + +## Deployment considerations for v6.1.0+ + +From Mattermost Desktop v6.1.0, the Windows MSI installer defaults to per-machine (system-wide) installation to meet enterprise compliance requirements. The application installs to `C:\Program Files\Mattermost` with registry keys in `HKLM` (HKEY_LOCAL_MACHINE), and requires administrator privileges for deployment. + +Users upgrading from v5.9 to v6.0.4 with per-user installations must manually uninstall the old version before installing v6.1.0 to avoid duplicate installs. See [Desktop troubleshooting](#upgrade-to-v6-1-0-fails-or-installs-duplicate-version-windows-msi) for detailed upgrade instructions. + +## Multi-view and Group Policies + +From desktop v6.0, users can run multiple Mattermost workspaces at the same time in the desktop app. Use existing methods to pre-provision multiple workspaces for users, as follows: + +- On Windows, seed the approved list using the `DefaultServerList` Group Policy. +- For scripted installs, seed `config.json` on first run to include multiple entries in the `teams` array. See the [Silent Windows desktop distribution](/deployment-guide/desktop/silent-windows-desktop-distribution) documentation for details. +- To prevent users from adding or removing workspaces, use the existing `EnableServerManagement` Group Policy. +- Disable `EnableAutoUpdates` to turn off update notifications. + +### Verify group policy settings have been applied + +1. Open up the Registry Editor by selecting **Start**, typing `Registry Editor` in the search field, then selecting the **Registry Editor** option in the search results. + + ![When verifying group policy settings, open the Registery Editor by going to Start, typing Registry Editor into the search field, then selecting the resulting Registry Editor search option.](/images/desktop/msi_gpo/msi_gpo_installation_test_00013.png) + +2. In the **Registry Editor** window, navigate to `Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mattermost\DefaultServerList` and verify the servers you added using the **Edit group policy** app are listed. + +3. Once verified, close the **Registry Editor**. + + ![Go to Computer \> HKEY_LOCAL_MACHINE \> SOFTWARE \> Policies \> Mattermost \> DefaultServerList to veryfiy the servers you added, then close the Registry Editor.](/images/desktop/msi_gpo/msi_gpo_installation_test_00014.png) + +## Install the Mattermost Desktop App using the MSI installer + + + +- If the desktop app is running when you install via the MSI, Mattermost prompts you to close the app manually. After acknkowledging the prompt, select **Retry** to continue the MSI installation. +- Avoid selecting **Ignore**. If you do, force close the desktop app using Task Manager, ensure the `Mattermost.exe` process is stopped, and then restart the MSI installation. + + + +1. Within the folder the MSI installer was downloaded to, double-click on the MSI installer to begin the Mattermost Desktop installation process. + + ![Go to the folder where you downloaded the Mattermost Desktop App, and double-click on the MSI file to begin the installation process.](/images/desktop/msi_gpo/msi_gpo_installation_test_00015.png) + +2. Installation of the MSI requires admin permission, so accept the resulting request to allow the installer to make changes to your device. + + ![You'll be prompted to allow the Mattermost Desktop App to make changes to your system. You must select Yes to continue with the installation process.](/images/desktop/msi_gpo/msi_gpo_installation_test_00016.png) + +3. Select **Finish** when the installation is complete. + + ![When the installation is complete, select Finish.](/images/desktop/msi_gpo/msi_gpo_installation_test_00017.png) + +### Verify group policy settings in the installed desktop app + +1. Launch the newly installed Mattermost app from the **Start** menu. + +2. Verify the app loads the first server you defined in the **Edit group policy** app. + + ![Verify group policy settings in the Mattermost Desktop App by opening the app from the Start menu, and verifying that the app loads the first server you defined in the Edit group policy.](/images/desktop/msi_gpo/msi_gpo_installation_test_00018.png) + +## Advanced MSI options + + + +You must be a system admin to run these commands, or you must run them from an admin command prompt or PowerShell. + + + +### Silent installation + +Perform a silent installation of the MSI by running the following command: + + + +Ensure the desktop app is closed before proceeding with a silent installation. Because it's a silent installation, Mattermost won't prompt you to close the desktop app. + + + +**Command Prompt:** `msiexec /i mattermost-desktop-v6.1.2-x64.msi /qn` + +**PowerShell:** `Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList '/i mattermost-desktop-v6.1.2-x64.msi /qn'` + + + +\- Replace `<version>` with the actual version number (e.g., `v6.1.2`). - From v6.1.0, the MSI installs per-machine by default, requiring administrator privileges. + + + +From version v5.9.0 of the Mattermost desktop app, the following silent MSI installation options are also available. + +### Specify an install directory + +Use the `APPLICATIONFOLDER` parameter to specify an installation directory for the MSI installation: + +- **Command Prompt:** `msiexec /i mattermost-desktop-v6.1.2-x64.msi APPLICATIONFOLDER="<install directory>"` +- **PowerShell:** `Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList '/i mattermost-desktop-v6.1.2-x64.msi APPLICATIONFOLDER="<install directory>"'` + +Change this command as new versions of the Mattermost Desktop App are released. diff --git a/docs/main/deployment-guide/desktop/desktop-troubleshooting.mdx b/docs/main/deployment-guide/desktop/desktop-troubleshooting.mdx new file mode 100644 index 000000000000..be85225e4b66 --- /dev/null +++ b/docs/main/deployment-guide/desktop/desktop-troubleshooting.mdx @@ -0,0 +1,229 @@ +--- +title: "Desktop app troubleshooting" +--- +## Broken shortcuts after upgrading to v6.1.0 (Windows MSI only) + +After upgrading to Mattermost Desktop v6.1.0 using the Windows MSI installer from an older release, the desktop or taskbar shortcut shows the wrong icon or fails to launch. This is due to a one-time icon handling change in the Windows MSI installer to improve shortcut reliability for future upgrades. + +This issue doesn't block app usage and only affects Windows MSI installer upgrades from pre-v6.1.0 versions. Users can launch Mattermost from the Start Menu or a working desktop shortcut.Future upgrades to v6.1.1 and later will not require shortcut recreation. + +To resolve this issue, recreate the shortcut: + +1. Right-click the broken shortcut on the taskbar and select **Unpin from taskbar**. +2. Launch Mattermost Desktop from the Start Menu or a working desktop shortcut. +3. Right-click the Mattermost icon in the taskbar while the application is running. +4. Select **Pin to taskbar**. + +The new shortcut will work correctly for all future upgrades. + +Organizations standardizing on Windows installations can choose between Windows Store (recommended for automatic updates) or MSI packages (traditional deployment). The MSI method includes this one-time shortcut adjustment; the Windows Store method doesn't. + +## Where is configuration stored locally? + +The location of the Mattermost desktop app configuration file depends on the platform where you're running Mattermost (and, in the case of macOS, how you've chosen to install the app): + +- Windows: `Users\<username>\AppData\Roaming\Mattermost` +- macOS installer: `/Users/<username>/Library/Application Support/Mattermost` +- macOS App Store: `/Users/<username>/Library/Containers/Mattermost.Desktop/Data/Library/Application Support/Mattermost` (via Finder: `~/Library/Application Support/Mattermost` as the extension is hidden) +- Linux: `~/.config/Mattermost` + + + +- Local configuration data is not automatically removed when uninstalling the desktop app. If you wish to remove all data, you must manually remove the files from the applicable location noted above. +- Prior to uninstalling, you can choose to log out of any active sessions. You can terminate active sessions from another Mattermost session in **Profile \> Security \> View and Logout of Active Sessions**, then select **Log Out**. Desktop app sessions are labeled as **Native Desktop App**. + + + +## Update notifications not appearing + +If you're not seeing in-app update notifications when new versions are available: + +1. **Check your internet connection**: Ensure outbound HTTPS communication to `mattermost.com` is allowed. +2. **Manually check for updates**: Go to **Help \> Check for Updates** or **Settings \> General \> Check for Updates Now** to trigger an immediate check. +3. **Verify update notifications are enabled**: + - On Windows: Go to **… \> File \> Settings** and ensure **Automatically check for updates** is enabled. + - On macOS: Go to **Mattermost \> Settings** and ensure **Automatically check for updates** is enabled. +4. **Check Group Policy settings** (Enterprise deployments): Your system administrator may have disabled update notifications via the `EnableAutoUpdates` Group Policy. Contact your IT department for clarification. +5. **Version previously skipped**: If you selected **Skip This Version** for the current release, manually check for updates to see it again. + +## Update required screen + +From Mattermost server v11.6.0, system admins can set a minimum Desktop App version in **System Console \> Site Configuration \> Customization \> Minimum desktop app version**. If your Desktop App version is below the configured minimum, you will see an update required screen and cannot access Mattermost until you update. + +The screen includes a **Download** button that links to the apps download page configured by your admin. Select **Download** to go to that page, then follow the [manual update steps](/deployment-guide/desktop/desktop-troubleshooting#how-to-manually-update-mattermost-desktop) for your platform. + +If you believe your app is already up to date, contact your system admin to confirm the configured minimum version. + +## How to manually update Mattermost Desktop + +From v6.1.0, Mattermost Desktop updates are manual. Follow these steps for your platform: + +**macOS (App Store)**: + +1. Open the App Store application. +2. Go to **Updates** section. +3. Find Mattermost Desktop and select **Update**. + +**macOS (DMG installation)**: + +1. Download the latest DMG from [https://mattermost.com/download](https://mattermost.com/download) or the [GitHub releases page](https://github.com/mattermost/desktop/releases/latest). +2. Open the downloaded DMG file. +3. Drag the Mattermost application to your Applications folder, replacing the existing version. +4. Restart Mattermost Desktop. + +**Windows (Microsoft Store)**: + +1. Open the Microsoft Store application. +2. Go to **Library \> Get updates**. +3. Find Mattermost and select **Update**. + +**Windows (MSI installation)**: + +1. Download the latest MSI installer from the [GitHub releases page](https://github.com/mattermost/desktop/releases/latest). +2. Run the MSI installer. +3. Follow the installation prompts (it will upgrade your existing installation). + +**Linux**: + +1. Visit the [GitHub releases page](https://github.com/mattermost/desktop/releases/latest). +2. Download the appropriate package for your distribution (AppImage, .deb, .rpm, Flatpak, etc.). +3. Install using your package manager or standard installation method. + + + +For AppImage users: Simply download the new AppImage file and replace the old one. Make sure to make it executable: `chmod +x mattermost-desktop-*.AppImage` + + + +## How do I access logs? + +From Mattermost desktop v5.3, you can access logs via **Help \> Show logs**, which opens the file manager window showing the location of the log file. + +## How do I download app diagnostics? + +From Mattermost desktop v5.3, you can download a diagnostics text file via **Help \> Run diagnostics**, which can be attached to a Support ticket. + +## Deep links open in the wrong workspace in multi-view + +If you experience deep links opening in the wrong workspace, ensure all relevant workspaces are pre-provisioned via the Group Policy `DefaultServerList`. See the [multi-view and group policies](/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install#multi-view-and-group-policies) documentation for details. + +- Verify that workspace URLs match exactly (including protocol and subdomain) so links route to the intended workspace. +- Edit the workspace list to correct or remove stale entries, then retry the link. + +## High CPU or memory when multiple workspaces open + +Verify the device is powerful enough to run several workspaces concurrently. Close unused tabs and pop-out windows to reduce load. + +Check the [desktop app advanced settings](/end-user-guide/preferences/customize-desktop-app-experience). Toggle **Use GPU hardware acceleration** off on systems with unstable drivers. + +## Desktop App displays white screen while launching and doesn't load the page + +1. Delete the local `Mattermost desktop app` configuration file. See the [Where is configuration stored locally?](#where-is-configuration-stored-locally) section above for file location details. +2. Reinstall the application. + +## Upgrade to v6.1.0 fails or installs duplicate version (Windows MSI) + +After installing v6.1.0 MSI, the old version still appears, both versions are present, or the upgrade doesn't seem to work. This is because you had a per-user installation from v5.9 to v6.0.4. From v6.1.0, the MSI installer defaults to per-machine (system-wide) installation. MSI installers cannot automatically upgrade across different installation contexts (per-user to per-machine). + +To check your installation type before upgrading, open File Explorer. + +- If Mattermost is in `C:\Program Files\Mattermost` or `C:\Program Files (x86)\Mattermost`: Per-machine install (upgrade will work normally) +- If Mattermost is in `C:\Users\\AppData\Local\...`: Per-user install (requires manual uninstall before v6.1.0) + +To resolve this issue, you must manually uninstall the old version before installing v6.1.0: + +1. Uninstall both versions: + - Go to **Settings \> Apps** or **Control Panel \> Programs and Features**. + - Uninstall all Mattermost Desktop entries. +2. Download the v6.1.0 MSI installer again from the [releases page](https://github.com/mattermost/desktop/releases). +3. Install v6.1.0 with administrator privileges (it will install to `C:\Program Files\Mattermost`). +4. Future upgrades will work normally. + +## "Installation has failed" dialog + +The app data might be corrupted. Remove all the files in `%LOCALAPPDATA%\mattermost`, then try reinstalling the app. + +## "The application "Mattermost" can't be opened" dialog + +On macOS Catalina, this dialog can be triggered if the Mac Archive Utility is the default method for decompressing files. In this case using a third-party tool such as [Keka](https://www.keka.io) or [Unarchiver](https://macpaw.com/the-unarchiver) may resolve the problem. + +## Desktop App window is black and doesn't load the page + +1. Ensure you have installed the latest desktop app version available. +2. Clear your cache and reload the app from **View \> Clear Cache and Reload** or press Ctrl Shift R on Windows or Linux, or R on Mac. +3. Quit the app and restart it to see if the issue clears. +4. Disable GPU hardware acceleration. + +> - On Windows or Linux, select **File \> Settings** and clear the **Use GPU hardware acceleration** option. +> - On macOS, select **Mattermost \> Settings** and clear the **Use GPU hardware acceleration** option. + +5. If you are using a special video driver, such as Optimus, try disabling it to see if the problem is resolved. + +## Desktop App window is white and doesn't load the page + +1. Ensure you have installed the latest desktop app version available. +2. Delete the `%userprofile%\AppData\Roaming\Mattermost` directory on your local machine. +3. Reinstall the desktop app. + +## Desktop App is not visible, but the Mattermost icon is in the Task Bar + +This issue can occur on Windows in a multiple-monitor setup. When you disconnect the monitor that Mattermost is displayed on, Mattermost continues to display at screen coordinates that no longer exist. + +To resolve this issue, you can reset the desktop app screen location by deleting the screen location file. When the file is not present, the desktop app displays on the primary monitor by default. + +To reset the desktop app screen location: + +1. If the desktop app is running, right-click the Mattermost icon in the task bar, then select **Close Window**. +2. Open Windows File Explorer, and go to the `%APPDATA%\Mattermost` folder. +3. Delete the file `bounds-info.json`. + +## Desktop App constantly refreshes the page + +This issue can occur when `localStorage` has an unexpected state. To resolve the issue: + +- Windows: Open Windows File Explorer, go to the `%APPDATA%\Mattermost` folder, then delete the `Local Storage` folder. +- Mac: Open Finder, go to the `~/Library/Application Support/Mattermost` folder, then delete the `Local Storage` folder. +- Linux: Open the File Manager, go to the `~/.config/Mattermost` folder, then delete the `Local Storage` folder. Linux file managers may hide folders starting with a period by default. You can delete them from the terminal using `rm -rf ~/.config/Mattermost`. + +## Desktop App constantly asks to log in to Mattermost server + +This issue can occur after a crash or unexpected shutdown of the desktop app that causes the app data to be corrupted. To resolve the issue: + +- Windows: Open Windows File Explorer, go to the `%APPDATA%\Mattermost` folder, then delete the `IndexedDB` folder and the `Cookies` and `Cookies-journal` files. +- Mac: Open Finder, go to the `~/Library/Application Support/Mattermost` folder, then delete the `IndexedDB` folder and the `Cookies` and `Cookies-journal` files. +- Linux: Open the file manager, go to the `~/.config/Mattermost` folder, then delete the `IndexedDB` folder and the `Cookies` and `Cookies-journal` files. Linux file managers may hide folders starting with a period by default. You can delete them from the terminal using `rm -rf ~/.config/Mattermost`. + +## "Internal error: BrowserWindow 'unresponsive' event has been emitted" + +Selecting **Show Details** on the dialog provides logs. Ways to resolve the issue: + +1. Clear the cache via **View \> Clear Cache and Reload** or press Ctrl Shift R on Windows or Linux, or R on Mac. +2. Go to App Settings via **File \> Settings** (or by pressing Ctrl , on Windows or Linux, or , on Mac) and unselect hardware acceleration. + +## Desktop app not responsive within Citrix Virtual Apps or Desktop Environment + +Append `Mattermost.exe;` to the Registry Key `HKLM\SYSTEM\CurrentControlSet\Services\CtxUvi\UviProcessExcludes` and reboot the system. + +For further assistance, review the [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) for previously reported errors, or [join the Mattermost user community for troubleshooting help](https://mattermost.com/community/). + +## Can I uninstall the desktop app I installed using snap on Linux? + +Yes. Run the following command from a terminal window: `sudo snap remove mattermost-desktop`. + +### Report Desktop App issues + +When reporting issues found in the Mattermost desktop app, it's helpful to include the contents of the Developer Tools Console along with [the information on this page](https://support.mattermost.com/hc/en-us/articles/360060662492-Opening-a-Support-Ticket-for-Self-Managed-Deployments). + +To access the Developer Tools Console: + +1. In the menu bar, go to **View \> Developer Tools \> Developer Tools for Current Tab**. +2. Select the **Console** tab. +3. Right-click the log entry, then select **Save As**. +4. Save the file, then send it along with a description of your issue. +5. Close the console to disable the Developer Tools. + +You can open an additional set of developer tools for each server you have added to the desktop app. The tools can be opened by pasting this command in the Developer Tools Console you opened with the steps described above: + +> ``` javascript +> document.getElementsByTagName("webview")[0].openDevTools(); +> ``` diff --git a/docs/main/deployment-guide/desktop/distribute-a-custom-desktop-app.mdx b/docs/main/deployment-guide/desktop/distribute-a-custom-desktop-app.mdx new file mode 100644 index 000000000000..231da6f15357 --- /dev/null +++ b/docs/main/deployment-guide/desktop/distribute-a-custom-desktop-app.mdx @@ -0,0 +1,80 @@ +--- +title: "Distribute a custom desktop app" +--- + + +You can customize and distribute your own Mattermost desktop application by configuring [src/common/config/buildConfig.ts](https://github.com/mattermost/desktop/blob/master/src/common/config/buildConfig.ts). + +1. Configure the desktop app's `buildConfig.ts` file. You can configure the following parameters to customize the user experience, including [defaultTeams](#defaultTeams), [helpLink](#helpLink), and [enableServerManagement](#enableServerManagement). +2. Follow the [Mattermost Desktop Development Guide](https://developers.mattermost.com/contribute/more-info/desktop/developer-setup/) to build the application. +3. Distribute the application to your users. + +## `defaultTeams` + +List of server URLs and their display names added to the desktop app by default, which the user cannot modify. Users can still add servers [through the Server Management page](#enableservermanagement) unless `enableServerManagement` is set to `false`. Expects an array of key-value pairs. + +Example: + +``` text +defaultTeams: [ + { + name: 'example', + url: 'https://example.com' + }, + { + name: 'mattermost', + url: 'https://www.mattermost.com' + } +] +``` + +## `helpLink` + +The URL of the help documentation in **Help \> Learn More** menu bar item. If none is specified, the menu option is hidden. Expects a string. + +Example: + +``` text +helpLink: 'https://docs.mattermost.com/messaging/managing-desktop-app-servers.html' +helpLink: '' +``` + +## `enableServerManagement` + +Controls whether users can add, edit, or remove servers on the app settings page. If set to false, at least one server must be specified for `defaultTeams` or else users cannot interact with any servers. Expects a boolean, true or false. + +Example: + +``` text +enableServerManagement: true +``` + +## Managed resources + +[Custom builds](/deployment-guide/desktop/distribute-a-custom-desktop-app) of the Mattermost desktop app support managed resources which are services available on the same hostname and protocol as the Mattermost server. + +To configure managed resources, add their path to the `managedResources` field in your configuration file. Selecting a managed resource opens it as a pop-up window in the desktop app. + +Additionally, you must configure the :ref:Managed Resource Paths \\` server configuration setting. For example, adding the `/video` path: + +``` text +[...] + managedResources: ['trusted', 'video'], +[...] +``` + +Below are examples of server URLs with valid and invalid managed resource URLs: + +Server: `https://mattermost.my.org` + +- Valid: `https://mattermost.my.org/video` +- Valid: `https://mattermost.my.org/conference` +- Invalid: `http://mattermost.my.org/video` (different protocol) +- Invalid: `https://conference.my.org` (different origin) + +Server: `https://my.org/mattermost` + +- Valid: `https://my.org/video` +- Valid: `https://my.org/conference` +- Invalid: `http://my.org/video` (different protocol) +- Invalid: `https://conference.my.org` (different origin) diff --git a/docs/main/deployment-guide/desktop/linux-desktop-install.mdx b/docs/main/deployment-guide/desktop/linux-desktop-install.mdx new file mode 100644 index 000000000000..b94bea574b98 --- /dev/null +++ b/docs/main/deployment-guide/desktop/linux-desktop-install.mdx @@ -0,0 +1,157 @@ +--- +title: "Install desktop app on Linux" +--- + + +This page describes how to install the Mattermost desktop app on Linux. + +
+ +Ubuntu/Debian + +Both a `.deb` package (Beta), and an official APT repository is available for Debian 9 and for Ubuntu releases 20.04 LTS or later. Automatic app updates are supported and enabled. When a new version of the desktop app is released, your app updates automatically. + + + +The GPG public key has changed. If you had previously set up the repository on your system, you'll need to [download the new key](https://deb.packages.mattermost.com/pubkey.gpg). You can set the `UPDATE_GPG_KEY=yes` environment variable when running the setup script to configure it to overwrite the previous key on your system with the new one. The first step of installation then becomes: `curl -fsS -o- https://deb.packages.mattermost.com/setup-repo.sh | sudo UPDATE_GPG_KEY=yes bash`. Depending on your setup, additional steps may also be required, particularly for installations that don't rely on the repository setup script. + + + +1. At the command line, set up the Mattermost repository on your system: + +> ``` sh +> curl -fsS -o- https://deb.packages.mattermost.com/setup-repo.sh | sudo bash +> ``` + +2. Install the Mattermost desktop app: + +> ``` sh +> sudo apt install mattermost-desktop +> ``` + +3. Update the Mattermost desktop app: + +> ``` sh +> sudo apt upgrade mattermost-desktop +> ``` + +## Snapcraft Package + +A snap is available for systems that have Snapcraft installed. Snapcraft is installed by default on Ubuntu 16.04 and later, but for most other Linux distributions you can install it manually. To install Snapcraft, see [Install snapd](https://snapcraft.io/docs/installing-snapd) on the Snapcraft website for details. + +1. At the command line, execute the following command: + +> ``` sh +> sudo snap install mattermost-desktop +> ``` + +2. Run Mattermost as a desktop app. + + + +You can review the current version of your desktop app by selecting the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top left corner of the desktop app, then selecting **Help \> Version...**. + + + +
+ +
+ +CentOS/RHEL + +Beta `.rpm` packages are available for CentOS and RHEL 7 and 8. Automatic app updates aren't supported. You must update your app manually. + +## Install the Mattermost desktop app + +1. Download the latest version of the Mattermost desktop app for 64-bit systems: [mattermost-desktop-6.1.2-linux-x86_64.rpm](https://releases.mattermost.com/desktop/6.1.2/mattermost-desktop-6.1.2-linux-x86_64.rpm) +2. At the command line, execute the following command: + +> ``` sh +> sudo rpm -i mattermost-desktop-6.1.2-linux-x86_64.rpm +> ``` + +3. Run Mattermost as a desktop app. + +To manually update the desktop app, run the following command: + +> ``` sh +> sudo rpm -u mattermost-desktop-6.1.2-linux-x86_64.rpm +> ``` + + + +You can review the current version of your desktop app by selecting the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top left corner of the desktop app, then selecting **Help \> Version...**. + + + +
+ +
+ +Flatpak + +From Mattermost Desktop v6.1, Flatpak packages are available for Linux systems. Flatpak is a universal Linux package format that provides a sandboxed environment and includes runtime dependencies. The Flatpak version is currently in **beta**. + + + +Flatpak requires the Flatpak runtime to be installed on your system. The Mattermost Desktop Flatpak package uses Freedesktop Platform/SDK 25.08 and Electron BaseApp 25.08. Wayland display server support is enabled by default. + + + +## Available architectures + +Flatpak packages are available for: + +- **x86_64** (Intel/AMD 64-bit processors) +- **aarch64** (ARM 64-bit processors) + +## Install Flatpak + +1. Ensure Flatpak is installed on your system. If not, see the [Flatpak setup guide](https://flatpak.org/setup/) for your distribution. +2. Download the latest Mattermost Desktop Flatpak package for your architecture from the [Desktop App's Github releases page](https://github.com/mattermost/desktop/releases): + - For x86_64: `mattermost-desktop-{VERSION}-linux-x86_64.flatpak` + - For aarch64: `mattermost-desktop-{VERSION}-linux-aarch64.flatpak` +3. Install the Flatpak package: + +> ``` sh +> flatpak install mattermost-desktop-{VERSION}-linux-{ARCH}.flatpak +> +> Replace ``{VERSION}`` with the version number (e.g., ``6.1.2``) and ``{ARCH}`` with your architecture (``x86_64`` or ``aarch64``). +> ``` + +4. Run Mattermost as a desktop app: + +> ``` sh +> flatpak run com.mattermost.Desktop +> ``` + +## Considerations + +- The Flatpak version runs in a sandboxed environment, which may affect certain integrations or file access patterns. +- Automatic app updates are handled through the Flatpak update mechanism. +- The application requires access to Flathub or a compatible Flatpak repository for runtime dependencies. + + + +You can review the current version of your desktop app by selecting the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top left corner of the desktop app, then selecting **Help \> Version...**. + + + +
+ +
+ +Generic Linux + +The Desktop app is available in two formats which are usable on most Linux distributions: a compressed tarball, and an AppImage binary. Both can be downloaded from the [Desktop App's Github releases page](https://github.com/mattermost/desktop/releases). Automatic app updates are supported and enabled on AppImage binary builds. When a new version of the desktop app is released, your app updates automatically. + +For instructions on how to use the AppImage binary, please refer to the [AppImage Quickstart documentation page](https://docs.appimage.org/introduction/quickstart.html). + +## Install the Desktop App's compressed tarball + +1. Download the latest version of the Mattermost desktop app for 64-bit systems: [mattermost-desktop-6.1.2-linux-x64.tar.gz](https://releases.mattermost.com/desktop/6.1.2/mattermost-desktop-6.1.2-linux-x64.tar.gz) +2. Extract the archive to a convenient location, then give `chrome-sandbox` in the extracted directory the required ownership and permissions: `sudo chown root:root chrome-sandbox && sudo chmod 4755 chrome-sandbox` +3. Execute `mattermost-desktop` located inside the extracted directory. +4. To create a Desktop launcher, open the file `README.md`, and follow the instructions in the **Desktop launcher** section. + +
diff --git a/docs/main/deployment-guide/desktop/silent-windows-desktop-distribution.mdx b/docs/main/deployment-guide/desktop/silent-windows-desktop-distribution.mdx new file mode 100644 index 000000000000..eb6d1fb19a15 --- /dev/null +++ b/docs/main/deployment-guide/desktop/silent-windows-desktop-distribution.mdx @@ -0,0 +1,116 @@ +--- +title: "Silent Windows desktop distribution" +--- + + +You can distribute the official Windows desktop app silently to end users using the MSI installer, pre-configured with server URLs and settings. For comprehensive MSI installation options including Group Policy configuration, see the [MSI installer and Group Policy guide](/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install). + +## Silent MSI installation + +1. Download the latest Windows MSI installer from the [Mattermost Desktop releases page on GitHub](https://github.com/mattermost/desktop/releases/latest). + +2. Move the MSI file to a shared location such as a file server with read-only permissions. + +3. Use your software deployment tool (SCCM, Intune, PDQ Deploy, etc.) to deploy the MSI with silent installation parameters: + + **Silent install:** + + ``` text + msiexec /i \\SERVER\shared_folder\mattermost-desktop-v6.1.0-x64.msi /qn + ``` + +## Pre-configuration with config.json + +To pre-configure servers and settings, create a `config.json` file in the user's Mattermost data directory before first launch: + +**Location**: `%APPDATA%\Mattermost\config.json` + +**Example config.json**: + +``` json +{ + "version": 2, + "teams": [ + { + "name": "core", + "url": "https://community.mattermost.com", + "order": 0 + }, + { + "name": "hq", + "url": "https://hq.example.com", + "order": 1 + } + ], + "showTrayIcon": true, + "trayIconTheme": "light", + "minimizeToTray": true, + "notifications": { + "flashWindow": 2, + "bounceIcon": true, + "bounceIconType": "informational" + }, + "showUnreadBadge": true, + "useSpellChecker": true, + "enableHardwareAcceleration": true, + "autostart": false, + "spellCheckerLocale": "en-US", + "darkMode": false +} +``` + +**Batch script for silent install with pre-configuration:** + +``` batch +rem Install Mattermost desktop app silently +msiexec /i \\SERVER\shared_folder\mattermost-desktop-v6.1.0-x64.msi /qn + +rem Wait for installation to complete +timeout /t 10 + +rem Create config directory if it doesn't exist +if not exist "%APPDATA%\Mattermost" mkdir %APPDATA%\Mattermost + +rem Copy pre-configured config.json +copy \\SERVER\shared_folder\config.json %APPDATA%\Mattermost\config.json +``` + +## Windows App: Silently removing the app + +The MSI installer can be silently uninstalled using: + +``` text +msiexec /x {PRODUCT-CODE-GUID} /qn +``` + +To find the product code for your installed version: + +``` powershell +Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "*Mattermost*"} | Select-Object Name, IdentifyingNumber +``` + +Alternatively, uninstall by searching for the MSI file: + +``` text +msiexec /x mattermost-desktop-v6.1.0-x64.msi /qn +``` + +## Migration from EXE to MSI + +Organizations currently using the Windows EXE installer must migrate to the MSI installer or Microsoft Store version: + +1. **Uninstall existing EXE version** (if desired, optional): + + ``` text + %userprofile%\AppData\local\Programs\mattermost-desktop\Uninstall Mattermost.exe /currentuser /S + ``` + +2. **Install MSI version** using silent installation commands above. + +3. **User data preservation**: User settings and credentials are stored in `%APPDATA%\Mattermost` and will be preserved across the migration. + + + +The EXE installer will not receive v6.1.0 or later updates. Plan your migration accordingly. + + diff --git a/docs/main/deployment-guide/disaster-recovery-aws.mdx b/docs/main/deployment-guide/disaster-recovery-aws.mdx new file mode 100644 index 000000000000..a7f59ffbd8d7 --- /dev/null +++ b/docs/main/deployment-guide/disaster-recovery-aws.mdx @@ -0,0 +1,375 @@ +--- +title: "Active/passive DR deployment on AWS" +--- + + +Before you begin, ensure the following are in place: + +- AWS account access with IAM permissions to manage RDS, S3, and OpenSearch resources in both regions +- A chosen primary and secondary AWS region pair for failover +- An existing, healthy Mattermost primary deployment +- DNS control over the domain used to reach Mattermost, so you can redirect traffic during failover +- Required RDS Aurora PostgreSQL global cluster permissions and a verified, restorable database backup +- OpenSearch 2.x with fine-grained access control available in both regions +- Network connectivity between the primary and secondary regions confirmed + +Enterprise customers who use Mattermost for mission-critical operations must ensure continuous availability and operational resilience. A robust disaster recovery strategy is essential to mitigate risks associated with data center failures, ensuring that users can access Mattermost seamlessly, even in the event of unexpected outages. + +This page details the steps needed to set up Mattermost in an active/passive disaster recovery configuration on AWS, and how to fail over from one data center to another. + + + +To learn how to safely upgrade your deployment in Kubernetes for High Availability and Active/Active support, see the [Upgrading Mattermost in Kubernetes and High Availability Environments](/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha) documentation. + + + +## Set up in one data center + +As a first step, set up Mattermost in a single data center. The following diagram illustrates a basic single data center architecture: + +![An architecture diagram showing a single proxy that's forwarding traffic to 2 nodes, a database with single writer + n readers, and an S3 bucket and ES/OS using AWS OpenSearch service.](/images/dr1.png) + +The diagram above has a single proxy, forwarding traffic to 2 nodes. There's also a database with single writer + n readers and an S3 bucket and ES/OS using AWS OpenSearch service. + +At this stage, we are ignoring other details like LDAP/SAML, SMTP etc. + + + +The following architecture would be implemented when an entire region goes down. It does not cover the case when a single server/service goes down. For example: + +- If a single app node goes down, follow best practices to provision a new node. +- If a database replica node goes down, create a new replica from AWS console. Or set a policy to do so automatically. + + + +## Replicate database + +The next tasks include creating a global AWS Cluster. + +1. Select the RDS instance in the AWS Console, and expand the **Actions** menu to select **Add AWS Region**. +2. Choose the secondary region and enter the other details. + + + +Select the **Enable write forwarding** option on the secondary cluster to help forward write operations from secondary to primary. See the [AmazonRDS write forwarding](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database-write-forwarding-apg.html#aurora-global-database-write-forwarding-enabling-apg) documentation for details. + +Also verify the PostgreSQL version and ensure it allows `write forwarding`. Not all PostgreSQL versions allow it. See the [Amazon RDS write forwarding region and version availability](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database-write-forwarding-apg.html#aurora-global-database-write-forwarding-regions-versions-apg) documentation for details. + + + +You should now have a global cluster with the primary cluster in `us-west-1`, and the secondary cluster in `us-east-1`: + +![A screenshot of the AWS console with a global RDS cluster where the primary cluster is us-west-1 and the secondary cluster is us-east-1.](/images/dr2.png) + +## Replicate S3 bucket + +1. Create a new S3 bucket in the secondary region. +2. Back in the original bucket, go to the **Properties** tab, and enable **Bucket versioning**. +3. Go to the **Management** tab, scroll down to **Replication Rules**, and create a new replication rule. +4. In the rule, select the source bucket, and then choose **Apply to all objects in the bucket** to replicate everything in the bucket. +5. Choose the destination bucket. +6. For the IAM role, select **Create new role**. + + + +Select the **Replica modification sync** option for the bucket to help keep the replica and source buckets in sync with each other. + + + +7. Select **Save**. +8. Select **Yes** when prompted to start a job to replicate any existing objects to the secondary bucket or not. +9. Perform these same steps on the secondary bucket. + +Now you have bi-directional replication working between these S3 replica and source buckets. + +## Replicate ES/OS storage + +1. To replicate ES/OS storage, set up CCR (cross-cluster replication) for AWS OpenSearch with the following requirements: + +> - Elasticsearch 7.10 or OpenSearch 2.x +> - Fine-grained access control enabled +> - Node-to-node encryption enabled + + + +If you are already running OpenSearch 2.x, all you need to do is enable fine-grained access control — node-to-node encryption is enabled automatically once fine-grained access control is turned on. + + + +2. You also need to add the `CrossClusterGet` permission on the IAM policy for the OS cluster set under the **Security Configuration** tab for your OS domain. We recommend the following as per AWS, but feel free to fine-tune as necessary: + +> ``` json +> { +> "Version": "2012-10-17", +> "Statement": [ +> { +> "Effect": "Allow", +> "Principal": { +> "AWS": "*" +> }, +> "Action": "es:ESHttp*", +> "Resource": "arn:aws:es:<region>::domain//*" +> }, +> { +> "Effect": "Allow", +> "Principal": { +> "AWS": "*" +> }, +> "Action": "es:ESCrossClusterGet", +> "Resource": "arn:aws:es:<region>::domain/" +> } +> ] +> } +> ``` + +To recap: + +- Use OpenSearch 2.x. +- Enable fine-grained access control. +- Create the master user, and note the server credentials. +- Set the IAM policy as above. + + + +After creating the master user, IP based access to the OS might not work from Mattermost application nodes. You may need to update the `ElasticsearchSettings` section in `config.json` to update the server [username](/administration-guide/configure/environment-configuration-settings#server-username) and [password](/administration-guide/configure/environment-configuration-settings#server-password). + + + +3. Create a new OS cluster in the secondary region. Follow the same steps again for this cluster. + +>
+> +>
+> +> Warning +> +>
+> +> At this stage, ensure that you have all indices populated with data in the primary region. Run a bulk index to do that if you haven't already. +> +>
+ +4. Begin replication from the primary to secondary region. + +> 1. First, create a connection from secondary to primary. Note that replication in OS works in a "pull" model, so the secondary site pulls data from the primary. +> 2. In the Amazon OpenSearch Service console, select the secondary domain, go to the **Connections** tab, and choose **Request**. +> 3. For **Connection alias**, enter a name for your connection. +> 4. Choose **connect to a domain in another AWS account or region**, and enter the **ARN** of the primary domain. +> 5. Select **Request** to send a permission request to the primary domain. +> 6. Open the primary domain to see and accept the incoming request under the **Connections** tab. + +5. Now set up the replication rules for indices. + +> 1. SSH into an app node in the secondary region to set up an auto-follow rule for the `posts*` indices because of the daily naming scheme and monthly aggregation. +> 2. For the other indices, replicate each of them. You can also set up a rule with `*` to replicate everything, but that would also include the hidden and system indices which you don't want. +> 3. Set up the auto-follow for `posts*` indices: +> +> > ``` sh +> > curl -XPOST -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/_autofollow?pretty' -d ' +> > { +> > "leader_alias" : "", +> > "name": "autofollow-rule", +> > "pattern": "posts*", +> > "use_roles":{ +> > "leader_cluster_role": "all_access", +> > "follower_cluster_role": "all_access" +> > } +> > }' +> > ``` +> +> 4. Check the status of the auto-follow rule: +> +> > ``` sh +> > curl -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/autofollow_stats?pretty' +> > { +> > "num_success_start_replication" : 2, +> > "num_failed_start_replication" : 0, +> > "num_failed_leader_calls" : 0, +> > "failed_indices" : [ ], +> > "autofollow_stats" : [ +> > { +> > "name" : "autofollow-rule", +> > "pattern" : "posts*", +> > "num_success_start_replication" : 2, +> > "num_failed_start_replication" : 0, +> > "num_failed_leader_calls" : 0, +> > "failed_indices" : [ ], +> > "last_execution_time" : 1737699113927 +> > } +> > ] +> > } +> > ``` +> +> 5. Next, set up replication for the other indices: +> +> > ``` sh +> > curl -XPUT -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/channels/_start?pretty' -d ' +> > { +> > "leader_alias": "", +> > "leader_index": "channels", +> > "use_roles":{ +> > "leader_cluster_role": "all_access", +> > "follower_cluster_role": "all_access" +> > } +> > }' +> > +> > curl -XPUT -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/users/_start?pretty' -d ' +> > { +> > "leader_alias": "", +> > "leader_index": "users", +> > "use_roles":{ +> > "leader_cluster_role": "all_access", +> > "follower_cluster_role": "all_access" +> > } +> > }' +> > +> > curl -XPUT -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/files/_start?pretty' -d ' +> > { +> > "leader_alias": "", +> > "leader_index": "files", +> > "use_roles":{ +> > "leader_cluster_role": "all_access", +> > "follower_cluster_role": "all_access" +> > } +> > }' +> > ``` +> +> 6. Check the status of the replication rules: +> +> > ``` sh +> > curl -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/channels/_status?pretty' +> > curl -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/files/_status?pretty' +> > curl -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/users/_status?pretty' +> > curl -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/posts_/_status?pretty' +> > Sample output: +> > { +> > "status" : "SYNCING", +> > "reason" : "User initiated", +> > "leader_alias" : "", +> > "leader_index" : "", +> > "follower_index" : "", +> > "syncing_details" : { +> > "leader_checkpoint" : 16, +> > "follower_checkpoint" : 16, +> > "seq_no" : 17 +> > } +> > } +> > ``` +> +> 7. Check for indices. You should be able to see all the indices from the primary domain in the secondary domain: +> +> > ``` sh +> > curl -s -u ':' 'https:///_cat/indices?pretty' +> > ``` + +## Replicate job servers + +If the job scheduler is left running in the secondary region, it will pick up jobs and start running them. Follow these steps to manage it correctly. See the [RunScheduler configuration setting](/administration-guide/configure/environment-configuration-settings#run-scheduler) documentation for details. + +1. **Precondition:** Set `JobSettings.RunScheduler` to `false` on all nodes in the secondary region before enabling that region. +2. **On failover:** Set `JobSettings.RunScheduler` to `true` on all nodes in the new primary region. +3. **Immediately after:** Set `JobSettings.RunScheduler` to `false` on all nodes in the new secondary region. +4. **Verify:** Confirm that jobs execute only in the active region. Submit a test job (for example, trigger an index rebuild) and check the job logs to ensure it runs on the new primary, not the secondary. + +## Test the secondary region + +With the above steps complete, you have a fully functioning secondary region. You can replicate the same setup of nodes and a proxy server like the primary region. The app nodes in the secondary region won't be able to come up the first time because Mattermost will try to run some DDL statements which are not allowed with write-forwarding. So it will be stuck in a loop trying to connect. Once you fail over the region, it will start working. The primary region will still be readable, and any periodic writes will be forwarded to the secondary (now primary). + + + +Ensure you have separate `ClusterNames` for the different clusters in two regions to use the same database across 2 clusters. + + + +## Failover RDS to secondary + +To perform the failover, go to the RDS global cluster, and under **Actions**, select **Switchover or Failover global database**, and then select **switchover** to switch over without any data loss (which will take more time to complete). Alternatively, you can choose **failover** for a quicker failover at the expense of data-loss. If the entire region is unavailable anyways, then **failover** is no worse than **switchover**. + +After this is done, the app nodes which were stuck trying to connect should move forward and everything should be functional. You can read/write, upload images and everything should be replicated. Everything except OpenSearch data. + +## Failover ES/OS to secondary + +ES/OS does not allow multi-writer for a single index. You can only write to 1 index at one time. Therefore, you need to perform some manual steps to reverse the replication direction, and start replicating from secondary to primary. + +For simplicity, let's say `site1` is primary, and `site2` is secondary. Therefore, OS in `site1` is the leader domain, and in `site2` is the follower. The follower pulls from the leader. To switch the direction where `site2` becomes leader, and `site1` becomes follower. + +1. Remove the rule from `site1` \> `site2` in AWS Console. This will auto-pause the replication, but the indices in `site2` will still be read-only. Remove the replication rules for that. +2. Remove auto-follow rule: + +> ``` sh +> curl -XDELETE -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/_autofollow?pretty' -d ' +> { +> "leader_alias" : "", +> "name": "autofollow-rule" +> }' +> ``` + +3. Check the status of the auto-follow rule as mentioned before. +4. Remove replication rules: + +> ``` sh +> curl -XPOST -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/channels/_stop?pretty' -d '{}' +> curl -XPOST -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/files/_stop?pretty' -d '{}' +> curl -XPOST -H 'Content-Type: application/json' -u ':' 'https:///_plugins/_replication/users/_stop?pretty' -d '{}' +> ``` + +5. Check the status of replication rules as mentioned before. +6. Now indices will become writable +7. Add rule from `site2` \> `site1` in AWS console. +8. In `site1`, make all the indices as followers. You must delete all indices first: + +> ``` sh +> curl -XDELETE -u ':' 'https:///posts*?pretty' +> curl -XDELETE -u ':' 'https:///channels?pretty' +> curl -XDELETE -u ':' 'https:///files?pretty' +> curl -XDELETE -u ':' 'https:///users?pretty' +> ``` + +9. Refresh indices: + +> ``` sh +> curl -XPOST -u ':' 'https:///_refresh?pretty' +> ``` + +10. Confirm that everything is deleted: + +> ``` sh +> curl -s -u ':' 'https:///_cat/indices?pretty' +> ``` + +11. Add the auto-follow rule add replication rules. Follow the same steps as before. +12. List the indices again to confirm that replication has started and indices are available. + + + +There's nothing you need to do to ensure the S3 bucket is auto-replicating both ways. + + + +## Testing end to end + +Once the failover has happened, and the ES/OS replication direction has been swapped, the new site can be used normally. + +This becomes the final architecture: + +![A diagram showing the final architecture with Mattermost set up in 2 data centers.](/images/dr3.png) + +You can use DNS to easily switch between PRIMARY to SECONDARY during a failover. + + + +Websockets will still point to the old data center even if you have switched DNS. You need to roll over each app node gradually to move those connections to the new data center. If all your nodes are down, no action is necessary and the clients will automatically re-connect to the new data center. + + + +The S3 bucket is replicated bi-directionally while the database and ES/OS is replicated uni-directionally. + +## Restore to primary data center + +When the disaster event is resolved and you are ready to restore normal operations, perform the same failover steps in reverse to return traffic to the original primary data center: + +1. Perform an RDS switchover back to the original primary region using the **Switchover or Failover global database** option in the RDS console. +2. Reverse the ES/OS replication direction by following the same steps in the [Failover ES/OS to secondary](#failover-esos-to-secondary) section, swapping the roles of `site1` and `site2`. +3. Update DNS to redirect traffic back to the original primary data center. +4. Re-enable `JobSettings.RunScheduler` on the original primary nodes and disable it on the secondary nodes. +5. Roll over app nodes gradually to move websocket connections back to the primary data center. diff --git a/docs/main/deployment-guide/encryption-options.mdx b/docs/main/deployment-guide/encryption-options.mdx new file mode 100644 index 000000000000..a5320d3cf5cf --- /dev/null +++ b/docs/main/deployment-guide/encryption-options.mdx @@ -0,0 +1,56 @@ +--- +title: "Encryption options" +--- + + +Mattermost provides encryption-in-transit and encryption-at-rest capabilities. This page guides you through setting up appropriate encryption security. + +Encryption is not required for GDPR, although it can be used as an additional safeguard against data breach. + +## Encryption-in-transit + +Mattermost supports TLS encryption including AES-256 with 2048-bit RSA on all data transmissions between Mattermost client applications and the Mattermost server. You may either set up TLS on the Mattermost Server or install a proxy such as NGINX and set up TLS on the proxy. Refer to our [configuration guide for more details](/deployment-guide/server/setup-tls). + +Connections to Active Directory/LDAP can [optionally be secured with TLS or stunnel](/administration-guide/configure/authentication-configuration-settings#ad-ldap-port). + +Connections to calls are secured with a combination of: + +> - TLS: The existing WebSocket channel is used to secure the signaling path. +> - DTLS v1.2 (mandatory): Used for initial key exchange. Supports `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` and `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA` algorithms. +> - SRTP (mandatory): Used to encrypt all media packets (i.e. those containing voice or screen share). Supports `AEAD_AES_128_GCM` and `AES128_CM_HMAC_SHA1_80` algorithms. + +## Gossip encryption + +In a High Availability mode, Mattermost supports encryption of cluster data in-transit when using the gossip protocol, which is based on principles outlined in the [SWIM protocol developed by researchers at Cornell University](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf). The gossip protocol is a communication mechanism in distributed systems where nodes randomly exchange information to ensure data consistency across the network. It is decentralized, scalable, and fault-tolerant, making it ideal for systems with numerous nodes. Information is spread in a manner similar to social gossip, with nodes periodically "gossiping" updates to random peers until the network converges to a consistent state. Widely used in distributed databases, blockchain networks, and peer-to-peer systems, the protocol is simple to implement and resilient to node failures. However, it can suffer from redundancy and propagation delays in large networks. + +From Mattermost v10.11, [gossip encryption](/administration-guide/configure/environment-configuration-settings#enable-gossip-encryption) is enabled by default for new deployments while existing deployments maintain their current configuration. + +The encryption uses AES-256 by default, and it is not configurable. However, it is possible to manually set the value in the `Systems` table for the `ClusterEncryptionKey` row. A key is a byte array converted to base64. It can be set to a length of 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 respectively. + +## Encryption-at-rest + +Encryption-at-rest is available for messages via hardware and software disk encryption solutions applied to the Mattermost database, which resides on its own server within your infrastructure. To enable end user search and compliance reporting of message histories, Mattermost does not offer encryption within the database. + +Both the database and file storage can be secured using software or hardware disk encryption solutions. Full-disk encryption methods such as LUKS (Linux), BitLocker (Windows), or database-specific solutions like Transparent Data Encryption (TDE) can be employed. Integration with external encrypted storage systems is supported. + +Additionally, encryption-at-rest is available for files stored via hardware and software disk encryption solutions applied to the server used for local/network storage or S3-compatible storage. + +### Database + +See the [PostgreSQL](https://www.postgresql.org/docs/10/encryption-options.html) database documentation for details on encryption options at the disk level. + +### File storage + +For local storage, NFS, or S3-compatible storage, encryption-at-rest is available for files stored via hardware and software disk encryption solutions applied to the server. + +For Amazon’s proprietary S3 system, encryption-at-rest is available via [server-side encryption with Amazon S3-managed keys](/administration-guide/configure/environment-configuration-settings#enable-server-side-encryption-for-amazon-s3) in Mattermost enterprise-badge. + +## SAML encryption support + +Mattermost supports the following encryption methods for SAML: + +- aes128-gcm +- aes192-gcm +- aes256-gcm +- aes128-cbc +- aes256-cbc diff --git a/docs/main/deployment-guide/manual-postgres-migration.mdx b/docs/main/deployment-guide/manual-postgres-migration.mdx new file mode 100644 index 000000000000..7c0c94c4b5ab --- /dev/null +++ b/docs/main/deployment-guide/manual-postgres-migration.mdx @@ -0,0 +1,802 @@ +--- +title: "Manually migrate from MySQL to PostgreSQL" +--- + + +Migrating a MySQL database to PostgreSQL manually involves the following steps: + +- [install recommended tools](#tool-recommendations) +- [familiarize yourself with system requirements and configurations](#system-requirements-and-configurations-for-manual-migrations) +- [ensure migration prerequisites are met](#before-a-manual-migration) +- [review schema differences](#schema-diffs) +- [prepare a target database](#prepare-target-database) +- [migrate the data](#migrate-the-data) +- [complete post-migration wrap-up activities](#after-the-migration) + + + +See the [plugin migrations](#plugin-migrations) section for details on migrating collaborative playbooks and Boards. + + + +Not sure upgrading manually is the right path forward? Mattermost customers looking for tailored guidance based on their Mattermost deployment can contact a [Mattermost Expert](https://mattermost.com/contact-sales/). + +## Tool recommendations + +If you prefer to migrate to Postgres manually, we recommend the following tools for the migration process: + +- [pgloader](#pgloader) +- [morph](#morph) +- [dbcmp (optional)](#dbcmp-optional) + +This page includes instructions on how to install each of these tools, and then proceed with the database migration. + +Once you've installed the necessary tools, review the [system requirements and configurations](#system-requirements-and-configurations) documentation, and know what's required [before starting your migration](#before-the-migration) to prepare for your migration. + +Start your migration by [preparing your target database](#prepare-target-database), then [migrate the data](#migrate-the-data), and complete all [post-migration steps](#after-the-migration). + +See the [plugin migrations](#plugin-migrations) documentation for details on migrating collaborative playbooks and boards. + +### pgloader + +Use the `pgloader` tool to migrate your data from MySQL to PostgreSQL. + +#### Install pgloader + +To install `pgloader`, see the official [installation guide](https://pgloader.readthedocs.io/en/latest/install.html). + + + +If you are using MySQL v8: Due to a [known bug](https://github.com/dimitri/pgloader/issues/1183) in pgloader-compiled binaries, you need to compile pgloader from the source. Please follow the steps [here](https://pgloader.readthedocs.io/en/latest/install.html#build-from-sources) to build from the source. + + + +Alternatively, you may want to use our `mattermost-pgloader` Docker image to avoid installing or building `pgloader`. See the documentation below for details. + +#### Use pgloader + +##### Pull the Docker image and verify pgloader + +For a manual migration, run the following command to pull the `mattermost-pgloader` image and verify that pgloader is working correctly: + +``` sh +docker run -it --rm -v $(pwd):/home/migration mattermost/mattermost-pgloader:latest pgloader --version +``` + +This command pulls the `mattermost/mattermost-pgloader:latest` image and runs `pgloader` to check its version and ensure it works as expected. + +##### Map local directory + +Use the `-v $(pwd):/home/migration` flag to map your current working directory to the Docker container. This allows you to use your local directory for storing logs and other files. + +##### Set network configuration + +Depending on your network requirements, set the `--network` flag accordingly. For example, to access localhost, you need to set the network to `host`. + +### morph + +The `morph` tool creates the PostgreSQL schema. + + + +Both `morph` and `dbcmp` requires Go toolchain. To install Go compiler, follow the [Go documentation](https://go.dev/doc/install). + + + +#### Install morph + +You can install morph CLI by running the following command: + +``` sh +go install github.com/mattermost/morph/cmd/morph@v1 +``` + +### dbcmp (Optional) + +The `dbcmp` tool enables you to compare the data following the migration by comparing every table and reporting whether there is a diversion between two schemas. + +#### Install dbcmp + +You can install [dbcmp](https://github.com/mattermost/dbcmp) by running the following command: + +``` sh +go install github.com/mattermost/dbcmp/cmd/dbcmp@latest +``` + +## System requirements and configurations for manual migrations + +Before starting a manual migration process, it's essential to ensure that your system meets the necessary requirements for a smooth and efficient migration. We strongly recommend the following system specifications and adjustments: + +- Ensure you have enough system memory resources. 16GB of RAM is recommended as a default. In scenarios where system memory is insufficient, users can fine-tune pgloader settings, such as the `number of workers`, `prefetch rows`, and especially `rows per range` if `concurrency` is set above `1`. These adjustments can help optimize resource utilization based on available system resources. For further detail see [pgloader documentation](https://pgloader.readthedocs.io/en/latest/batches.html). +- A multi-core processor with sufficient processing power is recommended for the migration process, especially when dealing with large datasets. +- Ensure that there is enough disk space available for storing both the MySQL and PostgreSQL databases, as well as any temporary files generated during the migration process. The amount of required disk space depends on the size of the databases being migrated. +- To reduce migration time further, users may choose to manually drop indexes on the target PostgreSQL database before initiating the migration process. This approach can potentially accelerate the migration by reducing overhead with index builds during data insertion. + +### Before a manual migration + + + +This guide requires a schema of v7.1 ESR or later. So, if you have an earlier version and planning to migrate, please update your Mattermost Server to v7.1 at a minimum. See the [extended support releases](/product-overview/release-policy#extended-support-releases) documentation for details. + +- Back up your MySQL data. +- Confirm your Mattermost version. See the **About** modal for details. +- Schedule the migration window. This process requires you to stop the Mattermost Server during the migration. +- See the [schema-diffs](#schema-diffs) section to ensure data compatibility between schemas. +- Prepare your PostgreSQL environment by creating a database and user. See the [database](/deployment-guide/server/preparations) documentation for details. +- On [newer versions](https://www.postgresql.org/docs/release/15.0/) of PostgreSQL, newly created users do not have access to `public` schema. The access should be explicitly granted by running `GRANT ALL ON SCHEMA public to mmuser`. + + + +### Schema diffs + +Before the manual migration, due to differences between the two schemas, some manual steps may be required for an error-free migration. + +#### Text to character varying + +We encourage you to check if the sizes are consistent within the PostgreSQL schema limits since the Mattermost MySQL schema uses the `text` column type in the various tables instead of `varchar` representation in the PostgreSQL schema. + +You can check if there are any required deletions or updates. For example, to do so in the `Audits` table/`Action` column; run: + +``` sql +SELECT FROM mattermost.Audits where LENGTH(Action) > 512; +``` + +The following table shows the deletions or updates you can proceed with that don't incur further consequences. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TableColumnData type castingConsequence on deletion
AuditsActiontext -> varchar(512)No side effect on how the application works (The affected row needs to be deleted).
AuditsExtraInfotext -> varchar(1024)No side effect on how the application works (The affected row needs to be deleted).
ClusterDiscoveryHostNametext -> varchar(512)No side effect on how the application works (The affected row needs to be deleted).
CommandsIconURLtext -> varchar(1024)The field can be deleted or updated with a new URL.
CommandsAutoCompleteDesctext -> varchar(1024)The field can be deleted or rewritten.
CommandsAutoCompleteHinttext -> varchar(1024)The field can be deleted or rewritten.
RemoteClustersTopicstext -> varchar(512)The field can be removed.
SystemsValuetext -> varchar(1024)Edge case, ideally should never happen.
+ +The following table shows several occurrences where the schema can differ and data size constraints within the PostgreSQL schema can result in errors. Each table/row requires individual inspection hence we added the possible consequence of deletion. + + + +Several reports have been received from our community that the `LinkMetadata` and `FileInfo` tables had some overflows, so we recommend checking these tables in particular. Please check if your data in the MySQL schema exceeds these limitations. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TableColumnData type castingConsequence on deletion
CompliancesKeywordstext -> varchar(512)The filter for compliance needs to be updated.
CompliancesEmailstext -> varchar(1024)The filter for compliance needs to be updated.
FileInfoPathtext -> varchar(512)Previous links to this file won't work (The affected row needs to be deleted).
FileInfoThumbnailPathtext -> varchar(512)Previous links to this file won't work (The affected row needs to be deleted).
FileInfoPreviewPathtext -> varchar(512)Previous links to this file won't work (The affected row needs to be deleted).
FileInfoNametext -> varchar(256)Previous links to this file won't work (The affected row needs to be deleted).
FileInfoMimeTypetext -> varchar(256)Previous links to this file won't work (The affected row needs to be deleted).
LinkMetadataURLtext -> varchar(2048)Previous links to this file won't work (The affected row needs to be deleted).
RemoteClustersSiteURLtext -> varchar(512)Previous remote cluster will be removed (The affected row needs to be deleted).
SessionsDeviceIdtext -> varchar(512)Users will be logged out on these devices (The affected row needs to be deleted).
UploadSessionsFileNametext -> varchar(256)The upload session will be lost (The affected row needs to be deleted).
UploadSessionsPathtext -> varchar(512)The upload session will be lost (The affected row needs to be deleted).
+ +#### Full-text indexes + +It's possible that some words in the `Posts` and `FileInfo` tables can exceed the [limits of the maximum token length](https://www.postgresql.org/docs/11/textsearch-limitations.html) for full-text search indexing. In these cases, we are dropping the `idx_posts_message_txt` and `idx_fileinfo_content_txt` indexes from the PostgreSQL schema, and creating these indexes after the migration by running the following queries: + +To prevent errors during the migration, we have included following queries: + +``` text +DROP INDEX IF EXISTS {{ .source_db }}.idx_posts_message_txt; +DROP INDEX IF EXISTS {{ .source_db }}.idx_fileinfo_content_txt; +``` + +#### Unsupported unicode sequences + +There is a specific unicode sequence that is [disallowed](https://www.postgresql.org/docs/16/datatype-json.html#DATATYPE-JSON) in PostgreSQL which is `\u0000`. There is a chance that this sequence may appear in several rows across a bunch of tables in your MySQL database. If it is the case, during the migration you will likely receive an error as following: `unsupported Unicode escape sequence: \u0000 cannot be converted to text.`. To prevent this from happening, we advise to sanitize your data before starting to the migration. You can use the following query to replace `\u0000` sequence with empty string. + + + +You can use this query as-is in a script, or you may need to set the delimiter to something else (e.g., `DELIMITER //`) when defining it in the MySQL console. Once you are done defining the procedure, please set the delimiter back to the original (i.e., `DELIMITER ;`). + + + +``` text +CREATE PROCEDURE SanitizeUnsupportedUnicode() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE curTableName text; + DECLARE curColumnName text; + DECLARE cursors CURSOR FOR + SELECT table_name, column_name + FROM information_schema.COLUMNS + WHERE data_type = 'json' + AND table_schema = DATABASE(); +DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + +OPEN cursors; + +WHILE NOT DONE DO + FETCH cursors INTO curTableName, curColumnName; + SET @query_string = CONCAT('UPDATE ', curTableName, ' SET ', curColumnName, ' = REPLACE(', curColumnName, ', \'\\\\u0000\', \'\') WHERE ', curColumnName, ' LIKE \'%\\u0000%\';'); + + PREPARE dynamic_query FROM @query_string; + EXECUTE dynamic_query; + DEALLOCATE PREPARE dynamic_query; +END WHILE; + +CLOSE cursors; +END; + +CALL SanitizeUnsupportedUnicode(); + +DROP PROCEDURE IF EXISTS SanitizeUnsupportedUnicode; +``` + + + +There is also a specific byte sequence value that is not allowed and will cause an `invalid byte sequence for encoding 'UTF8': 0x00"` error during the migration. To prevent this error, you can add the `remove-null-characters` clause to the text casting rules. However, since pgloader will modify the data on the fly, there may be differences between the tables (if any are affected) during the comparison phase. + + + +#### Artifacts may remain from previous configurations/versions + +Prior to `v6.4`, Mattermost was using [golang-migrate](https://github.com/golang-migrate/migrate) to handle the schema migrations. Since we don't use it anymore, we exclude the table `schema_migrations`. If you were using Mattermost before `v6.4` consider dropping this table and excluding it from comparison as well. + +``` sql +DROP TABLE mattermost.schema_migrations; +``` + +Some community members have reported that they had `description` and `nextsyncat` columns in their `SharedChannelRemotes` table. These columns should be removed from the table. Consider running the following DDL to drop the columns. (This migration will be added to future versions of Mattermost). + +``` sql +ALTER TABLE SharedChannelRemotes DROP COLUMN description, DROP COLUMN nextsyncat; +``` + +An error has been identified in the 96th migration that was previously released. Before proceeding with the migration, it is necessary to remove a specific column. To ensure the Threads table reaches the expected state, execute the following prepared statement: + +``` sql +SET @preparedStatement = (SELECT IF( + ( + SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Threads' + AND table_schema = DATABASE() + AND column_name = 'TeamId' + ) > 0, + 'ALTER TABLE Threads DROP COLUMN TeamId;', + 'SELECT 1' +)); + +PREPARE alterIfExists FROM @preparedStatement; +EXECUTE alterIfExists; +DEALLOCATE PREPARE alterIfExists; +``` + +#### Configuration in database + +If you were previously utilizing a database for handling the [Mattermost configuration](/administration-guide/configure/configuration-in-your-database), those tables will not be migrated from your MySQL database with the migration [script](#migrate-the-data). + +Two migrations are necessary: + +- migrate database configuration to the file system +- migrate file system configuration back to the database + +##### Migrate database configuration to the file system + +Use the `mmctl config migrate` command to [migrate your config](/administration-guide/manage/mmctl-command-line-tool#mmctl-config-migrate) to the file system, as follows: + +``` sh +mmctl config migrate ":@tcp(:3306)/?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s&multiStatements=true" /opt/mattermost/config/config.json --local +``` + +Where ``, ``, ``, and `` are replaced with your environment values. Ensure you use `--local` when running this command. The first parameters (``, ``) is the database the configuration is stored in, the second parameter (``, ``) is the file we are saving the configuration to. + +In the configuration file, update the `SqlSettings.DataSource` and `SqlSettings.DriverName` fields to reflect new changes. To do so, open the `json` file and change the respective fields. + +##### Migrate file system configuration back to the database + +To save configuration back to the database, Use the `mmctl config migrate` command again and reverse the parameters. Ensure you use the new database credentials moving it back to the target database. + +``` sql +SELECT * FROM Configurations WHERE Active = 't'; +``` + +You should update the `SqlSettings.DataSource` and `SqlSettings.DriverName` fields accordingly. Also, note that the `MM_CONFIG` environment variable should point to the new DSN after the migration is completed. + +## Prepare target database + +It is essential to create tables and indexes to ensure that the PostgreSQL database schema is properly structured according to the required specifications. Since Mattermost repository contains all of the required SQL queries to achieve that, we can leverage this by running the following steps: + +- Clone the `mattermost` repository for your specific version: + +``` sh +git clone -b git@github.com:mattermost/mattermost.git --depth=1 +``` + +- Run all schema migrations\* on your PostgreSQL database using morph CLI with the following command: + +``` sh +morph apply up --driver postgres --dsn "postgres://user:pass@localhost:5432/?sslmode=disable" --path ./mattermost/db/migrations/postgres --number -1 +``` + +\* After `v8`, due to project re-organization, the migrations directory has been changed to `./mattermost/server/channels/db/migrations/postgres/` relative to where you cloned Mattermost repository. Please set `--path` flag accordingly. + +## Migrate the data + +Once we set the schema to a desired state, we can start migrating the **data** by running `pgloader` + + + +In the example below, the hosts for both databases are assumed to be in the same instance. Please update addresses accordingly if they are on different machines. Also you can test the `.load` file by simply running `pgloader` with `--dry-run` flag. For instance `pgloader --dry-run migration.load` command. + + + +Use the following configuration for the baseline of the data migration: + +``` text +LOAD DATABASE + FROM mysql://{{ .mysql_user }}:{{ .mysql_password }}@{{ .mysql_address }}/{{ .source_db }} + INTO pgsql://{{ .pg_user }}:{{ .pg_password }}@{{ .postgres_address }}/{{ .target_db }} + +WITH data only, + workers = 8, concurrency = 1, + multiple readers per thread, rows per range = 10000, + prefetch rows = 10000, batch rows = 2500, + create no tables, create no indexes, + preserve index names + +SET PostgreSQL PARAMETERS + maintenance_work_mem to '128MB', + work_mem to '12MB' + +SET MySQL PARAMETERS + net_read_timeout = '120', + net_write_timeout = '120' + +CAST column Channels.Type to "channel_type" drop typemod, + column Teams.Type to "team_type" drop typemod, + column UploadSessions.Type to "upload_session_type" drop typemod, + column ChannelBookmarks.Type to "channel_bookmark_type" drop typemod, + column Drafts.Priority to text, + type int when (= precision 11) to integer drop typemod, + type bigint when (= precision 20) to bigint drop typemod, + type text to varchar drop typemod using remove-null-characters, + type tinyint when (<= precision 4) to boolean using tinyint-to-boolean, + type json to jsonb drop typemod using remove-null-characters + +EXCLUDING TABLE NAMES MATCHING ~, ~, 'schema_migrations', 'db_migrations', 'db_lock', + 'Configurations', 'ConfigurationFiles', 'db_config_migrations', 'calls' + +BEFORE LOAD DO + $$ ALTER SCHEMA public RENAME TO {{ .source_db }}; $$, + $$ TRUNCATE TABLE {{ .source_db }}.systems; $$, + $$ DROP INDEX IF EXISTS {{ .source_db }}.idx_posts_message_txt; $$, + $$ DROP INDEX IF EXISTS {{ .source_db }}.idx_fileinfo_content_txt; $$ + +AFTER LOAD DO + $$ UPDATE {{ .source_db }}.db_migrations set name='add_createat_to_teamembers' where version=92; $$, + $$ ALTER SCHEMA {{ .source_db }} RENAME TO public; $$, + $$ SELECT pg_catalog.set_config('search_path', '"$user", public', false); $$, + $$ ALTER USER {{ .pg_user }} SET SEARCH_PATH TO 'public'; $$; +``` + +Once you save this configuration file, e.g. `migration.load`, you can run the `pgloader` with the following command: + +``` sh +pgloader migration.load > migration.log +``` + +Feel free to contribute to and/or report your findings through your migration to us. + +## After the migration + +### Restore full-text indexes + +To avoid performance regression on `Posts` and `FileInfo` table access, following queries should be executed once the migration finishes: + +``` sql +CREATE INDEX IF NOT EXISTS idx_posts_message_txt ON public.posts USING gin(to_tsvector('english', message)); +CREATE INDEX IF NOT EXISTS idx_fileinfo_content_txt ON public.fileinfo USING gin(to_tsvector('english', content)); +``` + + + +If any of the entries in your `Posts` and `FileInfo` tables exceed the limit mentioned above, index creation query will warn with the `ERROR: string is too long for tsvector` log while trying to create these indexes. This means the content that didn't fit into a `tsvector` was ignored. If you still want to index the truncated content, you can use `substring()` function on the content while creating the indexes. + +Start with a substring length of 1000000 and gradually decrease if the error persists: + + + +``` sql +-- Start with 1000000 +CREATE INDEX IF NOT EXISTS idx_fileinfo_content_txt ON public.fileinfo USING gin(to_tsvector('english', substring(content,0,1000000))); + +-- If that fails, try 800000 +CREATE INDEX IF NOT EXISTS idx_fileinfo_content_txt ON public.fileinfo USING gin(to_tsvector('english', substring(content,0,800000))); + +-- Continue decreasing as needed (e.g., 600000, 500000) until the index creates successfully +``` + +### Compare the data + +We developed an internal tool called `dbcmp` to simplify database comparison. It checks every table in two databases and reports any differences in their schemas. However, `dbcmp` does not compare individual rows. Instead, it calculates checksum values based on a specified page-size and compares them. This means it cannot generate row-level diffs. + +We recommend using `dbcmp` as an additional check to verify data integrity, especially if custom casting rules (beyond the defaults or those provided by us) were used during migration. Otherwise, running this tool is not necessary. + +The tool includes a few flags to run a comparison: + +``` sh +Usage: + dbcmp [flags] + +Flags: + --exclude strings exclude tables from comparison, takes comma-separated values. + --include strings include only matching tables for comparison, takes comma-separated values. + -h, --help help for dbcmp + --source string source database dsn + --target string target database dsn + -v, --version version for dbcmp +``` + + + +`--exclude` and `--include` flags are mutually exclusive and they can't be used together. + + + +For our case, we can simply run the following command: + +``` sh +dbcmp --source "${MYSQL_DSN}" --target "${POSTGRES_DSN} " --include="posts,users" +``` + +An example command would look like: `dbcmp --source "user:password@tcp(address:3306)/db_name --target "postgres://user:password@address:5432/db_name` + + + +`POSTGRES_DSN` should start with a `postgres://` prefix. This way `dbcmp` decides which driver to use while connecting to a database. + + + +Another exclusion we are making is in the `db_migrations` table which has a small difference (a typo in a single migration name) and creates a diff. Since we created the PostgreSQL schema with morph, and the official `mattermost` source, we can skip it safely without concerns. On the other hand, `systems` table may contain additional diffs if there were extra keys added during some of the migrations. Consider excluding the `systems` table if you run into issues, and perform a manual comparison as the data in the `systems` table is relatively smaller in size. + + + +If the `remove-null-characters` transform function is utilized during the migration and there were `0x00` byte sequences in the MySQL database, those tables will have differences during the comparison phase. + + + +### Restore the search path + +If you closely examine the `pgloader` configuration file (e.g., `migration.load`), you will notice that the `search_path` of the database user is set to `public`. This is the only requirement for the Mattermost application. However, if you need to include other schemas in the search path, you should modify the `search_path` accordingly to meet your specific requirements. + +## Plugin migrations + +On the plugin side, we are going to take a different approach from what we have done above. We are not going to use `morph` tool to create tables and indexes this time. We are going to utilize `pgloader` to create the tables on behalf of us. The reason for doing so is that collaborative playbooks and boards leverage application logic to facilitate SQL queries. But we don't want to use any level of application at this point. + +### Collaborative playbooks + +The `pgloader` configuration provided for playbooks is based on `v1.38.1` and the plugin should be at least `v1.36.0` to perform the migration. + +Once we are ready to migrate, we can start migrating the **schema** and the **data** by running `pgloader` + +Use the following configuration for the baseline of the data migration: + +``` text +LOAD DATABASE + FROM mysql://{{ .mysql_user }}:{{ .mysql_password }}@{{ .mysql_address }}/{{ .source_db }} + INTO pgsql://{{ .pg_user }}:{{ .pg_password }}@{{ .postgres_address }}/{{ .target_db }} + +WITH include drop, create tables, create indexes, no foreign keys, + workers = 8, concurrency = 1, + multiple readers per thread, rows per range = 50000, + preserve index names + +SET PostgreSQL PARAMETERS + maintenance_work_mem to '128MB', + work_mem to '12MB' + +SET MySQL PARAMETERS + net_read_timeout = '120', + net_write_timeout = '120' + +CAST column IR_ChannelAction.ActionType to text drop typemod, + column IR_ChannelAction.TriggerType to text drop typemod, + column IR_Incident.ChecklistsJSON to "json" drop typemod + +INCLUDING ONLY TABLE NAMES MATCHING + ~/IR_/ + +BEFORE LOAD DO + $$ ALTER SCHEMA public RENAME TO {{ .source_db }}; $$ + +AFTER LOAD DO + $$ ALTER TABLE {{ .source_db }}.IR_ChannelAction ALTER COLUMN ActionType TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_ChannelAction ALTER COLUMN TriggerType TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ReminderMessageTemplate TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ReminderMessageTemplate SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedInvitedUserIDs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedInvitedUserIDs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedWebhookOnCreationURLs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedWebhookOnCreationURLs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedInvitedGroupIDs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedInvitedGroupIDs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN Retrospective TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN Retrospective SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN MessageOnJoin TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN MessageOnJoin SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedWebhookOnStatusUpdateURLs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedWebhookOnStatusUpdateURLs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN CategoryName TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN CategoryName SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedBroadcastChannelIds TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ConcatenatedBroadcastChannelIds SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ChannelIDToRootID TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Incident ALTER COLUMN ChannelIDToRootID SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ReminderMessageTemplate TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ReminderMessageTemplate SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedInvitedUserIDs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedInvitedUserIDs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedWebhookOnCreationURLs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedWebhookOnCreationURLs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedInvitedGroupIDs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedInvitedGroupIDs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN MessageOnJoin TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN MessageOnJoin SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN RetrospectiveTemplate TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN RetrospectiveTemplate SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedWebhookOnStatusUpdateURLs TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedWebhookOnStatusUpdateURLs SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedSignalAnyKeywords TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedSignalAnyKeywords SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN CategoryName TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN CategoryName SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ChecklistsJSON TYPE JSON USING ChecklistsJSON::JSON; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedBroadcastChannelIds TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ConcatenatedBroadcastChannelIds SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN RunSummaryTemplate TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN RunSummaryTemplate SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ChannelNameTemplate TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Playbook ALTER COLUMN ChannelNameTemplate SET DEFAULT ''::text; $$, + $$ ALTER TABLE {{ .source_db }}.IR_PlaybookMember ALTER COLUMN Roles TYPE varchar(65536); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Category_Item ADD CONSTRAINT ir_category_item_categoryid FOREIGN KEY (CategoryId) REFERENCES {{ .source_db }}.IR_Category(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Metric ADD CONSTRAINT ir_metric_metricconfigid FOREIGN KEY (MetricConfigId) REFERENCES {{ .source_db }}.IR_MetricConfig(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Metric ADD CONSTRAINT ir_metric_incidentid FOREIGN KEY (IncidentId) REFERENCES {{ .source_db }}.IR_Incident(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_MetricConfig ADD CONSTRAINT ir_metricconfig_playbookid FOREIGN KEY (PlaybookId) REFERENCES {{ .source_db }}.IR_Playbook(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_PlaybookAutoFollow ADD CONSTRAINT ir_playbookautofollow_playbookid FOREIGN KEY (PlaybookId) REFERENCES {{ .source_db }}.IR_Playbook(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_PlaybookMember ADD CONSTRAINT ir_playbookmember_playbookid FOREIGN KEY (PlaybookId) REFERENCES {{ .source_db }}.IR_Playbook(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_Run_Participants ADD CONSTRAINT ir_run_participants_incidentid FOREIGN KEY (IncidentId) REFERENCES {{ .source_db }}.IR_Incident(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_StatusPosts ADD CONSTRAINT ir_statusposts_incidentid FOREIGN KEY (IncidentId) REFERENCES {{ .source_db }}.IR_Incident(Id); $$, + $$ ALTER TABLE {{ .source_db }}.IR_TimelineEvent ADD CONSTRAINT ir_timelineevent_incidentid FOREIGN KEY (IncidentId) REFERENCES {{ .source_db }}.IR_Incident(Id); $$, + $$ CREATE UNIQUE INDEX IF NOT EXISTS ir_playbookmember_playbookid_memberid_key on {{ .source_db }}.IR_PlaybookMember(PlaybookId,MemberId); $$, + $$ CREATE INDEX IF NOT EXISTS ir_statusposts_incidentid_postid_key on {{ .source_db }}.IR_StatusPosts(IncidentId,PostId); $$, + $$ CREATE INDEX IF NOT EXISTS ir_playbookmember_playbookid on {{ .source_db }}.IR_PlaybookMember(PlaybookId); $$, + $$ ALTER SCHEMA {{ .source_db }} RENAME TO public; $$, + $$ SELECT pg_catalog.set_config('search_path', '"$user", public', false); $$, + $$ ALTER USER {{ .pg_user }} SET SEARCH_PATH TO 'public'; $$; +``` + +``` sh +pgloader playbooks.load > playbooks_migration.log +``` + +### Focalboard + +As of `v9.0` Boards will transition to being fully community supported as the Focalboard plugin. Hence this guide covers only version `v7.10.x` of the schema. [Official announcement](/product-overview/deprecated-features#mattermost-server-v9-0-0). + +Once we are ready to migrate, we can start migrating the **schema** and the **data** by running `pgloader` + +Use the following configuration for the baseline of the data migration: + +``` text +LOAD DATABASE + FROM mysql://{{ .mysql_user }}:{{ .mysql_password }}@{{ .mysql_address }}/{{ .source_db }} + INTO pgsql://{{ .pg_user }}:{{ .pg_password }}@{{ .postgres_address }}/{{ .target_db }} + +WITH include drop, create tables, create indexes, reset sequences, + workers = 8, concurrency = 1, + multiple readers per thread, rows per range = 50000, + preserve index names + +SET PostgreSQL PARAMETERS + maintenance_work_mem to '128MB', + work_mem to '12MB' + +SET MySQL PARAMETERS + net_read_timeout = '120', + net_write_timeout = '120' + +CAST column focalboard_blocks.fields to "json" drop typemod, + column focalboard_blocks_history.fields to "json" drop typemod, + column focalboard_schema_migrations.name to "varchar" drop typemod, + column focalboard_sessions.props to "json" drop typemod, + column focalboard_teams.settings to "json" drop typemod, + column focalboard_users.props to "json" drop typemod, + type int when (= precision 11) to int4 drop typemod, + type json to jsonb drop typemod + +INCLUDING ONLY TABLE NAMES MATCHING + ~/focalboard/ + +BEFORE LOAD DO + $$ ALTER SCHEMA public RENAME TO {{ .source_db }}; $$ + +AFTER LOAD DO + $$ UPDATE {{ .source_db }}.focalboard_blocks SET "fields" = '{}'::json WHERE "fields"::text = ''; $$, + $$ UPDATE {{ .source_db }}.focalboard_blocks_history SET "fields" = '{}'::json WHERE "fields"::text = ''; $$, + $$ UPDATE {{ .source_db }}.focalboard_sessions SET "props" = '{}'::json WHERE "props"::text = ''; $$, + $$ UPDATE {{ .source_db }}.focalboard_teams SET "settings" = '{}'::json WHERE "settings"::text = ''; $$, + $$ UPDATE {{ .source_db }}.focalboard_users SET "props" = '{}'::json WHERE "props"::text = ''; $$, + $$ ALTER SCHEMA {{ .source_db }} RENAME TO public; $$, + $$ SELECT pg_catalog.set_config('search_path', '"$user", public', false); $$, + $$ ALTER USER {{ .pg_user }} SET SEARCH_PATH TO 'public'; $$; +``` + +``` sh +pgloader focalboard.load > focalboard_migration.log +``` + +### Calls + +If you are running a version of Mattermost that is greater than `v9.9` or the Calls plugin above `v0.27`, you can opt to migrate the data for the plugin. We are going to take a similar approach with Boards and Playbooks migration and let pgloader create the tables. + +Once we are ready to migrate, we can start migrating the **schema** and the **data** by running `pgloader` + +Use the following configuration for the baseline of the data migration: + +``` text +LOAD DATABASE + FROM mysql://{{ .mysql_user }}:{{ .mysql_password }}@{{ .mysql_address }}/{{ .source_db }} + INTO pgsql://{{ .pg_user }}:{{ .pg_password }}@{{ .postgres_address }}/{{ .target_db }} + +WITH include drop, create tables, create indexes, reset sequences, + workers = 8, concurrency = 1, + multiple readers per thread, rows per range = 50000, + preserve index names + +SET PostgreSQL PARAMETERS + maintenance_work_mem to '128MB', + work_mem to '12MB' + +SET MySQL PARAMETERS + net_read_timeout = '120', + net_write_timeout = '120' + +CAST type json to jsonb drop typemod + +INCLUDING ONLY TABLE NAMES MATCHING + ~/calls/ + +BEFORE LOAD DO + $$ ALTER SCHEMA public RENAME TO {{ .source_db }}; $$ + +AFTER LOAD DO + $$ ALTER SCHEMA {{ .source_db }} RENAME TO public; $$, + $$ SELECT pg_catalog.set_config('search_path', '"$user", public', false); $$, + $$ ALTER USER {{ .pg_user }} SET SEARCH_PATH TO 'public'; $$; +``` + +``` sh +pgloader calls.load > calls_migration.log +``` + +## Troubleshooting + +See [troubleshooting errors during migration from MySQL to PostgreSQL](/deployment-guide/postgres-migration#troubleshooting) diff --git a/docs/main/deployment-guide/mobile/configure-microsoft-intune-mam.mdx b/docs/main/deployment-guide/mobile/configure-microsoft-intune-mam.mdx new file mode 100644 index 000000000000..b8e84f95fbea --- /dev/null +++ b/docs/main/deployment-guide/mobile/configure-microsoft-intune-mam.mdx @@ -0,0 +1,874 @@ +--- +title: "Configure Microsoft Intune Mobile Application Management (MAM)" +draft: true +--- + + +You can configure the Mattermost Mobile App on iOS to enforce Microsoft Intune App Protection Policies (MAM) so organizational data remains protected on Bring Your Own Device (BYOD) and mixed-use devices without requiring device enrollment (MDM). + +This guide documents the required configuration to enable Intune MAM successfully on iOS. + +## Read This First + +Intune MAM enforcement in Mattermost is identity-based and applies only to the sign-in method selected as the enforced **Auth Provider** in **System Console \> Environment \> Mobile Security**. + +- The enforced authentication provider must resolve users using Azure AD `objectId` (`IdAttribute = objectId`). +- MSAL access tokens must include the `oid` claim, and it must match the same Azure AD `objectId` (confirm identity alignment: `objectId ↔ oid`). + + + +If Intune MAM enrollment fails due to a technical error, the affected Mattermost server is removed from the mobile app and cached data for that server is wiped from the device. + + + +## Unsupported Scenarios + +This guide doesn't apply when: + +- You require Intune MAM on Android devices. +- You want Intune MAM enforcement for a sign-in method not backed by Microsoft Entra ID. +- The enforced authentication provider cannot resolve users to Azure AD `objectId`. +- You require a rollout model where users can bypass or defer Intune MAM for the enforced sign-in method. + +Other authentication methods, such as guest access, may still be enabled separately, but they aren't evaluated by Intune MAM. + +## Prerequisites + +Confirm the following before continuing: + +- Microsoft Entra ID is used for authentication. +- You can commit to Azure AD `objectId` as the authoritative identity. +- Mattermost Enterprise Advanced licensing is available for the server. +- Target users are licensed for Microsoft Intune. +- You can register applications and grant tenant-wide admin consent in Microsoft Entra. +- If enforcing Intune MAM on SAML, users already exist in Mattermost (mobile sign-in does not create users for SAML). + + + +In this guide, OpenID Connect (OIDC) refers to the Microsoft Entra sign-in method used by the Mattermost Mobile App via MSAL. + + + +## Configuration Overview + +Successful Intune MAM enforcement requires coordinated configuration across: + +- **Microsoft Entra ID** – app registration, scope, API permissions, admin consent +- **Microsoft Intune** – iOS App Protection Policies +- **Mattermost Server** – MAM enablement and provider selection +- **Mattermost Mobile App (iOS)** – enrollment and enforcement + +Complete the steps below in order. + +## Setup Summary + +1. Confirm identity requirements and alignment (`objectId ↔ oid`). +2. Configure Microsoft Entra (server-referenced application). +3. Configure Intune App Protection Policies. +4. Enable Intune MAM in Mattermost and select the enforced provider. +5. Deploy the official Mattermost iOS app. +6. Validate enrollment and enforcement. + +## Values You’ll Need Later + +Capture these during setup: + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueWhere to get itWhere you use it
Directory (tenant) IDEntra app registration overviewMattermost System Console
Application (client) IDEntra app registration overviewMattermost System Console
Application ID URIEntra app > Expose an APIUsed to form the api://<APPLICATION-ID>/login.mattermost scope reference in Authorized client applications
login.mattermost scopeEntra app > Expose an APIAuthorized client applications
Mobile client application IDProvided by MattermostEntra app > Authorized client applications
iOS bundle IDs (prod/beta)This guideIntune App Protection Policies
+ +## Step 1: Identity Configuration for Intune MAM + +
+ +This step defines the required identity model for the authentication provider selected for Intune MAM enforcement. + +
+ +### Required Identity Model + +Microsoft Intune MAM for Mattermost requires Azure AD `objectId` as the authoritative user identifier. The following is non-negotiable. + +- `IdAttribute` must equal `objectId` for the enforced provider. +- MSAL access tokens must include the `oid` claim. +- Confirm identity alignment (`objectId ↔ oid`) before enabling Intune MAM. + +### Confirm Identity Alignment (objectId ↔ oid) + +
+ +For the same user, the following values must match: + +
+ +- Azure AD `objectId` +- MSAL access token `oid` claim +- SAML `objectidentifier` (if applicable) +- LDAP `msDS-aadObjectId` (if applicable) + +Any mismatch prevents enrollment. + +### Identity Enforcement by Authentication Method + +**OIDC (Mobile sign-in via MSAL)** + +- Mattermost uses the MSAL access token for identity and enrollment. +- Confirm identity alignment (`objectId ↔ oid`). + +**SAML (Entra-backed)** + +- `SamlSettings.IdAttribute` must map to `objectidentifier`. +- Email, UPN, and `immutableID` aren't supported. +- Users must already exist in Mattermost before mobile sign-in. + +**LDAP (Entra ID Domain Services)** + +- Use `msDS-aadObjectId`. +- Do not use `objectGUID`. + +### Runtime Enforcement Behavior + +When Intune MAM is enabled for a provider: + +- Enforcement occurs during active sessions, not only at login. +- If Intune MAM becomes newly required due to policy, licensing, or configuration changes, enrollment may be triggered immediately. +- Users can’t bypass enforcement for the enforced provider. + +### Pre-flight Checklist + +- Licensed Intune test user available +- Ability to grant tenant-wide admin consent +- Enforced provider identified (OIDC or SAML) +- `IdAttribute = objectId` configured +- Identity alignment verified (`objectId ↔ oid`) +- Official Mattermost iOS app deployed +- Target bundle IDs known: `com.mattermost.rn` (Production), `com.mattermost.rnbeta` (Beta) + +## Step 2: Microsoft Entra Configuration for Intune MAM + +
+ +You register a single-tenant Microsoft Entra application that is referenced by Mattermost Server. This application validates MSAL access tokens and supports Intune MAM enrollment. + +
+ +You don't register the Mattermost Mobile app itself. Redirect URI configuration isn't required. + +### Entra Application Registration + +1. Go to **Identity \> Applications \> App registrations** +2. Select **New registration** +3. Configure: + - **Name**: Mattermost Mobile (Intune MAM) + - **Supported account types**: Single tenant +4. Register the app +5. Copy: + - **Application (client) ID** + - **Directory (tenant) ID** + +### Expose the API and Create the Scope + +1. Go to **Expose an API** +2. Confirm **Application ID URI** is set (for example, `api://`) +3. Add a scope named `login.mattermost` +4. Save your changes. + +### Authorize the Official Mobile Client + +Authorize the official Mattermost Mobile client application ID (provided by Mattermost) to request the `login.mattermost` scope. + +1. In the Entra app registration, go to **Expose an API**. +2. Under **Authorized client applications**, select **Add a client application**. +3. Add the official Mattermost Mobile client application ID (provided by Mattermost) as: + +> - Beta: `64e9952b-20eb-46dc-92ad-99089ed24903` +> - Production: `9ac649f1-4f77-44d6-9792-b2f54ab3c9a7` + +4. Authorize the `api:///login.mattermost` scope. +5. Save your changes. + +### API Permissions and Admin Consent + + + +These are the permissions the customer admin must grant for the Entra application referenced by Mattermost Server. + +If these permissions are missing or lack tenant-wide admin consent, enrollment can fail with an Entra permissions/admin-consent error (for example, `AADSTS650057`) or a user-visible **Consent Denied** message during first sign-in. + +### Configure MSAL tokens and required claims + +Before enabling Intune MAM, ensure the Entra app registration issues access tokens with the claims Mattermost expects during mobile sign-in. + +1. In the Entra app registration, go to **Token configuration**. +2. Select **Add optional claim**. +3. Under **Token type**, select **Access**. +4. Add the following optional claims: + - `email` + - `family_name` + - `given_name` + - `preferred_username` + - `upn` +5. Save your changes. + + + +Mattermost Intune MAM enforcement uses the MSAL access token. If required claims are missing, sign-in and/or enrollment may fail. + + + +### Enable MSAL v2 access tokens + +1. Open the app **Manifest**. +2. Set the token version to `2`: + - If your manifest shows `api.requestedAccessTokenVersion`, set it to `2`. + - Otherwise set `accessTokenAcceptedVersion` to `2`. +3. Save your changes. + +## Step 3: Configure Intune App Protection Policies + +1. Go to **Intune admin center \> Apps \> App protection policies**. +2. Create a policy: + - **Platform**: iOS/iPadOS + - **Targeted app**: Managed apps +3. Add the Mattermost app by bundle ID: + - `com.mattermost.rn` (Production) + - `com.mattermost.rnbeta` (Beta) +4. Configure protection settings. +5. Assign to Entra ID user groups. +6. Save your changes. + +Separate policies are required for Production and Beta apps. + +## Step 4: Configure Mattermost Server for Intune MAM + +
+ +1. Go to **System Console \> Environment \> Mobile Security** +2. Set **Enable Microsoft Intune MAM** to **True** +3. Select **Auth Provider**: + - OpenID Connect (Entra-backed) + - SAML 2.0 (Entra-backed) +4. Enter: + - **Tenant ID** + - **Application (Client) ID** +5. Save your changes. + +
+ +The enforced provider must resolve identity using `IdAttribute = objectId`. + +## Step 5: Deploy the Mattermost iOS App + +Download and install the official Mattermost iOS app using: + +- Apple App Store (Production) +- TestFlight (Beta) + +Wrapped, re-signed, or privately distributed apps aren't supported. + +## Step 6: Validate Enrollment + +Validate with a licensed test user on iOS. + +Confirm: + +- Enrollment completes successfully +- Enforcement applies at sign-in and mid-session +- Identity alignment is correct (`objectId ↔ oid`) + +## Expected Behavior During Mobile Sign-In + +1. User signs in via MSAL. +2. Mattermost validates the access token. +3. Intune MAM enrollment is triggered. +4. App Protection Policies are applied. + +If enrollment is required but cannot complete, access is blocked until enrollment succeeds. + +## Troubleshooting + +
+ +Most failures are caused by: + +
+ +- Identity mismatch (`objectId ↔ oid`) +- `IdAttribute` not set to `objectId` +- Missing Entra API permissions or admin consent +- App Protection Policy not targeting the user or app +- Unsupported client or platform + +### Quick Diagnostics + +1. Confirm identity alignment (`objectId ↔ oid`). +2. Confirm `IdAttribute = objectId`. +3. Confirm Entra permissions and admin consent. +4. Confirm Auth Provider selection. +5. Confirm Intune policy targeting. + +If the user declines enrollment, retry is allowed. + +### Intune MAM Errors + +The errors below may occur during mobile sign-in or when Intune MAM enforcement is triggered mid-session. Some errors are shown in the Mattermost Mobile App, while others are silent and must be diagnosed using Mattermost server logs. + + + +In the table below, **Fallback: Web SSO** means the mobile app uses the **non-Intune** version of the configured sign-in method (SAML or OpenID Connect) as if Intune MAM were not enabled. + + + + + + + + + + + + + + + + {/* Enrollment Failed */} + + + + + + + {/* Enrollment Declined */} + + + + + + + {/* Consent Denied (admin consent missing) */} + + + + + + + {/* Enterprise not compiled */} + + + + + + + {/* Intune not configured */} + + + + + + + {/* Bot login forbidden */} + + + + + + + {/* Account locked/deactivated */} + + + + + + + {/* IsConfigured() false */} + + + + + + + {/* IdAttribute mapping failed */} + + + + + + + {/* SAML user not found */} + + + + + + + {/* Token validation failed */} + + + + + + + {/* Token expired */} + + + + + + + {/* Missing claims */} + + + + + + + {/* Invalid tenant */} + + + + + + + {/* AADSTS650057 */} + + + + + + + {/* NotLicensed */} + + + + + + + {/* HTTP 403 Forbidden */} + + + + + + + +
ErrorMeaningAdmin cause & next step
+ Enrollment Failed +
+
Error ID: (varies)
+
HTTP: (varies)
+
Scenario: Enrollment failed (technical)
+
User message: "Enrollment Failed"
+
Retry: No
+
Fallback: None
+
+
+ Intune MAM enrollment failed due to a technical error. + + Cause: Enrollment could not be completed due to a technical failure (MSAL error, Intune enrollment API failure, identity mismatch, or missing Entra permissions).
+ Behavior: The server is removed immediately and there is no retry option; cached data for that server is wiped.
+ Next step: Fix the underlying issue, then have the user re-add the server in the mobile app.
+ Admin checks: Verify IdAttribute = objectId; confirm identity alignment (objectId ↔ oid); confirm tenant-wide admin consent; confirm App Protection Policy targets the user and the correct iOS bundle ID. +
+ Enrollment Declined +
+
Error ID: (varies)
+
HTTP: (varies)
+
Scenario: User declined enrollment
+
User message: "Enrollment Declined"
+
Retry: Yes
+
Fallback: None
+
+
+ The user declined Intune MAM enrollment. + + Cause: The user canceled the enrollment prompt.
+ Behavior: A Retry option is shown; no server data is removed unless a later technical enrollment failure occurs.
+ Next step: Instruct the user to retry enrollment when ready. +
+ Consent Denied +
+
Error ID: (varies)
+
HTTP: (varies)
+
Scenario: Admin consent missing (first login)
+
User message: "You denied consent for Intune management. The affected accounts have been unenrolled and signed out."
+
Retry: Yes (after admin consent)
+
Fallback: None
+
+
+ Enrollment cannot complete because required Entra app permissions don’t have tenant-wide admin consent. + + Cause: Tenant-wide admin consent has not been granted for the required delegated permissions on the Entra app registration configured in Mattermost Server.
+ Behavior: The message may appear as if the user denied consent, but the underlying issue is missing admin consent.
+ Next step: In Microsoft Entra, grant tenant-wide admin consent for Microsoft Graph delegated permissions email and profile on the same Entra app registration configured in Mattermost, then have the user retry mobile sign-in. +
+ (silent) +
+
Error ID: api.user.login_by_intune.not_available.app_error
+
HTTP: 501
+
Scenario: Enterprise not compiled
+
User message: (silent)
+
Retry: No
+
Fallback: Standard SSO (non-Intune)
+
+
+ Intune MAM login is not available on this server. + + Cause: The server does not support Intune MAM (feature not available in this build or not enabled for the deployment).
+ Next step: Confirm the server build includes Intune MAM support and the deployment is licensed for Enterprise Advanced.
+ User guidance: Have the user sign in via web/desktop using the standard (non-Intune) SSO flow for their provider (SAML or OpenID Connect) while the server is updated or configuration is corrected. +
+ (silent) +
+
Error ID: api.user.login_by_intune.not_configured.app_error
+
HTTP: 400
+
Scenario: Intune not configured
+
User message: (silent)
+
Retry: No
+
Fallback: Standard SSO (non-Intune)
+
+
+ Intune MAM is enabled for the org but not configured on the server. + + Cause: Intune MAM isn't fully configured in System Console > Environment > Mobile Security.
+ Next step: Enable Microsoft Intune MAM and ensure Tenant ID, Application (Client) ID, and Auth Provider are set correctly.
+ Admin checks: Confirm the selected auth provider is Entra-backed and required permissions/admin consent have been granted for the Entra app registration.
+ User guidance: Have the user sign in via web/desktop using the standard (non-Intune) SSO flow for their provider (SAML or OpenID Connect) while the server is updated or configuration is corrected. +
+ Bot accounts cannot sign in using this method. +
+
Error ID: api.user.login_by_intune.bot_login_forbidden.app_error
+
HTTP: 403
+
Scenario: Bot tried to login
+
User message: "Bot accounts cannot sign in using this method."
+
Retry: No
+
Fallback: None
+
+
+ The account cannot use Intune MAM sign-in. + + Cause: Bot accounts are not allowed to authenticate via Intune MAM.
+ Next step: Use a human user account for Intune MAM enrollment and access. +
+ Your account has been deactivated. Please contact your administrator. +
+
Error ID: api.user.login_by_intune.account_locked.app_error
+
HTTP: 409
+
Scenario: User deleted/disabled
+
User message: "Your account has been deactivated. Please contact your administrator."
+
Retry: No
+
Fallback: None
+
+
+ The account is not permitted to sign in. + + Cause: The user is deleted, disabled, or locked in Mattermost.
+ Next step: Re-enable or restore the user account in Mattermost, then retry sign-in and enrollment. +
+ (silent) +
+
Error ID: ent.intune.login.not_configured.app_error
+
HTTP: 403
+
Scenario: IsConfigured() = false
+
User message: (silent)
+
Retry: No
+
Fallback: Standard SSO (non-Intune)
+
+
+ Intune MAM is not configured for the current sign-in path. + + Cause: Intune MAM isn't configured for the requested authentication path (configuration incomplete or mismatched provider selection).
+ Next step: Confirm Intune MAM is enabled and configured, and the selected Auth Provider matches how users authenticate (OIDC vs SAML).
+ User guidance: Have the user sign in via web/desktop using the standard (non-Intune) SSO flow for their provider (SAML or OpenID Connect) while the server is updated or configuration is corrected. +
+ We couldn't complete your sign in. Please try again. +
+
Error ID: ent.intune.login.extract_auth_data.app_error
+
HTTP: 400
+
Scenario: IdAttribute mapping failed
+
User message: "We couldn't complete your sign in. Please try again."
+
Retry: Yes (1x)
+
Fallback: None
+
+
+ Identity mapping failed during sign-in. + + Cause: The server couldn’t extract or map the identity attribute required for Intune MAM (commonly IdAttribute is misconfigured or the token isn't MSAL v2).
+ Next step: Ensure IdAttribute = objectId, then confirm identity alignment (objectId ↔ oid). Verify the Entra app issues v2 tokens (accessTokenAcceptedVersion = 2). +
+ Your account isn't fully set up yet. Please sign in to Mattermost via the web or desktop app first. +
+
Error ID: ent.intune.login.account_not_found.app_error
+
HTTP: 428
+
Scenario: SAML user account not found
+
User message: "Your account isn't fully set up yet. Please sign in to Mattermost via the web or desktop app first."
+
Retry: No
+
Fallback: None
+
+
+ The user does not exist in Mattermost for SAML-based sign-in. + + Cause: When SAML is the selected provider for Intune MAM enforcement, mobile sign-in cannot create a new user.
+ Next step: Have the user sign in once via the web or desktop app to provision the account, then retry mobile sign-in.
+ Admin checks: Ensure provisioning is in place (web/desktop first sign-in, LDAP sync, or another provisioning method). +
+ We couldn't verify your sign in. Please try again. +
+
Error ID: ent.intune.validate_token.invalid_token.app_error
+
HTTP: 400
+
Scenario: Token validation failed
+
User message: "We couldn't verify your sign in. Please try again."
+
Retry: Yes (1x)
+
Fallback: None
+
+
+ The access token could not be validated. + + Cause: Token validation failed (token malformed, wrong issuer/audience, missing permissions, or Entra configuration mismatch).
+ Next step: Verify the configured Tenant ID and Application (Client) ID match the Entra app registration referenced by Mattermost Server. Confirm tenant-wide admin consent has been granted for Microsoft Graph delegated permissions email and profile on that same app registration. Then confirm identity alignment (objectId ↔ oid) for the affected user.
+ Admin checks: Confirm v2 tokens (accessTokenAcceptedVersion = 2) and that Microsoft Graph delegated permissions email and profile have tenant-wide admin consent. +
+ Your sign in session has expired. Please try signing in again. +
+
Error ID: ent.intune.validate_token.token_expired.app_error
+
HTTP: 400
+
Scenario: Token expired
+
User message: "Your sign in session has expired. Please try signing in again."
+
Retry: Yes (1x)
+
Fallback: None
+
+
+ The authentication session expired before enrollment completed. + + Cause: The access token or interactive session expired during sign-in/enrollment.
+ Next step: Have the user sign in again and complete enrollment promptly.
+ Admin checks: If repeated, confirm the device can reach Entra/Intune endpoints during enrollment and prompts aren't being blocked. +
+ We couldn't complete your sign in. Please contact your IT administrator. +
+
Error ID: ent.intune.validate_token.missing_claims.app_error
+
HTTP: 400
+
Scenario: Required claims missing
+
User message: "We couldn't complete your sign in. Please contact your IT administrator."
+
Retry: No
+
Fallback: None
+
+
+ The access token is missing required claims for sign-in and enrollment. + + Cause: Required claims are missing from the MSAL access token (most commonly oid, or optional claims required by Mattermost).
+ Next step: Confirm MSAL v2 access tokens are issued (accessTokenAcceptedVersion = 2) and the token includes oid. In the Entra app registration, go to Token configuration and ensure optional claims are added for the Access token: email, family_name, given_name, preferred_username, and upn. Confirm the enforced provider uses IdAttribute = objectId, then verify identity alignment (objectId ↔ oid). +
+ There was a configuration issue. Please contact your IT administrator. +
+
Error ID: ent.intune.validate_token.invalid_tenant_id.app_error
+
HTTP: 400
+
Scenario: Token tenant ≠ configured tenant
+
User message: "There was a configuration issue. Please contact your IT administrator."
+
Retry: No
+
Fallback: None
+
+
+ The token tenant does not match the configured tenant. + + Cause: The token was issued by a different tenant than the one configured in Mattermost.
+ Next step: Verify the Tenant ID configured in System Console > Environment > Mobile Security matches the Entra tenant issuing MSAL tokens for the user. +
+ AADSTS650057
+ (invalid_resource) +
+
Error ID: (AADSTS650057)
+
HTTP: (varies)
+
Scenario: invalid_resource
+
User message: (MSAL/Entra error)
+
Retry: No (until fixed)
+
Fallback: None
+
+
+ The Entra app configuration is missing required permissions and/or admin consent. + + Cause: Required Intune MAM API permissions are missing or do not have tenant-wide admin consent.
+ Next step: In the Microsoft Entra admin center, go to Enterprise applications (not App registrations), search for Mattermost Mobile / Mattermost Mobile Beta, then open Permissions and add/grant admin consent for the Intune MAM permissions (for example, https://msmamservice.api.application/.default and Microsoft Mobile Application Managementuser_impersonation (Delegated)). Then have the user retry sign-in. +
+ NotLicensed +
+
Error ID: (NotLicensed)
+
HTTP: (varies)
+
Scenario: License missing or inactive
+
User message: (varies)
+
Retry: No
+
Fallback: None
+
+
+ The server is not licensed for Intune MAM enforcement. + + Cause: Enterprise Advanced licensing is missing or not applied to the server.
+ Next step: Apply an Enterprise Advanced license to the server and confirm the license is active, then retry. +
+ HTTP 403 Forbidden +
+
Error ID: (HTTP 403)
+
HTTP: 403
+
Scenario: Server-side access blocked
+
User message: (varies)
+
Retry: No
+
Fallback: None
+
+
+ Server-side access is blocked by a gating condition. + + Cause: A server gating condition is preventing enrollment (not an Intune service failure).
+ Next step: Verify Enterprise Advanced licensing, Intune MAM is enabled, Auth Provider selection matches how users authenticate, configured Tenant ID and Application (Client) ID are correct, and tenant-wide admin consent is granted. Then confirm identity alignment (objectId ↔ oid) and Intune App Protection Policy targeting for the correct iOS bundle ID. +
+ +### Consent During First Login + +If a user’s first mobile sign-in fails with **Consent Denied** or: + +`You denied consent for Intune management. The affected accounts have been unenrolled and signed out.` + +Treat this as missing tenant-wide admin consent for the Entra app registration referenced by Mattermost Server. See the **Consent Denied** entry in the [Intune MAM Errors](#intune-mam-errors) table above for remediation steps. + +To resolve this: + +1. In the Microsoft Entra admin center, go to **Enterprise applications**. +2. Search for **Mattermost Mobile** or **Mattermost Mobile Beta**. +3. Go to **Permissions** and add/grant **tenant-wide admin consent** for the Intune MAM permissions (for example, `https://msmamservice.api.application/.default` and Microsoft Mobile Application Management → `user_impersonation` (Delegated)). +4. Have the user retry mobile sign-in. + +## Rollout and Recovery Guidance + +- Pilot with a small group first +- Validate identity alignment before broad rollout +- Expect enforcement to occur mid-session if requirements change diff --git a/docs/main/deployment-guide/mobile/consider-mobile-vpn-options.mdx b/docs/main/deployment-guide/mobile/consider-mobile-vpn-options.mdx new file mode 100644 index 000000000000..54bbb499202b --- /dev/null +++ b/docs/main/deployment-guide/mobile/consider-mobile-vpn-options.mdx @@ -0,0 +1,49 @@ +--- +title: "Mobile VPN options" +--- + + +To connect to your private network Mattermost instance, you need to set up a way to connect to your private network Mattermost instance, using an external proxy with encrypted transport through HTTPS and WSS network connections. + +Depending on your security policies, we recommend deploying Mattermost behind a VPN and using a [per-app VPN](#id3) with your EMM provider, or a mobile VPN client. + +Also consider deploying a mobile VPN client with multi-factor authentication (MFA) to your preferred login method, such as GitLab SSO with MFA, or run Mattermost Enterprise Edition with [multi-factor authentication (MFA)](/administration-guide/onboard/multi-factor-authentication) enabled. + +## Mobile VPN options + +A Virtual Private Network (VPN) allows a device outside a firewall to access content inside the firewall as if it were on the same network. + + + +Some mobile VPN options depend on the requirements of your organization and the demands and/or the needs of your users. + + + +We recommend one of two options: [per-app VPN](#id3) or a [device VPN](#id4) to secure your deployment. Both options are compatible with most EMM providers. + +We also recommend you review the following [commonly-asked questions](/deployment-guide/mobile/mobile-faq) about data security on mobile devices: + +- How data is handled on a device after an account is deleted? +- What post metadata is sent in mobile push notifications? +- What are my options for securing the Mobile apps? +- What are my options for securing push notifications? + +### Per-app VPN + +A common approach is to use a per-app VPN. This provides a connection to the VPN when needed (on-demand). If using a per-app VPN with Mattermost, you can configure the following options: + +- **useVPN:** Mattermost waits until the connection to the VPN server is established before making any requests (otherwise they will fail). This is only supported on iOS as Android OS cannot support waiting. It still works but the first connection attempt may fail. +- **timeoutVPN (iOS only):** How long to wait for the connection to the VPN server before trying. + +### Device VPN + +With this option, all internet traffic routes through the VPN specified in the profile. This could cause issues for personal applications. + +## Connect via corporate proxy server + +Review the following commonly-asked questions about connecting through a corporate proxy server: + +- [How do I receive mobile push notifications if my IT policy requires the use of a corporate proxy server?](/deployment-guide/mobile/mobile-faq#how-do-i-receive-mobile-push-notifications-if-my-it-policy-requires-the-use-of-a-corporate-proxy-server) +- [Deploy Mattermost with connection restricted post-proxy relay in DMZ or a trusted cloud environment](/deployment-guide/mobile/mobile-faq#deploy-mattermost-with-connection-restricted-post-proxy-relay-in-dmz-or-a-trusted-cloud-environment) +- [Whitelist Mattermost push notification proxy to bypass your corporate proxy server](/deployment-guide/mobile/mobile-faq#whitelist-mattermost-push-notification-proxy-to-bypass-your-corporate-proxy-server) +- [Run App Store versions of the Mattermost Mobile apps](/deployment-guide/mobile/mobile-faq#run-app-store-versions-of-the-mattermost-mobile-apps) diff --git a/docs/main/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider.mdx b/docs/main/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider.mdx new file mode 100644 index 000000000000..ee446483871b --- /dev/null +++ b/docs/main/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider.mdx @@ -0,0 +1,183 @@ +--- +title: "Deploy using an EMM provider" +--- + + +You can enhance mobile security by deploying the Mattermost mobile app with [Enterprise Mobility Management (EMM)](https://en.wikipedia.org/wiki/Enterprise_mobility_management) and Mattermost AppConfig compatibility to secure mobile endpoints with management application configuration. + +You can use an EMM to: + +- Enforce users to download the Mattermost pre-built or custom apps managed by your organization. +- Set default server url address. +- Restrict users from changing servers. +- Enforce security policies. + +An EMM provider pushes Mattermost Mobile apps to EMM-enrolled devices. This approach is recommended for organizations that typically use EMM solutions to deploy Mobile apps to meet security and compliance policies. + +## Manage app configuration using AppConfig + +AppConfig is our recommended approach for app configuration and management. It was introduced by the [AppConfig Community](https://www.appconfig.org/), a group of leading EMM providers and app developers who have come together to make it easier for developers and customers to drive mobility in business. + +AppConfig provides an easy way to configure enterprise mobile apps with any EMM providers listed on the [AppConfig website](https://www.appconfig.org/). Using AppConfig, you can manage default settings and security controls on public app stores and custom-built mobile clients. For example, you can pre-configure your Mattermost server URL and username. + +### Mattermost AppConfig values + +The following table shows all the configuration options that can be sent from the EMM provider of your choice to the Mattermost mobile apps. You can also [download an XML template](/samples/mattermost-specfile.xml) of the configuration file for use with your EMM provider. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescriptionDefault/Valid ValuesiOS SupportAndroid for Work Support
inAppPinCode
String
Require users to authenticate as the device owner before using the app. Prompts for fingerprint or passcode when the app first opens and when the app has been in the background for more than five minutes.Default: false
Valid: true | false
blurApplicationScreen
String
Blur the app when it's set to background to protect any confidential on-screen information. On Android, it also prevents taking screenshots of the app.Default: false
Valid: true | false
jailbreakDetection
String
Disable app launch on jailbroken or rooted devices.Default: false
Valid: true | false
copyAndPasteProtection
String
Disable the ability to copy from or paste into any text inputs in the app.Default: false
Valid: true | false
(since v1.24.0)
serverUrl
String
Set a default Mattermost server URL. Supports a single server only while v2.0 of the mobile app supports multiple server connections.Valid: URL
serverName
String
Automatically populates the server display name for the URL specified in serverURL.Valid: alphanumeric or empty
allowOtherServers
String
Allow the user to change the above server URL. If set to true, users can connect to multiple servers that aren't specified in the server URL setting. If set to false, users can only connect to a single defined server.Default: true
Valid: true | false
username
String
Set the username or email address to use to authenticate against the Mattermost Server.
useVPN
String
Enable connection to the Mattermost Server to use a per-app VPN or VPN on-demand.Default: false
Valid: true | false
timeoutVPN
String
Set how long the request waits (in milliseconds) for an initial VPN connection to establish before timeout.Default: 30000
vendor
String
Name of the EMM vendor or company deploying the app. Used in help text when prompting for passcodes so users are aware why the app is being protected.Default: Mattermost
inAppSessionAuth
String
Use the app's internal browser for SSO instead of an external browser. From Mattermost v10.2 and mobile v2.2.1, deprecated in favor of the mobile external browser server configuration setting.Default: false
Valid: true | false
+ +### Other AppConfig settings + +As part of AppConfig, EMM administrators can set the following additional configuration options for the Mattermost mobile apps: + +1. **App Tunnel:** Leverage the "Per-app VPN" capabilities in most commercial VPN solutions. +2. **Prevent App Backup:** Prevent users from backing up app data. +3. **Enforce App Encryption:** Set security policies such as requiring encryption. +4. **Remotely Wipe App:** Use the EMM tool to distribute the app to devices as a managed application so it can be remotely wiped. If the app was previously installed, mark it so the EMM converts the app to a managed app. + +Other configurations may be available depending on your EMM provider. + + + +\- Mattermost only supports the AppConfig standard for securing Mattermost mobile apps via an EMM provider due to incompatibilities with app wrapping and React Native applications. Different EMM vendors refer to “wrapping” in different ways, but it ultimately comes down to unpacking the mobile client bundle, injecting additional SDKs, and re-packaging/re-signing. React Native is the technology used to develop the Mattermost mobile apps. - Mattermost doesn’t support app wrapping, and Mattermost mobile apps won't function properly when using app wrapping (e.g., Websockets for real-time messaging will break). Use app wrapping/containerization technology at your own risk. - A Mattermost Enterprise subscription plan (or a legacy Enterprise Edition license) is required to request assistance or troubleshooting help from [Mattermost Customer Support](https://mattermost.com/support/) when building and deploying custom mobile apps. Customers on other Mattermost subscription plans can develop and deploy custom mobile apps, but can't request technical support assistance through Mattermost Customer Support. - With the release of Mattermost mobile app v2.0, mobile app v1.55 becomes the official [extended support mobile release](/product-overview/mattermost-mobile-releases), and will be supported for an extended timeframe. + + + +## Enroll devices + +When building your own custom versions or deploying the pre-built Mattermost Mobile apps, consider your organization’s mobile policy: + +- Can users bring their own device (BYOD) If so, what devices will be used? +- Are devices company-owned and company-issued? +- Are both options supported? +- What operating systems do you want to start testing? + +Once you know what possible device configurations you’ll be supporting, consider creating a sample configuration, then running validation tests against each configuration item. + +## Generate and assign device profiles + +Generate and assign a device profile for device-wide configurations through the EMM provider. diff --git a/docs/main/deployment-guide/mobile/distribute-custom-mobile-apps.mdx b/docs/main/deployment-guide/mobile/distribute-custom-mobile-apps.mdx new file mode 100644 index 000000000000..a295ef6105f7 --- /dev/null +++ b/docs/main/deployment-guide/mobile/distribute-custom-mobile-apps.mdx @@ -0,0 +1,56 @@ +--- +title: "Distribute a custom mobile app" +--- + + +To control the look and feel of the Mattermost mobile app requires building your own mobile apps, [hosting your own push proxy service](/deployment-guide/mobile/host-your-own-push-proxy-service), and managing your own app distribution. + + + +- Mattermost Enterprise customers are eligible for support guidance on distributing their own custom mobile apps. +- With the release of Mattermost mobile app v2.0, mobile app v1.55 becomes the official [extended support mobile release](/product-overview/mattermost-mobile-releases), and v1.55 will continue to be supported for an extended timeframe. + + + +## Key considerations + +The Mattermost Mobile App is an open source project. Customizing Mattermost mobile apps requires a fork of the source code. Your team will be responsible for maintaining that fork, as well as keeping that fork updated with any changes made by Mattermost. + +Building your own mobile apps will present some challenges, including: + +- Installing the necessary developer tools (such as Nodejs, XCode Developer Tools, Android SDKs, as well as others). +- Obtaining and providing certificates for your custom Mattermost mobile apps\*. +- Signing your custom Mattermost mobile apps\*. +- Distributing your Mobile app to your users. + +This means that you manage the maintenance of your custom Mattermost mobile apps, such as rebuilding and incorporating feature and/or security updates. If this isn't done regularly, your applications won't match the functionality of our publicly-available applications, and could be incompatible with future versions of Mattermost Server. + +This process can be complicated and can greatly increase deployment time, not only initially, but whenever the mobile apps need to be updated. We recommend having your development team [review the Mattermost Mobile Apps developer documentation](https://developers.mattermost.com/contribute/mobile/) to ensure they understand the scale and requirements of taking this path. This documentation provides guidance on building, compiling, signing, and white-labeling Mattermost Mobile apps. + +### URL schema limitations + +If you are building your own version of Mattermost's mobile client, you need to be aware of the following limitations: + +- To allow users to simultaneously run the App Store versions of Mattermost, in addition to the custom company version, you will need to adapt the URL schemes used for the app in the build, as well as configure those schemes on the server using [App Custom URL Schemes](/administration-guide/configure/site-configuration-settings#app-custom-url-schemes) +- Be aware that the `bundleid` for the application should not include `rnbeta`. +- The same change would be required in a custom build of the Mattermost desktop app. +- The mobile and desktop custom clients would no longer be able to log into other Mattermost servers (unless they had the same custom app schema configuration change applied). + +## Deployment options + +When you decide to build your own Mattermost mobile apps, you have multiple ways to deploy them to your organization. + +Our recommend approach is to submit your app to an Enterprise App Store. Once your custom app is added to your own enterprise App Store, your users can download it from the store directly or from an EMM catalog. + +Alternatively, use [an Enterprise Mobile Management (EMM) provider](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) to push the mobile app to the user’s device, and use the AppConfig standard to enforce a selection of app-specific controls. Or, you can use [another distribution method](#using-another-distribution-method), such as a file sharing platform. + +You can also submit your app to [public app stores](#using-public-app-stores). This is the same process Mattermost uses to make Mattermost mobile apps available for everyone. However, before your app can be listed on the public app stores, you need to submit it to the public app stores for review and approval. + +- As part of the submission process, you need to identify an update strategy that accounts for the release of new versions of Mattermost mobile apps that includes reviewing compatibility requirements, validating mobile app versions connecting to the server, and updating Mattermost server. +- We highly recommend you update your custom Mattermost mobile apps to incorporate any security or service releases. +- Prior to distribution, check any compatibility requirements for the mobile apps and the Mattermost server. +- Not all provided updates are compatible with all previous versions of Mattermost server. Updating only Mattermost mobile apps or updating the mobile apps before Mattermost Server can result in incompatibility issues. + +## Custom whitelabeling + +Ensure you select a unique app name that helps users distinguish your version from others, such as "\ Collaboration". See our [Brand and Visual Design Guidelines](https://handbook.mattermost.com/operations/operations/company-processes/publishing/publishing-guidelines/brand-and-visual-design-guidelines#name-usage-guidelines.html) in our company Handbook for details. diff --git a/docs/main/deployment-guide/mobile/host-your-own-push-proxy-service.mdx b/docs/main/deployment-guide/mobile/host-your-own-push-proxy-service.mdx new file mode 100644 index 000000000000..16877caf54c2 --- /dev/null +++ b/docs/main/deployment-guide/mobile/host-your-own-push-proxy-service.mdx @@ -0,0 +1,40 @@ +--- +title: "Host your own push proxy service" +--- + + +Customers building their own custom mobile apps must host their own push proxy service using one of the following methods: + +- Compile your own MPNS from the [open source repository](https://github.com/mattermost/mattermost-push-proxy). +- Use the [pre-compiled version of MPNS available on GitHub](https://github.com/mattermost/mattermost-push-proxy/releases). + +See our [developer documentation](https://developers.mattermost.com/contribute/mobile/push-notifications/service/) on working with the Mattermost Push Notification Service. + +## Enable MPNS + +1. Go to **System Console \> Environment \> Push Notification Server**. +2. Under **Enable Push Notifications**, select **Manually enter Push Notification Service location**. +3. Enter the location of your MPNS in the **Push Notification Server** field, then select **Save**. + +**Deployment recommendations:** + +- Deploy the MPNS on your own infrastructure - whether on-premises behind your firewall or in your public cloud. +- Ensure the Mattermost server has network access to the MPNS instance. Mattermost clients don't need any inbound connectivity. +- The MPNS does not connect with Mattermost mobile apps directly; the MPNS parses and forwards push notifications from the Mattermost server to the Apple Push Notification Service (APNS) or the Firebase Cloud Messaging (FCM). +- The MPNS must be able to communicate with the Apple Push Notification Service over HTTP/2. If an outbound proxy appliance is deployed between the MPNS and APNS, ensure it supports HTTP/2. +- Configure TLS encryption between your MPNS and your Mattermost server. +- Sign the mobile applications during your build process, and obtain and configure valid push certificates for both Android and iOS. Without these certificates, the apps will be unable to send or receive notifications via your MPNS instance. +- Subscribe to [Mattermost Security Bulletins](https://mattermost.com/security-updates/#sign-up) to receive and promptly apply MPNS-related security updates. + +## Configure ID-only push notification contents (Enterprise) + +By default, push notification message content passes through Apple Push Notification Service (APNS) or Google Firebase Cloud Messaging (FCM) before it reaches a device. This potentially presents a problem for organizations with ultra-strict security and compliance requirements. + +With the ID-only option, message contents can be fetched directly from the server once a push notification is delivered to a device. APNS and FCM can’t read push notifications since only a unique message ID is sent in each notification payload. While message content will take slightly longer to send, this feature helps organizations meet advanced compliance requirements. + +To set mobile push notification contents to ID-only: + +1. Go to **System Console \> Site Configuration \> Notifications**. +2. Under **Push Notification Contents**, select **Full message content fetched from the server on receipt**, then select **Save**. + - As part of the process of building the applications, you'll need to sign the applications. You must also obtain the appropriate certificate for both Android and iOS. If this isn't done, the applications won't be able to interact with your instance of the MPNS. Once this is complete, you can proceed with the deployment of your MPNS instance. + - We strongly recommend that you subscribe to [Mattermost Security Bulletins](https://mattermost.com/security-updates/#sign-up). When you're notified of security updates for the MPNS, apply them promptly. diff --git a/docs/main/deployment-guide/mobile/mobile-app-deployment.mdx b/docs/main/deployment-guide/mobile/mobile-app-deployment.mdx new file mode 100644 index 000000000000..10abd1b307dd --- /dev/null +++ b/docs/main/deployment-guide/mobile/mobile-app-deployment.mdx @@ -0,0 +1,26 @@ +--- +title: "Mobile App Deployment" +--- + + +The Mattermost mobile app is available for iPhone and Android devices, and provides a native experience on the go, ensuring you can stay connected and productive from anywhere. + +Learn more about [mobile app software requirements](/deployment-guide/software-hardware-requirements#mobile-apps), [available releases and server compatibility](/product-overview/mattermost-mobile-releases), [what's changed across releases](/product-overview/mobile-app-changelog), and [commonly asked questions](/deployment-guide/mobile/mobile-faq). + +## Download + +Download and install the Mattermost mobile app from the [Apple App Store (iOS)](https://www.apple.com/app-store/) or [Google Play Store (Android)](https://play.google.com/store/games?hl=en). When new mobile app releases become available, your mobile app is automatically updated. + +If you prefer to manage distribution of the mobile app to your users, we recommend using an [EMM provider](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) to maintain full control over the distribution process, as well as enforce or restrict specific security policies. See the deployment options below for details. + +## Deployment options + +Learn what’s required to build and deploy Mattermost mobile apps. + +- [Configure Microsoft Intune MAM for Mattermost](/deployment-guide/mobile/configure-microsoft-intune-mam) +- [Distribute custom mobile apps](/deployment-guide/mobile/distribute-custom-mobile-apps) +- [Host your own push proxy service](/deployment-guide/mobile/host-your-own-push-proxy-service) +- [Mobile VPN options](/deployment-guide/mobile/consider-mobile-vpn-options) +- [Mobile security features](/deployment-guide/mobile/mobile-security-features) +- [Secure mobile file storage](/deployment-guide/mobile/secure-mobile-file-storage) +- [Mobile apps FAQ](/deployment-guide/mobile/mobile-faq) diff --git a/docs/main/deployment-guide/mobile/mobile-faq.mdx b/docs/main/deployment-guide/mobile/mobile-faq.mdx new file mode 100644 index 000000000000..b463727a211f --- /dev/null +++ b/docs/main/deployment-guide/mobile/mobile-faq.mdx @@ -0,0 +1,368 @@ +--- +title: "Mobile apps FAQ" +--- +## Can I connect to multiple Mattermost servers using the mobile apps? + +Yes, using Mattermost mobile app v2.0. Mobile v1.x only supports connecting to one server at a time. + +## What data is stored? + +The data that can be found on the device depends solely on whether or not the user is logged in to the Mattermost server, and is independent of the state of the device's connection or the state of the app. While logged in, anything that the user is normally allowed to see is eligible for storage on the device, which includes the following content: + +- Messages +- Files and images that are attached to messages +- Profile pictures, usernames, and email addresses of people in the currently open channel + +In addition, metadata that the app uses for keeping track of its operations is also cached. The metadata includes user IDs, channel IDs, team IDs, and message IDs. + +Currently, cache cannot be reset remotely on connected mobile devices. + +### What about push notifications? + +Push notification storage is managed by the operating system on the device. Mattermost can be configured to send limited amounts of information that does not include the message text or channel name, and it can also be configured to not send push notifications at all. + +## Where is the data stored and how is that data protected? + +The data is stored in the app's local storage. It's protected by the security measures that a device normally provides to the apps that are installed on it. + +## How long is the data stored? + +Data is stored until the user logs out, or until it is purged during normal cache management. Deactivating a user account forces a logout and subsequent purging of data from the device. + +## How is data handled after a user account is deactivated? + +App data is wiped from the device when a user logs out of the app. If the user is logged in when the account is deactivated, then within one minute of deactivation the system logs the user out. Thereafter all app data is wiped from the device. + +If file attachments are enabled on the server, users can download files that are attached to messages and store them on their local file system. After they are downloaded, the files are outside the control of the app and can remain on the device indefinitely. + +## Are messages pre-loaded? + +No. Messages are sent to the device on demand. They are not pre-loaded in anticipation of users scrolling up or switching channels. + +## Do I need to compile the mobile apps to host my own push notification server? + +Yes. To host your own push notification server, you'll need to compile the mobile apps. See [documentation](/deployment-guide/mobile/distribute-custom-mobile-apps) to learn how to compile your own mobile apps. + +## How do push notifications work? + +Your Mattermost server sends push notifications to a hosted push proxy server, which relays them via mobile push notification services provided by Apple and Google. + +To ensure push notifications are coming from a trusted source, Apple and Google only allow push notifications sent from a service using a key or signature corresponding to a secret compiled into the mobile app itself. + +The full process is outlined below: + +1. An action triggering a push notification is detected in the Mattermost server running in your private network. +2. Your Mattermost server sends a push notification message to a Mattermost Push Notification Service (MPNS), either self-hosted in your private network, or publicly hosted by Mattermost, Inc. +3. MPNS sends a push notification message to either Apple Push Notification Service (APNS) or to Google’s Firebase Cloud Messaging (FCM) service over a TLS connection. + +> - If sent to Apple, the message has a signature corresponding to a secret compiled in the iOS app. +> - If sent to Google, the message uses a key corresponding to a secret compiled in the Android app. + +Regardless of whether you're using iOS or Android, the MPNS needs to have access to the appropriate secret compiled into the mobile app. + +This means if you use the Mattermost apps from the [Apple App Store](https://www.apple.com/app-store/) or [Google Play Store](https://play.google.com/store/games?hl=en), you need to use the hosted push notification service from Mattermost, Inc. If you compile the apps yourself, you must also compile and use your own MPNS with the corresponding secret. + +4. Either APNS or FCM receives the push notification message from MPNS over TLS, and then relays the message to the user's iOS or Android device to be displayed. + + + +The use of push notifications with iOS and Android applications will require a moment where the contents of push notifications are visible and unencrypted by a server controlled by either Apple or Google. This is standard for any iOS or Android app. For this reason, there is an option available in Mattermost Enterprise to omit the contents of Mattermost messages from push notifications, or to configure message contents to be fetched from the server when notifications reach the device. See our [Configuration Settings](/administration-guide/configure/site-configuration-settings#push-notification-contents) documentation for details. + + + +## Is TLS v1.3 supported? + +Yes. Mattermost mobile app v2.0 supports both TLS v1.2 and TLS v1.3 for websocket connections. + +## What post metadata is sent in mobile push notifications? + +The following post metadata is sent in all push notifications: + +- `Team ID` +- `Channel ID` +- `Post ID` +- `User ID` (post author) +- `Username` (post author or webhook override username) +- `Root ID` (only if the post is in a thread) +- `Type` (create or clear push notification) +- `Category` (iOS only, determines if the notifications can be replied to) +- `Badge number` (what the notification badge on the app icon should be set to when the notification is received) + +Additional metadata may be sent depending on the System Console setting for [Push Notification Contents](/administration-guide/configure/site-configuration-settings#push-notification-contents): + +- **Generic description with sender and channel names**: `Channel name` metadata will be included. +- **Full message content sent in the notification payload**: `Post content` and `Channel name` metadata will be included. +- **Full message content fetched from the server on receipt** (available in Mattermost Enterprise): `Post content` and `Channel name` are not included in the notification payload, instead the `Post ID` is used to fetch `Post content` and `Channel name` from the server after the push notification is received on the device. + +## How can I use ID-Only Push Notifications to protect notification content from being exposed to third-party services? + +When it comes to mobile data privacy, many organizations prioritize secure handling of messaging data, particularly when it may contain mission-critical or proprietary information. These organizations may have concerns about using mobile notifications because data must pass through third-party entities like Apple Push Notification Service (APNS) or Google Firebase Cloud Messaging (FCM) before it reaches a device. + +This poses a potential risk for organizations that operate under strict compliance requirements and cannot expose message data to external entities. To solve this, we offer an option for greater protection for Mattermost push notification message data by only sending a unique message ID in the notification payload rather than the full message data (available in Mattermost Enterprise). Once the device receives the ID, it then fetches the message content directly from the server and displays the notification per usual. + +External entities, such as APNS and FCM, handle only the ID and are unable to read any part of the message itself. If your organization has strict privacy or compliance needs, the [ID-Only Push Notification](/administration-guide/configure/site-configuration-settings#push-notification-contents) setting offers a high level of privacy while still allowing your team members to benefit from mobile push notifications. + +The following payload shows an example of the json that is transmitted to the push notification service when using the ID-Only setting: + +> ``` json +> { +> "ack_id": "nnfbqk5bnffe5karxuzs8o5rec", +> "platform": "apple_rn", +> "server_id": "aoej8izzfffr9e67d6uz3g387h", +> "device_id": "32f198dbdd7427be7e6f03ba721ffdceba58c3f0bfa9c4655a6e7cc8271ba539", +> "post_id": "77d9cs9aq3b1fpoepbdbmqfs4c", +> "category": "CAN_REPLY", +> "message": "You've received a new message.", +> "badge": 3, +> "channel_id": "et3ghiycm7g7bb41ihg85pqgah", +> "type": "message", +> "sender_id": "g774dzud4tgaxgphso4wm8xrxe", +> "version": "v2", +> "is_id_loaded": true +> } +> ``` + +where the following definitions are applied: + +- `ack_id`: An ephemeral identifier generated per notification that determines whether the notification sent was received by the device (using same method that generates identifiers to the rest of the models in the server). This information is available in the `notifications.log` file on the Mattermost server. The `ack_id` is only used for receipt delivery from the mobile app to the Mattermost server to confirm whether the notification sent was received. +- `server_id`: A server identifier created on the server, called `DiagnosticId`. In the future, this value will be used in the mobile app (for multi-server support) to identify which server the notification belongs to. +- `device_id`: The token that APNs and FCM return when you allow the device to receive notifications. So when the user logs into Mattermost, Mattermost sends this `device_id` to attach it to the session. If the session is terminated, the `device_id` is no longer present in the server database because the session record is removed. When the user logs back in, the `device_id` is registered again with the same value because the identifier is specific to the device. This value won't be the same across apps or devices owned by the same person, but will be the same for each session the user creates from the same app on the same device. +- `version`: Tells the mobile app how data is structured so it can parse it properly. Current value is `v2`. +- `is_id_loaded`: (Mattermost Enterprise only) When true, the mobile app look for the contents of the notification on the server because those details are not part of the payload. + +## What are my options for securing the mobile apps? + +The following options for secure mobile app deployments are available: + +1. Securing network connection to mobile apps + +> - Use HTTPS and WSS network connections to encrypt transport. +> - Use of a mobile VPN client on mobile devices to establish secure connection to Mattermost server within private network. + +2. Use multifactor authentication options + +> - If a VPN client with multifactor authentication is not in use, it's highly recommended that MFA is required on authenticating into Mattermost, either within Mattermost itself or via your SSO provider. + +## What are my options for securing push notifications? + +The following options are available for securing your push notification service: + +1. Protecting notification contents + +> - You can [choose what type of information to include in push notifications](/administration-guide/configure/site-configuration-settings#push-notification-contents), such as excluding the message contents if your compliance policies require it. Default server settings have message contents turned off. + +2. Disabling push notifications + +> - Push notifications can also be disabled entirely depending on security requirements. Default server settings have push notifications disabled. + +3. Encrypting connections for apps you compile yourself: + +> - When using a privately-hosted Mattermost Push Notification Service (MPNS), use encrypted TLS connections between: +> - MNPS and Apple Push Notification Service (APNS) +> - MPNS and Google’s Firebase Cloud Messaging (FCM) +> - MPNS and your Mattermost server + +4. Securing apps installed through the Apple App Store and Google Play: + +> - When using Mattermost mobile apps from the App Store and Google Play, purchase an annual subscription to Mattermost Enterprise or Professional to use Mattermost's [Hosted Push Notification Service (HPNS)](/administration-guide/configure/environment-configuration-settings#enable-push-notifications). + + + +For configuration details, see guides for [deploying the Mattermost mobile app](/deployment-guide/mobile/mobile-app-deployment) and [deploying your own version of the apps](/deployment-guide/mobile/distribute-custom-mobile-apps). + + + +## Why do I sometimes see a delay in receiving a push notification? + +[Apple Push Notification Service (APNS)](https://developer.apple.com/documentation/usernotifications) and [Google Fire Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) determine when your device receives a push notification from Mattermost. Thus, a delay is usually as a result of those services. + +The technical flow for the device to receive a push notification is as follows: + +1. User posts a message in Mattermost. +2. Mattermost server identifies if notifications need to be sent. +3. If yes, Mattermost server sends a payload containing the push notification to the push proxy. +4. The push proxy parses the notification and relays it to APNS and FCM. +5. APNS and FCM informs the relevant devices that there is a push notification for Mattermost. This usually happens almost immediately, but may be delayed by a couple of minutes. +6. Mattermost processes the notification and displays it on the user's device. + +## How do I deploy Mattermost with Enterprise Mobility Management (EMM) providers? + +Mattermost enables customers with high privacy and custom security requirements to deploy mobile app and push notification services using keys that they alone control. + +[Learn more about using AppConfig for EMM providers](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider). + +## How do I host the Mattermost push notification service? + +First, you can use the [Mattermost Hosted Push Notification Service (HPNS)](/administration-guide/configure/environment-configuration-settings#enable-push-notifications). Organizations can also [host their own push proxy server](/deployment-guide/mobile/host-your-own-push-proxy-service) instead. This is applicable when you want to: + +1. Customize the Mattermost mobile apps; +2. Deploy your own push notification service, or +3. Repackage the mobile apps with BlueCedar or AppDome (both of which are not officially supported but have been successfully deployed by some organizations). + +## How do I white label the app and customize build settings? + +All files in the `/assets/base` folder can be overridden as needed without conflicting with changes made to the upstream version of the app. To do this: + +1. Create the folder `/assets/override`. +2. Copy any files or folders that you wish to replace from `/assets/base` into `/assets/override`. +3. Make your changes to the files in `/assets/override`. + +When you compile the app or run `make dist/assets`, the contents of those two folders will be merged with files in `/assets/override`, taking precedence in the case of any conflicts. For binary files such as images, an overridden file will completely replace the base version, while `JSON` files will be merged so that fields not set in the overridden copy use the base version. + +For a more specific example of how to use this feature, see the following section. + +## How do I preconfigure the server URL for my users? + +You can preconfigure the server URL and other settings by overriding default `config.json` settings and building the mobile apps yourself. + +1. Fork the [mattermost-mobile repository](https://github.com/mattermost/mattermost-mobile). +2. Create the file `/assets/override/config.json` in your forked mattermost-mobile repository. +3. Copy and paste all the settings from `assets/base/config.json` to the newly-created `/assets/override/config.json` file that you want to override. +4. To override the server URL, set `DefaultServerURL` to the server URL of your Mattermost server in `/assets/override/config.json`. +5. (Optional) If you want to prevent users from changing the server URL, set `AutoSelectServerUrl` to `true`. +6. (Optional) Override any other settings you like. + +After the above, your `/assets/override/config.json` file would look something like this: + +> ``` json +> { +> "DefaultServerURL": "my-mattermost-instance.example.com", +> "AutoSelectServerUrl": true, +> "ExperimentalUsernamePressIsMention": true +> } +> ``` + +7. Finally, [compile your own version](https://developers.mattermost.com/contribute/mobile/build-your-own/) of the Mattermost mobile app and Mattermost push proxy server. + +## How can I get Google SSO to work with the Mattermost mobile app? + +The apps on the Apple App Store and Google Play Store cannot support Google SSO out of the box. This is because Google requires a unique Google API key that's specific to each organization. + +If you need Google SSO support, you can create a custom version of the app for your own organization. Fork the [mattermost-mobile](https://github.com/mattermost/mattermost-mobile) repository and add support for Google SSO before compiling the app yourself. If this is something you’re interested in, please [file an issue in GitHub](https://github.com/mattermost/mattermost-mobile/issues) to start the discussion. + +## How do I configure deep linking? + +The app checks for platform-specific configuration on app install. If no configuration is found, then the deep linking code sits silently and permalinks act as regular links. + +**Set up for iOS** + +1. Create an `apple-app-site-association` file in the `.well-known` directory at the root of your server. It should be accessible by navigating to `https://<your-site-name>/.well-known/apple-app-site-association`. There should not be a file extension. +2. In order to handle deep links, paste the following `JSON` into the `apple-app-site-association` file. Make sure to place your app ID in the `appID` property: + +{/* */} + + { + "applinks": { + "apps": [], + "details": [ + { + "appID": "<your-app-id-here>", + "paths": ["**/pl/*", "**/channels/*"] + } + ] + } + } + +3. Add the associated domains entitlement to your app via the Apple developer portal. +4. Add an entitlement that specifies the domains your app supports via the Xcode entitlements manager. +5. Before installing the app with the new entitlement, make sure that you can view the contents of the `apple-app-site-association` file via a browser by navigating to `https://<your-site-name>/.well-known/apple-app-site-association`. The app will check for this file on install and, if found, will allow outside permalinks to open the app. + +Official documentation for configuring deep linking on iOS can be found [here](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html). + +**Set up for Android** + +Please refer to the the App Links Assistant in Android Studio for configuring [deep linking on Android](https://developer.android.com/studio/write/app-link-indexing). + +## How do I connect users across internal and external networks? + +By setting up global network traffic management, you can send a user to an internal or external network when connecting with a mobile app. Moreover, you can have two separate layers of restrictions on internal and external traffic, such as: + +> - In the internal network, deploy on a private network via per device VPN. +> - In the external network, deploy with [TLS mutual auth](/administration-guide/onboard/ssl-client-certificate) with an NGINX proxy, and [client-side certificates](/administration-guide/onboard/certificate-based-authentication) for desktop and iOS. + +Many services such as Microsoft Azure provide options for [managing network traffic](https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview), or you can engage a services partner to assist. + +## How do I receive mobile push notifications if my IT policy requires the use of a corporate proxy server? + +When your IT policy requires a corporate proxy to scan and audit all outbound traffic the following options are available: + +### Deploy Mattermost in a proxy-aware configuration with a pre-proxy relay + +The Mattermost push notification service is designed to send traffic directly to the [Apple Push Notification Service (APNS)](https://developer.apple.com/documentation/usernotifications) and [Google Fire Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) services. + +In a proxy-aware configuration, a pre-proxy relay accepts messages from the [Mattermost Push Proxy](https://developers.mattermost.com/contribute/mobile/push-notifications/service/) and forwards them to a corporate proxy enforcing your internal IT requirements, before transmitting to their final destination. + +See a sample architectural overview below: + +![The Mattermost push notification service is designed to send traffic directly to the Apple Push Notification Service (APNS) and Google Fire Cloud Messaging (FCM) services. However, if your organization requires a corporate proxy to scan and audit all outbound traffic, you can deploy Mattermost in a proxy-aware configuration with a pre-proxy relay. The relay accepts messages from the Mattermost Push Proxy, and forwards them to a corporate proxy that enforces your internal IT requirements before delivering the notification to a mobile device. This configuration requires a trusted root certificate.](/images/mobile-pre-proxy-relay.png) + +This enables the **pre-proxy relay** to act as the APNS and to forward the request to its final destination via your corporate proxy, not requiring the APNS traffic to be proxy-aware. The APNS traffic is redirected to the pre-proxy relay via `/etc/hosts` entry. The entry uses a trusted CA that signs a certificate for the Mattermost Push Proxy to trust the pre-proxy relay. See the Apple Developer documentation on [user notifications](https://developer.apple.com/documentation/usernotifications) for more information. + +Google's [FCM traffic](https://firebase.google.com/docs/cloud-messaging) is proxy-aware via environment variables, so no actions are required for it. + +Moreover, APNS traffic requires HTTP/2, so your corporate proxy server must support HTTP/2 requests in order to send the push notifications to Apple devices. HTTP/2 support for the pre-proxy relay is also required. + +### Deploy Mattermost with connection restricted post-proxy relay in DMZ or a trusted cloud environment + +Some legacy corporate proxy configurations may be incompatible with the requirements of modern mobile architectures, such as the requirement of HTTP/2 requests from Apple to send push notifications to iOS devices. + +In this case, a post-proxy relay can be deployed to take messages from the Mattermost server passing through your corporate IT proxy in the incompatible format, e.g. HTTP/1.1, transform it to HTTP/2 and relay it to its final destination, either to the [Apple Push Notification Service (APNS)](https://developer.apple.com/documentation/usernotifications) and [Google Fire Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) services. + +Ths **post-proxy relay** [can be configured using the Mattermost Push Proxy installation guide](https://developers.mattermost.com/contribute/mobile/push-notifications/service/) with connection restrictions to meet your custom security and compliance requirements. + +In place of a DMZ, you can also host in a trusted cloud environment such as AWS or Azure depending on your internal approvals and policies. + +![The Mattermost push notification service is designed to send traffic directly to the Apple Push Notification Service (APNS) and Google Fire Cloud Messaging (FCM) services. However, if your organization doesn't support HTTP/2 requests to send push notifications to mobile devices, you can deploy a post-proxy relay to take messages form the Mattermost server, transform it from the incompatible format, and relay it to its final destination. The post-proxy relay can be configured using connection restrictions to meet your custom security and compliance requirements.](/images/mobile-post-proxy-relay.png) + +### Whitelist Mattermost push notification proxy to bypass your corporate proxy server + +Depending on your internal IT policy and approved waivers/exceptions, you may choose to deploy the [Mattermost Push Proxy](https://developers.mattermost.com/contribute/mobile/push-notifications/service/) to connect directly to [Apple Push Notification Service (APNS)](https://developer.apple.com/documentation/usernotifications) without your corporate proxy. + +You will need to [whitelist one subdomain and one port from Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1) for this option: + +- Development server: `api.development.push.apple.com:443` +- Production server: `api.push.apple.com:443` + +### Run App Store versions of the Mattermost mobile apps + +You can use the mobile applications hosted by Mattermost in the [Apple App Store](https://apps.apple.com/ca/app/mattermost/id1257222717) or [Google Play Store](https://play.google.com/store/apps/details?id=com.mattermost.rn) and connect with the [Mattermost Hosted Push Notification Service (HPNS)](/administration-guide/configure/environment-configuration-settings#hosted-push-notifications-service-hpns)) through your corporate proxy. + + + +The use of hosted applications by Mattermost [can be deployed with Enterprise Mobility Management solutions via AppConfig](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) but wrapping is not supported. See the [product documentation](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider#manage-app-configuration-using-appconfig) for details. + + + +### How the `deviceId` behaves + +The `deviceId` is a identifier provided by a push notification service, such as Apple Push Notification service (APNs) and Firebase Cloud Messaging (FCM), that identifies the relationship between device, app, and the notification service. + +When the app starts, if the push notification permissions are enabled, the app will try to connect with the corresponding notification service (APNs for iOS, FCM for Android) to get the `deviceId`. If there is any change to the `deviceId`, the app will notify any connected server about this change. + +Based on the [Apple Developer Documentation on registering apps with APNS](https://developer.apple.com/documentation/usernotifications/registering-your-app-with-apns?changes=_8) and the [Google Documentation on FCM](https://firebase.google.com/docs/cloud-messaging/android/client#java_1), the `deviceId` only will change in the following cases: + +- The app is restored from a backup from a different device +- The user clears the app data +- The user reinstalled the app +- The user installed the app on a different device + +If the device has a `deviceId`, when the user logs into a Mattermost server, an audit log entry `login` will store the `deviceId`, and the `deviceId` will also be added in the session data in the database. However, it's possible the `deviceId` isn't available, due to several reasons including: + +- The device is not connected to the network +- The notification service is not reachable for any reason +- The app is not properly signed +- The device has not been granted the needed permissions + +In these scenarios, the `login` audit log won't have the `deviceId`, and the session data won't have the `deviceId`. If the app receives the `deviceId` later, the device will send the new `deviceId` to the server, generating an `attachDeviceId` audit log, and adding the `deviceId` to the session data in the database. + +Since the `deviceId` relates to the application, connections through the web browser, even on mobile, won't have a `deviceID`. + +## Where can I find mobile message notification logs? + +Notification messages are logged to the `notifications.log` file. System admins must enable notification logs in the `config.json` file by setting `EnableFile` to `true`, and specifying an optional file location via `FileLocation`. When no location is configured, the `notifications.log` file is stored in the default Mattermost directory. See the [logging configuration settings](/administration-guide/configure/environment-configuration-settings#logging) documentation for details. + +The team members / users can access their notification logs based on their device platform. Android users can view the logs using `logcat`. iOS users can acess the logs in the `console app` on their MacOS. + +## How do I gather mobile app logs? + +See the Mattermost Support Knowledge Base article on [gathering mobile app logs](https://support.mattermost.com/hc/en-us/articles/30147601934100-How-to-Gather-Mobile-App-Logs) for details. diff --git a/docs/main/deployment-guide/mobile/mobile-security-features.mdx b/docs/main/deployment-guide/mobile/mobile-security-features.mdx new file mode 100644 index 000000000000..620ca225adda --- /dev/null +++ b/docs/main/deployment-guide/mobile/mobile-security-features.mdx @@ -0,0 +1,128 @@ +--- +title: "Mobile security features" +--- + + +This document outlines the key security features implemented in the mobile application, explains the significance of each control, and details our continuous security practices to maintain an up-to-date security posture. + +## Jailbreak and root detection + +Mattermost leverages built-in checks from the Expo framework to identify jailbroken (iOS) and rooted (Android) devices: + +- On **Android**, the app looks for the presence of known jailbreak/root binaries, such as the `su` binary in `/system/xbin/su`, which is a common indicator that the device has been rooted to allow unauthorized elevated access. +- On **iOS**, the detection process involves checking for unusual apps (e.g., Cydia), modified system paths, and testing whether the app can alter protected system files—all signs that the device may be jailbroken. + +See the [jailbreak/root protection configuration setting](/administration-guide/configure/environment-configuration-settings#enable-jailbreak-root-protection) documentation for details on enabling this feature. + + + +Client-side detection methods are not bulletproof and can be bypassed by a sufficiently motivated user with root or jailbreak access. Determined users can employ reverse engineering to disable or modify these checks to produce false positives/negatives or even modify and recompile the source code to remove them entirely, allowing app usage on rooted/jailbroken devices. + + + +## Biometric authentication + +Mattermost integrates with iOS Face ID/Touch ID and Android’s Biometric API. When enabled by the server administrator, biometric checks are required before accessing specific servers, and the Mattermost mobile app mandates that a device PIN or biometric lock is active. + +See the [biometric authentication configuration setting](/administration-guide/configure/environment-configuration-settings#enable-biometric-authentication) documentation for details on enabling this feature and the user workflows in which users must authenticate. + + + +Biometric authentication, such as Face ID or fingerprint recognition, is handled by the device’s operating system. Mattermost does not provide or warrant the biometric functionality. The app will unlock if the OS determines that the biometric input is a positive match. Accuracy, security, and availability of biometric authentication depend entirely on the device and its underlying platform. + + + +## Screenshot and screen recording prevention + +Preventing screenshots and screen recordings protects sensitive information from being inadvertently or maliciously shared. This control is essential in ensuring that confidential communications and data remain within the secure confines of the app. By blocking unauthorized screen captures, Mattermost significantly reduces the risk of data leakage via visual content. + +- On **iOS**, the app detects attempts to capture the screen. For screen recordings, it immediately applies a blur overlay to the view to obscure any sensitive information, while screenshots will capture no content at all. +- On **Android**, the app utilizes the FLAG_SECURE flag to block screen captures and recordings. + +See the [prevent screen capture configuration setting](/administration-guide/configure/environment-configuration-settings#prevent-screen-capture) documentation for details on enabling this feature. + + + +This feature prevents screen recording and screenshot capture on the mobile device where the Mattermost app is running. It cannot control or prevent recording from external devices, such as another phone or camera pointed at the screen. Mattermost provides these protections through mobile OS-level capabilities but cannot guarantee absolute prevention of visual data capture through other means. + + + +## Secure file previews + +Preventing file downloads protects sensitive information from being inadvertently or maliciously shared. This control is essential in ensuring that confidential documents and media remain within the secure confines of the app. By enabling in-app previews for supported file types and restricting downloads, Mattermost significantly reduces the risk of data leakage while maintaining essential file-viewing capabilities. + +See the [secure file preview](/administration-guide/configure/environment-configuration-settings#enable-secure-file-preview-on-mobile) and [managing PDF link navigation](/administration-guide/configure/environment-configuration-settings#allow-pdf-link-navigation-on-mobile) configuration settings documentation for details on enabling these features. + +## Microsoft Intune Mobile Application Management (MAM) + +Mattermost supports Microsoft Intune MAM to enforce identity-based, app-level data protection on iOS devices without requiring full device enrollment in a mobile device management (MDM) solution. + + + +Microsoft Intune MAM enforcement for Mattermost is currently supported on **iOS** only. We recommend using Android for Work profiles until Android Intune support is available. + + + +Intune MAM applies security policies directly to the Mattermost mobile app using Microsoft Entra ID as the identity authority. This enables organizations to protect corporate or mission-sensitive data on Bring Your Own Device (BYOD) and mixed-use devices while preserving user privacy. + +Key security capabilities enabled through Intune MAM include: + +- **Mandatory enrollment** before accessing Mattermost on mobile +- **Identity-based enforcement** using Microsoft Entra ID +- **Selective wipe** of Mattermost work data without affecting personal apps or device data +- **Clipboard, file sharing, and data transfer restrictions** +- **Screenshot and screen recording prevention** +- **Managed browser enforcement** and controlled link handling +- **Immediate enforcement** when policies or licensing change, including during active sessions + +Intune MAM enforcement is applied **per Mattermost workspace** and evaluated continuously at runtime. If a device becomes non-compliant, enrollment fails, or required policies are not met, access to protected content is blocked automatically. + +This approach allows organizations to extend zero-trust and data loss prevention (DLP) controls to mobile users without assuming ownership or management of the underlying device. + +See the [Microsoft Intune MAM configuration guide](/deployment-guide/mobile/configure-microsoft-intune-mam) for deployment and configuration details. + +## Mobile data isolation + +Mattermost mobile applications are designed to ensure that sensitive data is stored securely and isolated from other applications on the device. This isolation is achieved through a combination of OS-level security features, app sandboxing, and secure data storage practices. + +Mattermost stores 3 types of data within the mobile app: + +- **SQLite Database**: For offline access to posts and channels that the user has viewed. +- **Cached Files**: For temporary storage (e.g., PDFs) of viewed files. They are periodically purged. +- **Logs**: Minimal logs kept for troubleshooting purposes. + +The Mattermost mobile app for Apple iOS and Android devices uses the native OS security architecture to encrypt data-at-rest on mobile devices, ensuring that stored information remains secure even if the device is lost or stolen. This encryption protects sensitive data, such as messages and files, from unauthorized access. + +Data stored by the Mattermost mobile app only resides within the app’s private storage container. This storage location is isolated by each platform’s rigorous sandboxing model. Learn more about [secure file storage](/deployment-guide/mobile/secure-mobile-file-storage) for Mattermost mobile applications. + +### Security measures + +- **OS sandboxing & app access isolation**: Mattermost’s data is confined within its app-specific sandbox (see [Apple’s iOS sandboxing](https://support.apple.com/guide/security/security-of-runtime-process-sec15bfe098e/web) and [Android’s sandboxing](https://source.android.com/docs/security/app-sandbox) guidelines). This sandboxing mechanism ensures that all stored data—whether in the SQLite databases, cached files, or logs—is isolated and inaccessible to other applications. This is why TikTok, and any other application is blocked from accessing Mattermost data. + - **iOS** employs a rigorous sandboxing model that relies on containerized file systems and strict process isolation. Each app operates within its own sandbox, with its home directory randomly assigned during installation. As a result, data stored within the Mattermost app’s sandbox directory remains accessible only to the app unless explicitly shared by the user. + - **Android** employs scoped storage by assigning each app its own Linux user ID and a dedicated private directory. This model prevents other applications from accessing an app’s private directory without explicit permission. As a result, the Mattermost app’s data remain inaccessible to other apps—unless the device is rooted, or the user explicitly shares the data. +- **Cache invalidation**: Cached files are periodically deleted. +- **No Google or Apple Cloud backup**: Mattermost files are not backed up during normal cloud backup procedures. + - On **Android**, the application explicitly disables backups (using the appropriate manifest settings), ensuring that all Mattermost files remain strictly on-device. + - On **iOS**, although the operating system automatically backs up files stored in the app's `Documents` folder, Mattermost intentionally stores its files in the `Library/Caches` directory, which is excluded from iCloud backups. +- **Controlled data export**: Data only leaves Mattermost through explicit user actions such as: + - Manually exporting a file. + - Takes a screenshot (if not blocked by policy or with a secondary camera). + - Sharing content using OS features (e.g., share sheet). + + + +This feature restricts direct access to stored data through robust OS-level sandboxing and storage controls. However, it cannot prevent unauthorized extraction if attackers employ alternative methods. For instance, on jailbroken (iOS) or rooted (Android) devices, where system integrity is compromised, an attacker may bypass standard security measures. + +Similarly, exploiting zero-day or known OS vulnerabilities—or malicious apps that exploit permission weaknesses—could grant access to device storage. Mattermost uses mobile OS-level safeguards but cannot guarantee absolute prevention of such unauthorized data access. + + + +## Security compliance + +- **Secure SDLC**: The mobile app adheres to the same secure Software Development Lifecycle (SDLC) process as all Mattermost components. This guarantees that new mobile features undergo comprehensive security reviews and that any issues are addressed before release. +- **Vulnerability management**: The Mattermost mobile app is included in Mattermost’s public bug bounty program, inviting security researchers to rigorously assess the application. Additionally, established remediation SLAs ensure that any security issues are resolved promptly. +- **Continuous dependency scanning**: Mattermost uses Snyk Open Source to conduct daily scans of all dependencies. This continuous approach ensures that any newly disclosed vulnerabilities are quickly identified and addressed within defined SLAs. +- **BESPIN compliance**: Mattermost adheres to strict security evaluations including: + - Device Protection Profiles (NIAP Evaluation) + - Security Dependency & Code Analysis + - Code Complexity & Testing Standards diff --git a/docs/main/deployment-guide/mobile/mobile-troubleshooting.mdx b/docs/main/deployment-guide/mobile/mobile-troubleshooting.mdx new file mode 100644 index 000000000000..87dfc200f672 --- /dev/null +++ b/docs/main/deployment-guide/mobile/mobile-troubleshooting.mdx @@ -0,0 +1,126 @@ +--- +title: "Mobile deployment troubleshooting" +--- + + +## I keep getting a message "Cannot connect to the server. Please check your server URL and internet connection." + +First, confirm that your server URL has no typos and that it includes `http://` or `https://` according to the server deployment configuration. + +If the server URL is correct, there could be an issue with the SSL certificate configuration. + +To check your SSL certificate set up, test it by visiting a site such as [SSL Labs](https://www.ssllabs.com/ssltest/index.html). If there’s an error about the missing chain or certificate path, there is likely an intermediate certificate missing that needs to be included. + +Please note that the apps cannot connect to servers with self-signed certificates, consider using [Let's Encrypt](/deployment-guide/server/setup-nginx-proxy#configure-nginx-with-ssl-and-http-2) instead. + +## Login with ADFS/Office365 is not working + +In line with Microsoft guidance we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). + +## I see a “Connecting…” bar that does not go away + +If your app is working properly, you should see a grey “Connecting…” bar that clears or says “Connected” after the app reconnects. + +If you are seeing this message all the time, and your internet connection seems fine, ask your server administrator if the server uses NGINX or another webserver as a reverse proxy. If so, they should check that it is configured correctly for [supporting the websocket connection for APIv4 endpoints](/deployment-guide/server/setup-nginx-proxy#configure-nginx-as-a-proxy-for-mattermost-server). + +## All my outbound connections need to go through a proxy. How can I connect to the Mattermost Hosted Push Notification Service? + +You can set up an internal server to proxy the connection out of their network to the Mattermost Hosted Push Notification Service (HPNS) by following the steps below: + +1. Make sure your proxy server is properly configured to support SSL. Confirm it works by checking the URL at [https://www.digicert.com/help/](https://www.digicert.com/help/). +2. Setup a proxy to forward requests to `https://push.mattermost.com`. +3. In Mattermost set **System Console** \> **Notification Settings** \> **Mobile Push** \> **Enable Push Notifications** in prior versions or **System Console \> Environment \> Push Notification Server \> Enable Push Notifications** in versions after 5.12 to "Manually enter Push Notification Service location" +4. Enter the URL of your proxy in the **Push Notification Server** field. + + + +Depending on how your proxy is configured you may need to add a port number and create a URL like `https://push.internalproxy.com:8000` mapped to `https://push.mattermost.com` + + + +## Build gets stuck at `bundleReleaseJsAndAssets` + +As a workaround, you can bundle the `js` manually first with + +``` sh +react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ +``` + +and then ignore the gradle task with + +``` sh +./gradlew assembleRelease -x bundleReleaseJsAndAssets +``` + +## No image previews available in the mobile app + +This can happen if the server running Mattermost has its mime types not set up correctly. A server running Linux has this file located in `/etc/mime.types`. This might vary depending on your specific OS and distribution. + +Some distributions also ship without `mailcap` which can result in missing or incorrectly configured mime types. + +## Messages with emojis aren't being sent from the Mobile App + +This can occur if the server running Mattermost is configured with an incorrect character set. To resolve this issue, in the `config.json` file under `SqlSettings`, ensure that the `DataSource` key is configured correctly, then restart the Mattermost server. + +For example: + +``` text +"SqlSettings": { + "DataSource": "@/mattermost?charset=utf8mb4,utf8", + [...] + } +``` + +See our [Configuration Settings](/administration-guide/configure/environment-configuration-settings#data-source) documentation for details on configuring the connection string to the master database. + +## Testing mobile push notifications + +Make sure to configure push notifications for your [pre-built mobile apps](/deployment-guide/mobile/mobile-app-deployment), or for [your custom built mobile apps](/deployment-guide/mobile/distribute-custom-mobile-apps). + +Then use the following instructions to confirm push notifications are working properly. + +1. Log in to your mobile app with an account on your Mattermost Server, which we’ll refer to as “Account A”. +2. (iOS) When the app asks whether you wish to receive notifications, **confirm you want to receive notifications**. + +> Mattermost prompts you to confirm whether you want to allow mobile push notifications. To test mobile push notifications, you must select Allow. + +3. Confirm push notifications are enabled for “Account A”. + +> 1. Go to the notification settings menu in the mobile app. +> +> Access notification settings by selecting your profile picture to access Settings > Notifications. +> +> 2. Check that the mobile push notifications are set to send. +> +> Select Push Notifications to confirm when mobile push notifications will be sent. +> +> Specify whether all new messages or only mentions and direct messages send push notifications. + +4. Have “Account A” put the app to background or close the app. +5. Using a browser, log in to “Account B” on the same Mattermost Server. +6. Open a direct message with “Account A”, and send a message. +7. A push notification with the message should appear on the mobile device of “Account A”. + +## Troubleshooting push notifications + +If you did not receive a push notification when testing push notifications, use the following procedure to troubleshoot: + +1. In **System Console \> Environment \> Logging \> File Log Level**, select **DEBUG** in order to watch for push notifications in the server log. +2. Delete your mobile application, and reinstall it. +3. Log in with "Account A" and **confirm you want to receive push notifications** when prompted by the mobile app. +4. Go to **Profile** \> **Security** \> **View and Logout of Active Sessions** to confirm that there is a session for the native mobile app matching your login time. +5. Retest push notifications. +6. If no push notification displays, go to **System Console** \> **Server Logs**, then select **Reload**. Look at the bottom of the logs for a message similar to: + +`[2016/04/21 03:16:44 UTC] [DEBG] Sending push notification to 608xyz0... wi msg of '@accountb: Hello'` + +> - If the log message displays, it means a message was sent to the HPNS server and was not received by your mobile app. Please [create a support ticket](https://support.mattermost.com/hc/en-us/requests/new) with the subject "HPNS issue" for help from Mattermost's Support team. +> - If the log message does not display, it means no mobile push notification was sent to “Account A”. Please repeat the process starting at step 2 and double-check each step. + + + +To conserve disk space, once your push notification issue is resolved, go to **System Console \> Environment \> Logging \> File Log Level**, then select **ERROR** to switch your logging detail level from **DEBUG** to **Errors Only**. + + + +If push notifications are not being delivered on the mobile device, confirm that you're logged in to the **Native** mobile app session through **Profile \> Security \> View and Log Out of Active Sessions**. Otherwise, the DeviceId won't get registered in the Sessions table and notifications won't be delivered. diff --git a/docs/main/deployment-guide/mobile/secure-mobile-file-storage.mdx b/docs/main/deployment-guide/mobile/secure-mobile-file-storage.mdx new file mode 100644 index 000000000000..c4769871bfbd --- /dev/null +++ b/docs/main/deployment-guide/mobile/secure-mobile-file-storage.mdx @@ -0,0 +1,163 @@ +--- +title: "Secure file storage" +--- + + +This document outlines the security measures governing file storage in the Mattermost mobile app for iOS and Android. It describes how files are stored, accessed, and protected within the application container, addressing concerns related to sensitive data on mobile devices. The objective is to ensure that only authorized personnel can view, access, or share such data while preventing exposure to unauthorized parties and ensuring isolation from third-party applications. + +Mattermost leverages robust sandboxing mechanisms on both iOS and Android to securely store files in its cache folder within the application container, ensuring isolation from unauthorized third-party apps. User-initiated actions (download, share, copy link) are controlled by server-side permissions, allowing administrators to restrict access to sensitive data, like HIPAA-regulated information, to authorized personnel only. + +## File storage and app sandbox security + +Files uploaded or accessed via the Mattermost mobile app are stored in the app’s cache folder, which resides within the app’s private storage container. This storage location is isolated by each platform’s sandboxing model: + +### iOS – app sandbox + +- **Sandboxing & storage:** + + iOS employs a rigorous sandboxing model that relies on containerized file systems and strict process isolation. Each app operates within its own sandbox, with its home directory randomly assigned during installation. As a result, files stored within the Mattermost app’s cache folder remain accessible only to the app unless explicitly shared by the user. + +- **Secure file viewing:** + + - Non-image and non-video files are rendered using secure frameworks such as QLPreviewController. This controller displays file previews within the app’s sandbox, ensuring that raw file data isn’t exposed to external processes. + - Supported image and video files are previewed directly within the app, with the files downloaded to the app's cache folder located within its secure sandbox. For unsupported image and video formats, the Mattermost mobile app uses the QLPreviewController framework, just as it does for other file types. + - If the file format is also unsupported by QLPreviewController and [mobile downloads are enabled](/administration-guide/configure/site-configuration-settings#allow-file-downloads-on-mobile) on the server, users can download the file to a location of their choosing. However, if mobile downloads are disabled, these files become unavailable to the user. + +- **Official references:** + + - [Apple App Sandbox Design Guide](https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html) + - [Security of runtime process in iOS, iPadOS and visionOS](https://support.apple.com/en-gb/guide/security/sec15bfe098e/web) + - [Apple Security Guide](https://help.apple.com/pdf/security/en_GB/apple-platform-security-guide-b.pdf) + +### Android – scoped storage + +- **Sandboxing & storage:** + + Android employs scoped storage by assigning each app its own Linux user ID and a dedicated private directory. This model prevents other applications from accessing an app’s cache without explicit permission. As a result, the Mattermost app’s files remain inaccessible to other apps—unless the device is rooted, or the user explicitly shares the data. + +- **Secure file viewing:** + + - When users attempt to view non-image/video files, Mattermost uses an `Intent.ACTION_VIEW` to open the file. This intent delegates rendering to an external app only if the user explicitly triggers the action, while the file remains securely stored within Mattermost’s cache folder. + - Viewing non-image/video files is available only if [mobile downloads are enabled](/administration-guide/configure/site-configuration-settings#allow-file-downloads-on-mobile) on the server. + - Image and video files with supported formats are previewed directly within the app, with the files downloaded to the app's cache folder located within its secure sandbox. For unsupported image and video formats, the Mattermost mobile app uses `Intent.ACTION_VIEW` to open the file with an external application, just as it does for other file types. + +- **Official reference:** + + - [Scoped Storage](https://developer.android.com/about/versions/10/privacy/changes#scoped-storage) + +Additionally, both platforms may clear cached data automatically (e.g., under low storage conditions or upon user logout), thereby reducing the risk of sensitive information remaining on the device. + +## Differentiating file handling to external applications + +- **Previewing files:** + + File previewing follows the secure viewing practices described above in the “Secure File Viewing” sections for iOS and Android. All files prior to being previewed are stored in the cache folder of the Mattermost app sandbox. Images and videos with supported formats are previewed directly within the Mattermost mobile app. Non‑image and non‑video files are also previewed in-app in iOS but are handed off to an external application in Android while the raw data remains securely stored in the app’s cache. Previewing non-image/non-video files is possible only if [mobile downloads are enabled](/administration-guide/configure/site-configuration-settings#allow-file-downloads-on-mobile) on the server side. + +- **Downloading files:** + + - When a user initiates a file download, the file is first stored in Mattermost’s private cache directory. The user is then immediately prompted to save it to another destination via platform-specific sharing methods. + - On **iOS** devices: + - The built-in sandboxing ensures that the downloaded files remain inaccessible to other apps unless the user explicitly shares or saves them through the system’s file sharing mechanisms. Once downloaded, the file appears in the gallery. + - If the server has the download setting enabled, the user has two options: + 1. Download the file: Opens the **Files** app, allowing the user to save the file to any permitted location, including iCloud. + 2. Share the file: Launches the native share sheet, enabling the user to share the file with other compatible applications. + - On **Android** devices, the app employs the system’s file picker. This allows the end-user to select a preferred storage location. Once saved, the file becomes accessible to other apps based on the chosen location and the device’s file sharing permissions. + +## File accessibility options + +Depending on server configuration, users may download files, share them, or copy a public link directly from the Mattermost mobile app. These actions are always user‑initiated, ensuring that sensitive data is only exposed with explicit consent. + +Additionally, administrators have the option to restrict mobile file uploading and downloading to ensure that sensitive content remains within approved channels. When mobile file downloads are disabled, the app allows only image and video file previews. However, if general file sharing is enabled on the Mattermost server, file operations via mobile browsers will still be possible. + +## Layered defense strategies for sensitive eata + +Mattermost is designed to protect sensitive data—such as sensitive information and HIPAA-regulated information—by ensuring that only authorized personnel can access or share it. The platform combines secure mobile app features with powerful server-side controls, providing a layered defense that minimizes the risk of data exposure. + +### Core defense pillars + +- **Robust authentication:** Mattermost requires user authentication through SSO (e.g., SAML, LDAP, OpenID Connect) or traditional username/password logins. This authentication is managed by server-side identity controls, ensuring that only verified users can access the app and its data. For more details, see the [Mattermost Security Overview](/security-guide/security-guide-index). +- **Server-side access controls:** Administrators can enforce policies through the System Console to restrict file downloads, sharing, and public link generation. Currently, policies are applied at the server level. For more details, see [Configuration Settings - File Sharing and Downloads](/administration-guide/configure/site-configuration-settings#file-sharing-and-downloads). +- **Sandbox isolation:** As discussed earlier, Mattermost’s mobile apps store files in a sandboxed environment. This isolation ensures that even if a device is shared or compromised, other apps cannot access the cached files without explicit user action. +- **Controlled file previews:** File previews (via QLPreviewController on **iOS** or open intent on **Android**) occur within the application’s controlled environment or delegate to OS-approved apps without duplicating sensitive data outside the sandbox. +- **OS-Level encryption:** While files in the cache folder are stored unencrypted by default, they are protected at rest by OS-level encryption (iOS File Data Protection and Android Full Disk Encryption). + +By combining strict authentication, server-side controls, sandbox isolation, and secure file handling, Mattermost ensures that sensitive data remains confined to authorized users, with access and sharing tightly controlled by server policies, platform security features, and explicit user consent. + +## Testing procedure to validate file isolation + +The playbook below aims to test and confirm that files stored in the Mattermost app’s private cache folder—where sensitive data may reside—are not accessible by unauthorized third-party applications. The tests are designed to show that while public directories, such as Downloads/ can be accessed, the private Mattermost cache remains isolated unless a file is explicitly shared by an authorized user. + +1. **Preparation** + + - On **Android**: + - Install Adobe Acrobat Reader for PDF viewing. + - Install Files by Google as a file manager. + - Install Google Chrome as a system browser. + + - On **iOS**: + - Install Adobe Acrobat Reader (from the App Store). + - Use the built-in Files app. + - Use Safari as the default browser. + + - Any PDF viewer, file manager, or browser can be used for these steps. + +2. **Control test: Verify public directory accessibility** + + - **Android:** + - Open Files by Google. + - Navigate to a known public directory (e.g., Downloads/). + - Confirm that files in this location are visible and can be opened. + + - **iOS:** + - Open the Files app. + - Browse to an accessible directory (e.g., iCloud Drive or “On My iPhone” public folders). + - Confirm these files are accessible. + + This step demonstrates that allowed directories can be accessed, setting a baseline for comparison. + +3. **Attempt unauthorized access to Mattermost’s private cache** + + - **Android:** + - In Files by Google, try navigating through the directory structure to identify files of the Mattermost application. + - Verify that you cannot access private directories such as Mattermost app’s private cache folder. + + - **iOS:** + - Open the Files app. + - Verify that the Mattermost app’s private cache folder does not appear under “On My iPhone/iPad.” + +4. **Attempt unauthorized access to a specific file in Mattermost’s private cache** + + - **Android:** + - Use the search functionality in Files by Google to search for a known file name from the Mattermost cache. + - Verify that the file does not appear in search results. + + - **iOS:** + - Use the Files app’s search capability to look for a specific file name from the Mattermost cache. + - Confirm that the file does not appear in search results. + +5. **Attempt authorized access to downloaded file** + + - **Android:** + - Confirm that mobile downloads are enabled on the server. + - Download a file using the Mattermost mobile app. + - Open the Files by Google app and verify that the downloaded file is visible and opens correctly. + + - **iOS:** + - Confirm that mobile downloads are enabled on the server. + - Download a file using the Mattermost mobile app. + - Open the iOS Files app and verify that the downloaded file appears and can be opened successfully. + +6. **Repeat across multiple apps and devices** + + The steps above use the Files app of Google and iOS. Repeat these tests using each suggested app on different devices and OS versions (both Android and iOS) to ensure that the private cache folder remains inaccessible under all conditions. + +## Test execution & findings + +Mattermost executed the playbook above, including scanning for hidden files, both during normal operation and after forcing the app to stop or crash, and observed the following results: + +- **Devices Tested**: iPhone 12, iOS 18.4, Android 11 +- **Apps Used**: Adobe Reader, Google Files app, Android’s native Files app, iOS Files app, Files Media Manager, Hidden Files Finder, Hidden Files Finder & Recover +- **Results**: Third-party file browsers and recovery tools consistently failed to access the Mattermost app’s cache folder or its contents. Access was only possible when files were explicitly downloaded or shared via Mattermost’s controlled functionality by an authorized user. +- **Outcome**: Files remain isolated within the app container, adhering to platform security guidelines and protecting against unauthorized access. + +The documented testing procedures confirm that the app’s file storage remains inaccessible to unauthorized third-party applications, thereby maintaining a strong security posture. Coupled with strong authentication and native OS encryption, the Mattermost mobile app provides a robust framework that keeps sensitive data on mobile devices confined to authorized users while addressing key access control and risk mitigation requirements. diff --git a/docs/main/deployment-guide/postgres-migration-assist-tool.mdx b/docs/main/deployment-guide/postgres-migration-assist-tool.mdx new file mode 100644 index 000000000000..ceb5e1587948 --- /dev/null +++ b/docs/main/deployment-guide/postgres-migration-assist-tool.mdx @@ -0,0 +1,206 @@ +--- +title: "Automated PostgreSQL migration" +--- + + +Migrating databases can be a daunting task, and it can be easy to overlook or misinterpret some of the required steps if you haven't performed a migration before. Our `migration-assist` tool provides an efficient, error-free migration experience that automates the [tasks to be executed](/deployment-guide/manual-postgres-migration), even in air-gapped deployment environments. + +Not sure this tool is right for your Mattermost deployment? Mattermost customers looking for tailored guidance based on their Mattermost deployment can contact a [Mattermost Expert](https://mattermost.com/contact-sales/). + +## Install + +Download the Mattermost `migration-assist` tool from the GitHub repository [releases page](https://github.com/mattermost/migration-assist/releases). + +While you can run the `migration-assist` tool on the same server as your Mattermost deployment, we recommend running the tool in a virtual machine on the same network as your Mattermost server instead. The tool itself is lightweight and does not require a large server. A server with 2 CPU cores and 16 GB of RAM should be sufficient. If preferred, you can download and [compile](#compile-the-migration-assist-tool) the `migration-assist` tool yourself. + +You'll also need to install the `pgloader` tool to migrate your data from MySQL to PostgreSQL. We recommend running `pgloader` in a virtual machine on the same network as your Mattermost server. You can use our official Mattermost Docker image for pgloader (`mattermost/pgloader:latest`); please note that it does **not** currently support MySQL’s `caching_sha2_password` authentication plugin. If you require `caching_sha2_password` support, you’ll need to build your own image and include the [qitab/qmynd](https://github.com/qitab/qmynd) library. See the [pgloader](/deployment-guide/manual-postgres-migration#install-pgloader) installation documentation for details. + +## Usage + + + +- If you encounter heap exhaustion errors in `pgloader`, edit your generated `migration.load` and under the `WITH` block set: `prefetch rows = 1000` and consider reducing it if the issue persists. +- Please make sure you have the necessary environment to perform the migration. Ensure that the MySQL and PostgreSQL databases are running and accessible. To set up a PostgreSQL instance, see the [prepare your Mattermost database](/deployment-guide/server/preparations) documentation for details. +- If you were previously utilizing a database for handling the [Mattermost configuration](/administration-guide/configure/configuration-in-your-database), those tables will not be migrated from your MySQL database with the migration [script](#migrate-the-data). You will need to manually migrate those configuration settings to your PostgreSQL database after completing the migration process. See the [configuration in database](/deployment-guide/manual-postgres-migration#configuration-in-database) documentation for details. + + + +### Step 1 - Check the MySQL database schema + +Run the following command to check the MySQL database schema: + +``` sh +migration-assist mysql "" # example DSN: "user:password@tcp(address:3306)/db_name" +``` + +This command outputs the readiness status and prints required fixes for common issues. The flags for fixes are as follows (you can combine all of them): + +``` text +--fix-artifacts Removes the artifacts from older versions of Mattermost +--fix-unicode Strips unsupported Unicode characters from MySQL tables +--fix-varchar Removes rows exceeding column lengths +``` + +### Step 2 - Create the PostgreSQL database schema + +Before running migrations, ensure the `public` schema is owned by your migration user: + +``` sql +sudo -u postgres psql -d mattermost -c "ALTER SCHEMA public OWNER TO mmuser; GRANT ALL ON SCHEMA public TO mmuser;" +``` + +Then run: + +``` sh +migration-assist postgres "" \ + --run-migrations \ + --mattermost-version="" +``` + +- `` example: `postgres://user:password@address:5432/db_name` +- `` example: `10.5.4` + +By default, two pre-checks run before migration: + +- `--check-schema-owner=true` +- `--check-tables-empty=true` + +To disable them: + +``` sh +--check-schema-owner=false \ +--check-tables-empty=false +``` + +### Step 3 - Generate a pgloader configuration + +Run the following command to emit a pgloader configuration file: + +``` sh +migration-assist pgloader \ + --mysql="" \ + --postgres="" \ + --remove-null-chars \ + > migration.load +``` + +- By default, null characters in text columns are stripped. Disable with `--remove-null-chars=false`. + +- If you run out of heap, edit `migration.load` and under the `WITH` block set: + + ``` text + prefetch rows = 1000 + ``` + +### Step 4 - Run pgloader + +[Run pgloader](/deployment-guide/manual-postgres-migration#pgloader) with the generated configuration file: + +``` sh +pgloader migration.load > migration.log +``` + +Carefully review migration.log for errors (e.g., duplicate-key or missing-table warnings). Use the `mattermost/pgloader:latest` Docker image to avoid build/auth issues. + +### Step 5 - Restore full-text indexes & create all indexes + +Run: + +``` sh +migration-assist postgres post-migrate --create-indexes "" +``` + +- The `--create-indexes` flag rebuilds full-text indexes on `Posts` and `FileInfo`, plus all other Mattermost indexes. +- Omitting that flag only restores full-text indexes for `Posts` and `FileInfo`. + +See the [Restore full-text indexes](/deployment-guide/manual-postgres-migration#restore-full-text-indexes) documentation for details. + +### Step 6 - Complete plugin migrations + +Generate pgloader configs for Playbooks, Boards, and Calls: + +``` sh +migration-assist pgloader boards \ + --mysql="" \ + --postgres="" > boards.load +migration-assist pgloader playbooks \ + --mysql="" \ + --postgres="" > playbooks.load +migration-assist pgloader calls \ + --mysql="" \ + --postgres="" > calls.load +``` + +Run each: + +``` sh +pgloader boards.load > boards_migration.log +pgloader playbooks.load > playbooks_migration.log +pgloader calls.load > calls_migration.log +``` + +Skip any plugin you don't use; check logs for JSON or missing-table errors. See the [Plugin migrations](/deployment-guide/manual-postgres-migration#plugin-migrations) guide for more. + +### Step 7 - Configure Mattermost to use PostgreSQL + +In your `config.json` or via environment variables, update: + +``` json +"SqlSettings": { + "DriverName": "postgres", + "DataSource": "postgres://mmuser:pass@db:5432/mattermost?sslmode=disable" +} +``` + +If your config was stored in the database, update `MM_CONFIG` accordingly. See the [environment configuration settings](/administration-guide/configure/environment-configuration-settings#database) documentation for details. + + + +If your Mattermost deployment was initially configured with MySQL, there's a good chance your systemd service file has a `BindsTo=mysql.service` directive in it. This will cause the Mattermost server to be shut down if you deactivate your MySQL service. To fix this, update all references to `mysql.service` in your service file to use `postgresql.service` instead. This is only an issue if your Database and Mattermost are running on the same system. + + + +## Air-gapped environments + +Follow these steps to migrate within an air-gapped environment: + +1. **Verify** that the migration-assist binary is the latest version available to benefit from improvements and fixes. + +2. **Transfer** the latest migration-assist binary into the air-gapped environment (e.g., via secure media). + +3. **Generate** the MySQL schema+data output using fix flags. This produces `mysql.output`: + + ``` sh + migration-assist mysql "user:pass@tcp(localhost:3306)/mattermost" \ + --fix-artifacts --fix-unicode --fix-varchar > mysql.output + ``` + +4. **Apply** migrations using the generated output: + + ``` sh + migration-assist postgres \ + "postgres://mmuser:pass@localhost:5432/imported?sslmode=disable" \ + --run-migrations --applied-migrations="./mysql.output" + ``` + +5. **Continue** from **Step 3** through **Step 7** above to complete data transfer and configuration. + +## Tool commands + +The `migration-assist` tool offers 3 core commands: + +1. `migration-assist mysql` — Checks MySQL schema readiness and offers fixes. +2. `migration-assist postgres` — Builds the PostgreSQL schema and applies migrations. +3. `migration-assist pgloader` — Generates a pgloader config for data transfer. + +## Compile the migration-assist tool + +Requires Go ≥ v1.22. Install with: + +``` shell +go install github.com/mattermost/migration-assist/cmd/migration-assist@latest +``` + +## Troubleshooting + +See [troubleshooting errors during migration from MySQL to PostgreSQL](/deployment-guide/postgres-migration#troubleshooting). diff --git a/docs/main/deployment-guide/postgres-migration.mdx b/docs/main/deployment-guide/postgres-migration.mdx new file mode 100644 index 000000000000..f1f93705a938 --- /dev/null +++ b/docs/main/deployment-guide/postgres-migration.mdx @@ -0,0 +1,234 @@ +--- +title: "Migration guidelines from MySQL to PostgreSQL" +--- + + +From Mattermost v8.0, [PostgreSQL](/deployment-guide/software-hardware-requirements#database-software) is our database of choice for Mattermost to enhance the platform’s performance and capabilities. Recognizing the importance of supporting the community members who are interested in migrating from a MySQL database, we have taken proactive measures to provide guidance and best practices. + +- [Automated migration from MySQL to PostgreSQL](/deployment-guide/postgres-migration-assist-tool) - A comprehensive set of guidelines and a `migration-assist` tool to streamline the migration process, alleviate potential challenges, and faciliate a smooth transition. +- [Manually migrate from MySQL to PostgreSQL](/deployment-guide/manual-postgres-migration) - A good option if your organization has database administrators to own the migration process, or if you want to learn what the `migration-assist` tool automates for you. + +## Frequently asked questions + +### Why is Mattermost dropping support for MySQL? + +Mattermost has decided to drop support for MySQL databases to streamline development and focus on delivering more efficient and optimized features. By supporting only PostgreSQL, which is generally considered more advanced and better-suited for enterprise environments, Mattermost can reduce complexity, improve performance, and better allocate resources to enhance the product. This change helps ensure more consistent, robust, and scalable database interactions for all Mattermost deployments. + +### Is migrating to PostgreSQL before upgrading Mattermost recommended? + +Yes. We also recommend upgrading to Mattermost server v8.x or later before migrating to PostgreSQL. + +### Can the migration-assist be run on the Mattermost server? + +Technically, yes. The `migration-assist` tool can be run on the Mattermost server. However, it is recommended to run the tool on a separate server to avoid any performance issues. We advise running the migration against a copy of the MySQL database to ensure that the migration process does not impact the production environment. + +### How large should the PostgreSQL server be? + +The size of the PostgreSQL server should match that of the MySQL server initially. We recommend monitoring the performance of the PostgreSQL server and adjusting the resources as needed. + +### How large should the server running `migration-assist` server be? + +The tool itself is lightweight and does not require a large server. A server with 2 CPU cores and 16 GB of RAM should be sufficient for default configurations. However, you may need to adjust the resources based on the size of the MySQL database, your downtime limitations, and the configuration of `pgloader`. + +### Do we/will Mattermost bundle pgloader or is that a separate install? + +Mattermost doesn't bundle pgloader with the Mattermost server. You will need to install pgloader separately. For more information, see the [install pgloader](/deployment-guide/manual-postgres-migration#install-pgloader) documentation. + +### Are there any other migrations available for plugins, or just Boards, Playbooks, and Calls? + +We're developing migrations for other plugins, such as NPS-plugin. Please stay tuned for updates. + +### Do these processes support AWS RDS databases? + +Yes, the processes support AWS RDS databases. However, you may need to adjust the security group settings to allow the migration process to access the databases. + +### Does Mattermost support MariaDB? If not, why not? + +Mattermost does not support MariaDB. The primary reason for this decision is to streamline development and maintenance by focusing on a single database technology. By standardizing on PostgreSQL, Mattermost can deliver optimized features, improved performance, and a more focused engineering effort. PostgreSQL is well-regarded for its robustness, advanced features, and suitability for enterprise use, making it the chosen database for Mattermost. + +MariaDB, while compatible with MySQL to a large extent, introduces additional complexity and potential inconsistency, which the Mattermost development team aims to avoid by limiting database support. + +Because of these reasons we also don't support migrations directly from MariaDB to PostgreSQL. Oracle provides documentation on \[how to migrate from MariaDB to MySQL\]([https://blogs.oracle.com/mysql/post/how-to-migrate-from-mariadb-to-mysql-80](https://blogs.oracle.com/mysql/post/how-to-migrate-from-mariadb-to-mysql-80)) which can be used as a starting point for the migration to PostgreSQL. + +## Troubleshooting + +### Unsupported authentication for MySQL + +If you are facing an error due to authentication with MySQL v8, it may be related to a [known issue](https://github.com/dimitri/pgloader/issues/782) with pgloader. The fix is to set the default authentication method to `mysql_native_password` in your MySQL configuration. To do so, add the `default-authentication-plugin=mysql_native_password` value to your `mysql.cnf` file. Also, do not forget to update your user to use this authentication method. + +``` sql +ALTER USER ''@'%' IDENTIFIED WITH mysql_native_password BY ''; +``` + +### Errors during the pgloader command execution + +If you encounter errors during the execution of the `pgloader` command, ensure that both of the databases are accessible and that the users have the necessary permissions to access the database. Do not continue with the migration if there are errors during the execution of the `pgloader` command. + + + +For experienced users, it is recoverable to run the `pgloader` without requiring a restart of the migration from scratch. In this case, you will need to manually fix the issues with the table, and run the `pgloader` command with a tailored configuration specifically for those tables. Also ensure that the schema name is reverted back to `public`, and the `search_path` is restored (or remove necessary clauses from the configuration). + + + +The following sections detail how to resolve some common errors you may encounter during the execution of the `pgloader` command: + +#### Invalid input syntax for type JSON + +If you receive an error message similar to the following: + +``` text +ERROR Database error 22P02: invalid input syntax for type json +``` + +The data in the MySQL database is not in a valid JSON format. You can fix this issue by updating the data in the MySQL database to be in a valid JSON format. To find out which row is causing the issue, run the following query (where `` and `` should be replaced with the actual table and column names indicated in the `pgloader` output): + +``` sql +SELECT * FROM WHERE JSON_VALID() = 0; +``` + +You can find and update the data in the MySQL database to be in a valid JSON format with the query above. After updating the data, you can run the `pgloader` command again. + +#### Failed to find column or table + +If you receive an error message similar to the following: + +``` text +pgloader failed to find column +``` + +The column or table is missing in the PostgreSQL database. You can fix this issue by checking whether you have created the correct version of Postgres schema. After re-creating the schema, you can run the `pgloader` command again. + +#### Fell through ECASE expression + +If you receive an error message similar to the following: + +``` text +ERROR mysql: 76 fell through ECASE expression. +``` + +It is a [known issue](https://github.com/dimitri/pgloader/issues/1183) with pgloader. You can fix this issue by either compiling `pgloader` from source or simply avoid this by running `pgloader` with our docker image. See: [install pgloader](/deployment-guide/manual-postgres-migration#install-pgloader) for more information. + + + +Also, there may be cases where pgloader continues to migrate remaining tables and skip one or more tables during migration. In such cases, we recommend identifying issues with the table and fixing them before running the `pgloader` command again with a clean database. It is possible to run the `pgloader` command with the `--debug` flag to get more information about the errors. + + + +### Mattermost can't connect to the PostgreSQL database + +If you are facing an issue where Mattermost can't connect to the PostgreSQL database, ensure that the PostgreSQL server is running and that the database is accessible. If there were errors during the execution of the `pgloader` command, it can fail to revert the schema name back to `public`, or potentially fail to restore the `search_path`. You can manually revert the schema name back to `public` and restore the `search_path` by running the following commands: + +1. Connect to PostgreSQL using `sudo -u postgres psql`. +2. Select the `mattermost` database using `\c mattermost`. Verify you are using the right database by running `SELECT current_database();`. The command should output `mattermost`. +3. Revert the schema name change (optional) + +``` sql +ALTER SCHEMA RENAME TO public; +``` + +Also ensure that the database user has the necessary settings to have default access to the `public` schema. You can do this by running the following commands: + +4. Set the search_path for the mmuser: + + ``` sql + ALTER USER mmuser SET search_path TO "$user", public; + ``` + +5. Terminate the connection and connect again to your psql server. + +6. Verify the search_path is set correctly: + + ``` sh + SHOW search_path; + ``` + + This should return `"$user", public`. + +7. If the issue persists, also run: + + ``` sql + SELECT pg_catalog.set_config('search_path', '"$user", public', false); + ``` + +### Permission issues when accessing the schema in PostgreSQL + +If you run into a permission issue during step 2 where the command reports a permission issue similar to the following: + +``` text +An Error Occurred: could not check schema owner: the user “mmuser” is not owner of the “public” schema +``` + +Ensure that the `mmuser` user in PostgreSQL is the owner of the schema. + +1. Connect to PostgreSQL using `sudo -u postgres psql`. + +2. Select the `mattermost` database using `\c mattermost`. Verify you are using the right database by running `SELECT current_database();`. The command should output `mattermost`. + +3. Run the following commands: + + ``` sql + ALTER SCHEMA public OWNER TO mmuser; + GRANT USAGE, CREATE ON SCHEMA public TO mmuser; + ``` + +Then, re-run the command from step 2. + +### Incoming webhook channel names become case-sensitive after migration + +After migrating from MySQL to PostgreSQL, incoming webhooks that previously worked with mixed-case channel names (e.g., `"Tech-Talk"`) will fail with the following error: + +``` text +GetChannelByName: Channel does not exist. +``` + +This occurs because Mattermost doesn't allow the creation of channels with uppercase characters. All new channels names must only contain lowercase characters. Additionally, MySQL is case-insensitive when matching channel names, while PostgreSQL is case-sensitive. This means that webhook payloads that worked with MySQL's forgiving case-insensitive matching will fail with PostgreSQL's strict case-sensitive matching. In rare cases, older channels may still exist with mixed-case names in your database. These channels are considered invalid and may cause issues when performing operations like updating channel headers. + +**Solution:** + +Update all webhook payloads to use only lowercase channel names. + +**Prevention:** + +Before migrating to PostgreSQL: + +1. Audit your incoming webhooks and update any that use mixed-case channel names in their payloads. +2. Check for any legacy channels with mixed-case names that may have been created in earlier versions. +3. Consider renaming any mixed-case channels to lowercase to prevent issues. + +This is expected behavior with PostgreSQL and reflects Mattermost's channel naming requirements. + +### Legacy Boards tables causing migration errors + +During database migration from MySQL to PostgreSQL, while using schema comparison tools (such as dbcmp) you may encounter the following error: + +``` text +error during comparison: no pk defined for table: focalboard_file_info +``` + +This typically relates to legacy tables from older versions of Boards that are no longer in use. If you're using Boards version 8.0.0 or later, these tables are no longer required and can be ignored in the migration process. + +**Applies To:** + +- Boards version 8.0.0 and above +- All staging, UAT, QA, or production environments + + + +Does not apply to standalone Boards versions prior to v8.0.0 + + + +**Solution:** + +If you're using Boards version 8.0.0 or higher, the following legacy tables which were used only in the standalone version and can be safely ignored: + +- `focalboard_file_info` - Used in standalone version; no longer relevant in plugin and later versions. Stores uploaded files and attachments for boards. +- `focalboard_sessions` - Used in standalone version. Tracks user login sessions for boards. +- `focalboard_teams` - Used in standalone version. Legacy team mapping not used in later versions. Stores team board settings and permissions. +- `focalboard_users` - Used in standalone version. Stores user preferences and settings for boards. + +These tables may be empty or unused in your current environment. If so, they do not need to be migrated to PostgreSQL. + +## Contact Support + +Mattermost customers looking for guidance tailored to their Mattermost deployment can contact a [Mattermost Expert](https://mattermost.com/contact-sales/) for guidance. diff --git a/docs/main/deployment-guide/quick-start-evaluation.mdx b/docs/main/deployment-guide/quick-start-evaluation.mdx new file mode 100644 index 000000000000..f7f04383aeb6 --- /dev/null +++ b/docs/main/deployment-guide/quick-start-evaluation.mdx @@ -0,0 +1,120 @@ +--- +title: "Quick Start Evaluation" +--- +This guide provides instructions for quickly trying out Mattermost using either Docker or Azure Marketplace. These options are ideal for testing and evaluation purposes as they allow you to quickly get a Mattermost instance up and running for exploration and testing. However, these quick start options are not recommended for production use. They are configured for demonstration purposes only. + +## Deployment options + +
+ +Azure Marketplace + +Mattermost is published as an **Azure Marketplace** solution that deploys a single Ubuntu virtual machine with Mattermost, PostgreSQL, network configurations, and the necessary Azure resources. This quick start evaluation option is preferred for customers already using Azure, as it integrates seamlessly within their existing infrastructure. + +## Prerequisites + +- An active **Azure subscription** with permission to create resources and accept **Azure Marketplace** billing terms for the offer. +- Familiarity with the **Azure portal** (resource groups, networking, and virtual machines). + +## What gets deployed + +The template provisions a small, self-contained stack in the resource group you select, including: + +1. **Virtual machine (Linux):** Runs Mattermost, PostgreSQL, and the reverse proxy. +2. **Public IP address:** Allows access to the Mattermost workspace over the public internet, enabling users to connect to the platform securely. +3. **Network interface:** Facilitates communication between the Virtual Machine and other Azure resources through a defined network layer. +4. **Network security group:** Acts as a virtual firewall, controlling inbound and outbound traffic to protect the deployed resources from unauthorized access. +5. **Managed OS disk:** Provides persistent storage mounted to the Virtual Machine for storing files generated by Mattermost, including uploaded documents and system configurations. +6. **Virtual network:** An isolated network environment for the deployed resources, enabling private and controlled connectivity between infrastructure components. This can be a newly created or existing environment depending on your selection in the portal. + +## Step 1: Select a plan and start creation + +Go to the [Mattermost - Quick Start Evaluation (VM)](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/mattermost.mattermost-all-in-one) Azure Marketplace application to begin. Click **Get it now**, then select the **Mattermost - Quick Start Evaluation (VM)** plan, and click **Create** to open the deployment wizard. + +## Step 2: Basic Configuration + +On the **Basics** tab, configure the following: + +1. **Subscription:** Choose the Azure subscription where the deployment will live. +2. **Resource group:** Either select an existing resource group or create a new one. Using a **new** resource group keeps evaluation resources easy to find. +3. **Region:** Select the deployment region for your Virtual Machine (for example, **East US** or **West Europe**). +4. **Virtual Machine name:** Provide a unique name for your Virtual Machine. +5. **Username:** Linux administrator account on the VM. +6. **Email:** Used for Let's Encrypt registration when the instance requests a TLS certificate. Use a mailbox you can access since you may receive operational emails from the certificate authority. +7. **Support email:** Contact email for end users to reach the instance administrator for troubleshooting. +8. **Authentication type:** **Password** or **SSH public key** only for Linux sign-in to the VM. Password is often simpler for a quick trial; SSH key is appropriate if your organization requires key-based Linux access. + +## Step 3: Virtual Machine Settings and Network Configuration + +On **Virtual Machine Settings** tab, configure the following: + +1. **Virtual machine size:** For trials, we recommend **Standard_F2s_v2** size but you can choose any other size available in your region. +2. **Public IP address:** Typically **create new**. You must set a **DNS prefix** (label) that is **globally unique** in Azure; it forms part of your URL. This DNS will allow public access to your workspace. It is important that you do not already have a matching DNS name within your Azure subscription, or your deployment may fail later in the process. +3. **Virtual network:** **Create new** with the suggested address space, or attach an existing VNet and subnet that meet the constraints. Using a new virtual network avoids collisions with overlapping address spaces in the same subscription. + +The portal may show a preview of your URL in the form `https://<dns-label>.<region>.cloudapp.azure.com`. That is the address you will use once TLS and Mattermost are ready. + +## Step 4: Review and create + +Review settings, accept any **Marketplace** terms if prompted, then select **Create**. Provisioning usually takes a few minutes, and the first-boot configuration may take more time before HTTPS works reliably. + +**After deployment completes:** + +- In the Azure portal, open the **resource group** you used. + +- Open the **Public IP address** resource (often named `<your-vm-name>-ip` unless you changed it). + +- Under **Essentials**, note the **DNS name**. Your site URL is: + + `https://<dns-label>.<region>.cloudapp.azure.com` + + Example: `https://myorg.eastus.cloudapp.azure.com` + +Use **https**; the deployment is intended to serve Mattermost over TLS. + +## Step 5: Open Mattermost and create your administrator + +In a browser, go to your **HTTPS** URL. Mattermost will prompt you to **create the first user**, which becomes the **System Administrator**. That account is different from the **Linux** username and password (or SSH key) you configured in Step 3. + +Congratulations! You’ve successfully deployed Mattermost for evaluation. + +
+ +
+ +Docker Preview Container + +The fastest way to try Mattermost is using the official Docker preview container. This method requires minimal setup and provides a fully functional Mattermost instance. + +## Docker Preview Prerequisites + +- Docker installed on your system +- At least 1GB of available RAM +- At least 1GB of available disk space + +## Run Mattermost using Docker + +1. Pull and run the Mattermost preview container: + +> ``` bash +> docker run --name mattermost-preview -d --publish 8065:8065 mattermost/mattermost-preview +> ``` + +2. Access Mattermost at `http://localhost:8065` +3. Create your first admin account when prompted. + +
+ +## Next steps + +After setting up your Mattermost instance using either method: + +- Create your first team and channels +- Invite users to join your workspace +- Explore Mattermost features and integrations +- Review the [Application architecture](/deployment-guide/reference-architecture/application-architecture) to understand the system better +- Consider [Server deployment](/deployment-guide/server/server-deployment-planning) for a production deployment + +For additional help or questions, visit the [Mattermost community forums](https://forum.mattermost.com/) or refer to the [Deployment troubleshooting](/deployment-guide/deployment-troubleshooting) guide. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/deployment-guide/reference-architecture/application-architecture.mdx b/docs/main/deployment-guide/reference-architecture/application-architecture.mdx new file mode 100644 index 000000000000..79ef8da6bb50 --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/application-architecture.mdx @@ -0,0 +1,256 @@ +--- +title: "Application architecture" +--- +Mattermost is an open-source collaboration platform that offers secure messaging, file sharing, and integrations for team communication. It's self-hosted, providing IT admins full control over data, security, integrations, and customization. The platform is built with modular components to ensure scalability, flexibility, and extensibility. + +Mattermost network diagram shows how the components can be deployed. Includes optional configurations for scaling for larger enterprise organizations. + +## Workflow overview + +Users connect through various access points (web, mobile, desktop, email). Their requests are processed by the application layer (Mattermost Server), which manages API communications, authentication, notifications, and data workflows. + +The backend infrastructure supports these operations by storing all data and files in well-architected storage systems. + +Extendability and security layers ensure that the platform integrates seamlessly with enterprise systems while protecting sensitive data. + +## Core components + +The technical architecture revolves around 3 main layers: [Access layer](#access-layer), [Application layer](#application-layer), and [Backend infrastructure](#backend-infrastructure). + +### Access layer + +The Access Layer includes all the ways users interact with Mattermost, ensuring secure, scalable, and reliable communication across preferred platforms. High availability measures provide uninterrupted functionality for users, even in the face of server or network failures. + +- **Web Interface**: Users can access Mattermost through a web browser (Chrome, Firefox, Safari, Edge). The web client communicates with the Mattermost server over HTTPS protocols. High availability for web interfaces can be achieved through load-balanced reverse proxies (e.g., NGINX or HAProxy) that distribute user traffic across multiple Mattermost server instances. Backup proxy servers can ensure failover scenarios to keep the web interface operational during outages. +- **Desktop and Mobile Apps**: Native apps for iOS, Android, macOS, Windows, and Linux provide seamless functionality across devices. These apps rely on secure APIs to interact with the server for real-time messaging and updates. High availability can be ensured by deploying redundant server clusters to handle API requests, along with failover mechanisms that automatically redirect traffic to healthy servers. Mobile apps also benefit from retry mechanisms and fallback services for push notifications to maintain real-time responsiveness. +- **Email Interaction**: Support for email clients like Outlook, Gmail, or Thunderbird enables integration of email notifications (e.g., new message alerts, invitations) into users' typical workflows. The Access Layer ensures that users are always connected via platforms of their choice while maintaining secure, synchronized communication paths. Email services can be configured with multiple SMTP servers for redundancy, ensuring that notifications are sent without delay even if a primary mail server becomes unavailable. + +The Access Layer plays a critical role in ensuring that users are always connected via the platforms of their choice while maintaining secure, synchronized communication paths. With high availability measures in place, organizations can guarantee a seamless user experience, regardless of the scale or complexity of their deployment. + +### Application layer + +The Mattermost Server is the heart of the platform and responsible for processing all user and system operations. It's composed of multiple modular elements as follows: + +Mattermost architecture basics + +**RESTful JSON Web Service**: Handles all incoming API requests (from web clients, apps, and integrations) and ensures that responses are formatted in JSON. Acts as the communication bridge between the clients (Access Layer) and backend systems. To ensure high availability, this layer can be distributed across multiple servers and load-balanced, preventing service disruptions due to high traffic or server failure. + +**Authentication client**: Manages user authentication, ensuring secure login sessions. Integrates with traditional username/password-based authentication or enterprise-grade solutions like SSO (Single Sign-On) through Active Directory/LDAP. High availability is maintained through redundant authentication nodes and failover mechanisms, ensuring uninterrupted access even if a primary authentication service fails. + +**Authentication Provider**: Provides pluggable authentication frameworks to support OAuth, SSO, and third-party identity services. Particularly important for enterprise environments with centralized identity management. Redundancy and failover strategies ensure reliability by distributing authentication frameworks across multiple servers and offering fallback options for seamless identity management. + +**Notification Service**: Sends notifications through supported mediums: + +- **Push Notifications**: Real-time notifications to iOS and Android devices (via a Push Notification Service). High availabilty is ensured through multiple notification servers and retry mechanisms, guaranteeing that notifications are delivered even in the event of service disruptions. +- **Email Notifications**: Delivered to users when they are offline or need event alerts. Load balancing and backup mail server configurations help ensure email delivery remains consistent and reliable. + +**Data Management Service**: Responsible for managing message data, metadata, user profiles, and logs. Ensures the integrity of data passed between the database and the server. This layer serves as the operational core of the platform, orchestrating user activities with data handling and integration capabilities. + +High availability is achieved through database replication, failover strategies, and distributed data handling mechanisms. These measures ensure uninterrupted access to data and protect against component failures or downtime. The Data Management Service serves as the operational core of the platform, orchestrating user activities with scalable and fault-tolerant data handling capabilities. + +### Backend infrastructure + +The backend infrastructure provides the storage and data handling capabilities required for Mattermost operations. It consists of the following components: + +**Database Systems**: Mattermost uses PostgreSQL as its primary database (supports Amazon RDS for cloud-hosted PostgreSQL) to store all persistent data, such as: + +- Messages +- User accounts and credentials +- Configuration settings +- Team/channel metadata + +To ensure high availability, database systems can leverage clustering, replication, and failover mechanisms. PostgreSQL supports features like synchronous and asynchronous replication to create replicas for redundancy. Cloud-hosted solutions like Amazon RDS provide automatic failover and backup capabilities, ensuring continuous operation during system failures. + +**File Storage**: Manages all multimedia assets (e.g., file uploads, images, videos) shared across channels. Storage solutions include the following options: + +- **Local Storage**: Files stored directly on the server’s filesystem. For high availability, redundancy can be achieved using RAID configurations or backups to recover from disk failures. +- **Network Attached Storage (NAS)**: Common for enterprises centralizing file storage within their network. NAS setups can include fault-tolerant configurations like distributed systems or replication for uninterrupted access. +- **S3**: Offers cloud-based scalable storage for larger environments or organizations with distributed deployments. The database and file storage handle scalability, ensuring efficient support for millions of messages and files while guaranteeing data consistency. S3 inherently supports high availability by distributing data across multiple availability zones, ensuring no single point of failure. + +High availability measures ensure scalable and fail-safe support for millions of messages and files while guaranteeing data consistency. + +**System Extensions**: Mattermost is not only a collaboration tool but also a platform designed for extensibility. Key extensibility features include: + +**Self-Hosted Integrations**: Connect Mattermost to other local or cloud-based systems like Jira, GitLab, or any custom integrations your team needs. Leverage built-in APIs and webhooks to automate workflows and trigger system-to-system communications. For high availaiblity, integrations can employ redundant communication channels and retry mechanisms to handle transient failures gracefully. + +**Third-Party Authentication**: Bind integrations to third-party platforms (e.g., Slack-importing APIs, OAuth services). Third-party identity services ensure consistent and secure user access flows. Third-party identity services can leverage load-balancing and failover strategies to ensure consistent and secure user access flows, even under high traffic or outages. + +**Security and Scalability Features**: Security and scalability are baked into the architecture, making Mattermost ideal for enterprise use cases: + +**Security** + +- A reverse proxy like NGINX or a hardware proxy is deployed to manage external traffic. It protects servers, enforces HTTPS, and handles load balancing. +- Configurable SSL/TLS encryption ensures data security during transmission. +- Granular user permissions and roles secure sensitive information within teams. + +**Scalability and High Availability**: The Enterprise Edition supports deploying multiple Mattermost servers in a clustered environment to balance user requests across multiple servers for reliability and performance in large organizations. Clustering ensures automatic failover so that user traffic is shifted to functioning servers in case of outages. + +**Notifications and communication services**: Mattermost supports asynchronous and real-time communication, enhanced by notification systems tailored for different workflows: + +- **Push Notifications**: Delivered to mobile devices for message alerts or mentions. High availability is achieved with backup notification services and retry mechanisms for reliable delivery. +- **Email Integration**: Provides regular notifications when users are offline or inactive. Failover mail servers and distributed configurations ensure email notifications are sent without interruption. + +These services ensure continuous engagement and communication. + +### Communication protocols + +There are also communication protocols (HTTPS and WS) that define the type of connection the user makes with the Mattermost server. High availability measures ensure reliable and resilient connections between clients and the Mattermost server, especially in production environments. + +**HTTPS Connection** (Secure Hypertext Transfer Protocol) + +- HTTPS connections to the Mattermost server render pages and provide access to core platform functionality, but do not include real-time interactivity (which is enabled by WSS connections). +- HTTPS is a secure, encrypted protocol and is highly recommended for production. Unencrypted HTTP connections may be used in initial testing and configuration, but should never be used in a production environment. For high availability, HTTPS traffic should be handled by a reverse proxy (e.g., NGINX or HAProxy) with load balancer configurations to distribute connections across multiple Mattermost server instances. Redundant proxy servers ensure failover capabilities, providing uninterrupted service. + +**WSS Connection** (Secure WebSocket Protocol) + +Secure WebSocket (WSS) connections to the Mattermost Server enable real-time updates and notifications between clients and the server. + +If a WSS connection is not available and HTTPS is substituted, the system will appear to work but real-time updates and notifications will not. In this mode of operation, updates will only appear on a page refresh. WSS has a persistent connection to the Mattermost server when a client is connected, while HTTPS has an intermittent connection and only connects to the server when a page or file is requested. + +High availability for WSS connections can be achieved through clustering Mattermost servers and load balancing WebSocket connections across those cluster nodes. Proxy servers and WebSocket-specific configurations (such as sticky sessions or connection persistence) are essential to maintain real-time interactivity during server or network failures. + +Mattermost architecture with protocol connections + +By incorporating high availability strategies into communication protocols, the platform ensures secure, scalable, and reliable connections for both regular user interactions (via HTTPS) and real-time updates (via WSS). These measures are critical for mission-critical environments and distributed deployments where continuous communication is necessary. + +**Behind a VPN** + +Mattermost is intended to be installed within a private network which can offer multiple factors of authentication, including secure access to computing devices and physical locations. If outside access is required, a virtual private network client (VPN), such as [OpenVPN](https://openvpn.net/), with additional authentication used to connect to Mattermost for web, desktop, and mobile experiences, is recommended. + +**Non-VPN setup** + +If Mattermost is accessible from the open internet, the following is recommended: + +1. An IT admin should be assigned to set up appropriate network security, subscribe to [the Mattermost security bulletin](https://mattermost.com/security-updates/#sign-up), and [apply new security updates](/administration-guide/upgrade/upgrading-mattermost-server). +2. The organization enables [SAML Single Sign-on](/administration-guide/onboard/sso-saml) or enable [MFA](/administration-guide/onboard/multi-factor-authentication). + +If Mattermost is accessible from the open internet with no VPN or MFA set up, we recommended using it only for non-confidential, unimportant conversations where impact of a compromised system is not essential. + +#### Mattermost services ports + +The following table lists the Mattermost services ports for Mattermost Server, push proxy, and mobile app clients. System admins with clients that need to speak to the Mattermost server without a proxy can open specific firewall ports as needed. + +**Mattermost Server** + + ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Service NameConfig SettingPort (default)ProtocolDirectionInfo
HTTP/WebsocketServiceSettings.ListenAddress8065/80/443 (TLS)TCPInboundExternal (no proxy) / Internal (with proxy) Usually this requires port 80 and 443 when running HTTPS. Internal
ClusterClusterSettings.GossipPort8074TCP/UDPInbound
MetricsMetricsSettings.ListenAddress8067TCPInboundExternal (no proxy) / Internal (with proxy)
DatabaseSqlSettings.DataSource5432 (PostgreSQL) / 3306 (MySQL)TCPOutboundUsually internal (recommended)
LDAPLdapSettings.LdapPort389TCP/UDPOutbound
S3 StorageFileSettings.AmazonS3Endpoint443 (TLS)TCPOutbound
SMTPEmailSettings.SMTPPort10025TCP/UDPOutbound
Push NotificationsEmailSettings.PushNotificationServer443 (TLS)TCPOutbound
+ +**Push Proxy** + + ++++++++ + + + + + + + + + + + + + + + + + + + + +
Service NameConfig SettingPort (default)ProtocolDirectionInfo
Push ProxyListenAddress8066TCPInboundExternal (no proxy) / Internal (with proxy)
+ +**Mobile Clients** + +To receive push notifications, your network must allow traffic on [port 5223 for iOS devices](https://support.apple.com/en-us/102266) and [ports 5228-5230 for Android](https://firebase.google.com/docs/cloud-messaging/concept-options#messaging-ports-and-your-firewall). diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment.mdx new file mode 100644 index 000000000000..28b0caf157aa --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment.mdx @@ -0,0 +1,452 @@ +--- +title: "Deploy in Air-Gapped Environments" +--- +An air-gapped environment is one that is isolated from the public internet, requiring all necessary components to be available locally. This guide outlines what you'll need to deploy Mattermost in a self-hosted air-gapped environment, focusing on appropriate preparation, deployment guidance and configurations required for a successful deployment. + +## Overview + +At a high level, deploying Mattermost in an air-gapped environment requires preparing all necessary software, container images, and configuration resources in advance, since the target system has no direct internet access; transferring these artifacts to the isolated network using secure media; and then installing, configuring, and validating the deployment within the air-gapped environment. This is a summary of the steps involved: + +1. **Select your preferred Mattermost deployment option:** + +This step is often dictated by the infrastruture already running in your air-gapped environment. If you're deploying from scratch, we recommend reviewing our [server deployment documentation](/deployment-guide/server/server-deployment-planning#deployment-options) to select the optimal option given your organizations needs. + +2. **Setup a private container registry or package mirror:** + +Ideally the air-gapped environment already has a private container registry or package mirror available. If not, we recommend following [our frequently asked questions](#frequently-asked-questions) or referencing online resources specific to your environment. + +3. **Prepare your Bill of Materials:** + +Depending on your deployment method method, you'll need to download, tag, and push required materials into your private registry or mirror. + +4. **Transfer materials into the air-gapped environment:** + +If the private registry cannot access the public internet, you can prepare an archive of the registry data on your internet connected machine and securely transfer it using approved data transfer methods - for example, burning to a disk. + +5. **Install Mattermost Server** + +Once you have all the necessary resources in your air-gapped environment, you can move forward with deployment following the instructions for [Linux](/deployment-guide/server/deploy-linux), [Kubernetes](/deployment-guide/server/deploy-kubernetes), or [Docker](/deployment-guide/server/deploy-containers). + +6. **Install Mattermost Desktop Apps** + +Since air-gapped devices cannot access the publicly available app stores, you'll need to install the apps directly from the latest [packages available on our GitHub release page](https://github.com/mattermost/desktop/releases). You'll find [installation instructions](/deployment-guide/desktop/desktop-app-deployment) in our documentation based on your desired deployment method. + +6. **Configure Mattermost for air-gapped operation** + +The [configuration settings](#server-configuration) recommended in this document accomodate for the lack of internet access to operate Mattermost in an air-gapped environment. + + + +Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs support deploying Mattermost and supporting services in an air-gapped environment. + + + +## Bill of Materials + +On an internet connected machine, you must gather all required packages, container images, and dependencies needed for the installation process. The resources you'll need will depend on your deployment method, specifically: + +
+ +Linux + +Using our provided tarball is recommeded as the simplest installation method for air-gapped environments. You can install the Mattermost Server in a few minutes on any air-gapped 64-bit Linux system. + +> **Prerequisites** +> +> - [Mattermost tarball](/product-overview/version-archive). We recommend using the latest [ESR](/product-overview/release-policy#extended-support-releases) for extended support where server upgrades may be infrequent. +> - Database: PostgreSQL [installation packages](https://www.postgresql.org/download/) or container images for your Linux distribution +> - File Storage: Local filesystem storage is sufficient for deployments under 2,000 users. For larger deployments requiring high availability, we recommend using an S3-compatible object storage solution or an NFS (Network File System) server for shared storage needs. +> - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy) from these [Linux packages](https://nginx.org/en/linux_packages.html). +> - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. +> +> **(Optional) Supporting Services** Consider downloading these additional resources if you plan to enable these optional components: +> +> - [Mattermost Calls](/administration-guide/configure/calls-deployment-guide): [mattermost-calls-offloader](https://github.com/mattermost/calls-offloader/releases) (required for recording, transcription and live captions) and [mattermost-rtcd](https://github.com/mattermost/rtcd/releases) (required for performance and scalability). +> - [Elasticsearch](https://www.elastic.co/downloads/elasticsearch) can be [deployed](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/installing-elasticsearch) for enhanced search performance at scale. +> - [Prometheus](https://prometheus.io/download/) and [Grafana](https://grafana.com/grafana/download) for monitoring and observability + +
+ +
+ +Kubernetes + +Kubernetes is recommended for a highly scalable and robust deployment if your organization is already running a Kubernetes cluster in the air-gapped environment. + +> **Prerequisites** +> +> - [Mattermost Operator](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-operator) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-operator/values.yaml) +> - Database: We recommend options such as the [Postgres Operator](https://access.crunchydata.com/documentation/postgres-operator/latest/quickstart) from Crunchy Data, [CloudNativePG](https://cloudnative-pg.io/documentation/1.27/installation_upgrade/) or [pgEdge](https://github.com/pgEdge/pgedge-helm). +> - File Storage: We recommend using an S3-compatible storage service or a mounted NFS volume for shared storage needs. +> - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy), using the [NGINX Ingress Controller operator](https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-operator/). +> - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. +> +> **(Optional) Supporting Services** Consider downloading these additional resources if you plan to enable these optional components: +> +> - [Mattermost Calls](/administration-guide/configure/calls-deployment-guide) helm charts: [mattermost-calls-offloader](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-calls-offloader) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-calls-offloader/values.yaml) (required for recording, transcription and live captions), [mattermost-rtcd](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-rtcd) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-rtcd/values.yaml) (required for performance and scalability). +> - [Elasticsearch](https://www.elastic.co/docs/deploy-manage/deploy/cloud-on-k8s) can be [deployed in air-gapped k8 environments](https://www.elastic.co/guide/en/cloud-on-k8s/2.8/k8s-air-gapped.html) for enhanced search performance at scale. +> - [Prometheus](https://github.com/prometheus-operator/prometheus-operator) and [Grafana](https://github.com/grafana/grafana-operator) operators for monitoring and observability + +
+ +
+ +Docker + +Docker can be used if you don't have a running Kubernetes cluster in the air-gapped environment, but want to use containers for simplified installation and dependency management. Docker is not recommended for production environments at high scale, as it doesn’t support clustered deployments or High Availability (HA) configurations out-of-the-box. + +> **Prerequisites** +> +> - [Mattermost Enterprise Edition](https://hub.docker.com/r/mattermost/mattermost-enterprise-edition) image. +> - Database: [PostgreSQL](https://hub.docker.com/_/postgres) image. +> - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy) from this [images](https://hub.docker.com/_/nginx). +> - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. +> +> **(Optional) Supporting Services** Consider downloading these additional resources if you plan to enable these optional components: +> +> - [Mattermost Calls](/administration-guide/configure/calls-deployment-guide) images: [calls-offloader](https://hub.docker.com/r/mattermost/calls-offloader) (required for recording, transcription and live captions) and [rtcd](https://hub.docker.com/r/mattermost/rtcd) (required for performance and scalability). +> - [Elasticsearch](https://hub.docker.com/_/elasticsearch) image for enhanced search performance at scale. +> - [Prometheus](https://hub.docker.com/r/prom/prometheus) and [Grafana](https://hub.docker.com/r/grafana/grafana) images for monitoring and observability. + +
+ +### Mattermost Plugins + +Mattermost includes a number of [pre-built integrations](/integrations-guide/popular-integrations) for mission-critical tools. If you'd like to use any plugins beyond those that are pre-built in the Mattermost package you'll need to download the plugin binaries from the [Mattermost Marketplace](https://mattermost.com/marketplace/). Once you have Mattermost deployed, these plugin binaries can be uploaded directly in the System Console. + +### SSL/TLS Certificates and Keys + +If your deployment requires SSL, ensure you have the necessary certificates. This includes certificates and keys for enabling HTTPS with Mattermost, as well as any CA files or certificates needed to access internal services such as LDAP or SAML. + +### Local Documentation + +Mattermost documenation can be [built locally](https://github.com/mattermost/docs?tab=readme-ov-file#build-locally) so you'll have access to installation and configuration documentation in the air-gapped environment. Otherwise, you can download the necessary deployment and configuration documents directly from the [GitHub docs repository](https://github.com/mattermost/docs). + +**Prerequisites** The following software is required to build the documentation locally: + +- Git [\[download\]](https://git-scm.com/downloads) +- Python 3.11 or later [\[download\]](https://www.python.org/downloads) +- Pipenv [\[download\]](https://pipenv.pypa.io) +- GNU Make 3.82 or later [\[download\]](https://ftp.gnu.org/gnu/make/) + +## Server configuration + +After successful deployment, you'll need to configure Mattermost for air-gapped operation. The following sections describe these configuration options and offers recommendations for settings. + +### Mobile push notifications + +Mattermost can use mobile push notifications to notify users of new messages and activity. These notifications require a server component to be deployed to send the notifications to the mobile devices. By default, Mattermost will use the public push notification service which is not available in an air-gapped environment. We recommend [disabling push notifications](/administration-guide/configure/environment-configuration-settings#enable-push-notifications) in **System Console \> Environment \> Push Notification Server**. + +### Email + +Unless you have setup an internal air-gapped email service, we recommend disabling email invitations and email verification from **System Console \> Authentication \> Signup**. + +### Website link previews + +Website link previews require a connection to the internet to fetch the content of the links. We recommend [disabling website link previews](/administration-guide/configure/site-configuration-settings#enable-website-link-previews) in **System Console \> Site Configuration \> Posts**. + +### GIF picker + +The GIF picker relies on a third-party service which has a dependency on external internet access. You can disable it in **System Console \> Integrations \> GIF**. + +### Notices + +[In-product notices](/administration-guide/manage/in-product-notices) require internet access to periodcally inform administrators and end users of new product improvements, features, and releases. You can disable notices in **System Console \> Site Configuration \> Notices**. + +### Telemetry + +To avoid log errors we recommend disabling [Telemetry-related features](/administration-guide/manage/telemetry), including the security update check, and error and diagnostics reporting features. + +## Frequently Asked Questions + +### What if my air-gapped environment doesn't have a private container registry or package mirror? + +A private container registry securely stores the Docker images necessary for air-gapped deployments, ensuring compliance with data isolation requirements. Similarly, a private package mirror stores operating system packages necessary for air-gapped deployments in Ubuntu or RHEL/CentOS Linux environments. Setting up a local registry or mirror is a critical step in deploying Mattermost to ensure all images, dependencies and packages are available to you in the air-gapped environment. The steps below outline the process required to setup a local registry or mirror, depending on the deployment method you are using. These steps are a rough guide, and can be supplemented with online resources depending on your specific deployment needs. + +
+ +Linux + +**(Ubuntu) Set up a private Debian package mirror** + +We will use Aptly to create a local mirror, although you can also use other options such as debmirror. + +1. **Install Aptly** (on an internet-connected machine): + + ``` bash + apt-get update + apt-get install aptly gnupg + ``` + +2. **Create GPG key for signing packages**: + + ``` bash + gpg --gen-key + ``` + +3. **Create a mirror configuration**: + + ``` bash + aptly mirror create -architectures=amd64 debian-bullseye http://deb.debian.org/debian bullseye main contrib non-free + ``` + +4. **Update the mirror to download packages**: + + ``` bash + aptly mirror update debian-bullseye + ``` + +5. **Create and publish a snapshot**: + + ``` bash + aptly snapshot create debian-bullseye-$(date +%Y%m%d) from mirror debian-bullseye + aptly publish snapshot debian-bullseye-$(date +%Y%m%d) + ``` + +6. **Serve the repository**: + + ``` bash + aptly serve + ``` + +7. **Client configuration:** Configure apt to use your local mirror: + + ``` bash + cat > /etc/apt/sources.list << EOF + deb http://mirror.example.com/debian bullseye main contrib non-free + EOF + ``` + +**(RHEL/CentOS) Set up a private RHEL package mirror** + +We will use reprosync for a local mirror. + +1. **Install required tools** (on an internet-connected RHEL system): + + ``` bash + yum install yum-utils createrepo + ``` + +2. **Download packages**: + + ``` bash + mkdir -p /var/www/html/repos/rhel8 + reposync -p /var/www/html/repos/rhel8 --download-metadata --repo=rhel-8-for-x86_64-baseos-rpms + reposync -p /var/www/html/repos/rhel8 --download-metadata --repo=rhel-8-for-x86_64-appstream-rpms + ``` + +3. **Create repository metadata**: + + ``` bash + createrepo /var/www/html/repos/rhel8/rhel-8-for-x86_64-baseos-rpms + createrepo /var/www/html/repos/rhel8/rhel-8-for-x86_64-appstream-rpms + ``` + +4. **Set up a web server**: + + ``` bash + yum install httpd + systemctl enable httpd + systemctl start httpd + ``` + +5. **Client configuration:** Disable existing repositories: + + ``` bash + cd /etc/yum.repos.d/ + mkdir backup + mv *.repo backup/ + ``` + +6. **Client configuration:** Create new repository files: + + ``` bash + cat > /etc/yum.repos.d/local-baseos.repo << EOF + [local-baseos] + name=Red Hat Enterprise Linux 8 BaseOS + baseurl=http://mirror.example.com/repos/rhel8/rhel-8-for-x86_64-baseos-rpms + enabled=1 + gpgcheck=0 + EOF + + cat > /etc/yum.repos.d/local-appstream.repo << EOF + [local-appstream] + name=Red Hat Enterprise Linux 8 AppStream + baseurl=http://mirror.example.com/repos/rhel8/rhel-8-for-x86_64-appstream-rpms + enabled=1 + gpgcheck=0 + EOF + ``` + +7. **Client configuration:** Clear cache and test: + + ``` bash + yum clean all + yum repolist + ``` + +
+ +
+ +Kubernetes + +**Set up a self-hosted private container registry** + +1. **Install Docker Registry**: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry registry:2 + ``` + +2. **Configure persistent storage**: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry \ + -v /mnt/registry:/var/lib/registry \ + registry:2 + ``` + +3. **Add TLS security** (recommended): + + 1. Generate self-signed certificates: + + ``` bash + mkdir -p certs + openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ + -x509 -days 365 -out certs/domain.crt + ``` + + 2. Run the registry with TLS: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry \ + -v /mnt/registry:/var/lib/registry \ + -v $(pwd)/certs:/certs \ + -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ + -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ + registry:2 + ``` + +**Configure Kubernetes to use private image registries** + +When using Kubernetes in an air-gapped environment, you need to configure it to use your private registry. + +1. **Create a kubernetes secret for registry authentication**: + + ``` bash + kubectl create secret docker-registry regcred \ + --docker-server=registry.example.com:5000 \ + --docker-username=your_username \ + --docker-password=your_password \ + --docker-email=your_email@example.com + ``` + +2. **Reference the secret in pod specifications**: + + ``` yaml + apiVersion: v1 + kind: Pod + metadata: + name: mattermost-pod + spec: + containers: + - name: mattermost + image: registry.example.com:5000/mattermost/mattermost-enterprise-edition:latest + imagePullSecrets: + - name: regcred + ``` + +3. **For Helm deployments**, specify the registry in `values.yaml`: + + ``` yaml + image: + repository: registry.example.com:5000/mattermost/mattermost-enterprise-edition + tag: latest + pullPolicy: IfNotPresent + + imagePullSecrets: + - name: regcred + ``` + +
+ +
+ +Docker + +**Set up a self-hosted private container registry** + +1. **Install Docker Registry**: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry registry:2 + ``` + +2. **Configure persistent storage**: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry \ + -v /mnt/registry:/var/lib/registry \ + registry:2 + ``` + +3. **Add TLS security** (recommended): + + 1. Generate self-signed certificates: + + ``` bash + mkdir -p certs + openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ + -x509 -days 365 -out certs/domain.crt + ``` + + 2. Run the registry with TLS: + + ``` bash + docker run -d -p 5000:5000 --restart=always --name registry \ + -v /mnt/registry:/var/lib/registry \ + -v $(pwd)/certs:/certs \ + -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ + -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ + registry:2 + ``` + +**Populate your private registry** + +Ensure the required images from the [Bill of Materials](bill-of-materials) are downloaded and pushed to the private registry. + +**Configure Docker to use private image registries** + +Configure Docker on all hosts to trust and use your private registry. + +1. **Add your registry to Docker's trusted registries**: + + Edit or create `/etc/docker/daemon.json`: + + ``` json + { + "insecure-registries": ["registry.example.com:5000"] + } + ``` + + For registries using self-signed certificates: + + ``` bash + mkdir -p /etc/docker/certs.d/registry.example.com:5000 + cp domain.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt + ``` + +2. **Restart Docker daemon**: + + ``` bash + systemctl restart docker + ``` + +3. **Test the configuration**: + + ``` bash + docker pull registry.example.com:5000/mattermost/mattermost-enterprise-edition:latest + ``` + +
diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations.mdx new file mode 100644 index 000000000000..fc8357e0f359 --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations.mdx @@ -0,0 +1,93 @@ +--- +title: "Deploy for Enterprise to Edge DDIL Operations" +--- +## Overview + +Disconnected, Denied, Intermittent, and Limited (DDIL) network conditions present unique challenges for enterprise-to-edge operations. Field operations, remote deployments, and edge environments often become temporarily isolated from the internet, interrupting direct access to Microsoft 365 services such as Teams and Outlook. + +Mattermost enables resilient collaboration by remaining fully operational in DDIL environments. Mission users continue to access self-hosted messaging collaboration, workflow automation, and mission planning within their mobile tactical network. No internet connectivity is required for enhanced collaboration functions, including mission tuned AI agents powered by self-hosted LLMs, and audio and screen sharing services. + +When connectivity is restored, mission users regain access to M365 enterprise systems in addition to collaboration continuity with enterprise users through the [embedded Mattermost experience](/integrations-guide/mattermost-mission-collaboration-for-m365) inside their Microsoft Teams and Outlook applications. All mission activity during the period of disconnection becomes available across enterprise and tactical environments when connectivity returns. + +Traditional cloud-only solutions fail in these scenarios, while fully disconnected systems don't integrate with enterprise tools during normal operations. This deployment architecture [extends sovereign collaboration with Microsoft Teams and Outlook](/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration) to the tactical edge, providing a hybrid solution that enables enterprise integration and fully disconnected tactical collaboration. + +![Mattermost diagram displays the deployment components and relationships outlined in detail in this document.](/images/architecture-ms-teams-ddil.png) + + + +Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs support deploying Mattermost and supporting services for DDIL operations. + + + +## Architecture components + +This hybrid deployment architecture provides optimal collaboration in both connected and disconnected states, including: + +- **Enterprise Network:** Network containing enterprise services and continuous access to Microsoft 365. The network may have a firewall or access gateway protecting egress and ingress, such as network policies, IP allowlists, or WAFs depending on your networking configurations. +- **Enterprise Users:** Users within the enterprise network boundary accessing client applications for M365 services and Mattermost. +- **Tactical Network:** Operates independently during internet disconnections, hosting a self-contained Mattermost deployment to ensure mission users maintain collaboration capabilities. +- **Mission Users:** Tactical or edge users who may be intermittently disconnected from enterprise systems and Microsoft services. +- **Identity Providers:** + - **Microsoft Entra ID:** Enterprise users authenticate to M365 applications and Mattermost using [single sign-on Entra ID](/administration-guide/onboard/sso-entraid) via OpenID Connect (OIDC) or SAML. This provider only works with functioning internet access. + - **Alternative Local Identity Provider:** Deployed within the tactical network to provide authentication services for mission users during disconnected periods when M365 is unreachable. The local IdP serves as the primary authentication source for Mattermost and maintains an independent user directory that operates without internet connectivity. +- **Client Applications:** + - **Microsoft 365 Desktop Apps:** Teams and Outlook with [embedded Mattermost application.](/integrations-guide/mattermost-mission-collaboration-for-m365) + - When internet connected: Enables seamless enterprise-to-edge collaboration within a familiar interface. + - When internet disconnected: Microsoft services are unreachable, but embedded Mattermost application remains fully operational for tactical teams. + - **Mattermost Desktop Apps:** Access Mattermost via [desktop](/deployment-guide/desktop/desktop-app-deployment) or web apps in addition to the embedded views from Teams and Outlook. *(Optional - not shown)* + - **Mattermost Mobile Apps:** Access Mattermost via [iPhone and Android apps](/deployment-guide/mobile/mobile-app-deployment), with support for [ID-only push notifications](/deployment-guide/mobile/host-your-own-push-proxy-service) to ensure compliance with data sovereignty requirements. *(Optional when connectivity permits - not shown)* +- **Mattermost Deployment:** Mattermost deployed for sovereign tactical collaboration on local infrastructure, such as [Azure Local](https://learn.microsoft.com/en-us/azure/azure-local/manage/disconnected-operations-overview), supporting data residency regulations and [disconnected operations](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment). See [reference architecture](/administration-guide/scale/server-architecture) documentation for Mattermost deployment configurations based on expected scale. + - **Mattermost Server:** Core application server handling tactical collaboration workloads, including: + - [Messaging Collaboration](/end-user-guide/messaging-collaboration): DDIL-ready 1:1, group messaging, and structured channel collaboration with [rich integration capabilities](/integrations-guide/integrations-guide-index) and [enterprise-grade search](/administration-guide/scale/scaling-for-enterprise#enterprise-search). + - [Workflow Automation](/end-user-guide/workflow-automation): Playbooks provide structure, monitoring and automation for repeatable processes built-in to your local Mattermost deployment. + - [Project Tracking](/end-user-guide/project-task-management): Boards enables project management capabilities built-in to your local Mattermost deployment. + - [AI Agents](/administration-guide/configure/agents-admin-guide): AI Agents run against a local LLM hosted within your tactical network. + - [Audio & Screenshare](/administration-guide/configure/calls-deployment-guide): Calls offers native real-time self-hosted audio calls and screen sharing within your tactical network. + - **Proxy Server:** The [proxy server](/deployment-guide/server/setup-nginx-proxy) handles HTTP(S) routing within the cluster, directing traffic between the server and clients accessing Mattermost services. NGINX is recommended for load balancing with support for WebSocket connections, health check endpoints, and sticky sessions. The proxy layer provides SSL termination and distributes client traffic across application servers. + - **PostgreSQL Database:** Stores persistent application data on a [PostgreSQL v13+ database](/deployment-guide/server/preparations) hosted locally within your tactical network. + - **Object Storage:** File uploads, images, and attachments are stored outside the application node on an [S3-compatible store](/deployment-guide/server/preparations) or network/local storage, hosted locally within your tactical network. + - **Recording Instance:** `calls-offloader` job service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, to offload heavy processing tasks from Mattermost Calls to self-hosted infrastructure within your tactical network, such as recordings, transcriptions, and live captioning. *(Optional)* +- **Self-hosted integrations:** [Custom apps, plugins, and webhooks](/integrations-guide/integrations-guide-index) can be deployed within your tactical network. *(Optional - not shown)* +- **Self-hosted LLM:** Locally hosted [OpenAI compatible LLM](/agents/docs/providers) for agentic powered collaboration within your tactical network. *(Optional)* +- **Microsoft Global Network:** [World-wide network](https://learn.microsoft.com/en-us/azure/networking/microsoft-global-network) of Microsoft data centers, delivering public cloud services when internet connectivity permits. + +## Operational Best Practices + +The following best practices and deployment configurations help ensure that Mattermost remains compliant and operationally resilient in contested environments. + +### User Authentication + +DDIL environments require authentication infrastructure that remains fully operational without internet connectivity. Relying solely on cloud-based identity providers like Microsoft Entra ID creates a critical single point of failure when tactical networks become disconnected. To ensure mission users maintain authentication capabilities, deploy a locally hosted identity provider within the tactical network. + +- **Enterprise Users:** Access Teams and Outlook by authenticating to Microsoft 365 via Entra ID, and their M365 session also provides access to the embedded Mattermost experience when the tactical network is internet connected. +- **Mission users:** Authenticate to Mattermost using a local IdP, such as [Keycloak](/administration-guide/onboard/sso-saml-keycloak) (open-source IdP with OIDC/SAML support), Active Directory with ADFS, or OpenLDAP with an OIDC bridge. When internet connected, the local IdP can optionally federate with Microsoft Entra ID to synchronize user accounts, credentials, and group memberships to enable access to Microsoft applications. + +User accounts must be provisioned in the local IdP before disconnection occurs to ensure authentication services remain available throughout DDIL conditions. + +### Sovereign AI + +Deploy an [OpenAI compatible LLM](/administration-guide/configure/agents-admin-guide) on tactical infrastructure to ensure AI capabilities remain fully sovereign and operational in disconnected scenarios. A self-hosted LLM can power [message and call summarization, semantic search](/end-user-guide/agents#analyze-threads-and-channels), and [mission-tuned AI agents](/administration-guide/configure/agents-admin-guide#agent-configuration) without relying on public cloud AI services. This guarantees compliance with strict data handling mandates and enables AI-enhanced workflows to function locally, even during extended disconnections. + +### Self-hosted audio & screensharing + +Effective collaboration at the tactical edge requires all voice and screen sharing capabilities remain operational without reliance on the internet or third-party services. Deploy [Mattermost Calls](/administration-guide/configure/calls-deployment-guide) in a self-hosted configuration, including: + +- The `rtcd` service, configured using the [RTCD Setup and Configuration](/administration-guide/configure/calls-rtcd-setup) guide, provides scalable, low-latency media routing hosted on-premises. Run multiple `rtcd` nodes for redundancy. +- The `calls-offloader` service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, offloads heavy processing tasks like recording, transcription and live captioning to a locally hosted compliance-approved job server. + +### High availability and fault tolerance + +Deploy Mattermost in a [cluster-based architecture](/administration-guide/scale/high-availability-cluster-based-deployment) to ensure continued availability during outages or hardware failures. High availability requires redundant infrastructure across each critical component: + +- Application servers: Scale horizontally across multiple nodes with a load balancer distributing client traffic. +- Search service: [Elasticsearch or AWS OpenSearch Service](/administration-guide/scale/scaling-for-enterprise#enterprise-search) provides optimized search performance with dedicated indexing for large-scale deployments. +- Object storage: Configure S3-compatible backends with erasure coding or replication for durability. All application servers must access shared file storage (NAS or S3) to ensure consistent data availability. +- Calls services: Run multiple `rtcd` and offloader nodes for resilience. + +### Compliance and retention + +Sovereign environments often require strict enforcement of retention policies, legal hold, and export controls. Configure Mattermost's built-in compliance features to meet organizational mandates. + +- Enable [compliance export](/administration-guide/comply/compliance-export) and [monitoring](/administration-guide/comply/compliance-monitoring) to produce auditable exports of message data and user activity logs. +- Configure [message retention](/administration-guide/comply/data-retention-policy) and [legal hold](/administration-guide/comply/legal-hold) policies to align with applicable regulations. +- Integrate with your organization's [eDiscovery](/administration-guide/comply/electronic-discovery) and archiving systems as required. diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-mission-partner.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-mission-partner.mdx new file mode 100644 index 000000000000..6c192e809972 --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-mission-partner.mdx @@ -0,0 +1,146 @@ +--- +title: "Deploy for Mission Partner Collaboration" +--- +## Overview + +Mission partner collaboration extends [sovereign collaboration](/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration) and [edge deployment](/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations) models to enable joint and allied operations across organizations using Mattermost, Microsoft 365 and legacy platforms. The solution architecture outlined in this document delivers a secure, sovereign, and intelligent mission environment that is federated across enterprise and coalition partner networks, enabling interoperability while maintaining compliance and control. + +Joint mission collaboration is achieved through federation using [connected workspaces](/administration-guide/onboard/connected-workspaces), [Matrix connectors](https://mattermost.com/marketplace/mattermost-matrix-connector/), [guest accounts](/administration-guide/onboard/guest-accounts), and [auto-translation](https://github.com/mattermost/mattermost-plugin-channel-translations) for fast, accurate comprehension across globally distributed teams. Additionally, integrating external data feeds, workflow automation, and sovereign AI enables allied and partner users to collaborate at mission speed while enforcing zero-trust policies and maintaining data sovereignty. + +Mattermost deployments may be hosted on-premises or in sovereign clouds, enabling allies and partners to retain control over sensitive data while extending interoperability to coalition partner enterprise networks. + +## Collaboration challenges + +Multi-agency collaborations face complex communication challenges: + +- **Platform diversity:** Organizations often use different platforms, including Microsoft 365, Mattermost, and Matrix - with some using Teams for enterprise productivity [supplemented with Mattermost](/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration) for sovereign collaboration, data residency, and offline resilience. +- **External access:** External partners need controlled access without full organizational membership. +- **Language barriers:** Organizations may speak different languages. +- **Compliance:** Data residency and compliance requirements vary across organizations. + +## Solution Architecture + +Traditional solutions require everyone to adopt the same platform or use insecure external tools. Mattermost powers a multi-layer approach addressing these collaboration challenges and diverse organizational needs, including: + +- **Mattermost ↔ Mattermost Collaboration:** Organizations with Mattermost deployments establish secure connections and share specific channels using [connected workspaces](/administration-guide/onboard/connected-workspaces) over standard HTTPS/VPN. +- **External users ↔ Mattermost Collaboration:** Users from external organizations receive Mattermost [guest accounts](/administration-guide/onboard/guest-accounts) with least-privilege access. External users in Microsoft environments may access Mattermost using the [embedded application](/integrations-guide/mattermost-mission-collaboration-for-m365) in their Teams and Outlook clients. +- **Matrix / XMPP ↔ Mattermost Collaboration:** Organizations using legacy XMPP systems or Matrix servers connect to Mattermost via the [Matrix bridge plugin](https://github.com/mattermost/mattermost-plugin-matrix-bridge) for bidirectional communication. +- **Automatic Language Translation:** The AI-powered [automatic translation plugin](https://github.com/mattermost/mattermost-plugin-channel-translations) enables seamless communication across language barriers in channels with distributed teams. + +![Mattermost diagram displays the deployment components and relationships outlined in detail in this document.](/images/architecture-mpe.png) + + + +Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs support deploying Mattermost and supporting services for mission partner collaboration. + + + +## Architecture components + +The deployment architecture includes the following components: + +- **Allied or Partner Networks:** Globally distributed and segregated networks for each allied or partner organization. + - Networks may have a firewall or access gateway protecting egress and ingress, such as network policies, IP allowlists, or WAFs depending on networking configurations. + - Networks may [operate in contested environments](/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations) where internet connectivity is intermittent. +- **Users:** Enterprise, allied, and coalition partner users accessing client applications for Mattermost and/or Microsoft 365. +- **Microsoft Entra ID (Identity Provider):** Partnered organizations using Microsoft 365 services may use [single sign-on Entra ID](/administration-guide/onboard/sso-entraid) for unified authentication to M365 and Mattermost applications. *(Optional)* +- **Federation Services:** + - **Connected workspaces:** [Federated collaboration](/administration-guide/onboard/connected-workspaces) across partner networks, with seamless synchronization of messages, threads, and files. + - **Guest Accounts:** [Secure participation](/administration-guide/onboard/guest-accounts) of external mission partners with least-privilege access. *(Optional)* + - **Matrix & XMPP Interoperability:** [Federation with legacy partner systems](https://github.com/mattermost/mattermost-plugin-matrix-bridge) for cross-domain coalition collaboration. *(Optional)* +- **Client Applications:** + - **Mattermost Desktop Apps:** Access Mattermost directly by deploying [desktop](/deployment-guide/desktop/desktop-app-deployment) or web apps in your organization. + - **Mattermost Mobile Apps:** Access Mattermost via [iPhone and Android apps](/deployment-guide/mobile/mobile-app-deployment), with support for [ID-only push notifications](/deployment-guide/mobile/host-your-own-push-proxy-service) to ensure compliance with data sovereignty requirements. *(Optional - not shown)* + - **Microsoft 365 Desktop Apps:** For partnered organizations using Microsoft 365 services, Teams and Outlook can be deployed with the [embedded Mattermost application](/integrations-guide/mattermost-mission-collaboration-for-m365) for cross-domain partner collaboration within a familiar interface. *(Optional)* +- **Mattermost Deployments:** Mattermost deployed for sovereign collaboration on private cloud or local infrastructure, such as [Azure](/deployment-guide/server/deploy-kubernetes) or [Azure Local](https://learn.microsoft.com/en-us/azure/azure-local/manage/disconnected-operations-overview), to maintain compliance with STIG, FedRAMP, and NIST 800-53 standards. See [reference architecture](/administration-guide/scale/server-architecture) documentation for Mattermost deployment configurations based on expected scale. + - **Mattermost Server:** Core application server handling collaboration workloads, including: + - [Messaging Collaboration](/end-user-guide/messaging-collaboration): Sovereign 1:1, group messaging, and structured channel collaboration. + - [Workflow Automation](/end-user-guide/workflow-automation): Playbooks provide structure, monitoring and automation for repeatable processes built-in to your sovereign Mattermost deployment. + - [Project Tracking](/end-user-guide/project-task-management): Boards enables project management capabilities built-in to your local Mattermost deployment. Boards enables project management capabilities built-in to your sovereign Mattermost deployment. + - [AI Agents](/administration-guide/configure/agents-admin-guide): AI Agents run against Azure OpenAI endpoints or a self-hosted LLM that is OpenAI-compatible. + - [Audio & Screenshare](/administration-guide/configure/calls-deployment-guide): Calls offers native real-time self-hosted audio calls and screen sharing within your own network. + - **Proxy Server:** The [proxy server](/deployment-guide/server/setup-nginx-proxy) handles HTTP(S) routing within the cluster, directing traffic between the server and clients accessing Mattermost services, including requests from users in [connected organizations](/administration-guide/onboard/connected-workspaces). NGINX is recommended for load balancing with support for WebSocket connections, health check endpoints, and sticky sessions. The proxy layer provides SSL termination and distributes client traffic across application servers. + - **PostgreSQL Database:** Stores persistent application data on a [PostgreSQL v13+ database](/deployment-guide/server/preparations), such as [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql). + - **Object Storage:** File uploads, images, and attachments are stored outside the application node on an [S3-compatible store](/deployment-guide/server/preparations) or an NFS (Network File System) server. [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) can be used, but needs an S3-compatible proxy for Mattermost to interface with. + - **Recording Instance:** `calls-offloader` job service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, to offload heavy processing tasks from Mattermost Calls, such as recordings, transcriptions, and live captioning, to local infrastructure or private cloud. *(Optional)* +- **Integration framework:** [Custom apps, plugins, and webhooks](/integrations-guide/integrations-guide-index) can be deployed for real-time data integrations and alerting. *(Optional - not shown)* +- **Self-hosted LLM:** Locally hosted [OpenAI compatible LLM](/agents/docs/providers) for agentic powered collaboration. *(Optional)* +- **Microsoft Global Network:** [World-wide network](https://learn.microsoft.com/en-us/azure/networking/microsoft-global-network) of Microsoft data centers, delivering public cloud services including M365 and Azure OpenAI. *(Optional)* + +## Operational Best Practices + +The following best practices and deployment configurations help ensure that Mattermost remains secure, resilient, and interoperable across federated mission partner environments. + +### Network Configuration + +When external access is enabled through various federation capabilities, it is recommended to deploy Mattermost in a DMZ rather than on the internal network. This approach provides defense-in-depth and preserves security boundaries by isolating each connected server deployment from the enterprise network. + +- **DMZ Deployment:** Position Mattermost application servers in the DMZ network segment, allowing both internal users and external partner federation traffic to access the collaboration platform through controlled network boundaries. +- **VPN Termination:** Terminate site-to-site VPN connections at the network perimeter or DMZ layer, enabling encrypted partner connectivity without exposing internal network infrastructure. VPN tunnels establish secure communication channels between partner organizations over the internet. +- **Firewall Segmentation:** Deploy ingress and egress firewall rules to control traffic flow between the DMZ, internal network, and external partner networks. Restrict database and object storage access to only originate from the DMZ segment where Mattermost servers reside. +- **Federation Traffic Isolation:** Partner federation traffic (Connected workspaces synchronize over HTTPS port 443/TCP) remains isolated within the DMZ, protecting internal systems while enabling partner collaboration and enforcing zero-trust principles across organizational boundaries. + +### Resilient federation for joint operations + +[Connected workspaces](/administration-guide/onboard/connected-workspaces) allow federated collaboration across multiple organizations and networks while maintaining local data control of each Mattermost deployment. Messages, threads, and files are securely synchronized between environments, ensuring mission continuity for multinational operations without requiring partners to join a single centralized deployment. + +- Enforce [zero-trust access](/administration-guide/onboard/connected-workspaces#create-a-secure-connection) and ensure that only authorized mission partners can view or contribute to shared collaboration channels. +- Configure [auto-translation](https://github.com/mattermost/mattermost-plugin-channel-translations) in shared channels for seamless multilingual cross-domain collaboration. +- Mattermost instances can operate independently during outages or intermittent connectivity and sync conversations once connectivity returns. + +Many mission partners continue to operate on legacy systems such as Matrix and XMPP. To enable joint operations without forcing migration, Mattermost supports [secure interoperability](https://github.com/mattermost/mattermost-plugin-matrix-bridge) with these environments for continuity of coalition communications while allowing modernized workflows to extend across federated networks. + +Synchronize Mattermost channels with Matrix or XMPP rooms, allowing messages, threads, and attachments to flow across systems in real-time. Each organization maintains control of its data and infrastructure, while interoperability is enabled through federation bridges rather than centralized services. + +### Controlled external access + +Mission partner collaboration may require involving external users such as allied forces, contractors, or coalition partners that do not have Mattermost deployments themselves. [Guest accounts](/administration-guide/onboard/guest-accounts) provide a controlled mechanism to enable these users to participate in joint mission operations while maintaining strict compliance and security boundaries. + +- Guest accounts are restricted to specific teams and channels. This ensures external users only have access to mission-critical resources necessary for their role. +- Guests can be granted access to shared channels, enabling collaboration with additional trusted organizations through [connected workspaces](/administration-guide/onboard/connected-workspaces). +- Guest users can be provided VPN credentials that allow them to connect specifically to the DMZ network segment where Mattermost resides. This architecture ensures external guests can access the collaboration platform without gaining access to internal corporate resources, files, or systems. + +### Zero-trust access controls + +Mission partner collaboration environments should adopt zero-trust principles by implementing [attribute-based access control (ABAC)](/administration-guide/manage/admin/attribute-based-access-control) to ensure access to mission channels is governed by dynamic attributes such as role, clearance, location, and mission context. + +- Restrict channel access based on [user attributes](/administration-guide/manage/admin/user-attributes) rather than static groups. +- Continuously audit ABAC policies to ensure compliance with multinational operational and legal requirements. + +### Sovereign AI + +AI capabilities enhance mission collaboration with summarization, translation, semantic search, and decision support. Sovereign AI ensures these capabilities remain fully under organizational control, without reliance on public cloud services or external data processing. Deploying AI in a self-hosted or compliance-approved environment enables secure, mission-ready augmentation. + +- Deploy [OpenAI compatible language models](/administration-guide/configure/agents-admin-guide) on local or private cloud infrastructure to maintain data sovereignty and ensure offline availability. +- Configure [custom agents](/administration-guide/configure/agents-admin-guide#agent-configuration) for summarization, workflow automation, and decision support while enforcing organizational compliance policies. +- Enable multilingual collaboration in shared channels using sovereign AI services to provide [real-time translations](https://github.com/mattermost/mattermost-plugin-channel-translations) across partner organizations. +- Embed AI into operational playbooks for automated task execution, situational summaries, and proactive recommendations. +- Allow authorized users from partner organizations to securely access locally hosted LLMs through shared channels in [connected workspaces](/administration-guide/onboard/connected-workspaces). + +### High availability and fault tolerance + +Deploy Mattermost in a [cluster-based architecture](/administration-guide/scale/high-availability-cluster-based-deployment) to ensure continued availability during outages or hardware failures. High availability requires redundant infrastructure across each critical component: + +- Application servers: Scale horizontally across multiple nodes with a load balancer distributing client traffic. +- Search service: [Elasticsearch or AWS OpenSearch Service](/administration-guide/scale/scaling-for-enterprise#enterprise-search) provides optimized search performance with dedicated indexing for large-scale deployments. +- Object storage: Configure S3-compatible backends with erasure coding or replication for durability. All application servers must access shared file storage (NAS or S3) to ensure consistent data availability. +- Calls services: Run multiple `rtcd` and offloader nodes for resilience. + +### Sovereign audio & screensharing + +Deploy [Mattermost Calls](/administration-guide/configure/calls-deployment-guide) in a self-hosted configuration to ensure voice and screen sharing capabilities remain operational without reliance on the internet, and that media traffic does not traverse non-compliant third-party services. + +- The `rtcd` service, configured using the [RTCD Setup and Configuration](/administration-guide/configure/calls-rtcd-setup) guide, provides scalable, low-latency media routing hosted on-premises. Run multiple `rtcd` nodes for redundancy. +- The `calls-offloader` service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, offloads heavy processing tasks like recording, transcription and live captioning to a compliance-approved job server. + +### Compliance and retention + +Sovereign environments often require strict enforcement of retention policies, legal hold, and export controls. Configure Mattermost's built-in compliance features to meet organizational mandates. + +- Enable [compliance export](/administration-guide/comply/compliance-export) and [monitoring](/administration-guide/comply/compliance-monitoring) to produce auditable exports of message data and user activity logs. +- Configure [message retention](/administration-guide/comply/data-retention-policy) and [legal hold](/administration-guide/comply/legal-hold) policies to align with applicable regulations. +- Integrate with your organization's [eDiscovery](/administration-guide/comply/electronic-discovery) and archiving systems as required. + +### Mobile notifications + +To prevent sensitive message content from being transmitted to external notification services such as Apple Push Notification Service (APNS) and Firebase Cloud Messaging (FCM), configure Mattermost to use [ID-only push notifications](/deployment-guide/mobile/host-your-own-push-proxy-service). In this mode, only a message identifier is sent to public push notification services, and the client retrieves the content securely from the Mattermost server over an encrypted channel. diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob.mdx new file mode 100644 index 000000000000..53d1a119bd22 --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob.mdx @@ -0,0 +1,110 @@ +--- +title: "Deploy for Out-of-Band (OOB) Communications" +--- +When a critical incident disrupts an organization’s primary infrastructure—due to a cyberattack, cloud outage, or internal failure—a secure, independent communication channel becomes essential. Mattermost can serve as that channel by operating in an Out-of-Band (OOB) environment: isolated, pre-provisioned, and ready to support incident response and business continuity teams. + +This document outlines architectural guidance for deploying Mattermost in an OOB scenario across [generic](#generic-oob-architecture), [AWS](#aws-based-oob-deployment), and [Azure](#azure-based-oob-deployment) environments. + +## Generic OOB architecture + +This platform-agnostic design establishes a fallback communication system, decoupled from primary networks and identity providers. + +Generic OOB Architecture + +### Architecture components + +- **Users (Cybersecurity, IR Teams)**: Pre-authorized personnel trained to access and use the OOB platform during emergencies. Credentials and access methods should be provisioned in advance. +- **Secure Access Layer**: A firewall or access gateway protecting entry into the OOB environment. May include network policies, IP allowlists, or WAFs. +- **Secondary IdP / Emergency Auth**: A dedicated identity provider not dependent on the organization’s primary SSO or IdP (e.g., a minimal Azure AD tenant, Okta org, or locally stored credentials with MFA). +- **VPN / Bastion Host**: A hardened jumpbox or independent VPN granting access to internal OOB components and Kubernetes control plane. +- **Failover DNS Manager**: Services like Cloudflare Load Balancer, Azure Traffic Manager, or Route 53 to monitor primary system health and reroute DNS to the OOB ingress. +- **Ingress Controller**: e.g., ingress-nginx to handle HTTP(S) routing within the cluster, directing traffic to Mattermost Web, API, and WebSocket endpoints. +- **Mattermost Operator & App**: Automates lifecycle of Mattermost instances in Kubernetes; ensures updates, scaling, and configuration consistency. +- **PostgreSQL Database**: Persistent storage for channels, messages, users, and configurations; can be self-hosted or managed externally with hardened access. +- **Backups**: + - **Velero**: Backs up Kubernetes resources to external object store (S3, Blob). + - **pg_dump / Cloud-native backup**: Regular logical exports or managed backups. + - **Object Storage**: Durable, versioned storage (e.g., S3, Azure Blob) for snapshots and dumps. + +## AWS-based OOB deployment + +Deploying Mattermost in AWS leverages managed services and strong isolation capabilities. + +AWS OOB Deployment diagram + +### AWS components + +- **Amazon EKS**: Managed Kubernetes for Mattermost Operator and application, with HA and auto-scaling. +- **Route 53**: DNS service for health-checked failover to the OOB environment. +- **Amazon Aurora PostgreSQL**: High-performance managed PostgreSQL with automated failovers. +- **Amazon S3**: Object storage for Velero snapshots, configurations, and database backups (with versioning and cross-region replication). +- **IAM Roles**: Scoped roles for EKS nodes and Velero using IRSA, enforcing least-privilege. + + + +- Use separate AWS accounts or VPCs for full isolation. +- Configure Route 53 health checks against public or synthetic endpoints. +- Encrypt secrets and enforce least-privilege IAM policies. + + + +## Azure-Based OOB deployment + +For Azure customers, AKS and related services provide a robust OOB platform for Mattermost. + +Azure OOB Deployment diagram + +### Azure components + +- **Azure Kubernetes Service (AKS)**: Runs Mattermost workloads with native autoscaling and Azure AD integration. +- **Azure DNS + Traffic Manager**: Global traffic routing and DNS failover based on endpoint health. +- **Azure Database for PostgreSQL**: Managed DB service with automated backups and patching. +- **Azure Blob Storage**: Destination for Velero snapshots and DB dumps; supports lifecycle policies and secure access. +- **Azure AD (Secondary Tenant)**: Acts as the IdP for OOB; deployed in a separate directory with scoped permissions and MFA. + + + +- Deploy in a dedicated subscription for security and billing separation. +- Use Azure Monitor for health checks and Traffic Manager probes. +- Harden AKS node pools and isolate workloads with namespaces and network policies. + + + +## Operational guidelines + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DomainRecommendation
Access ControlIsolate authentication from primary infrastructure. Use MFA, secure vaults, and emergency tokens. Preload user accounts in the secondary IdP.
DNS FailoverEmploy TTL-aware health checks via Route 53 or Traffic Manager. Monitor critical HTTP(S) or TCP endpoints.
Backup StrategySchedule frequent Velero and database backups. Store in versioned, encrypted object storage.
Disaster Recovery DrillsConduct quarterly failover exercises: DNS switching, Mattermost access, and data restores.
SecurityTreat OOB as Tier 0. Use hardened OS images, audit logging, strict RBAC, and centralized monitoring. Rotate secrets regularly.
+ +Mattermost can be an effective OOB communication platform when deployed with isolation, automation, and operational readiness. Whether on AWS, Azure, or a generic environment, prioritize independence, simplicity, and resilience. Pair these designs with standard IR playbooks and routine failover testing to build a confident, secure response capability. diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration.mdx new file mode 100644 index 000000000000..8ecb1be4b20b --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration.mdx @@ -0,0 +1,84 @@ +--- +title: "Deploy for Sovereign Collaboration in Microsoft" +--- +## Overview + +Agencies and critical infrastructure organizations often face strict data sovereignty requirements that restrict the use of public cloud services for sensitive collaboration. + +Deploying Mattermost for sovereign collaboration within Microsoft Teams and Outlook enables secure, compliant, and resilient communication while maintaining workflow continuity inside familiar Microsoft interfaces. Users access both Teams channels and Mattermost channels [from within the Microsoft ecosystem](/integrations-guide/mattermost-mission-collaboration-for-m365), providing a single-pane-of-glass experience and eliminating application switching. + +Mattermost can be hosted on-premises or in sovereign clouds, such as Azure GovCloud or Azure Local, ensuring that messages, files, recordings, and transcriptions remain in compliance-approved systems with encryption and strict policy enforcement. + +Unified authentication with Microsoft Entra-ID extends your Microsoft enterprise IT investments while delivering the compliance, control, and resilience required for mission-critical operations or out-of-band scenarios. + +This document outlines architectural guidance for enabling sovereign collaboration within your Microsoft ecosystem. + +![Mattermost diagram displays the deployment components and relationships outlined in detail in this document.](/images/architecture-ms-teams-collab.png) + + + +Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs support deploying Mattermost and supporting services for soverign collaboration within your Microsoft ecosystem. + + + +## Architecture components + +The deployment architecture includes the following components: + +- **Users:** Enterprise users within the network boundary accessing client applications for M365 services and Mattermost. +- **Microsoft Entra ID (Identity Provider):** Users authenticate to M365 applications and Mattermost using [single sign-on Entra ID](/administration-guide/onboard/sso-entraid) via OpenID Connect (OIDC) or SAML. +- **Client Applications:** + - **Microsoft 365 Desktop Apps:** Teams and Outlook with [embedded Mattermost application](/integrations-guide/mattermost-mission-collaboration-for-m365) for seamless collaboration within a familiar interface while enforcing regulatory compliance. + - **Mattermost Desktop Apps:** Access Mattermost via [desktop](/deployment-guide/desktop/desktop-app-deployment) or web apps in addition to the embedded views from Teams and Outlook. *(Optional - not shown)* + - **Mattermost Mobile Apps:** Access Mattermost via [iPhone and Android apps](/deployment-guide/mobile/mobile-app-deployment), with support for [ID-only push notifications](/deployment-guide/mobile/host-your-own-push-proxy-service) to ensure compliance with data sovereignty requirements. *(Optional - not shown)* +- **Mattermost Deployment:** Mattermost deployed for sovereign collaboration on enterprise-controlled infrastructure or private cloud, such as [Azure](/deployment-guide/server/deploy-kubernetes) or [Azure Local](https://learn.microsoft.com/en-us/azure/azure-local/manage/disconnected-operations-overview), to maintain compliance with STIG, FedRAMP, and NIST 800-53 standards. See [reference architecture](/administration-guide/scale/server-architecture) documentation for Mattermost deployment configurations based on expected scale. + - **Mattermost Server:** Core application server handling collaboration workloads, including: + - [Messaging Collaboration](/end-user-guide/messaging-collaboration): DDIL-ready 1:1, group messaging, and structured channel collaboration with [rich integration capabilities](/integrations-guide/integrations-guide-index) and [enterprise-grade search](/administration-guide/scale/scaling-for-enterprise#enterprise-search). + - [Workflow Automation](/end-user-guide/workflow-automation): Playbooks provide structure, monitoring and automation for repeatable processes built-in to your sovereign Mattermost deployment. + - [Project Tracking](/end-user-guide/project-task-management): Boards enables project management capabilities built-in to your sovereign Mattermost deployment. + - [AI Agents](/administration-guide/configure/agents-admin-guide): AI Agents run against Azure OpenAI endpoints or a self-hosted LLM that is OpenAI-compatible. + - [Audio & Screenshare](/administration-guide/configure/calls-deployment-guide): Calls offers native real-time self-hosted audio calls and screen sharing within your own network. + - **Proxy Server:** The [proxy server](/deployment-guide/server/setup-nginx-proxy) handles HTTP(S) routing within the cluster, directing traffic between the server and clients accessing Mattermost services. NGINX is recommended for load balancing with support for WebSocket connections, health check endpoints, and sticky sessions. The proxy layer provides SSL termination and distributes client traffic across application servers. + - **PostgreSQL Database:** Stores persistent application data on a [PostgreSQL v13+ database](/deployment-guide/server/preparations), such as [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql). + - **Object Storage:** File uploads, images, and attachments are stored outside the application node on an [S3-compatible store](/deployment-guide/server/preparations) or an NFS (Network File System) server. [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) can be used, but needs an S3-compatible proxy for Mattermost to interface with. + - **Recording Instance:** `calls-offloader` job service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, to offload heavy processing tasks from Mattermost Calls, such as recordings, transcriptions, and live captioning, to enterprise-controlled infrastructure or private cloud. *(Optional)* +- **Self-hosted integrations:** [Custom apps, plugins, and webhooks](/integrations-guide/integrations-guide-index) can be deployed within the enterprise boundary. *(Optional - not shown)* + +**Secure Access Layer:** A firewall or access gateway protecting entry into the enterprise network. This may include network policies, IP allowlists, or WAFs depending on your networking configurations. *(Optional)* + +**Microsoft Global Network:** [World-wide network](https://learn.microsoft.com/en-us/azure/networking/microsoft-global-network) of Microsoft data centers, delivering public cloud services including M365 and Azure OpenAI. + +**Azure OpenAI Service:** [LLM service](/agents/docs/providers) used for summarization, ai-enhanced search, and agent-assisted workflows, hosted within the Microsoft Global Network. *(Optional)* + +## Operational Best Practices + +The following best practices and deployment configurations help ensure that Mattermost remains compliant, resilient, and fully sovereign when deployed alongside Microsoft 365. + +### High availability and fault tolerance + +Deploy Mattermost in a [cluster-based architecture](/administration-guide/scale/high-availability-cluster-based-deployment) to ensure continued availability during outages or hardware failures. High availability requires redundant infrastructure across each critical component: + +- Application servers: Scale horizontally across multiple nodes with a load balancer distributing client traffic. +- Database layer: Use PostgreSQL replication or managed HA services with automatic failover. +- Search service: [Elasticsearch or AWS OpenSearch Service](/administration-guide/scale/scaling-for-enterprise#enterprise-search) provides optimized search performance with dedicated indexing for large-scale deployments. +- Object storage: Configure S3-compatible backends with erasure coding or replication for durability. All application servers must access shared file storage (NAS or S3) to ensure consistent data availability. +- Calls services: Run multiple `rtcd` and `calls-offloader` nodes for resilience. + +### Sovereign audio & screensharing + +Data sovereignty compliance may require that all voice and screen sharing traffic remain within enterprise-controlled infrastructure and does not traverse third-party services. Deploy [Mattermost Calls](/administration-guide/configure/calls-deployment-guide) in a self-hosted configuration to ensure that Microsoft Teams users and Mattermost users collaborate without media ever leaving the sovereign network. + +- The `rtcd` service, configured using the [RTCD Setup and Configuration](/administration-guide/configure/calls-rtcd-setup) guide, provides scalable, low-latency media routing hosted on-premises. Run multiple `rtcd` nodes for redundancy. +- The `calls-offloader` service, configured using the [Calls Offloader Setup and Configuration](/administration-guide/configure/calls-offloader-setup) guide, offloads heavy processing tasks like recording, transcription and live captioning to a compliance-approved job server. + +### Compliance and retention + +Sovereign environments often require strict enforcement of retention policies, legal hold, and export controls. Configure Mattermost's built-in compliance features to meet agency or sectoral mandates. + +- Enable [compliance export](/administration-guide/comply/compliance-export) and [monitoring](/administration-guide/comply/compliance-monitoring) to produce auditable exports of message data and user activity logs. +- Configure [message retention](/administration-guide/comply/data-retention-policy) and [legal hold](/administration-guide/comply/legal-hold) policies to align with applicable regulations. +- Integrate with your organization's [eDiscovery](/administration-guide/comply/electronic-discovery) and archiving systems as required. + +### Mobile notifications + +To prevent sensitive message content from being transmitted to external notification services such as Apple Push Notification Service (APNS) and Firebase Cloud Messaging (FCM), configure Mattermost to use [ID-only push notifications](/deployment-guide/mobile/host-your-own-push-proxy-service). In this configuration, only a message identifier is sent to public push notification services and the client retrieves the content securely from the Mattermost server over an encrypted channel. diff --git a/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index.mdx b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index.mdx new file mode 100644 index 000000000000..4f1955b80a4a --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index.mdx @@ -0,0 +1,12 @@ +--- +title: "Deployment Scenarios" +--- +This section outlines reference architectures and guidance tailored for specialized Mattermost deployment scenarios, enabling organizations to build secure, compliant, and resilient collaboration environments across diverse operational contexts. + +Whether you’re implementing out-of-band communications, mission partner collaboration, sovereign collaboration within Microsoft ecosystems, or mission-critical operations at the edge, these architectures offer comprehensive guidance, design patterns, and best practices to ensure robust and reliable deployments. + +- [Out-of-Band Communications](/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob) - Deploy Mattermost as an isolated, pre-provisioned communication system for incident response and business continuity. +- [Mission Partner Collaboration](/deployment-guide/reference-architecture/deployment-scenarios/deploy-mission-partner) - Multi-organizational collaboration architecture with secure information sharing between allied networks and coalition partners. +- [Enterprise to Edge DDIL Operations](/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations) - Deployment patterns for Denied, Degraded, Intermittent, and Limited (DDIL) communication environments with offline capabilities. +- [Sovereign Collaboration in Microsoft](/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration) - Integration architecture for sovereign cloud environments with Microsoft Teams, Outlook and other M365 services. +- [Air-gapped Deployment](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) - Guidance and best practices when deploying Mattermost in air-gapped environments. diff --git a/docs/main/deployment-guide/reference-architecture/reference-architecture-index.mdx b/docs/main/deployment-guide/reference-architecture/reference-architecture-index.mdx new file mode 100644 index 000000000000..133c0c28b5ce --- /dev/null +++ b/docs/main/deployment-guide/reference-architecture/reference-architecture-index.mdx @@ -0,0 +1,8 @@ +--- +title: "Reference Architecture" +--- +Mattermost reference architectures describe recommended deployment patterns and system designs that ensure secure, scalable, and resilient collaboration. These frameworks serve as a guide for implementing Mattermost at scale across a range of operational scenarios. + +- [Application Architecture](/deployment-guide/reference-architecture/application-architecture) - An overview of Mattermost's architecture and components. +- [Scaling Architecture](/administration-guide/scale/scaling-for-enterprise) - Reference architecture for high availability, clustering, and enterprise-scale deployments. +- [Deployment Scenarios](/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index) - Reference architectures tailored for specialized Mattermost deployment scenarios. diff --git a/docs/main/deployment-guide/server/configure-fips-at-install-time.mdx b/docs/main/deployment-guide/server/configure-fips-at-install-time.mdx new file mode 100644 index 000000000000..ef2517208987 --- /dev/null +++ b/docs/main/deployment-guide/server/configure-fips-at-install-time.mdx @@ -0,0 +1,110 @@ +--- +title: Configure FIPS at Install Time +sidebar_position: 15 +description: Enable FIPS 140-3 validated cryptography during Mattermost installation. FIPS mode cannot be enabled post-deploy. +--- + + + + + + +# Configure FIPS at Install Time + +FIPS 140-3 validated cryptography is required for many regulated deployments (FedRAMP Moderate, DoD IL4/IL5, FISMA-bounded systems, healthcare environments under HHS guidance). Mattermost supports FIPS mode using validated cryptographic modules. + +:::important FIPS cannot be enabled post-deploy +FIPS mode is an **install-time decision**, not a runtime hardening toggle. The cryptographic primitives used for password hashing, session token signing, and TLS handshakes must be FIPS-validated from the first request the server handles. Switching FIPS on after data has been written to the database invalidates existing hashes and tokens. + +If you intend to operate under FedRAMP Moderate or any DoD IL level, enable FIPS during initial install. Do not defer to a "we'll harden it later" sweep. +::: + +This page is the canonical entry point for FIPS configuration. It is intentionally located inside the **Install Mattermost Server** sub-tree, modelling [Red Hat OpenShift's pattern](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/installation_overview/installing-fips) of treating FIPS as a top-level install chapter rather than a hardening appendix. + +## What FIPS mode changes + +When FIPS mode is enabled at install: + +- **Cryptographic modules** — Mattermost binds to validated cryptographic libraries (BoringCrypto via Go's `GOEXPERIMENT=boringcrypto` build flag, or RHEL OpenSSL FIPS module for RHEL hosts). Non-FIPS algorithms (e.g., MD5, SHA-1 for security purposes) are unavailable. +- **TLS cipher suites** — Restricted to FIPS-approved cipher suites only. ChaCha20-Poly1305 is unavailable; AES-GCM is preferred. +- **Password hashing** — bcrypt remains the algorithm; the underlying cryptographic primitive uses the FIPS-validated module. +- **Session tokens** — HMAC-SHA-256 with the validated module. +- **Audit log** — every audit emission tagged with `fips_mode: true`. + +## What FIPS mode does *not* change + +- **User-visible behavior** — end users see no functional differences. Authentication, messaging, file uploads work identically. +- **Plugin compatibility** — most plugins work unchanged. Plugins that bundle non-FIPS crypto must be rebuilt against FIPS libraries before they can run in FIPS mode. +- **Performance** — typically under 2% overhead vs. non-FIPS builds on modern hardware. Negligible in practice. + +## CMVP certificate + +Mattermost's FIPS-validated build is based on **BoringCrypto** (the FIPS-validated cryptographic core of BoringSSL). + +| Cryptographic module | CMVP certificate | Status | +|---|---|---| +| BoringCrypto (Go) | Pending publication | Status updated by Mattermost compliance team as validation completes. | + +This table will be updated when validation is complete. The Mattermost release notes for the FIPS-enabled build will name the exact certificate number and module version — auditors copy these directly into SSPs. + +## Procedure + +1. **Choose a FIPS-validated build**. Mattermost publishes a FIPS-enabled Enterprise build alongside the standard build. The artifact is named with a `-fips` suffix: + - Linux tarball: `mattermost-VERSION-linux-amd64-fips.tar.gz` + - Container image: `mattermost/mattermost-enterprise-edition:VERSION-fips` + - Helm chart value: `image.tag: VERSION-fips` +2. **Install the FIPS build using the standard install procedure** for your platform: + - [Install on Linux](./deploy-linux.mdx) — replace the standard tarball with the `-fips` tarball. + - [Install on Kubernetes](./deploy-kubernetes.mdx) — set `image.tag` to a `-fips` tag. + - [Install on Containers](./deploy-containers.mdx) — pull the `-fips` image tag. +3. **Set the `FIPSMode` config flag**: + ```json + { + "ServiceSettings": { + "FIPSMode": true + } + } + ``` +4. **Verify FIPS mode is active**: + ``` + mmctl system info + ``` + The output includes a `FIPS mode: enabled` line. The server startup log also emits `FIPS mode active; validated cryptographic module loaded: BoringCrypto vX.Y`. +5. **Verify TLS cipher suite restriction**. Use `openssl s_client` from a client to the Mattermost endpoint: + ``` + openssl s_client -connect mattermost.example:443 -cipher 'CHACHA20' + ``` + Expected: connection fails (ChaCha20 is non-FIPS). + +## Migrating non-FIPS → FIPS + +There is no in-place migration from a non-FIPS Mattermost install to a FIPS install. The supported procedure: + +1. Provision a new Mattermost cluster from scratch in FIPS mode. +2. Export data from the non-FIPS cluster ([Migrate](../../administration-guide/) — Bulk Export). +3. Import into the new FIPS cluster ([Migrate](../../administration-guide/) — Bulk Loading). +4. Decommission the non-FIPS cluster. + +This is the same procedure Red Hat OpenShift documents for non-FIPS → FIPS migration. + +## Air-gapped + FIPS + +FIPS mode and air-gapped deployment are commonly paired. The combined procedure is: + +1. Stage the `-fips` artifact on the operator workstation. Verify checksum + signature. +2. Transfer across the air gap ([Air-Gapped Quick-Start Runbook](../air-gapped-operations/quick-start-runbook) step 1–2). +3. Publish to the internal mirror ([Mirror Package Repositories](../air-gapped-operations/mirror-package-repositories)). +4. Install the `-fips` build using the standard air-gapped install procedure. +5. Set `FIPSMode: true` in `config.json`. + +## References + +- [NIST FIPS 140-3](https://csrc.nist.gov/projects/cryptographic-module-validation-program/standards) — base standard. +- [BoringCrypto CMVP certificates](https://csrc.nist.gov/Projects/cryptographic-module-validation-program/Certificate/cmvp/all-certificates) — search for "BoringCrypto" to find the certificate referenced once Mattermost validation completes. +- [Red Hat OpenShift FIPS chapter](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/installation_overview/installing-fips) — reference model for "FIPS at install time" treatment. +- [Mattermost Trust Portal](https://mattermost.com/trust/) — formal attestation letters when available. diff --git a/docs/main/deployment-guide/server/containers/fips-stig.mdx b/docs/main/deployment-guide/server/containers/fips-stig.mdx new file mode 100644 index 000000000000..93b05352beff --- /dev/null +++ b/docs/main/deployment-guide/server/containers/fips-stig.mdx @@ -0,0 +1,25 @@ +--- +title: "Mattermost FIPS Overview" +sidebar_label: "FIPS / STIG container builds" +--- +From Mattermost v11, each release provides two variants: a FIPS-compliant build and a non-FIPS build. This ensures that organizations with strict compliance requirements can adopt the FIPS version while others can continue with the standard release, both staying in sync with Mattermost’s overall product lifecycle. + +Mattermost FIPS-compliant Docker images are built using Chainguard’s FIPS-certified base containers. These images help organizations meet stringent security requirements by ensuring compliance with the Federal Information Processing Standards (FIPS). + +On top of this foundation, Mattermost product code itself is aligned with FIPS requirements, using only FIPS-approved cryptographic algorithms. This ensures that both the underlying container base and the application layer meet compliance expectations. + +In addition, the Chainguard base images are STIG-hardened and rigorously scanned against the DISA General Purpose Operating System SRG, providing a robust and secure operational posture. + +Mattermost’s FIPS-compliant images are built using two Chainguard base images: + +- [Build-Time Image](https://images.chainguard.dev/directory/image/go-msft-fips/overview): Ensures compiled Mattermost binaries invoke OpenSSL through CGO for FIPS-compliance during compilation. +- [Runtime Image](https://images.chainguard.dev/directory/image/glibc-openssl-fips/overview): Enforces FIPS compliance in the runtime environment using strict OpenSSL configurations. + +All application-level code uses only FIPS-approved algorithms, ensuring that cryptographic requirements are consistently enforced across every layer of the system. + + + +- The Mattermost FIPS image includes only prepackaged Boards, Playbooks, and Agents. Additional plugins can be added to the Mattermost FIPS image, but they will run in non-FIPS mode. +- Existing Docker or Kubernetes-based deployments can change the image from `mattermost/mattermost-enterprise-edition` to `mattermost/mattermost-enterprise-fips-edition`. + + diff --git a/docs/main/deployment-guide/server/containers/install-docker.mdx b/docs/main/deployment-guide/server/containers/install-docker.mdx new file mode 100644 index 000000000000..17084dceb6e9 --- /dev/null +++ b/docs/main/deployment-guide/server/containers/install-docker.mdx @@ -0,0 +1,257 @@ +--- +title: "Install Docker" +--- +This guide provides step-by-step instructions for deploying Mattermost using Docker containers. + + + +- Mattermost server deployment using Docker is officially supported on Linux operating systems only. +- macOS and Windows Docker deployments are supported for testing and development purposes only. +- Docker is not ideal for High Availability (HA) because it lacks key features including automatic failover, shared storage, and load balancing. Docker also has challenges managing multiple nodes and recovering from failures. We recommend [deploying on Kubernetes](/deployment-guide/server/deploy-kubernetes) for HA for these features to ensure reliability. + + + +If you don't have Docker installed, follow the instructions below based on your operating system. You'll need [Docker Engine](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) (release 1.28 or later). + +# Deploy Mattermost on Docker + +This section provides a quick start guide for deploying Mattermost on Docker by leveraging [Docker Compose](https://docs.docker.com/compose/install/). + + + +- The deployment configuration results in two separate containers: a container for the database and a container for the application. An optional third container results when using NGINX for reverse proxy. +- Encountering issues with your Docker deployment? See the [Docker deployment troubleshooting](/deployment-guide/server/docker-troubleshooting) documentation for details. + + + +1. In a terminal window, clone the repository and enter the directory. + + ``` sh + git clone https://github.com/mattermost/docker + cd docker + ``` + +2. Create your `.env` file by copying and adjusting the `env.example` file. + + ``` sh + cp env.example .env + ``` + +
+ +
+ + Important + +
+ + - At a minimum, you must edit the `DOMAIN` value in the `.env` file to correspond to the domain for your Mattermost server. + - We recommend configuring the [Support Email](/administration-guide/configure/site-configuration-settings#support-email-address) via `MM_SUPPORTSETTINGS_SUPPORTEMAIL`. This is the email address your users will contact when they need help. + +
+ +3. Create the required directories and set their permissions. + + ``` sh + mkdir -p ./volumes/app/mattermost/{config,data,logs,plugins,client/plugins,bleve-indexes} + sudo chown -R 2000:2000 ./volumes/app/mattermost + ``` + +4. *(Optional)* Configure TLS for NGINX. If you're not using the included NGINX reverse proxy, you can skip this step. + + + +**Resource limits:** If you're using a custom `docker-compose.yml` file that sets pids_limit, we recommend using `mem_limit` instead to constrain resources while allowing normal connection scaling. Low `pids_limit` values can prevent the container from creating enough processes or threads, which may lead to unstable behavior under load. The current default in `docker-compose.yml` is set to `mem_limit: 4G`. + + + +# Create a new certificate and key + +> ``` sh +> bash scripts/issue-certificate.sh -d -o ${PWD}/certs +> ``` + +To include the certificate and key, uncomment the following lines in your `.env` file and ensure they point to the appropriate files. + +> ``` sh +> #CERT_PATH=./certs/etc/letsencrypt/live/${DOMAIN}/fullchain.pem +> #KEY_PATH=./certs/etc/letsencrypt/live/${DOMAIN}/privkey.pem +> ``` + +# Use a pre-existing certificate and key + +``` sh +mkdir -p ./volumes/web/cert +cp .pem ./volumes/web/cert/cert.pem +cp .pem ./volumes/web/cert/key-no-password.pem +``` + +To include the certificate and key, ensure the following lines in your `.env` file points to the appropriate files. + +> ``` sh +> CERT_PATH=./volumes/web/cert/cert.pem +> KEY_PATH=./volumes/web/cert/key-no-password.pem +> ``` + +5. Deploy Mattermost. + +# Deploy without using the included NGINX + +``` sh +docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml up -d +``` + +To access your new Mattermost deployment, navigate to `http://:8065/` in your browser. + +To shut down your deployment: + +> ``` sh +> docker compose -f docker-compose.yml -f docker-compose.without-nginx.yml down +> ``` + +# Deploy using the included NGINX + +> ``` sh +> docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d +> ``` + +To access your new Mattermost deployment via HTTPS, navigate to `https:///` in your browser. + +To shut down your deployment: + +> ``` sh +> docker compose -f docker-compose.yml -f docker-compose.nginx.yml down +> ``` + +6. Create your first Mattermost system admin user, [invite more users](/end-user-guide/collaborate/manage-channel-members), and explore the Mattermost platform. + +# Configure SSO With GitLab (Optional) + +To use SSO with GitLab with a self-signed certificate, you have to add the PKI chain for your authority. This is required to avoid the `Token request failed: certificate signed by unknown authority` error. + +To add the PKI chain, uncomment the following line in your `.env` file, and ensure it points to your `pki_chain.pem` file: + +``` sh +#GITLAB_PKI_CHAIN_PATH=/pki_chain.pem +``` + +Then uncomment the following line in your `docker-compose.yml` file, and ensure it points to the same `pki_chain.pem` file: + +``` sh +# - ${GITLAB_PKI_CHAIN_PATH}:/etc/ssl/certs/pki_chain.pem:ro +``` + +# Upgrade from mattermost-docker + +The [mattermost-docker](https://github.com/mattermost/mattermost-docker) GitHub repository is deprecated. Visit the [mattermost/docker](https://github.com/mattermost/docker) GitHub repository to access the official Docker deployment solution for Mattermost. + +To migrate from an existing `mattermost/mattermost-prod-app` image, we recommend migrating to either `mattermost/mattermost-enterprise-edition` or `mattermost/mattermost-team-edition` images, which are the official images supported by Mattermost. These images support PostgreSQL v11+ databases, which we know has been a long-running challenge for the community, and you will not lose any features or functionality by moving to these new images. + +For additional help or questions, please refer to [this issue](https://github.com/mattermost/mattermost-docker/issues/489). + +# Install a different version of Mattermost + +1. Shut down your deployment. + +2. Run `git pull` to fetch any recent changes to the repository, paying attention to any potential `env.example` changes. + +3. Adjust the `MATTERMOST_IMAGE_TAG` in the `.env` file to point your desired [enterprise](https://hub.docker.com/r/mattermost/mattermost-enterprise-edition/tags?page=1&ordering=last_updated) or [team](https://hub.docker.com/r/mattermost/mattermost-team-edition/tags?page=1&ordering=last_updated) image version. + +
+ +
+ + Important + +
+ + **For production environments**, we recommend using specific version tags such as `MATTERMOST_IMAGE_TAG=release-10.5` rather than generic tags like `MATTERMOST_IMAGE_TAG=release-10`. Generic `release-x` tags are intended for development use only and do not automatically receive new patch releases within that major version. Using specific version tags ensures a more reproducible and deterministic environment for your production deployment. + +
+ +4. Redeploy Mattermost. + +# Troubleshooting + +## Troubleshooting your Docker deployment + +If deploying on an M1 Mac and encountering permission issues in the Docker container, [redo the third step](#create-the-required-directores-and-set-their-permissions) and skip this command: + +``` sh +sudo chown -R 2000:2000 ./volumes/app/mattermost +``` + +If having issues deploying on Docker generally, ensure the docker daemon is enabled and running: + +``` sh +sudo systemctl enable --now docker +``` + +To remove all data and settings for your Mattermost deployment: + +``` sh +sudo rm -rf ./volumes +``` + +## Troubleshooting PostgreSQL + +For quick start deployments, you can change the Postgres username and/or password (recommended) in the `.env` file. If your database is managed externally, you'll need to change the password in your database management tool. Then, update the `.env` file with the new credentials. + +Troubleshooting TLS & NGINX + +For an in-depth guide to configuring the TLS certificate and key for Nginx, please refer to [this document in the repository](https://github.com/mattermost/docker/blob/main/docs/issuing-letsencrypt-certificate.md). + +# Trial Mattermost using Docker Preview + +Looking for a way to evaluate Mattermost on a single local machine using Docker? We recommend using the [Mattermost Docker Preview Image](https://github.com/mattermost/mattermost-docker-preview) to install Mattermost in Preview Mode. + + + +- This local image is self-contained (i.e., it has an internal database and works out of the box). Dropping a container using this image removes data and configuration as expected. You can see the [configuration settings](/administration-guide/configure/configuration-settings) documentation to learn more about customizing your trial deployment. +- **Preview Mode** shouldn't be used in a production environment, as it uses a known password string, contains other non-production configuration settings, has email disabled, keeps no persistent data (all data lives inside the container), and doesn't support upgrades. +- If you are planning to use the calling functionality in **Preview Mode** on a non-local environment, you should ensure that the server is running on a secure (HTTPs) connection and that the [network requirements](/administration-guide/configure/calls-rtcd-setup#network-requirements) to run calls are met. + + + +1. Install [Docker](https://www.docker.com/get-started/). +2. Once you have Docker, run the following command in a terminal window: + +> ``` sh +> docker run --name mattermost-preview -d --publish 8065:8065 --publish 8443:8443 mattermost/mattermost-preview +> ``` + +3. When Docker is done fetching the image, navigate to `http://localhost:8065/` in your browser to preview Mattermost. +4. Select **Don't have an account** in the top right corner of the screen to create an account for your preview instance. If you don't see this option, ensure that the [Enable open server](/administration-guide/configure/authentication-configuration-settings#enable-open-server) configuration setting is enabled. This setting is disabled for self-hosted Mattermost deployments by default. +5. Log in to your preview instance with your user credentials. + +## Troubleshooting your preview deployment + +The **Preview Mode** Docker instance for Mattermost is designed for product evaluation, and sets `SendEmailNotifications=false` so the product can function without enabling email. See the [Configuration Settings](/administration-guide/configure/configuration-settings) documentation to customize your deployment. + +To update your Mattermost preview image and container, you must first stop and delete your existing **mattermost-preview** container by running the following commands: + +``` sh +docker pull mattermost/mattermost-preview +docker stop mattermost-preview +docker rm mattermost-preview +``` + +Once the new image is pulled and the container is stopped and deleted you need to run the `docker run` command from above. + + + +On Linux, include `sudo` in front of all `docker` commands. + + + +To access a shell inside the container, run the following command: + +``` sh +docker exec -ti mattermost-preview /bin/bash +``` + + + +See the [deployment troubleshooting](/deployment-guide/deployment-troubleshooting) documentation for resolutions to common deployment issues. + + diff --git a/docs/main/deployment-guide/server/deploy-containers.mdx b/docs/main/deployment-guide/server/deploy-containers.mdx new file mode 100644 index 000000000000..1bfe631dd5ea --- /dev/null +++ b/docs/main/deployment-guide/server/deploy-containers.mdx @@ -0,0 +1,103 @@ +--- +title: "Deploy Mattermost using Containers" +--- +You can deploy Mattermost Server using container technologies for exploring functionality, testing, and development purposes, as it allows you to quickly set up a Mattermost instance without needing to manage the underlying infrastructure. This deployment method shouldn't be used in production environments as it doesn't support clustered deployments or High Availability (HA) configurations out-of-the-box. + +Choose your preferred container platform below for specific deployment instructions: + +
+ +FIPS/STIG + +
+ +
+ +Docker + +
+ +## Secure your Mattermost deployment + +Deploying Mattermost using Docker containers can be made secure with proper configurations for HTTPS and reverse proxying. This guide outlines the steps to set up TLS and an NGINX reverse proxy for your Mattermost deployment, ensuring secure communication between users and your server. + +1. Set Up an NGINX Container to serve as the reverse proxy. You can use NGINX either as a separate container or installed on the host machine. +2. Bind Volumes for NGINX Configuration and TLS Certificates: + +> - Bind Docker volumes for NGINX configuration files and TLS certificates to ensure persistent and secure storage of these assets. +> - Use permission restrictions on host directories where sensitive files such as TLS keys are stored. + +3. Create the NGINX Configuration File by designing a robust `nginx.conf` file to configure reverse proxying and HTTPS. Here's a basic example: + + ``` nginx + server { + listen 443 ssl; + server_name your-domain.com; + + ssl_certificate /etc/nginx/certs/fullchain.pem; + ssl_certificate_key /etc/nginx/certs/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + proxy_pass http://mattermost:8065; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + } + } + ``` + +Verify the configuration with `nginx -t` before applying. + +4. Obtain TLS Certificates: + +> - Use Let's Encrypt for free, automated certificates. Tools like Certbot can help automate the process. +> - Alternatively, purchase certificates from a trusted certificate authority (CA) and ensure proper setup of intermediate and root certificate chains. +> +> Keep private keys secure and avoid storing them directly inside Docker images. + +5. Connect Containers Using Docker Networking: + + > - Use Docker's networking features to isolate and link containers. + > + > - Create a custom Docker bridge network to ensure secure communication. For example: + > + > ``` sh + > docker network create mattermost-network + > ``` + > + > - Launch the Mattermost and NGINX containers on the same network: + > + > ``` sh + > docker network connect mattermost-network mattermost + > docker network connect mattermost-network nginx + > ``` + +6. Point your domain to the server IP address: + + Ensure your domain (e.g., your-domain.com) points to the public IP address of your server. If your IP is dynamic, consider setting up Dynamic DNS (DDNS) for seamless connectivity. + +7. After placing the certificates and updating the configuration, restart the NGINX container: + +8. Use logs (docker logs nginx) to troubleshoot and validate the container’s operation. + +9. Verify HTTPS Access by visiting `https://your-domain.com` in a web browser to confirm Mattermost is running securely over HTTPS. + +10. Use tools such as SSL Labs : [https://www.ssllabs.com/ssltest/](https://www.ssllabs.com/ssltest/) to validate the quality of your TLS setup. + +11. Enable HTTP Strict Transport Security (HSTS) in your NGINX configuration to prevent downgrade attacks. + +12. Use NGINX rate-limiting features to restrict abusive traffic, such as excessive requests: + +Additionally, consider: + +- Use Docker's security features such as Seccomp profiles and AppArmor to secure your container runtime. +- Avoid running containers with elevated privileges `--privileged` and utilize user namespaces. +- Always use trusted images (e.g., official NGINX and Mattermost images) to prevent exposure to vulnerabilities in third-party images. +- Update Mattermost, NGINX, and Docker to their latest versions regularly to ensure patches for known vulnerabilities are applied. +- Set up proper firewall rules to restrict unauthorized access and monitor traffic using tools like Fail2Ban or Wazuh. + +By following these steps, your Mattermost deployment using Docker containers will be accessible securely over HTTPS with efficient proxying through NGINX. Implementing the additional security recommendations will further protect your environment against evolving threats. diff --git a/docs/main/deployment-guide/server/deploy-kubernetes.mdx b/docs/main/deployment-guide/server/deploy-kubernetes.mdx new file mode 100644 index 000000000000..22161ebbee8a --- /dev/null +++ b/docs/main/deployment-guide/server/deploy-kubernetes.mdx @@ -0,0 +1,75 @@ +--- +title: "Deploy Mattermost on Kubernetes" +--- + + +Mattermost server can be deployed on various Kubernetes platforms, providing a scalable and robust infrastructure for your team communication needs. This guide covers deployment options for major cloud providers and general Kubernetes installations. + + + +To learn how to safely upgrade your deployment in Kubernetes for High Availability with Active/Active support, see the [Upgrading Mattermost in Kubernetes and High Availability Environments](/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha) documenation. + + + +## Platform + +Choose your preferred platform below for specific deployment instructions: + +
+ +
+ +Mattermost Operator + +
+ +
+ +
+ +Azure + +
+ +
+ +Oracle + +
+ +## Frequently Asked Questions + +### Why are my pods failing with a `CrashLoopBackOff` error after adding a custom CA certificate to my Docker image? + +You may see a `CrashLoopBackOff` error after adding a custom CA certificate to your Docker image's `/etc/ssl/certs` directory and deploying it to your Kubernetes environment via the Mattermost Enterprise Edition Helm Chart. This issue typically arises because the custom CA certificate is not being recognized by the system's certificate trust store, leading to TLS handshake failures when the application attempts to connect to services that require the custom CA. + +While core functionality may remain operational, you may notice the following symptoms: + +- Pods stuck in a crashloop with the error message: backoff - restarting failed container in pod. +- Debugging commands like `kubectl describe` and `kubectl logs` provide little to no valuable information. +- Integrations may be blocked. + +### Can I resolve this issue without rebuilding the Docker image? + +Yes. We recommend using Kubernetes-native solutions to manage custom CA certificates to simplify deployment processes and minimize disruptions caused by image rebuilds. You can inject the certificate directly into the pod using Kubernetes resources instead of modifying the Docker image to manage custom CA certificates dynamically without needing to rebuild and redeploy your Docker image every time the certificate changes. + +Use a Kubernetes secret to store your custom CA certificate and then mount it into the pod: + +1. Create a Kubernetes secret with your custom CA certificate. +2. Mount the certificate into the pod using the Helm chart’s configuration options. This method simplifies management and avoids the need to rebuild your Docker image for future certificate updates. + +Alternatively, to dynamically inject certificates without modifying the Docker image, use an `initContainer` to copy the certificate into the pod's filesystem and update the certificate trust store before the main container starts. + +### How to troubleshoot the root cause of the `CrashLoopBackOff` error? + +Use `kubectl describe pods` to check detailed event logs. + +Consider logging tools like Grafana to aggregate and analyze logs for additional insights. + +### Where is data stored in a self-hosted Kubernetes deployment? + +Where data is stored depends on the backend database (such as RDS, Azure Postgres, self-hosted PostgreSQL), and the backend filestore (such as AWS S3, other S3-compatible services, or a mounted volume) configured during deployment. + +For volume mounts, we recommend using an NFS volume to provide filestores as a "local" directory to the Mattermost server. + +Not all types of [Kubernetes persistent volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes) have been tested with Mattermost, and some may have limitations or specific configurations that may require additional setup to ensure proper permissions and access. We recommend system admins review documentation for their preferred persistent volume types and test to ensure compatibility with Mattermost. diff --git a/docs/main/deployment-guide/server/deploy-linux.mdx b/docs/main/deployment-guide/server/deploy-linux.mdx new file mode 100644 index 000000000000..0eecd057400c --- /dev/null +++ b/docs/main/deployment-guide/server/deploy-linux.mdx @@ -0,0 +1,51 @@ +--- +title: "Deploy Mattermost on Linux" +--- + +Mattermost Server runs on any 64-bit Linux system. For production, run Mattermost and the PostgreSQL database on separate hosts. A single-host install is suitable for development and testing. + +## Choose an install method + + + +## Before you install + +All three install methods require: + +- A 64-bit Linux host with at least **1 vCPU and 2 GB RAM** (supports up to ~1,000 users) +- **PostgreSQL 14+** — either local to the host, on a separate server, or a managed service. See [PostgreSQL Migration](/deployment-guide/postgres-migration) if you're moving from MySQL. +- Inbound ports **80** and **443** (HTTPS) and **8065** (System Console). See [Preparations](/deployment-guide/server/preparations) for the full pre-install checklist. +- Outbound port **10025** if you'll send notification email through a relay. + +## After you install + +Once Mattermost is running, complete these steps before exposing it to users: + +- [Set up an NGINX reverse proxy](/deployment-guide/server/setup-nginx-proxy) and [terminate TLS](/deployment-guide/server/setup-tls) at the proxy. Don't run Mattermost as an internet-facing service without a proxy. +- Decide whether you need [FIPS 140-3 cryptography](/deployment-guide/server/configure-fips-at-install-time). FIPS is **install-time only** — it cannot be enabled after data is written. +- Configure [pre-authentication secrets](/deployment-guide/server/pre-authentication-secrets) if your environment requires them. +- Review the [post-install configuration checklist](/deployment-guide/server/server-deployment-planning) under Server deployment planning. + +:::tip Air-gapped environments +If you're deploying into a network-isolated enclave, use the [Air-Gapped Quick-Start Runbook](/deployment-guide/air-gapped-operations/quick-start-runbook) instead of the connected install paths above. The runbook adds package mirroring, offline license activation, and the phone-home-disable inventory on top of the standard install. +::: + +:::note Troubleshooting +See [Deployment Troubleshooting](/deployment-guide/deployment-troubleshooting) for common install failures. +::: diff --git a/docs/main/deployment-guide/server/docker-troubleshooting.mdx b/docs/main/deployment-guide/server/docker-troubleshooting.mdx new file mode 100644 index 000000000000..c77960b9faa8 --- /dev/null +++ b/docs/main/deployment-guide/server/docker-troubleshooting.mdx @@ -0,0 +1,64 @@ +--- +title: "Docker deployment troubleshooting" +--- +## Permission issues on M1 Mac + +If you're deploying the Mattermost server using Docker on an M1 Mac and encountering permission issues in the Docker container, re-create the required directories and set their permissions, then skip the following command because it causes the deploy to stop working. + +``` sh +sudo chown -R 2000:2000 ./volumes/app/mattermost +``` + +If you're experiencing issues deploying on Docker generally, ensure the docker daemon is enabled and running: + +``` sh +sudo systemctl enable --now docker +``` + +To remove all data and settings for your Mattermost deployment: + +``` sh +sudo rm -rf ./volumes +``` + +## TLS and NGINX issues + +For an in-depth guide to configuring the TLS certificate and key for NGINX, please refer to [this document in the repository](https://github.com/mattermost/docker/blob/main/docs/issuing-letsencrypt-certificate.md). + +## Install a different version of Mattermost + +1. Shut down your deployment. + +2. Run `git pull` to fetch any recent changes to the repository, paying attention to any potential `env.example` changes. + +3. Adjust the `MATTERMOST_IMAGE_TAG` in the `.env` file to point your desired [enterprise](https://hub.docker.com/r/mattermost/mattermost-enterprise-edition/tags?page=1&ordering=last_updated) or [team](https://hub.docker.com/r/mattermost/mattermost-team-edition/tags?page=1&ordering=last_updated) image version. + +
+ +
+ + Important + +
+ + **For production environments**, we recommend using specific version tags such as `MATTERMOST_IMAGE_TAG=release-10.5` rather than generic tags like `MATTERMOST_IMAGE_TAG=release-10`. Generic `release-x` tags are intended for development use only and do not automatically receive new patch releases within that major version. Using specific version tags ensures a more reproducible and deterministic environment for your production deployment. + +
+ +4. Redeploy Mattermost. + +## Unintentional version downgrades + +If you experience an unintentional downgrade when using generic `MATTERMOST_IMAGE_TAG=release-x` tags, this is because these tags are designed for development use and may not point to the latest patch release within that major version. + +**Solution**: Use a more specific version tag for your Docker image, such as `MATTERMOST_IMAGE_TAG=release-10.5`, to avoid unexpected version changes and ensure consistent deployments. + + + +A [pipeline improvement](https://github.com/mattermost/mattermost/issues/30656) is in progress to ensure that generic `release-x` tags are updated to the latest version from the corresponding release branch. Once this improvement is implemented, the behavior of these tags will be more predictable. + + + +## Upgrading from `mattermost-docker` + +For an in-depth guide to upgrading from the deprecated [mattermost-docker repository](https://github.com/mattermost/mattermost-docker), please refer to [this document](https://github.com/mattermost/docker/blob/main/scripts/UPGRADE.md). For additional help, please refer to [this issue](https://github.com/mattermost/mattermost-docker/issues/489). diff --git a/docs/main/deployment-guide/server/image-proxy.mdx b/docs/main/deployment-guide/server/image-proxy.mdx new file mode 100644 index 000000000000..7c9c42358efd --- /dev/null +++ b/docs/main/deployment-guide/server/image-proxy.mdx @@ -0,0 +1,34 @@ +--- +title: "(Optional) Use an Image proxy" +--- + + +When enabled, the image proxy needs to be publicly accessible to both the Mattermost client and server. + +Mattermost clients will use the image proxy to load all external images. The Mattermost server will use the image proxy when possible, but will not use it when requesting content that may not be an image, such as for [image previews of plaintext URLs](https://github.com/mattermost/mattermost/issues/11857). + +Configure an image proxy by going to **System Console \> Environment \> Image Proxy**. + +## Local image proxy + +The local image proxy is available as part of the Mattermost server deployment. When using the local image proxy, images are served to clients through the server which helps anonymize users. If SSL is enabled on the server, it provides a secure connection. This method does not offer any caching behavior. + + + +With the local image proxy enabled, requests for images hosted on the local network are now affected by the `AllowUntrustedInternalConnections` setting. See [documentation](/administration-guide/configure/environment-configuration-settings#allow-untrusted-internal-connections) for more information or if you are seeing unintentionally blocked images. + + + +## atmos/camo image proxy + +The [atmos/camo](https://github.com/atmos/camo) image proxy is a standalone image proxy that can be deployed separately from the Mattermost server. It provides additional configuration options over the built-in image proxy, and it can also be used if isolation between the Mattermost server and image proxy is desired. + +Once you've deployed an `atmos/camo` ([https://github.com/atmos/camo](https://github.com/atmos/camo)) instance, you must specify the **Remote Image Proxy URL** and **Remote Image Proxy Options** settings. The **Remote Image Proxy Options** should be set to the image proxy's shared key which is specified with the `CAMO_KEY` environment variable used when setting up the image proxy. + +For example, if the image proxy is located at `https://image-proxy.mattermost.com`, it would be configured as follows: + +> - **Image Proxy Type**: `atmos/camo` +> - **Remote Image Proxy URL**: `https://image-proxy.mattermost.com` +> - **Remote Image Proxy Options**: `CAMO_KEY`, which is the secret string used for the sample `atmos/camo` deployment. + +![Enable and configure an atmos/camo image proxy in the System Console by going to Environment \> Image Proxy, specifying atmos/camo as the proxy type, providing the URL of the remote image proxy server, and by specifying the CAMO_KEY secret string.](/images/image-proxy.png) diff --git a/docs/main/deployment-guide/server/kubernetes/deploy-k8s-aks.mdx b/docs/main/deployment-guide/server/kubernetes/deploy-k8s-aks.mdx new file mode 100644 index 000000000000..2e801484dd4f --- /dev/null +++ b/docs/main/deployment-guide/server/kubernetes/deploy-k8s-aks.mdx @@ -0,0 +1,97 @@ +--- +title: "Deploy Mattermost on Azure Kubernetes Service (AKS)" +sidebar_label: "Deploy on AKS (Azure)" +--- +You can use a supported [Azure Marketplace Container Offer](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/mattermost.mattermost-operator) to install Mattermost on your existing Azure infrastructure. + +Before deploying, make sure you have the following: + +- **An AKS cluster**: with the [Application Gateway Ingress Controller (AGIC) add-on](https://learn.microsoft.com/en-us/azure/application-gateway/tutorial-ingress-controller-add-on-new) enabled or another Ingress controller deployed. +- **PostgreSQL v13.0+ database**: [Azure Database for PostgreSQL - Flexible Server with Private Access](https://learn.microsoft.com/en-us/azure/postgresql/) is recommended. Deploy one by following [this Microsoft quick start guide](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/quickstart-create-server-portal). +- **Private Network Connectivity**: Verify that there is network connectivity between your AKS cluster and the PostgreSQL database. +- **Valid DNS name and TLS certificate**: You must have access to a DNS zone and provide a valid TLS key and certificate for the Ingress Controller. +- **Node Capacity**: At least 2 AKS nodes for high availability when deploying for 100 users or more. +- **License Key**: Trial or Enterprise license to test high availability and other Enterprise features. + +# Installation steps + +The installation process includes deploying Mattermost and updating the server. + +## Step 1: Deploy Mattermost + +1. Deploy Mattermost from the [Azure Marketplace Container Offer](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/mattermost.mattermost-operator) and select **Get it now**. + +> Alternatively, you can go to the `Extensions + Applications` section of your AKS cluster and install the Mattermost offering from there. Visit the [Microsoft cluster extensions documentation](https://learn.microsoft.com/en-gb/azure/aks/cluster-extensions?tabs=azure-cli) to learn more. + +2. Choose the **Resource Group** and the **Region** of your installed AKS and PostgreSQL database. + +> ![An example of the Azure AKS Project details screen.](/_static/images/azure/basics.png) + +3. Choose your AKS cluster. + +> ![An example of the Azure AKS cluster setup screen.](/_static/images/azure/aks-cluster.png) + +4. Fill in the details for your PostgreSQL database. Ensure the user specified has full access. + +> ![An example of the Azure AKS Database setup screen.](/_static/images/azure/postgreSQL.png) + +5. Specify Deployment Details including Deployment Name and Deployment Size. You will need to configure file storage for your Mattermost instance. We recommend using an S3-compatible storage service or an NFS-compatible server. + +> ![An example of the Azure AKS Deployment Details setup screen.](/_static/images/azure/deployment-details.png) + +6. Configure Mattermost installation hostname and Ingress details. The AGIC add-on is used in the following example to show the ingress annotations required. + +> You can use any pre-installed Ingress Controller in your cluster as long as it supports Kubernetes Ingress and TLS termination. +> +> ``` yaml +> kubernetes.io/ingress.class: azure/application-gateway +> appgw.ingress.kubernetes.io/ssl-redirect: "true" +> ``` + +7. Additionally, we recommend considering: + +> 1. Enforcing a minimum TLS version (e.g., TLS 1.2). +> 2. Deploying a Web Application Firewall (WAF) for additional protection, if supported by your ingress controller. +> 3. Limiting access using Kubernetes Network Policies. +> +> ![An example of the Azure AKS Networking Details setup screen.](/_static/images/azure/networking-details.png) + +8. Ensure that everything is running. You should be able to check the installed plugin from the **AKS Extensions + Applications** page under the **Settings** menu. + +> When the deployment is complete, obtain the hostname or IP address of your Mattermost deployment using the following command: +> +> ``` sh +> kubectl -n mattermost-operator get ingress +> ``` + +9. Use your IP address from the `ADDRESS` column, and create a DNS record in your domain registration service. +10. Access your working Mattermost installation at the URL you’ve determined in your DNS record. + +Learn more about administrating your Mattermost server by visiting the [Administration Guide](/administration-guide/administration-guide-index). + +## Step 2: Upgrade Mattermost via your AKS cluster + +1. Visit the `Extensions + Applications` section of your AKS cluster where your Mattermost installation is deployed. +2. You can enable minor version auto upgrades since these are not updating Mattermost version +3. Expand the `Configuration Settings` table and add the below configuration and the version you want to install as a value. + +> ``` +> global.azure.mattermost.version +> +> .. image:: /_static/images/global-azure-mattermost-version.png +> :alt: An example of using custom Mattermost version. +> ``` + +4. Select **Save** and wait for the upgrade. + +# Looking for a sovereign deployment on Azure Local? + +For organizations requiring on-premises deployments with data sovereignty, **Azure Local** (formerly Azure Stack HCI) provides a hybrid cloud platform that enables you to run Mattermost on-premises while maintaining integration with Microsoft Teams and M365. + +We recommend engaging **Mattermost Professional Services** for Azure Local deployments to ensure optimal configuration and compliance with your security requirements. [Talk to an Expert](https://mattermost.com/contact-sales/) to discuss your Azure Local deployment needs. + + + +You are responsible for Azure costs associated with any infrastructure you spin up to host a Mattermost server, and Azure credits cannot be applied towards the purchase of a Mattermost license. + + diff --git a/docs/main/deployment-guide/server/kubernetes/deploy-k8s-oke.mdx b/docs/main/deployment-guide/server/kubernetes/deploy-k8s-oke.mdx new file mode 100644 index 000000000000..be4b9ddc69ee --- /dev/null +++ b/docs/main/deployment-guide/server/kubernetes/deploy-k8s-oke.mdx @@ -0,0 +1,162 @@ +--- +title: "Deploy Mattermost on Oracle Kubernetes Engine (OKE)" +sidebar_label: "Deploy on OKE (Oracle)" +--- +You can use the supported [Oracle Cloud Marketplace listing](https://cloudmarketplace.oracle.com/marketplace/en_US/listing/188386963) to install Mattermost Enterprise Edition on Oracle Cloud Infrastructure (OCI) using Oracle Kubernetes Engine (OKE). + +Before deploying, make sure you have the following: + +- **Oracle Cloud Account** with appropriate permissions +- **Permissions** to create/manage OKE, Compute, Networking, Database, Resource Manager, and Secrets +- **Compartment** for deployment +- **Domain Name and TLS Certificate** for secure access +- **Mattermost License Key** (Trial or Enterprise) +- **Node Capacity**: At least 2 OKE nodes for high availability when deploying for 100 users or more + +# Installation steps + +The installation process includes deploying Mattermost and configuring the necessary components. + +## Step 1: Start from Oracle Cloud Marketplace + +Go to the Mattermost listing and select **Launch Stack**. + +![Oracle Cloud Marketplace listing for Mattermost](/images/oracle/marketplace-listing.png) + +## Step 2: Stack Information + +On the **Create stack** page, review the information, and then set the name, compartment, and Terraform version. + +![Stack information page](/images/oracle/stack-info.png) + +## Step 3: Configure Variables + +Set all the details for your Mattermost deployment. Each section is important for a successful and secure installation. + +### OKE Cluster Configuration + +- **Create new OKE Cluster:** + - Check this if you want to create a new Kubernetes cluster. + - If you already have a cluster, you can uncheck and select your existing one. +- **Kubernetes Version:** + - Choose the latest stable version unless you have a specific requirement. +- **Node Pool Shape (Flex/Fixed):** + - Select a shape that fits your workload. For production, use at least 2 OCPUs and 16GB RAM per node. +- **Number of Nodes:** + - Minimum 2 for high availability. For testing, 1 is enough. For production environments, always use at least 2 nodes and enable high availability. +- **Operating System:** + - Oracle Linux 8 is recommended for best compatibility. + +### OKE Network Configuration + +- **Worker Node Visibility:** + - Private is more secure for production. Public is easier for testing. For production environments, use private nodes and restrict access to the API endpoint. +- **API Endpoint Visibility:** + - Public allows you to manage the cluster from anywhere. Private is more secure but requires VPN or bastion. +- **Create new Virtual Cloud Network (VCN):** + - Check this to create a new network, or uncheck to use an existing one. +- **VCN CIDR Block:** + - Set a unique network range (e.g., `10.20.0.0/16`). Avoid overlap with other networks. + +### OKE Worker Nodes + +- **Enable Cluster Autoscaler:** + - Allows the cluster to automatically add or remove nodes based on usage. +- **Initial/Min Number of Worker Nodes:** + - Set the minimum number of nodes. For high availability, use at least 2. Autoscaling helps manage costs and performance automatically. +- **Node Shape:** + - Choose a shape (e.g., `VM.Standard.E4.Flex`) and set OCPUs and memory. +- **Auto Generate SSH Key:** + - Enable this if you do not have your own SSH key for node access. +- **Image OS and Version:** + - Oracle Linux 8 is recommended. + +### PostgreSQL Configuration + +- **Admin Username:** + - The main user for your PostgreSQL database (e.g., `admin1`). +- **Password Type:** + - `PLAIN_TEXT` for testing, `SECRET` for production (uses Oracle Vault). Always use Oracle Vault for production passwords. +- **Password/Secret Name:** + - Enter a strong password or the name of a secret in Oracle Vault. +- **Database Password:** + - Required if not using a secret. + +### General Configuration + +- **Cluster Name Prefix:** + - Used to identify all resources (e.g., `mm-oke`). +- **Show Advanced Options:** + - Enable for more control (encryption keys, SSH keys, etc.). Use advanced options if you need custom encryption or want to manage your own SSH keys. +- **PostgreSQL Deployment Strategy:** + - Use "Database For PostgreSQL" for managed service. +- **Object Storage for File Storage:** + - Enable to use OCI Object Storage for Mattermost files. +- **Mattermost Version:** + - Use the latest stable version. +- **Namespace:** + - Default is `mattermost`. +- **License Key:** + - Upload or paste your Mattermost license. +- **Helm Repository:** + - Default is `https://helm.mattermost.com`. + +## Step 4: Review and Apply + +Check all your settings and select **Create** to start the deployment. Monitor the Resource Manager job and logs. + +![Resource Manager job monitor](/images/oracle/job-monitor.png) + +## Step 5: After Deployment + +When the job is finished, your OKE cluster, PostgreSQL database, and Mattermost will be ready. To find the Mattermost web address, run: + +``` sh +kubectl -n mattermost-operator get ingress +``` + +Copy the address and create a DNS record for your domain. Open your browser and go to your Mattermost URL. + +## Step 6: Upgrade Mattermost + +To upgrade your Mattermost installation: + +1. Access your OKE cluster through the Oracle Cloud Console +2. Navigate to the Mattermost operator deployment +3. Update the Mattermost version in the configuration +4. Apply the changes and wait for the upgrade to complete + + + +**Tips for Success** + +- Make sure you have all the permissions you need before you start. +- Use Oracle Vault to store passwords and sensitive data. +- Use private nodes and secure your network for production. +- Always monitor logs from the Resource Manager and pods using `kubectl logs` for more specific error messages. +- For more details, see the official [OCI Database with PostgreSQL documentation](https://www.oracle.com/cloud/postgresql/) and [OKE documentation](https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengoverview.htm). + + + +# Common Errors and How to Avoid Them + +- **Error: Kubernetes API not reachable** + - *Cause:* API endpoint is private and you're not connected to the VCN via VPN or Bastion. + - *Solution:* Ensure you have access to the network or make the endpoint public for testing. +- **Error: Stack creation fails with missing permissions** + - *Cause:* IAM policies are not set properly for the user or group. + - *Solution:* Ensure you have permissions for Resource Manager, OKE, Networking, and Secrets. +- **Error: No ingress returned by kubectl** + - *Cause:* Mattermost Ingress might not be ready or was misconfigured. + - *Solution:* Check with `kubectl describe ingress` and validate DNS, TLS, and Helm values. +- **Error: PostgreSQL password rejected** + - *Cause:* Password not set or mismatched with Oracle Vault. + - *Solution:* Re-check the password value or Vault secret used during setup. + + + +You are responsible for Oracle Cloud Infrastructure costs for the resources you create. Oracle Cloud credits cannot be used to buy a Mattermost license. + + + +Learn more about managing your Mattermost server by visiting the [Administration Guide](/administration-guide/administration-guide-index). diff --git a/docs/main/deployment-guide/server/kubernetes/deploy-k8s.mdx b/docs/main/deployment-guide/server/kubernetes/deploy-k8s.mdx new file mode 100644 index 000000000000..9a591ea7b231 --- /dev/null +++ b/docs/main/deployment-guide/server/kubernetes/deploy-k8s.mdx @@ -0,0 +1,272 @@ +--- +title: "Prerequisites" +sidebar_label: "Kubernetes prerequisites" +--- +You can use the Mattermost Kubernetes Operator to deploy Mattermost on Kubernetes using S3-compatible storage and a managed database service. While the operator supports a range of configurations, we strongly recommend using a cloud-native approach for production environments. + +Before you begin, ensure you have the following: + +- A functioning Kubernetes cluster (see the [Kubernetes setup guide](https://kubernetes.io/docs/setup/)). Your cluster should be running a [supported Kubernetes version](https://kubernetes.io/releases/). +- The kubectl command-line tool installed on your local machine (see the [kubectl installation guide](https://kubernetes.io/docs/reference/kubectl/)). +- A fundamental understanding of Kubernetes concepts, such as deployments, pods, and applying manifests. +- Sufficient Kubernetes resources allocated based on your expected user load. Consult the [scaling for Enterprise](/administration-guide/scale/scaling-for-enterprise#available-reference-architectures) documentation for resource requirements at different scales. + +# Installation steps + +The installation process involves setting up necessary operators and then deploying Mattermost itself. + +## Step 1: Install the NGINX Ingress Controller + +Follow the instructions in the [Kubernetes deployment documentation](https://kubernetes.github.io/ingress-nginx/deploy/) to install the NGINX ingress controller on your Kubernetes cluster. Mattermost recommends installing the Nginx Operator via helm, regardless of platform you are installing to. + +## Step 2: Install the Mattermost Operator + +The Mattermost Kubernetes Operator can be installed using Helm. + +1. Install Helm (version 3.13.0 or later). See the [Helm quickstart documentation](https://helm.sh/docs/using_helm/) for installation instructions. +2. Add the Mattermost Helm repository: + +> ``` sh +> helm repo add mattermost https://helm.mattermost.com +> ``` + +3. Create a file named `config.yaml` and populate it with the contents of the [Mattermost operator values file](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-operator/values.yaml). This file allows for customization of the operator. +4. Create a namespace for the Mattermost Operator: + +> ``` sh +> kubectl create ns mattermost-operator +> ``` + +5. Install the Mattermost Operator. If you don't specify a version, the latest version of the Mattermost Operator will be installed. We recommend using the latest version of the Mattermost Operator. + +> ``` sh +> helm install <your-release-name> mattermost/mattermost-operator -n +> ``` +> +> For example: +> +> ``` sh +> helm install mattermost-operator mattermost/mattermost-operator -n mattermost-operator +> ``` +> +> To use your custom `config.yaml` file: +> +> ``` sh +> helm install mattermost-operator mattermost/mattermost-operator -n mattermost-operator -f config.yaml +> ``` + +## Step 3: Deploy Mattermost + + + +- A Mattermost Enterprise license is required for multi-server deployments. +- For single-server deployments without an Enterprise license, add `Replicas: 1` to the `spec` section in step 2 below. See the [high availability documentation](/administration-guide/scale/high-availability-cluster-based-deployment) for more on highly-available deployments. + + + +1. **(Mattermost Enterprise only)** Create a Mattermost license secret. Create a file named `mattermost-license-secret.yaml` with the following content, replacing `[LICENSE_FILE_CONTENTS]` with your actual license: + +> ``` yaml +> apiVersion: v1 +> kind: Secret +> metadata: +> name: my-mattermost-license +> type: Opaque +> stringData: +> license: +> ``` + +2. Create a Mattermost installation manifest file named `mattermost-installation.yaml`. File names in this guide are suggestions; you can use different names. Use the following template, adjusting the values as needed: + +> ``` yaml +> apiVersion: installation.mattermost.com/v1beta1 +> kind: Mattermost +> metadata: +> name: # Example: mm-example-full +> spec: +> size: # Example: 5000users +> ingress: +> enabled: true +> host: # Example: example.mattermost-example.com +> annotations: +> kubernetes.io/ingress.class: nginx +> version: # Example: 9.3.0 +> licenseSecret: "" # If you created a license secret, put the name here +> ``` +> +> Key fields in the manifest include: +> +> - `metadata.name`: The name of your Mattermost deployment in Kubernetes. +> - `spec.size`: The size of your installation (e.g., "100users", "1000users", etc.). +> - `spec.ingress.host`: The DNS name for your Mattermost installation. +> - `spec.version`: The Mattermost version. See the [server version archive](/product-overview/version-archive) for available versions. You should use a [supported version](/product-overview/release-policy) of Mattermost in conjunction with the latest version of the Mattermost Operator. +> - `spec.licenseSecret`: The name of the Kubernetes secret containing your license (required for Enterprise). +> +> For a full list of configurable fields, see the [example manifest](https://github.com/mattermost/mattermost-operator/blob/master/docs/examples/mattermost_full.yaml) and the [Custom Resource Definition](https://github.com/mattermost/mattermost-operator/blob/master/config/crd/bases/installation.mattermost.com_mattermosts.yaml). + +3. Create a file named `mattermost-database-secret.yaml` for database credentials. This secret must be in the same namespace as the Mattermost installation. + +> ``` yaml +> apiVersion: v1 +> data: +> DB_CONNECTION_CHECK_URL: +> DB_CONNECTION_STRING: +> MM_SQLSETTINGS_DATASOURCEREPLICAS: +> kind: Secret +> metadata: +> name: my-postgres-connection +> type: Opaque +> ``` +> +> Example for AWS Aurora with PostgreSQL: +> +> ``` yaml +> apiVersion: v1 +> data: +> DB_CONNECTION_CHECK_URL: cG9zdGdyZXM6Ly91c2VyOnN1cGVyX3NlY3JldF9wYXNzd29yZEBteS1kYXRhYmFzZS5jbHVzdGVyLWFiY2QudXMtZWFzdC0xLnJkcy5hbWF6b25hd3MuY29tOjU0MzIvbWF0dGVybW9zdD9jb25uZWN0X3RpbWVvdXQ9MTA= +> DB_CONNECTION_STRING: cG9zdGdyZXM6Ly91c2VyOnN1cGVyX3NlY3JldF9wYXNzd29yZEBteS1kYXRhYmFzZS5jbHVzdGVyLWFiY2QudXMtZWFzdC0xLnJkcy5hbWF6b25hd3MuY29tOjU0MzIvbWF0dGVybW9zdD9jb25uZWN0X3RpbWVvdXQ9MTA= +> MM_SQLSETTINGS_DATASOURCEREPLICAS: cG9zdGdyZXM6Ly91c2VyOnN1cGVyX3NlY3JldF9wYXNzd29yZEBteS1kYXRhYmFzZS5jbHVzdGVyLXJvLWFiY2QudXMtZWFzdC0xLnJkcy5hbWF6b25hd3MuY29tOjU0MzIvbWF0dGVybW9zdD9jb25uZWN0X3RpbWVvdXQ9MTA= +> kind: Secret +> metadata: +> name: my-postgres-connection +> type: Opaque +> ``` + +## Step 4: Create the Filestore Secret + +Create a file named `mattermost-filestore-secret.yaml` to store the credentials for your object storage service (e.g., AWS S3 or any S3-compatible service). This secret must be created in the same namespace where you intend to install Mattermost. The file should contain the following YAML structure: + +``` yaml +apiVersion: v1 +kind: Secret +metadata: + name: # Choose a descriptive name (e.g., my-s3-credentials) +type: Opaque +data: + accesskey: + secretkey: +``` + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescriptionRequired
accesskeyBase64-encoded access key for your storage service.Yes
secretkeyBase64-encoded secret key for your storage service.Yes
metadata.nameThe name of the Kubernetes secret.Yes
+ + + +The `accesskey` and `secretkey` values must be **base64-encoded**. Do not enter the raw keys directly. Use a command-line tool or online encoder to generate the base64 strings. + +**Example (AWS S3):** + +``` yaml +apiVersion: v1 +kind: Secret +metadata: + name: my-s3-credentials +type: Opaque +data: + accesskey: QUNDRVNTX0tFWQo= # Example: Replace with your actual encoded key + secretkey: U1VQRVJfU0VDUkVUX0tFWQo= # Example: Replace with your actual encoded key +``` + + + +## Step 5: Configure the Mattermost Installation Manifest + +1. Modify the `mattermost-installation.yaml` file (created in step 2) to connect Mattermost to your external database and object storage. Refer to the supported fields for guidance on where to add these configurations within the YAML structure. +2. Connect to the database: + +> 1. Add the following to the `spec` section of your manifest: +> +> > ``` yaml +> > spec: +> > database: +> > external: +> > secret: <database-secret-name> # The name of the database secret (e.g., my-postgres-connection) +> > ``` + +3. Connect to Object Storage: + +> 1. Add the following to the `spec` section of your manifest: +> +> > ``` yaml +> > spec: +> > fileStore: +> > external: +> > url: <storage-service-url> # The URL of your storage service (e.g., s3.amazonaws.com) +> > bucket: <bucket-name> # The name of your storage bucket +> > secret: <filestore-secret-name> # The name of the filestore secret (e.g., my-s3-credentials) +> > ``` + +4. If you are using Amazon S3, it's recommended to enable server-side encryption (SSE) and SSL. Add the following environment variables to the `mattermostEnv` section: + +> ``` yaml +> spec: +> mattermostEnv: +> MM_FILESETTINGS_AMAZONS3SSL: true +> MM_FILESETTINGS_AMAZONS3SSE: true +> ``` + +# Review Mattermost Resource Status + +After a Mattermost installation has been created with the Operator, you can review its status with the following: + +``` sh +kubectl -n [namespace] get mattermost +``` + +The `kubectl describe` command can be used to obtain more information about the Mattermost server pods: + +``` sh +kubectl -n [namespace] describe pod +``` + +**Follow logs** + +The following command can be used to follow logs on any kubernetes pod: + +``` sh +kubectl -n [namespace] logs -f [pod name] +``` + +If the `-n [namespace]` is omitted, then the default namespace of the current context is used. We recommend specifying the namespace based on your deployment. + +This command can be used to review the Mattermost Operator or Mattermost server logs as needed. + + + +- If you're new to Kubernetes or prefer a managed solution, consider using a service like [Amazon EKS](https://aws.amazon.com/eks/), [Azure Kubernetes Service](https://azure.microsoft.com/en-ca/products/kubernetes-service/), [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/), or [DigitalOcean Kubernetes](https://www.digitalocean.com/products/kubernetes/). While this guidance focuses on using external, managed services for your database and file storage, the Mattermost Operator *does* offer the flexibility to use other solutions. For example, you could choose to deploy a PostgreSQL database within your Kubernetes cluster using the CloudNative PG operator (or externally however you wish), or use any self-hosted S3-compatible storage service. +- While using managed cloud services is generally simpler to maintain and our recommended approach for production deployments, using self-managed S3-compatible storage services and CloudNative PG for PostgreSQL are also valid options if you have the expertise to manage them. +- If you choose to use self-managed components, you'll need to adapt the instructions accordingly, pointing to your internal services instead. +- To customize your production deployment, refer to the [configuration settings documentation](/administration-guide/configure/configuration-settings). +- If you encounter issues during deployment, consult the [deployment troubleshooting guide](/deployment-guide/deployment-troubleshooting). + + + +# Frequently Asked Questions + +## What is the Operator's version compatibility with Mattermost Server? + +While generally speaking, the Operator should be compatible with most, or all versions of Mattermost Server, we recommend always using the latest version of the Operator in conjunction with a [supported version](/product-overview/release-policy) of Mattermost Server. diff --git a/docs/main/deployment-guide/server/linux/deploy-rhel.mdx b/docs/main/deployment-guide/server/linux/deploy-rhel.mdx new file mode 100644 index 000000000000..dc343e817f91 --- /dev/null +++ b/docs/main/deployment-guide/server/linux/deploy-rhel.mdx @@ -0,0 +1,342 @@ +--- +title: "Deploy Mattermost on Red Hat Enterprise Linux" +sidebar_label: "Red Hat (RHEL)" +--- + + + + +Install Mattermost Server on Red Hat Enterprise Linux (RHEL), Rocky Linux, AlmaLinux, Oracle Linux 7+, or CentOS Stream. RHEL doesn't have a signed APT-style repository, so this guide installs from the release tarball with manual systemd setup, then walks through the security configuration RHEL deployments typically need (SELinux contexts, firewalld rules, fapolicyd allow rules). + +:::info Minimum requirements +- **Operating system**: RHEL 7+, Rocky / Alma 8+, Oracle Linux 7+, CentOS Stream 8+. +- **Hardware**: 1 vCPU and 2 GB RAM (supports up to ~1,000 users). +- **Database**: [PostgreSQL 14+](/deployment-guide/postgres-migration). +- **Network**: TCP 80/443 inbound (TLS), 8065 inbound (System Console), 10025 outbound (SMTP relay if used). +::: + +## Step 1: Get a PostgreSQL database + +Choose one of: + +- **Install PostgreSQL locally** on the same host. See the [PostgreSQL installation documentation](https://www.postgresql.org/download/). +- **Use an external PostgreSQL server** and collect connection credentials before Step 2. +- **Use a managed database service** (AWS RDS, Azure Database for PostgreSQL, etc.). + +## Step 2: Prepare the database + +Follow the [database preparation](/deployment-guide/server/preparations#database-preparation) instructions to create the Mattermost database, user, and grants. + +## Step 3: Download the Mattermost Server tarball + +SSH onto the target host and download the release. Replace `amd64` with `arm64` for ARM-based hardware. + + + + +```sh +wget https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz +``` + + + + +```sh +wget https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz +``` + + + + +Enterprise and Team Edition releases are listed in the [version archive](/product-overview/version-archive). + + + + +## Step 4: Install Mattermost Server + +Update existing system packages first: + +```sh +sudo dnf update +sudo dnf upgrade +``` + +Extract the tarball, move it into place, and set ownership: + +```sh +tar -xvzf mattermost*.gz +sudo mv mattermost /opt +sudo mkdir /opt/mattermost/data +sudo useradd --system --user-group mattermost +sudo chown -R mattermost:mattermost /opt/mattermost +sudo chmod -R g+w /opt/mattermost +``` + +:::note Custom paths and users +If you use a path other than `/opt/mattermost` or a user/group name other than `mattermost`, use that name in every step that follows. +::: + +Create the systemd unit file at `/lib/systemd/system/mattermost.service`: + +```ini +[Unit] +Description=Mattermost +After=network.target + +[Service] +Type=notify +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost +LimitNOFILE=49152 + +[Install] +WantedBy=multi-user.target +``` + +Reload systemd: + +```sh +sudo systemctl daemon-reload +``` + +## Step 5: Configure and start the server + +Back up the default config before editing: + +```sh +sudo cp /opt/mattermost/config/config.json /opt/mattermost/config/config.defaults.json +``` + +Edit `/opt/mattermost/config/config.json` and set: + +- `SqlSettings.DriverName`: `"postgres"` +- `SqlSettings.DataSource`: `"postgres://mmuser:@:5432/mattermost?sslmode=disable&connect_timeout=10"` — replace each placeholder. +- `ServiceSettings.SiteURL`: the public URL of your deployment (e.g., `https://mattermost.example.com`). +- (Recommended) [`SupportSettings.SupportEmail`](/administration-guide/configure/site-configuration-settings#support-email-address): the email address users contact for help. + +Start the server: + +```sh +sudo systemctl start mattermost +curl http://localhost:8065 +``` + +You should see the Mattermost HTML response. Enable on boot: + +```sh +sudo systemctl enable mattermost.service +``` + +If start fails on a hardened RHEL system, continue to the [Hardened RHEL configuration](#hardened-rhel-configuration) section below before troubleshooting elsewhere — it's almost always SELinux, firewalld, or fapolicyd. + +## Step 6: Update the server + +Tarball-based installs are upgraded manually. See [Upgrading Mattermost Server](/administration-guide/upgrade/upgrading-mattermost-server). + +## Hardened RHEL configuration + +Hardened RHEL installs typically require additional configuration for SELinux, firewalld, and fapolicyd. Each is covered below. + + + + +RHEL 9 ships with SELinux in enforcing mode. Verify with `sestatus`. If it's enforcing, set the appropriate contexts before starting Mattermost. + +**Set the binary context** for `/opt/mattermost/bin`: + +```sh +sudo semanage fcontext -a -t bin_t "/opt/mattermost/bin(/.*)?" +sudo restorecon -RF /opt/mattermost/bin +``` + +**Set the directory context** for `/opt/mattermost`. Check current context: + +```sh +ls -Z /opt/mattermost +``` + +If the type is `default_t`, set a web-application context: + +```sh +sudo semanage fcontext -a -t httpd_sys_content_t "/opt/mattermost(/.*)?" +sudo restorecon -R /opt/mattermost +``` + +**Allow Mattermost to bind to port 8065** (or your configured port): + +```sh +sudo semanage port -l | grep 8065 +sudo semanage port -a -t http_port_t -p tcp 8065 +``` + +**Generate a custom policy** if SELinux blocks something specific. Check denials: + +```sh +sudo ausearch -m avc -ts recent +sudo cat /var/log/audit/audit.log | grep denied +``` + +Generate a policy module from those denials: + +```sh +sudo yum install -y policycoreutils-python-utils +sudo grep mattermost /var/log/audit/audit.log | audit2allow -M mattermost_policy +sudo semodule -i mattermost_policy.pp +``` + +**Restart and verify**: + +```sh +sudo systemctl restart mattermost +``` + +:::tip Testing-only fallback +For debugging, you can temporarily switch SELinux to permissive mode with `sudo setenforce 0`. Re-enable enforcement with `sudo setenforce 1` once contexts are correct. Don't ship a production deployment in permissive mode. +::: + +**References** + +- [SELinux User's and Administrator's Guide](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/index) +- [SELinux Project Wiki](https://github.com/SELinuxProject/selinux) + + + + +firewalld is the default firewall on RHEL. Check status: + +```sh +sudo systemctl status firewalld +``` + +**Open the Mattermost ports**: + +```sh +sudo firewall-cmd --permanent --add-port=8065/tcp +sudo firewall-cmd --permanent --add-service=http +sudo firewall-cmd --permanent --add-service=https +sudo firewall-cmd --reload +sudo firewall-cmd --list-all +``` + +The output should show `8065/tcp` and the `http` / `https` services. + +**Mattermost Calls ports** (if you're running the Calls plugin or the standalone rtcd service): + +```sh +# Integrated Calls plugin +sudo firewall-cmd --permanent --add-port=8443/udp +sudo firewall-cmd --permanent --add-port=8443/tcp +sudo firewall-cmd --reload + +# Standalone rtcd (adds API port) +sudo firewall-cmd --permanent --add-port=8045/tcp +sudo firewall-cmd --reload +``` + +- Port 8443 (UDP/TCP) carries RTC media (audio, video, screen share). +- Port 8045 (TCP) is the rtcd API. +- TCP support for RTC requires Calls v0.17+ and rtcd v0.11+. + +See the [Calls deployment guide](/administration-guide/configure/calls-deployment-guide) for the full topology. + + + + +fapolicyd (File Access Policy Daemon) blocks execution of untrusted binaries. In secure RHEL environments it commonly blocks Mattermost binaries and plugins — the symptom is "operation not permitted" errors in `mattermost.log`. + +**Confirm fapolicyd is the cause** by temporarily stopping it: + +```sh +sudo systemctl stop fapolicyd +sudo systemctl start mattermost +``` + +If Mattermost now works, restart fapolicyd and configure an allow rule. + +**Identify the denial**: + +```sh +sudo fapolicyd --debug +``` + +Look for a line like: + +```text +rule=15 dec=deny_audit perm=execute auid=-1 pid=19735 + exe=/opt/mattermost/bin/mattermost : path=/opt/mattermost/plugins/focalboard/server/dist/plugin-linux-amd64 + ftype=application/x-executable trust=0 +``` + +Note the rule number — your allow rule must be numbered lower so it's evaluated first. + +**Create an allow rule** at `/etc/fapolicyd/rules.d/80-mattermost.rules`: + +```text +allow perm=execute exe=/usr/bin/sudo trust=1 : dir=/opt/mattermost/ all trust=0 +allow perm=execute exe=/opt/mattermost/bin/mattermost : dir=/opt/mattermost all trust=0 +allow perm=execute exe=/usr/lib/systemd/systemd trust=1 : dir=/opt/mattermost/ all trust=0 +``` + +**Validate and load**: + +```sh +sudo fagenrules --check +sudo fagenrules --load +sudo systemctl restart fapolicyd +sudo systemctl restart mattermost +``` + +Verify: + +```sh +curl http://localhost:8065 +sudo systemctl status mattermost +``` + +**Rules for the standalone rtcd service** (if deployed): create `/etc/fapolicyd/rules.d/80-rtcd.rules`: + +```text +allow perm=execute exe=/usr/bin/sudo trust=1 : dir=/opt/rtcd/ all trust=0 +allow perm=execute exe=/opt/rtcd/bin/rtcd : dir=/opt/rtcd all trust=0 +allow perm=execute exe=/usr/lib/systemd/systemd trust=1 : dir=/opt/rtcd/ all trust=0 +``` + +Then reload fapolicyd as above. See [RTCD setup and configuration](/administration-guide/configure/calls-deployment-guide) for the full rtcd install path. + +:::note Rule numbering +fapolicyd rules are evaluated in order. Your allow rules must be numbered lower than the deny rule that's blocking Mattermost — `80-` is usually safe with a stock configuration. If denials persist, re-check the rule number from `fapolicyd --debug` and renumber accordingly. +::: + +**Reference**: [Mattermost and fapolicyd](https://support.mattermost.com/hc/en-us/articles/12167526545172-Mattermost-and-fapolicyd) support article. + + + + +## Remove Mattermost + +Stop the server, back up any data you need, then remove the install directory: + +```sh +sudo systemctl stop mattermost +sudo rm -rf /opt/mattermost +sudo rm /lib/systemd/system/mattermost.service +sudo userdel mattermost +``` + +:::important Back up before removing +`/opt/mattermost` contains `config/`, `logs/`, `plugins/`, `client/plugins/`, and `data/`. Back these up before running `rm -rf` if you may need to restore. +::: + +## Next steps + +- [Set up an NGINX reverse proxy](/deployment-guide/server/setup-nginx-proxy) +- [Set up TLS](/deployment-guide/server/setup-tls) +- [Configure FIPS at install time](/deployment-guide/server/configure-fips-at-install-time) +- [DISA STIG mapping](/security-guide/compliance-frameworks/disa-stig) if this deployment is bound for a regulated environment diff --git a/docs/main/deployment-guide/server/linux/deploy-tar.mdx b/docs/main/deployment-guide/server/linux/deploy-tar.mdx new file mode 100644 index 000000000000..5912e704d27e --- /dev/null +++ b/docs/main/deployment-guide/server/linux/deploy-tar.mdx @@ -0,0 +1,183 @@ +--- +title: "Deploy Mattermost manually from the tarball" +sidebar_label: "Manual (tarball)" +--- + + + + +Install Mattermost Server on any 64-bit Linux distribution directly from the release tarball. This is the most flexible install method and usually the choice for: + +- Distributions Mattermost doesn't package directly (Arch, SUSE, Gentoo, Alpine, …) +- Air-gapped environments where tarballs are staged on an internal mirror +- Custom paths, users, or systemd unit configurations +- Environments where you control every version pin and don't want a package manager auto-upgrade + +:::tip Use a packaged install if it fits +If you're on **Ubuntu / Debian**, use the [APT-based install](./deploy-ubuntu) for automatic security updates. If you're on **RHEL / Rocky / Alma / Oracle**, use the [RHEL install](./deploy-rhel) — it covers SELinux, firewalld, and fapolicyd configuration too. +::: + +:::info Minimum requirements +- **Operating system**: any 64-bit Linux distribution with `systemd` (or a comparable service manager). +- **Hardware**: 1 vCPU and 2 GB RAM (supports up to ~1,000 users). +- **Database**: [PostgreSQL 14+](/deployment-guide/postgres-migration). +- **Network**: TCP 80/443 inbound (TLS), 8065 inbound (System Console), 10025 outbound (SMTP relay if used). +::: + +## Step 1: Get a PostgreSQL database + +Choose one of: + +- **Install PostgreSQL locally** on the same host. See the [PostgreSQL installation documentation](https://www.postgresql.org/download/). +- **Use an external PostgreSQL server** and collect connection credentials before Step 2. +- **Use a managed database service** (AWS RDS, Azure Database for PostgreSQL, etc.). + +## Step 2: Prepare the database + +Follow the [database preparation](/deployment-guide/server/preparations#database-preparation) instructions to create the Mattermost database, user, and grants. + +## Step 3: Download the Mattermost Server tarball + +SSH onto the target host and download the release. Replace `amd64` with `arm64` for ARM-based hardware. + + + + +```sh +wget https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz +``` + + + + +```sh +wget https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz +``` + + + + +Enterprise and Team Edition releases are listed in the [version archive](/product-overview/version-archive). + + + + +:::note Air-gapped installs +In an air-gapped environment, stage the tarball on your operator workstation, verify the SHA-256 and PGP signature, then transfer it across the boundary. See [Air-Gapped Operations → Quick-Start Runbook](/deployment-guide/air-gapped-operations/quick-start-runbook) for the full procedure. +::: + +## Step 4: Install Mattermost Server + +Extract the tarball, move it into place, and set ownership. + +```sh +tar -xvzf mattermost*.gz +sudo mv mattermost /opt +sudo mkdir /opt/mattermost/data +sudo useradd --system --user-group mattermost +sudo chown -R mattermost:mattermost /opt/mattermost +sudo chmod -R g+w /opt/mattermost +``` + +:::note Custom paths and users +If you use a path other than `/opt/mattermost` or a user/group name other than `mattermost`, use that name in every step that follows. +::: + +Create the systemd unit file at `/lib/systemd/system/mattermost.service`: + +```ini +[Unit] +Description=Mattermost +After=network.target + +[Service] +Type=notify +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost +LimitNOFILE=49152 + +[Install] +WantedBy=multi-user.target +``` + +:::note Local database +If PostgreSQL is on the same host, add to the `[Unit]` section so Mattermost won't start before the database is ready: + +```ini +After=postgresql.service +BindsTo=postgresql.service +``` +::: + +Reload systemd: + +```sh +sudo systemctl daemon-reload +``` + +## Step 5: Configure and start the server + +Back up the default config before editing: + +```sh +sudo cp /opt/mattermost/config/config.json /opt/mattermost/config/config.defaults.json +``` + +Edit `/opt/mattermost/config/config.json` and set: + +- `SqlSettings.DriverName`: `"postgres"` +- `SqlSettings.DataSource`: `"postgres://mmuser:@:5432/mattermost?sslmode=disable&connect_timeout=10"` — replace each placeholder. +- `ServiceSettings.SiteURL`: the public URL of your deployment (e.g., `https://mattermost.example.com`). +- (Recommended) [`SupportSettings.SupportEmail`](/administration-guide/configure/site-configuration-settings#support-email-address): the email address users contact for help. + +Start the server: + +```sh +sudo systemctl start mattermost +curl http://localhost:8065 +``` + +You should see the Mattermost HTML response. Enable on boot: + +```sh +sudo systemctl enable mattermost.service +``` + +## Step 6: Update the server + +Tarball installs are upgraded manually — there's no package manager to pull the new version. See [Upgrading Mattermost Server](/administration-guide/upgrade/upgrading-mattermost-server) for the step-by-step procedure. The summary: + +1. Stop the running server (`sudo systemctl stop mattermost`). +2. Back up `config/`, `data/`, `plugins/`, and your PostgreSQL database. +3. Download the new tarball. +4. Extract over the install directory (preserving `config/`, `data/`, `plugins/`). +5. Reset ownership and permissions. +6. Start the server. + +## Remove Mattermost + +Stop the server, back up data you need to keep, then remove the install: + +```sh +sudo systemctl stop mattermost +sudo rm -rf /opt/mattermost +sudo rm /lib/systemd/system/mattermost.service +sudo userdel mattermost +``` + +:::important Back up before removing +`/opt/mattermost` contains `config/`, `logs/`, `plugins/`, `client/plugins/`, and `data/`. Back these up before running `rm -rf` if you may need to restore. +::: + +## Next steps + +- [Set up an NGINX reverse proxy](/deployment-guide/server/setup-nginx-proxy) +- [Set up TLS](/deployment-guide/server/setup-tls) +- [Configure FIPS at install time](/deployment-guide/server/configure-fips-at-install-time) +- For air-gapped deployments: [Air-Gapped Quick-Start Runbook](/deployment-guide/air-gapped-operations/quick-start-runbook), [Disable Phone-Home Features](/deployment-guide/air-gapped-operations/disable-phone-home-features) diff --git a/docs/main/deployment-guide/server/linux/deploy-ubuntu.mdx b/docs/main/deployment-guide/server/linux/deploy-ubuntu.mdx new file mode 100644 index 000000000000..022e1f1d0a1e --- /dev/null +++ b/docs/main/deployment-guide/server/linux/deploy-ubuntu.mdx @@ -0,0 +1,145 @@ +--- +title: "Deploy Mattermost on Ubuntu or Debian" +sidebar_label: "Ubuntu / Debian" +--- + + + + +Install Mattermost Server on Ubuntu or Debian from the signed Mattermost APT repository. The same `.deb` packages cover single-host installs and clustered deployments via tools like Packer. + +:::info Minimum requirements +- **Operating system**: Ubuntu 20.04 / 22.04 / 24.04 LTS, or Debian (current stable). Other Debian-family distributions usually work but aren't tested by Mattermost. +- **Hardware**: 1 vCPU and 2 GB RAM (supports up to ~1,000 users). +- **Database**: [PostgreSQL 14+](/deployment-guide/postgres-migration). +- **Network**: TCP 80/443 inbound (TLS), 8065 inbound (System Console), 10025 outbound (SMTP relay if used). +::: + +## Step 1: Get a PostgreSQL database + +Mattermost requires PostgreSQL. Choose one of: + +- **Install PostgreSQL locally** on the same host. Follow the [PostgreSQL installation documentation](https://www.postgresql.org/download/). +- **Use an external PostgreSQL server**. Collect the connection credentials (hostname, port, database, username, password) before starting Step 2. +- **Use a managed database service** (AWS RDS, Azure Database for PostgreSQL, etc.). + +## Step 2: Prepare the database + +Follow the [database preparation](/deployment-guide/server/preparations#database-preparation) instructions to create the Mattermost database, user, and grants. + +## Step 3: Add the Mattermost APT repository + +:::important GPG key change +The GPG public key has changed. Either [import the new public key](https://deb.packages.mattermost.com/pubkey.gpg) or run the repository setup script in the next step (recommended). Existing installations should remove the old key before adding the new one: + +For Ubuntu 22.04 LTS and 24.04 LTS: + +```sh +sudo rm /usr/share/keyrings/mattermost-archive-keyring.gpg +curl -sL -o- https://deb.packages.mattermost.com/pubkey.gpg \ + | gpg --dearmor \ + | sudo tee /usr/share/keyrings/mattermost-archive-keyring.gpg > /dev/null +``` +::: + +Run the repository setup script: + +```sh +curl -o- https://deb.packages.mattermost.com/repo-setup.sh | sudo bash -s mattermost +``` + +This configures the Mattermost APT repository, a PostgreSQL repository, an NGINX web server (used as a reverse proxy), and certbot for issuing and renewing SSL certificates. + +## Step 4: Install Mattermost Server + +Update your APT cache and any pending system packages: + +```sh +sudo apt update +``` + +Install the latest Mattermost Server: + +```sh +sudo apt install mattermost -y +``` + +Mattermost installs to `/opt/mattermost`. The package creates a `mattermost` user and group and a systemd unit file. The service is **not** enabled or started at this point. + +:::note systemd dependencies +The Mattermost package doesn't declare a database dependency in its systemd unit (the package is used for both single-host and external-database installs). If you installed PostgreSQL on the same host, add the following to the `[Unit]` section of `/lib/systemd/system/mattermost.service`: + +```ini +After=postgresql.service +BindsTo=postgresql.service +``` +::: + +## Step 5: Configure the server + +Copy the default configuration to the active config file with the right ownership and permissions: + +```sh +sudo install -C -m 600 -o mattermost -g mattermost \ + /opt/mattermost/config/config.defaults.json \ + /opt/mattermost/config/config.json +``` + +Edit `/opt/mattermost/config/config.json` and set: + +- `SqlSettings.DriverName`: `"postgres"` +- `SqlSettings.DataSource`: `"postgres://mmuser:@:5432/mattermost?sslmode=disable&connect_timeout=10"` — replace each placeholder. +- `ServiceSettings.SiteURL`: the public URL of your deployment (e.g., `https://mattermost.example.com`). +- (Recommended) [`SupportSettings.SupportEmail`](/administration-guide/configure/site-configuration-settings#support-email-address): the email address users contact for help. + +:::note TLS mode for `DataSource` +The `sslmode` value depends on your database environment. The two relevant options are `disable` and `require`. Managed services such as AWS Lightsail require `sslmode=require`. Check your provider's documentation. +::: + +Start the server: + +```sh +sudo systemctl start mattermost +``` + +Verify it's running: + +```sh +curl http://localhost:8065 +``` + +You should see the Mattermost HTML response. Enable the service on boot: + +```sh +sudo systemctl enable mattermost.service +``` + +## Step 6: Update Mattermost + +When a new release is published, update through APT: + +```sh +sudo systemctl stop mattermost +sudo apt update && sudo apt upgrade +sudo systemctl start mattermost +``` + +:::important Stop the server before upgrading +`apt upgrade` will replace the Mattermost binary while it's running. Stop the systemd service first to avoid corrupt state. +::: + +## Remove Mattermost + +```sh +sudo systemctl stop mattermost +sudo apt remove --purge mattermost +``` + +This removes the package but leaves `/opt/mattermost/data`, `/opt/mattermost/logs`, `/opt/mattermost/plugins`, and `/opt/mattermost/config` in place. Back these up before deleting if you may need to restore. + +## Next steps + +- [Set up an NGINX reverse proxy](/deployment-guide/server/setup-nginx-proxy) +- [Set up TLS](/deployment-guide/server/setup-tls) +- [Configure FIPS at install time](/deployment-guide/server/configure-fips-at-install-time) (FIPS is install-time only — decide before exposing the server) +- [Server deployment planning](/deployment-guide/server/server-deployment-planning) for the full post-install checklist diff --git a/docs/main/deployment-guide/server/orchestration.mdx b/docs/main/deployment-guide/server/orchestration.mdx new file mode 100644 index 000000000000..9c4b131e84eb --- /dev/null +++ b/docs/main/deployment-guide/server/orchestration.mdx @@ -0,0 +1,132 @@ +--- +title: "Deployment Solution Programs" +--- +Mattermost's **Deployment Solutions Programs** help IT administrators understand how Mattermost is being offered in third-party deployment solutions, including other open source projects as well as in commercial solutions. + +This is an optional program for third-party developers to increase awareness about their work and to enable Mattermost to refer its communities to different solutions. + +Individuals or companies interested in exploring deployment solutions with Mattermost are encouraged to reach out to us via the [Mattermost Partner Program Form](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=24278352368532). + +Deployment solutions are recognized by Mattermost at three-levels: + +- **Community Deployment Solutions** - Basic orchestration solutions for Mattermost, typically from the open source community or hosting companies who let us know about their work. The work of partners is included in blog posts and on social media as a benefit to the user and customer communities. + + > Examples: + > + > - [Puppet deployment solution for Mattermost](https://forge.puppet.com/liger1978/mattermost) by Richard Grainger + > - [Heroku deployment solution for Mattermost](https://chrisdecairos.ca/deploying-mattermost-to-heroku/) by Christopher De Cairos + +- **Registered Deployment Solutions** - Orchestration solutions that follow detailed Mattermost guidelines on keeping up-to-date with the latest Mattermost version and security updates (typically a one-line change), linking to official documentation, supporting branding guidelines, and maintaining a changelog. This level of engagement allows Mattermost to more prominently promote the work, knowing that it's committed to meeting explicit standards. + +- **Certified Deployment Solutions** - These solutions meet all the requirements of Registered Deployment Solutions, with the addition that they'll automate the version upgrade and security update processes (typically a one-line change). There is the added benefit that when Mattermost announces new versions and security updates, we can also announce the availability of updates to Certified Deployment Solutions. + +To summarize the commitment level of different solutions: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Deployment Solution RequirementCommunityRegisteredCertified
Installation`checkmark <mm-subst:checkmark>`__ checkmark checkmark




Minimum Documentation`checkmark <mm-subst:checkmark>`__ checkmark checkmark




Security Updates`checkmark <mm-subst:checkmark>`__ checkmark




Branding`checkmark <mm-subst:checkmark>`__ checkmark




Upgradecheckmark
+ +Requirement details are outlined below. + +## Deployment solution program requirements + +### Installation + +1. **Installation is designed for officially supported operating systems and platforms**. EXCEPTION: RHEL equivalents (CentOS, Amazon Linux, Oracle Linux, Scientific Linux) are acceptable as long as the exception is noted in README or equivalent with `This deployment uses [OPERATING_SYSTEM] as an equivalent to the officially supported version of Red Hat Enterprise Linux.` +2. **Automated installation passes basic testing**. After installation run the following manual tests: + +> 1. Create a new user account and use that account to create a new team and post to Town Square channel. +> 2. Create a second user account and join the newly created team and reply to first user's post in Town Square. +> 3. Go back to first user account and post reply with an image attached. +> 4. Confirm there are no errors and no red alert bar at the top of the screen with "Mattermost unreachable error" (which would indicate a websocket configuration error). + +### Documentation + +1. **Include link to official Mattermost documentation**. README or equivalent contains statement **Please see https://docs.mattermost.com for official documentation.** + +> Include the following information in text, markdown, HTML or other format. Square brackets `[]` indicate optional statements depending on the configuration of your solution: +> +> > This deployment solution installs \[and upgrades\] a Mattermost server to provide secure, private cloud messaging for teams and enterprises. More information is available at: [https://mattermost.com](https://mattermost.com) +> > +> > Following automated deployment, the following steps are required to make your system production-ready: +> > +> > - [Configure SSL for Mattermost](/deployment-guide/server/setup-nginx-proxy#configure-nginx-with-ssl-and-http-2) +> > - [Configure SMTP email for Mattermost](/administration-guide/configure/smtp-email) + +2. **Unofficial deployment options should be documented**. Unofficial deployment configurations, such as use of Linux operating systems that are not officially supported, should be documented in the README. + +### Security updates + +1. **Document commitment to providing security updates.** README or equivalent states `We highly recommend users subscribe to the Mattermost security updates email list. When notified of a security update, the maintainers of this deployment solution will make an effort to update to the secure version within 10 days.` +2. **Commit to making an effort for your deployment to provide the latest security update within 10 days of announcement**. This is typically a one-line change. + +### Branding + +**Support Mattermost branding and naming guidelines**. To ensure naming is clear across deployment solutions, README or equivalent should contain `` The name for this deployment solution in the context of `Mattermost branding guidelines [https://handbook.mattermost.com/operations/operations/publishing/publishing-guidelines/brand-and-visual-design-guidelines](https://handbook.mattermost.com/operations/operations/publishing/publishing-guidelines/brand-and-visual-design-guidelines)`_ is `[NAME] for Mattermost by [CREATOR]`. `` For example, `Multi-node Docker deployment solution for Mattermost by John Doe`. This is the name that will be used to refer to your work in Mattermost community materials. + +### Upgrade + +**Support upgrade of Mattermost**. Enable user interface or command line upgrade of a Mattermost deployment to latest version based on [upgrade procedure when Mattermost is embedded](https://developers.mattermost.com/integrate/faq/#how-should-i-automate-the-install-and-upgrade-of-mattermost-when-included-in-another-application). diff --git a/docs/main/deployment-guide/server/pre-authentication-secrets.mdx b/docs/main/deployment-guide/server/pre-authentication-secrets.mdx new file mode 100644 index 000000000000..31c8b4835e52 --- /dev/null +++ b/docs/main/deployment-guide/server/pre-authentication-secrets.mdx @@ -0,0 +1,156 @@ +--- +title: "Pre-authentication secrets" +--- + + +From Mattermost server v10.12 and mobile v2.32, Mattermost deployments can use a reverse proxy to validate authentication secrets before allowing desktop and mobile requests to reach the Mattermost server. This adds an additional security layer by checking for the `X-Mattermost-Preauth-Secret` header. + +Authentication secrets are only supported for mobile and desktop applications. When a secret is required, desktop prompts users directly while mobile displays the secret field in Advanced Options. Web browser clients don't support this feature. + +When authentication secret validation fails, the reverse proxy must return the `X-Reject-Reason: pre-auth` header along with the 403 status code. This header allows mobile and desktop applications to specifically identify authentication failures and provide appropriate error messaging to users. + + + +We recommend whitelisting certain endpoints where the authentication header may not be available. The specific endpoints depend on your authentication configuration: + +- `/api/v4/notifications/ack` - Required for proper notification acknowledgement functionality +- `/static/*`, `/api/v4/config/client` and `/login/desktop` - Required for authentication flows that redirect to the browser, such as SAML, OAuth and OpenID + +**Additional endpoints based on your authentication setup:** + +- SAML: `/login/sso/saml` +- OpenID: `/oauth/{service:[A-Za-z0-9]+}/complete`, `/oauth/{service:[A-Za-z0-9]+}/login`, `/oauth/{service:[A-Za-z0-9]+}/mobile_login`, `/oauth/{service:[A-Za-z0-9]+}/signup` +- OAuth: `/api/v3/oauth/{service:[A-Za-z0-9]+}/complete`, `/signup/{service:[A-Za-z0-9]+}/complete`, `/login/{service:[A-Za-z0-9]+}/complete` + +These endpoints are whitelisted because they're accessed during authentication flows where the authentication header can't be provided, such as OAuth redirects through external identity providers. + + + +## NGINX configuration example + +Here's an example partial NGINX configuration that validates the authentication secret header: + +``` text +server { + # ... + + # Define the expected auth secret + set $expected_secret "your-secure-auth-secret-here"; + + # Whitelist endpoints where auth secret may not be available + location = /api/v4/notifications/ack { + # Pass through without verifying auth secret validation + # ... + } + + location = /api/v4/config/client { + # Pass through without verifying auth secret validation + # ... + } + + location = /login/desktop { + # Pass through without verifying auth secret validation + # ... + } + + location ^~ /static/ { + # Pass through without verifying auth secret validation + # ... + } + + # Additional whitelisted endpoints based on authentication configuration + # Uncomment and configure as needed for your setup: + # Note: Replace {service:[A-Za-z0-9]+} with your specific service names + # (e.g., google, gitlab, openid, office365) or use the regex pattern for multiple services + + # SAML + # location = /login/sso/saml { + # # ... + # } + + # OpenID/OAuth patterns (use regex for multiple services) + # location ~ ^/oauth/[A-Za-z0-9]+/(complete|login|mobile_login|signup)$ { + # # ... + # } + # Or for specific services: + # location ~ ^/oauth/(google|gitlab|office365)/(complete|login|mobile_login|signup)$ { + # # ... + # } + # location ~ ^/api/v3/oauth/[A-Za-z0-9]+/complete$ { + # # ... + # } + # location ~ ^/(signup|login)/[A-Za-z0-9]+/complete$ { + # # ... + # } + + location / { + # Check if X-Mattermost-Preauth-Secret header matches expected value + if ($http_x_mattermost_preauth_secret != $expected_secret) { + add_header X-Reject-Reason pre-auth always; + add_header Cache-Control "no-store" always; + return 403 "Forbidden: Invalid pre-authentication secret"; + } + + # ... + } +} +``` + +Replace `your-secure-auth-secret-here` with a strong, unique secret that will be configured in your mobile and desktop applications. Store this secret securely and rotate it regularly as part of your security practices. + +For Apache2 configuration guidance, see [Configuring Apache2 as a proxy for Mattermost Server](https://support.mattermost.com/hc/en-us/articles/41170740463764-Configuring-Apache2-as-a-proxy-for-Mattermost-Server-Unofficial). + +## Rotate secrets + +To rotate an authentication secret: + +1. Generate a new secret: `openssl rand -base64 32`. +2. Update your reverse proxy configuration with the new secret. +3. Reload the reverse proxy. +4. Notify users: + +> - **Desktop users**: No action needed. They'll be automatically prompted for the new secret on their next connection attempt. +> - **Mobile users**: Manually update the secret by editing the server in the app by tapping **Servers**, swiping left, tapping **Edit \> Advanced Options** and updating the **Authentication secret**. + +## Security considerations + +
+ +Desktop + +The Mattermost desktop application stores authentication secrets using Electron's `safeStorage` API, which integrates with the operating system's secure credential storage: + +- **Windows**: Windows Credential Manager +- **macOS**: Keychain Access +- **Linux**: Secret Service API (requires kwallet, gnome-libsecret, or compatible backend) + +For more information about Electron's secure storage behavior, see the [Electron safeStorage documentation](https://www.electronjs.org/docs/latest/api/safe-storage). + + + +On Linux systems where no secure credential storage is available, the authentication secret may be stored in **plain text**. This occurs when: + +- No secret store backend is available (kwallet, gnome-libsecret, etc.) +- The desktop environment is not recognized +- The system falls back to Electron's `basic_text` storage + +The file is stored with permissions to prevent unauthorized access by other users, though the secret remains unencrypted. Consider the security implications before deploying authentication secrets in your environment. + + + +
+ +
+ +Mobile + +The Mattermost mobile application stores authentication secrets using platform-native secure storage: + +- **iOS**: iOS Keychain +- **Android**: Android Keystore system + +Mobile authentication secrets are always encrypted. Unlike desktop Linux systems, there is no plaintext fallback on mobile platforms. + +The authentication secret is included in all network requests, including REST API calls, WebSocket connections, and requests from share extensions and notification handlers. + +
diff --git a/docs/main/deployment-guide/server/preparations.mdx b/docs/main/deployment-guide/server/preparations.mdx new file mode 100644 index 000000000000..a111438344f6 --- /dev/null +++ b/docs/main/deployment-guide/server/preparations.mdx @@ -0,0 +1,371 @@ +--- +title: "Prepare your Mattermost Server environment" +sidebar_label: "Preparations" +--- +This guide outlines the key preparation steps required before installing the Mattermost Server, focusing on setting up the database and file storage systems. + +Before installing Mattermost Server, review the following preparation requirements: + +- [Review software and hardware requirements](/deployment-guide/software-hardware-requirements) - Ensure your system meets the minimum requirements for Mattermost deployment. +- [Set up an NGINX proxy](/deployment-guide/server/setup-nginx-proxy) - Configure NGINX as a reverse proxy for enhanced security and performance. +- [Set up TLS](/deployment-guide/server/setup-tls) - Enable secure communication with SSL/TLS encryption. +- [Use an image proxy](/deployment-guide/server/image-proxy) - Configure image proxy for enhanced privacy and security. + +## Database preparation + +PostgreSQL v14+ is required for Mattermost server installations. [MySQL database support](/deployment-guide/server/prepare-mattermost-mysql-database) is being deprecated starting with Mattermost v11. See the [PostgreSQL migration](/deployment-guide/postgres-migration) documentation for guidance on migrating from MySQL to PostgreSQL. + +1. Create an PostgreSQL server instance. See the [PostgreSQL documentation](https://www.postgresql.org/download/) for details. When the installation is complete, the PostgreSQL server is running, and a Linux user account called postgres has been created. + +2. Create the Mattermost database and user: + + 1. Access PostgreSQL by running: + + ``` sh + sudo -u postgres psql + ``` + + 2. Create the database: + + ``` sql + CREATE DATABASE mattermost WITH ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE=template0; + ``` + + If this steps fails with an error message like `invalid LC_COLLATE locale name: "en_US.UTF-8"`, you need to generate the locale first using `locale-gen en_US.UTF-8`. + + 3. Create the Mattermost user with a secure password: + + ``` sql + CREATE USER mmuser WITH PASSWORD 'mmuser-password'; + ``` + + 4. Grant database access to the user: + + ``` sql + GRANT ALL PRIVILEGES ON DATABASE mattermost to mmuser; + ``` + + 5. If using PostgreSQL v15.x or later, additional grants are required: + + ``` text + ALTER DATABASE mattermost OWNER TO mmuser; + -- Connect to the mattermost database so the schema grants below apply to the right schema + \c mattermost + ALTER SCHEMA public OWNER TO mmuser; + GRANT USAGE, CREATE ON SCHEMA public TO mmuser; + ``` + +3. Configure PostgreSQL for remote connections (if database is on a separate server): + + 1. Edit `postgresql.conf` to allow remote connections: + +
+ + Ubuntu/Debian + + Edit `/etc/postgresql/{version}/main/postgresql.conf`: + + ``` text + listen_addresses = '*' + ``` + +
+ +
+ + RHEL/CentOS + + Edit `/var/lib/pgsql/{version}/data/postgresql.conf`: + + ``` text + listen_addresses = '*' + ``` + +
+ + 2. Configure client authentication by editing `pg_hba.conf`: + + Add the following line, replacing `{mattermost-server-IP}`: + + ``` text + host all all {mattermost-server-IP}/32 md5 + ``` + +4. Restart the PostgreSQL service to apply the configuration changes: + +
+ + Ubuntu/Debian + + ``` sh + sudo systemctl restart postgresql + ``` + +
+ +
+ + RHEL/CentOS + + ``` sh + sudo systemctl restart postgresql + ``` + +
+ + + +If you are upgrading a major version of PostgreSQL, see [Upgrade PostgreSQL](/administration-guide/upgrade/upgrading-postgres) for the full upgrade procedure and post-upgrade steps. + + + +Once you've completed the database preparation, return to the [Linux deployment](/deployment-guide/server/deploy-linux) documentation to continue with your Mattermost server installation. + +## File storage preparation + +Mattermost requires a file storage system for storing user files, images, and attachments. You have several options, including: + +- S3-compatibile object storage (recommended) +- Network file storage +- Local file storage + +### S3-compatible object storage (Recommended) + +For production environments, we recommend using S3-compatible object storage such as: + +- Amazon S3 +- Digital Ocean Spaces +- Other S3-compatible services + +When using S3 storage, you'll need: + +1. A bucket created specifically for Mattermost +2. Access credentials (Access Key and Secret Key) +3. Appropriate bucket policies configured +4. The following information for configuration: + - Bucket name + - Region (if applicable) + - Access Key + - Secret Key + - Endpoint URL (for non-AWS S3 services) + +### Network file storage + +For production environments that cannot use S3-compatible object storage, we recommend using a Network Addressable Storage (NAS) solution with Network File System (NFS). + +You'll need to prepare an NFS server with a dedicated share for Mattermost (e.g. /mnt/mattermost_data) and mount it on all servers that will be running Mattermost. + +### Local file storage + +For simple deployments, you can use local file storage. However, we don't recommend this for production environments or multi-node deployments. + +1. Create a directory for file storage: + + ``` sh + sudo mkdir -p /opt/mattermost/data + ``` + +2. Set appropriate permissions: + + ``` sh + sudo chown -R mattermost:mattermost /opt/mattermost/data + ``` + +### (Optional) Use an image proxy + +Using an [image proxy](/deployment-guide/server/image-proxy) means that all requests for images made by Mattermost clients will go through the proxy instead of contacting third-party servers directly. This helps protect user privacy by preventing third-party servers from tracking who views an image. This also prevents the use of tracking pixels (invisible images that do the same thing without the user even seeing an image). + +Certain proxy servers also provide a layer of caching which can make loading images faster and more reliable. This caching also helps preserve posts by protecting them from dead images. + +## Network preparation + +The following table outlines the network ports and protocols required for Mattermost server: + + ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Service NameConfig SettingPort (default)ProtocolDirectionInfo
HTTP/WebsocketServiceSettings.ListenAddress8065/80/443 (TLS)TCPInboundExternal (no proxy) / Internal (with proxy) Usually this requires port 80 and 443 when running HTTPS.
ClusterClusterSettings.GossipPort8074TCP/UDPInboundInternal
MetricsMetricsSettings.ListenAddress8067TCPInboundExternal (no proxy) / Internal (with proxy)
DatabaseSqlSettings.DataSource5432 (PostgreSQL) / 3306 (MySQL)TCPOutboundUsually internal (recommended)
LDAPLdapSettings.LdapPort389TCP/UDPOutbound
S3 StorageFileSettings.AmazonS3Endpoint443 (TLS)TCPOutbound
SMTPEmailSettings.SMTPPort10025TCP/UDPOutbound
Push NotificationsEmailSettings.PushNotificationServer443 (TLS)TCPOutbound
+ + + +- All outbound ports may vary based on your specific configuration +- Mattermost can be configured to use an outbound proxy for any HTTP/HTTPS traffic (see below) +- Calls service may require additional ports + + + +### Outbound proxy configuration + +If your deployment requires using an outbound proxy, you can configure Mattermost using environment variables: + +1. Configure the proxy settings in your service configuration: + + ``` text + Environment=HTTP_PROXY=http://proxy.example.com:3128 + Environment=HTTPS_PROXY=https://proxy.example.com:3128 + Environment=NO_PROXY=localhost,127.0.0.1,.internal.example.com + ``` + +2. For authenticated proxies, include credentials in the URL: + + ``` text + Environment=HTTP_PROXY=http://username:password@proxy.example.com:3128 + Environment=HTTPS_PROXY=https://username:password@proxy.example.com:3128 + ``` + +3. The `NO_PROXY` variable can include: + + - IP addresses (e.g., `1.2.3.4`) + - CIDR ranges (e.g., `1.2.3.4/8`) + - Domain names (e.g., `example.com`) + - Subdomains (e.g., `.example.com`) + + + +When using an HTTPS proxy, ensure your Mattermost server has the proxy's root certificate configured to avoid connection issues. + +Example systemd Service Configuration + +``` ini +[Unit] +Description=Mattermost +After=network.target +After=postgresql.service +BindsTo=postgresql.service + +[Service] +Type=notify +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost +LimitNOFILE=49152 + +# Configure proxy settings if needed +#Environment=HTTP_PROXY=http://proxy.example.com:3128 +#Environment=HTTPS_PROXY=https://proxy.example.com:3128 +#Environment=NO_PROXY=localhost,127.0.0.1,.internal.example.com + +# Recommended security options +ProtectSystem=full +PrivateTmp=true +NoNewPrivileges=true + +[Install] +WantedBy=postgresql.service +``` + + + +## System requirements + +Ensure your system meets these minimum requirements: + +- Operating System: 64-bit Linux distribution +- Hardware: 1 vCPU/core with 2GB RAM (supports up to 1,000 users) +- Storage: Minimum 10GB available space +- Database: PostgreSQL v14+ +- Network: Reliable internet connection with sufficient bandwidth + +See the [software and hardware requirements](/deployment-guide/software-hardware-requirements) documentation for additional requirements. + +## Next steps + +Once you've completed these preparation steps, you can proceed with installing the Mattermost server. Choose your preferred installation method: + +- [Deploy with Kubernetes](/deployment-guide/server/deploy-kubernetes) +- [Deploy on Linux](/deployment-guide/server/deploy-linux) +- [Deploy with Containers](/deployment-guide/server/deploy-containers) diff --git a/docs/main/deployment-guide/server/prepare-mattermost-mysql-database.mdx b/docs/main/deployment-guide/server/prepare-mattermost-mysql-database.mdx new file mode 100644 index 000000000000..7c2cc9b587ba --- /dev/null +++ b/docs/main/deployment-guide/server/prepare-mattermost-mysql-database.mdx @@ -0,0 +1,307 @@ +--- +title: "Set up the Mattermost MySQL database" +--- +------------------------------------------------------------------------------------------------------------------------ + + + + + +- From Mattermost v11, Mattermost completely stops support MySQL as a database driver. MySQL support has been completely removed from the codebase, and the product will throw an invalid configuration error. +- PostgreSQL is our preferred database of choice. See the [database software](/deployment-guide/software-hardware-requirements#database-software) documentation for details on database version support, and see the [Migrate from MySQL to PostgreSQL](/deployment-guide/postgres-migration) documentation for details on migrating from MySQL to PostgreSQL. +- MySQL 8.0.22 contains an [issue with JSON column types](https://bugs.mysql.com/bug.php?id=101284) changing string values to integers which is preventing Mattermost from working properly. Users are advised to avoid this database version. + + + +To set up a MySQL database for use by the Mattermost server: + +1. Log into the server that will host the database, ands install MySQL. +2. Log in to MySQL as *root* by running `sudo mysql`. +3. Create the Mattermost user *mmuser* by running `mysql> create user 'mmuser'@'%' identified by 'mmuser-password';`. + +> - Use a password that is more secure than `mmuser-password`. +> - The `%` means that `mmuser` can connect from any machine on the network. However, it's more secure to use the IP address of the machine that hosts Mattermost. For example, if you install Mattermost on the machine with IP address `10.10.10.2`, then use the following command: `mysql> create user 'mmuser'@'10.10.10.2' identified by 'mmuser-password';` + +4. Create the Mattermost database by running `mysql> create database mattermost;`. +5. Grant access privileges to the user `mmuser` by running `mysql> grant all privileges on mattermost.* to 'mmuser'@'%';`. + +>
+> +>
+> +> Note +> +>
+> +> This query grants the MySQL user we just created all privileges on the database for convenience. If you need more security, use the following query to grant the user only the privileges necessary to run Mattermost: `mysql> GRANT ALTER, CREATE, DELETE, DROP, INDEX, INSERT, SELECT, UPDATE, REFERENCES ON mattermost.* TO 'mmuser'@'%';` +> +>
+ +6. Log out of MySQL by running `mysql> exit`. Once the database is installed and the initial setup is complete, you can install the Mattermost server. + + + +If you have installed MySQL on its own server, edit the `/etc/mysql/mysql.conf.d/mysqld.cnf` file and comment out the `bind-address = 127.0.0.1` using the `#` symbol, then restart your database server. + + + +# Back up the database + +Back up your Mattermost database using standard procedures depending on your database version. MySQL backup documentation \[https://dev.mysql.com/doc/refman/8.4/en/backup-types.html\](https://dev.mysql.com/doc/refman/8.4/en/backup-types.html\)\`\_ is available online. Use the selector on the page to choose your MySQL version. + +# Upgrade Mattermost + +
+ +Upgrade to v7.1 + +Mattermost v7.1 introduces schema changes in the form of a new column and its index. Our test results for the schema changes include: 12M Posts, 2.5M Reactions - ~1min 34s (instance: PC with 8 cores, 16GB RAM). + +You can run the following SQL queries before the upgrade that obtains a lock on `Reactions` table. + +`ALTER TABLE Reactions ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT "";` + +`UPDATE Reactions SET ChannelId = COALESCE((select ChannelId from Posts where Posts.Id = Reactions.PostId), '') WHERE ChannelId="";` + +`CREATE INDEX idx_reactions_channel_id ON Reactions(ChannelId) LOCK=NONE;` + +Users' reactions posted during this time won't be reflected in the database until the migrations are complete. This is fully backwards-compatible. + +If your connection collation and table collations are different, this can result in the error Illegal mix of collations. To resolve this error, set the same collation for both the connection and the table. There are different collations at different levels - connection, database, table, column, and database administrators may choose to set different collation levels for different objects. + +
+ +
+ +Upgrade to v7.0 + +Self-hosted Mattermost customers using MySQL databases may notice the migration to release v7.0 taking longer than usual when there are a large number of rows in the `FileInfo` table. See the [important upgrade notes](/administration-guide/upgrade/important-upgrade-notes) documentation for details. + +
+ +
+ +Upgrade to v6.7 + +Mattermost v6.7 introduces schema changes in the form of a new index. The following notes our test results for the schema changes: + +- 7M Posts - ~17s (instance: db.r5.xlarge) +- 9M Posts - 2min 12s (instance: db.r5.large) + +If you want a zero downtime upgrade, you can apply this index prior to doing the upgrade: + +`CREATE INDEX idx_posts_create_at_id on Posts(CreateAt, Id) LOCK=NONE;` + +This is fully backwards-compatible and will not acquire any table lock or affect any existing operations on the table. + +
+ +
+ +v6.0 database schema migrations + +The release of v6.0 introduces database schema changes and longer migration times should be expected, especially on MySQL installations. + +Mattermost v6.0 introduces several database schema changes to improve both database and application performance. The upgrade will run significant database schema changes that can cause an extended startup time depending on the dataset size. We've conducted extensive tests on supported MySQL database drivers, using realistic datasets of more than 10 million posts and more than 72 million posts. + +A migration to v6.0 of 10+ million posts will take approximately 1 hour and 22 minutes to complete for a MySQL database. + +A large migration from v5.39 to v6.0 of 72+ million posts will take approximately 3 hours and 40 minutes to complete for a MySQL database. See the [Migration results analysis](https://gist.github.com/streamer45/868c451164f6e8069d8b398685a31b6e) documentation for test specifications, data sizes, and test results. + +The following queries, executed during the migration process on an environment with 10+ million posts, will have a significant impact on database CPU usage and write operation restrictions for the duration of the query: + +`ALTER TABLE Posts MODIFY Props JSON;` (~26 minutes) + +`ALTER TABLE Posts DROP COLUMN ParentId;` (~26 minutes) + +`ALTER TABLE Posts MODIFY COLUMN FileIds text;` (~26 minutes) + +See the [Mattermost v6.0 DB schema migrations analysis](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055) documentation for test specifications, data sizes, test results, and a complete breakdown of MySQL queries, as well as their impact and duration. + +# MySQL Mitigation Strategies + +Run combined queries prior to the upgrade. The previous queries can be combined when run prior to the upgrade as follows: + +`ALTER TABLE Posts MODIFY COLUMN FileIds text, MODIFY COLUMN Props JSON;` + +This limits the time taken to that of a single query of that type. + +**Online migration**: An online migration that avoids locking can be attempted on MySQL installations, especially for particularly heavy queries or very big datasets (tens of millions of posts or more). This can be done through an external tool like [pt-online-schema-change](https://docs.percona.com/percona-toolkit/pt-online-schema-change.html). However, the online migration process can cause a significant spike in CPU usage on the database instance it runs. + +See the [Mattermost v6.0 DB schema migrations analysis](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055#online-migration-mysql) documentation for a sample execution and additional caveats. + +
+ +# High availabiilty configuration setting recommendations + +For MySQL, we recommend the following configuration options for high performance: + +- `innodb_buffer_pool_size`: Set to ~70% of your total RAM. +- `innodb_log_file_size`: Set to 256 MB. Increasing this helps in write intensive operations. Recovery times will be longer. +- `innodb_flush_log_at_trx_commit`: 2. This can potentially cause up to one second of loss of transaction data. +- `max_heap_table_size`: 64 MB. +- `tmp_table_size`: 64 MB. + +# Encryption-at-rest + +Encryption-at-rest is available for messages via hardware and software disk encryption solutions applied to the Mattermost database, which resides on its own server within your infrastructure. See the [MySQL](https://www.percona.com/blog/mysql-data-at-rest-encryption/) database documentation for details on encryption options at the disk level. + +# Use sockets for the database + +``` sh +mysql -u root -p +``` + +``` sql +CREATE DATABASE mattermostdb; +CREATE USER mmuser IDENTIFIED BY 'mmuser_password'; +GRANT ALL ON mattermostdb.* TO mmuser; +``` + +Mattermost is configured in `/etc/webapps/mattermost/config.json`, and strings need to be quoted. + +- set `DriverName` to `mysql`. +- set `DataSource` to `mmuser:mmuser_password@unix(/run/mysqld/mysqld.sock)/mattermostdb?charset=utf8mb4,utf8`. + +# Mattermost configuration in the database + +You can use the database as the single source of truth for the active configuration of your Mattermost installation. This changes the Mattermost binary from reading the default `config.json` file to reading the configuration settings stored within a configuration table in the database. + +``` text +mysql://mmuser:really_secure_password@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s +``` + +## Create an environment file + + + +If you're running Mattermost in a High Availability cluster-based deployment, this step must be done on all servers in the cluster. + + + +Create the file `/opt/mattermost/config/mattermost.environment` to set the `MM_CONFIG` environment variable to the database connection string. For example: + +``` text +MM_CONFIG='mysql://mmuser:mostest@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s' +``` + + + +Be sure to escape any single quotes in the database connection string by placing a `\` in front of them like this `\'`. For example: `MM_CONFIG='mysql://mmuser:it\'s-a-password!@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s'` + + + +``` text +MM_CONFIG='mysql://mmuser:it\'s-a-password!@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s' +``` + +Finally, run this command to verify the permissions on your Mattermost directory: + +``` sh +sudo chown -R mattermost:mattermost /opt/mattermost +``` + +## Modify the Mattermost `systemd` file + +First, find the `mattermost.service` file using: + +``` sh +sudo systemctl status mattermost.service +``` + +The second line of output will have the location of the running `mattermost.service`. + +``` text +Loaded: loaded (/lib/systemd/system/mattermost.service; enabled; vendor preset: enabled) +``` + +Edit this file as *root* to add the below text just above the line that begins with `ExecStart`: + +``` text +EnvironmentFile=/opt/mattermost/config/mattermost.environment +``` + +Here's a complete `mattermost.service` file with the `EnvironmentFile` line added: + +``` text +[Unit] +Description=Mattermost +After=network.target +After=mysql.service +Requires=mysql.service + +[Service] +Type=notify +EnvironmentFile=/opt/mattermost/config/mattermost.environment +ExecStart=/opt/mattermost/bin/mattermost +TimeoutStartSec=3600 +KillMode=mixed +Restart=always +RestartSec=10 +WorkingDirectory=/opt/mattermost +User=mattermost +Group=mattermost +LimitNOFILE=49152 + +[Install] +WantedBy=mysql.service +``` + +# Technical notes about searching + +By default, Mattermost uses full text search support included in MySQL. Select the **product menu** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. then select **About Mattermost** to see which database you’re using. + +- Stop words are filtered out of search results. See [MySQL](https://dev.mysql.com/doc/refman/5.7/en/fulltext-stopwords.html) database documentation for a full list of applicable stop words. +- Hashtags or recent mentions of usernames containing a dot don't return results. +- Avoid using underline `_` symbol to [perform a wildcard search](#wildcards). Use the asterisk `*` symbol instead. +- Stop words that are excluded from search in MySQL include: `"a", "about", "an", "are", "as", "at", "be", "by", "com", "de", "en", "for", "from", "how", "i", "in", "is", "it", "la", "of", "on", "or", "that", "the", "this", "to", "was", "what", "when", "where", "who", "will", "with", "und", "the", "www"`. + +## Perform searches in Chinese, Korean, and Japanese + +The best experience for searching in Chinese, Korean, and Japanese is to use MySQL 5.7.6 or later with special configuration. See the [Chinese, Japanese and Korean Search documentation](/administration-guide/configure/enabling-chinese-japanese-korean-search) for details. + +You can perform searches without this configuration by adding wildcards `*` to the end of search terms. + +# Migrate from Bitnami to a self-hosted Mattermost deployment + +If you're planning a migration from Bitnami to a self-hosted Mattermost installation with a MySQL database, read these notes in our migration guide: [Migrating from Bitnami](/administration-guide/onboard/migrating-to-mattermost#move-from-bitnami). + +# Downgrade Mattermost v6.0 to v5.38 + +``` sh +INSERT INTO Systems (Name,Value) VALUES ('Version','5.38.0') ON DUPLICATE KEY UPDATE Value = '5.38.0'; + +CREATE INDEX idx_status_status ON Status (Status); +DROP INDEX idx_status_status_dndendtime ON Status; +CREATE INDEX idx_channelmembers_user_id ON ChannelMembers (UserId); +DROP INDEX idx_channelmembers_channel_id_scheme_guest_user_id ON ChannelMembers; +DROP INDEX idx_channelmembers_user_id_channel_id_last_viewed_at ON ChannelMembers; +CREATE INDEX idx_threads_channel_id ON Threads (ChannelId); +DROP INDEX idx_threads_channel_id_last_reply_at ON Threads; +CREATE INDEX idx_channels_team_id ON Channels (TeamId); +DROP INDEX idx_channels_team_id_type ON Channels; +DROP INDEX idx_channels_team_id_display_name ON Channels; +CREATE INDEX idx_posts_root_id ON Posts (RootId); +DROP INDEX idx_posts_root_id_delete_at ON Posts; + +ALTER TABLE CommandWebhooks ADD COLUMN ParentId varchar(26); +UPDATE CommandWebhooks SET ParentId = ''; +ALTER TABLE Posts ADD COLUMN ParentId varchar(26); +UPDATE Posts SET ParentId = ''; + +ALTER TABLE Users MODIFY Timezone text; +ALTER TABLE Users MODIFY NotifyProps text; +ALTER TABLE Users MODIFY Props text; +ALTER TABLE Threads MODIFY Participants longtext; +ALTER TABLE Sessions MODIFY Props text; +ALTER TABLE Posts MODIFY Props text; +ALTER TABLE Jobs MODIFY Data text; +ALTER TABLE LinkMetadata MODIFY Data text; +ALTER TABLE ChannelMembers MODIFY NotifyProps text; +``` + + + +The inverse of [the final v6.0 upgrade query](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055#mysql-1) is intentionally omitted from these downgrade queries because its result is backwards compatible, and running the query would unnecessarily delay the downgrade process. + + diff --git a/docs/main/deployment-guide/server/server-deployment-planning.mdx b/docs/main/deployment-guide/server/server-deployment-planning.mdx new file mode 100644 index 000000000000..1dbd20c03951 --- /dev/null +++ b/docs/main/deployment-guide/server/server-deployment-planning.mdx @@ -0,0 +1,136 @@ +--- +title: "Server deployment planning" +--- +This section provides comprehensive guidance on deploying and managing your Mattermost server. Mattermost is a flexible, high-performance messaging platform built with Go and React, designed to provide secure team collaboration at scale. Use the navigation below to learn more about how Mattermost supports a wide range of deployment options, from single-server installations to complex, distributed architectures: + +- [Preparations](/deployment-guide/server/preparations) - Software and hardware requirements, proxy setup, TLS configuration, and other pre-deployment tasks. +- [Deploy with Kubernetes](/deployment-guide/server/deploy-kubernetes) - Scalable deployment on various Kubernetes platforms with high availability support. +- [Deploy with Linux](/deployment-guide/server/deploy-linux) - Direct installation on Linux servers for full control over the deployment. +- [Deploy with Containers](/deployment-guide/server/deploy-containers) - Docker-based deployment suitable for smaller installations. +- [Pre-authentication secrets](/deployment-guide/server/pre-authentication-secrets) - Configure reverse proxy validation for mobile and desktop applications using pre-authentication headers. +- [Deployment Solution Programs](/deployment-guide/server/orchestration) - Automated deployment tools and orchestration solutions. + +## Core technology stack + +Mattermost's architecture is built on modern, reliable technologies: + +- **Backend**: Written in Go, providing high performance and concurrent processing +- **Frontend**: React-based web application and mobile apps +- **Database**: PostgreSQL for primary data storage +- **Search**: Elasticsearch (optional) for advanced search capabilities +- **File Storage**: Local filesystem, network storage using NFS, or cloud storage (S3 or S3-compatible services) for media and attachments +- **Caching**: Built-in support for Redis for enhanced performance + +## Deployment options + +Mattermost offers several deployment options to suit your organization's needs: + +1. [Kubernetes (Recommended)](/deployment-guide/server/deploy-kubernetes) + + Our recommended approach for production deployments offers: + + - Scalability and high availability + - Automated updates and rollbacks + - Infrastructure as code + - Built-in monitoring and logging + - Easy integration with existing DevOps workflows + +2. [Linux Server Installation](/deployment-guide/server/deploy-linux) + + A direct installation on Linux servers offers: + + - Simple, straightforward setup + - Full control over the installation + - For situations where containers aren't preferred + +3. [Container-Based Deployment](/deployment-guide/server/deploy-containers) + + Docker containers are suitable for smaller deployments only as it offers: + + - Simplified installation and updates + - Consistent environments + - Easy dependency management + - No support for high availability + +## Prerequisites + +Before deploying Mattermost, ensure you have reviewed the [software and hardware requirements](/deployment-guide/software-hardware-requirements), and have: + +- A supported Linux distribution +- Database server (PostgreSQL 14+) +- Reverse proxy (NGINX recommended) +- SSL/TLS certificates for secure communication +- Adequate storage for files and database +- Network access and firewall configurations +- System requirements met based on expected user load + +## Plan your deployment + +When planning your Mattermost deployment, consider the following when choosing the deployment method that best aligns with your organization's requirements, technical expertise, and infrastructure capabilities: + +- Expected user count and growth +- High availability requirements +- Backup and disaster recovery needs +- Integration with existing systems +- Security and compliance requirements +- Monitoring and maintenance strategy + +The following server, desktop, and mobile application sections provide detailed instructions for each deployment approach. + +### Minimum database version policy + +To make planning easier and ensure your Mattermost deployment remains fast and secure, we are introducing a policy for updating the minimum supported version of PostgreSQL. The oldest supported PostgreSQL version Mattermost supports will match the oldest version supported by the PostgreSQL community. This ensures you benefit from the latest features and security updates. + +This policy change takes effect from Mattermost v10.6, where the minimum PostgreSQL version required will be PostgreSQL 13. This aligns with the PostgreSQL community's support policy, which provides 5 years of support for each major version. + + + +Mattermost v10.6 is not an [Extended Support Release (ESR)](/product-overview/release-policy#extended-support-releases). Going forward, this database version support policy will only apply to ESR releases. + + + +When a PostgreSQL version reaches its end of life (EOL), Mattermost will require a newer version starting with the next scheduled ESR release. This means the following future PostgreSQL minimum version increases as follows: + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

Mattermost Version | Release Date | Minimum PostgreSQL Version |

+
+
+
===========================================================+==================+================================+
+
+

v9.11 ESR | 2024-8-15 | 11.x

+
+
v10.5 ESR | 2025-2-15 | 11.x
v10.6 | 2025-3-15 | 13.x
v10.11 ESR2025-8-1513.x
v11.5 ESR *2026-2-1514.x (EOL 2026-11-12)
+ +`*` Forcasted release version and date. + +Customers will have 9 months to plan, test, and upgrade their PostgreSQL version before the new requirement takes effect. This policy aims to provide clarity and transparency so you can align database upgrades with the Mattermost release schedule. Contact a [Mattermost Expert](https://mattermost.com/contact-sales/). to discuss your options. diff --git a/docs/main/deployment-guide/server/setup-nginx-proxy.mdx b/docs/main/deployment-guide/server/setup-nginx-proxy.mdx new file mode 100644 index 000000000000..7872ac39e549 --- /dev/null +++ b/docs/main/deployment-guide/server/setup-nginx-proxy.mdx @@ -0,0 +1,709 @@ +--- +title: "(Recommended) Set up an NGINX proxy" +--- +A proxy server is a server (a computer system or an application) that acts as an intermediary for requests from clients seeking resources from other servers. Mattermost recommends using a proxy in front of Mattermost to increase security, performance and the ability to monitor and shape traffic connecting to Mattermost: + +- **Security:** A proxy server can manage Secure Socket Layer (TLS/SSL) encryption and set policy on how network traffic will be routed to the Mattermost server. +- **Performance:** In a High Availability configuration, the proxy server balances the network load across multiple Mattermost servers for optimized performance. A hardware proxy with dedicated devices for processing SSL encryption and decryption can also be used to increase performance. +- **Monitoring**: A proxy server can monitor connection traffic and record traffic in standard audit logs that common monitoring tools like Kibana and Splunk can consume and report on. Some of the events that can be captured include file uploads and downloads, which are not tracked by the Mattermost server logging process. + +Mattermost supports the [NGINX proxy](https://www.f5.com/go/product/welcome-to-nginx) + +![Mattermost architecture with NGINX proxy](/images/architecture_with_proxy.png) + +## Install NGINX server + +NGINX is a popular web server and is responsible for hosting some of the largest and highest-traffic sites on the internet. It's more resource-friendly than Apache in most cases, and can be used as a web server or reverse proxy. + +In a production setting, we recommend using a proxy server for greater security and performance of Mattermost: + +- SSL termination +- HTTP to HTTPS redirect +- Port mapping `:80` to `:8065` +- Standard request logs + +### Install NGINX on Ubuntu Server + +1. Log in to the server that will host the proxy and open a terminal window. +2. Install NGINX. + +> Because NGINX is available in Ubuntu's default repositories, it's possible to install it from these repositories using the `apt` packaging system. First, update your local `apt` package index for access to the most recent package listings. Then, install `nginx`: +> +> ``` sh +> sudo apt update +> sudo apt install nginx +> ``` +> +> After accepting the procedure, `apt` will install NGINX and any required dependencies to your server. + +3. After installing it, you already have everything you need. You can point your browser to your server IP address. You should see the default NGINX landing page: + +> ![Example of the default NGINX landing page.](/images/install_nginx_welcome.png) +> +> If you see this page, you've successfully installed NGINX on your web server. This page is included with NGINX to show you that the server is running correctly. +> +> Or you can also verify it by running `curl http://localhost`. +> +> If NGINX is running, you see the following output: +> +> ``` html +> <!DOCTYPE html> +> +> <head> +> Welcome to nginx! +> . +> . +> . +>

Thank you for using nginx.

+> +> +> ``` + +### Manage the NGINX process + +Now that you have your web server up and running, let's review some basic management commands. These are all run in the command line interface. + +To stop your web server, use: `sudo systemctl stop nginx` + +To start the web server when it's stopped, use: `sudo systemctl start nginx` + +To stop and then start the service again, use: `sudo systemctl restart nginx` + +If you're simply making configuration changes, NGINX can often reload without dropping connections. To do this, use: `sudo systemctl reload nginx` + +By default, NGINX is configured to start automatically when the server boots. If this isn't what you want, you can disable this behavior using: `sudo systemctl disable nginx` + +To re-enable the service to start up at boot, use: `sudo systemctl enable nginx` + +### What to do next + +1. Map a fully qualified domain name (FQDN) such as `mattermost.example.com` on your DNS server/service, to point to the NGINX server. +2. Configure NGINX to proxy connections from the internet to the Mattermost server. + +## Configure NGINX as a proxy for Mattermost server + +NGINX is configured using a file in the `/etc/nginx/sites-available` directory. You need to create the file and then enable it. When creating the file, you need the IP address of your Mattermost server and the fully qualified domain name (FQDN) of your Mattermost website. + +1. Log in to the server that hosts NGINX and open a terminal window. +2. Create a configuration file for Mattermost by running the following command: + +> `sudo touch /etc/nginx/sites-available/mattermost` on Ubuntu +> +> `sudo touch /etc/nginx/conf.d/mattermost` on RHEL 8 + +3. Open the file `/etc/nginx/sites-available/mattermost` (Ubuntu) or `/etc/nginx/conf.d/mattermost` (RHEL 8) as *root* user in a text editor and replace its contents, if any, with the following lines. Make sure that you use your own values for the Mattermost server IP address and FQDN for *server_name*. + +SSL and HTTP/2 are enabled in the provided configuration example. + + + +- If you're going to use Let's Encrypt to manage your SSL certificate, stop at step 3 and see the [NGINX HTTP/2 and SSL product documentation](/deployment-guide/server/setup-nginx-proxy#configure-nginx-with-ssl-and-http-2) for details. +- You'll need valid SSL certificates in order for NGINX to pin the certificates properly. Additionally, your browser must have permissions to accept the certificate as a valid CA-signed certificate. +- Note that the IP address included in the examples in this documentation may not match your network configuration. +- If you're running NGINX on the same machine as Mattermost, and NGINX resolves `localhost` to more than one IP address (IPv4 or IPv6), we recommend using `127.0.0.1` instead of `localhost`. + +``` text +upstream backend { + server 10.10.10.2:8065; + keepalive 32; +} + +server { + listen 80 default_server; + server_name mattermost.example.com; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name mattermost.example.com; + + ssl_certificate /etc/letsencrypt/live/{domain-name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain-name}/privkey.pem; + ssl_session_timeout 1d; + + # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC). + ssl_protocols TLSv1.2 TLSv1.3; + + # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to + # prevent replay attacks. + # + # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data + ssl_early_data on; + + ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384'; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:50m; + # HSTS (ngx_http_headers_module is required) (15768000 seconds = six months) + add_header Strict-Transport-Security max-age=15768000; + # OCSP Stapling --- + # fetch OCSP records from URL in ssl_certificate and cache them + ssl_stapling on; + ssl_stapling_verify on; + + add_header X-Early-Data $tls1_3_early_data; + + location ~ /api/v[0-9]+/(users/)?websocket$ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + client_max_body_size 50M; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + client_body_timeout 60s; + send_timeout 300s; + lingering_timeout 5s; + proxy_connect_timeout 90s; + proxy_send_timeout 300s; + proxy_read_timeout 90s; + proxy_http_version 1.1; + proxy_pass http://backend; + } + + location / { + client_max_body_size 100M; + proxy_set_header Connection ""; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + proxy_read_timeout 600s; + proxy_http_version 1.1; + proxy_pass http://backend; + } +} + +# This block is useful for debugging TLS v1.3. Please feel free to remove this +# and use the `$ssl_early_data` variable exposed by NGINX directly should you +# wish to do so. +map $ssl_early_data $tls1_3_early_data { + "~." $ssl_early_data; + default ""; +} +``` + + + +4. Remove the existing default sites-enabled file by running `sudo rm /etc/nginx/sites-enabled/default` (Ubuntu) or `sudo rm /etc/nginx/conf.d/default` (RHEL 8) +5. Enable the mattermost configuration by running `sudo ln -s /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/mattermost` (Ubuntu) or `sudo ln -s /etc/nginx/conf.d/mattermost /etc/nginx/conf.d/default.conf` (RHEL 8) +6. Restart NGINX by running `sudo systemctl restart nginx`. +7. Verify that you can see Mattermost through the proxy by running `curl https://localhost`. If everything is working, you will see the HTML for the Mattermost signup page. +8. Restrict access to port 8065. + +> By default, the Mattermost server accepts connections on port 8065 from every machine on the network. Use your firewall to deny connections on port 8065 to all machines except the machine that hosts NGINX and the machine that you use to administer the Mattermost server. If you're installing on Amazon Web Services, you can use Security Groups to restrict access. + +Now that NGINX is installed and running, you can configure it to use SSL, which allows you to use HTTPS connections and the HTTP/2 protocol. + +## Configure NGINX with SSL and HTTP/2 + +NGINX is configured using a file in the `/etc/nginx/sites-available` directory. You need to create the file and then enable it. When creating the file, you need the IP address of your Mattermost server and the fully qualified domain name (FQDN) of your Mattermost website. + +Using SSL gives greater security by ensuring that communications between Mattermost clients and the Mattermost server are encrypted. It also allows you to configure NGINX to use the HTTP/2 protocol. + +Although you can configure HTTP/2 without SSL, both Firefox and Chrome browsers support HTTP/2 on secure connections only. + +You can use any certificate that you want, but these instructions show you how to download and install certificates from [Let's Encrypt](https://letsencrypt.org/), a free certificate authority. + + + +If Let’s Encrypt is enabled, forward port 80 through a firewall, with [Forward80To443](/administration-guide/configure/environment-configuration-settings#forward-port-80-to-443) `config.json` setting set to `true` to complete the Let’s Encrypt certification. See the [Let's Encrypt/Certbot documentation](https://certbot.eff.org) for additional assistance. + + + +1. Log in to the server that hosts NGINX and open a terminal window. +2. Open the your Mattermost `nginx.conf` file as *root* in a text editor, then update the `{ip}` address in the `upstream backend` to point towards Mattermost (such as `127.0.0.1:8065`), and update the `server_name` to be your domain for Mattermost. + +>
+> +>
+> +> Note +> +>
+> +> - On Ubuntu this file is located at `/etc/nginx/sites-available/`. If you don't have this file, run `sudo touch /etc/nginx/sites-available/mattermost`. +> - On CentOS/RHEL this file is located at `/etc/nginx/conf.d/`. If you don't have this file, run `sudo touch /etc/nginx/conf.d/mattermost`. +> - The IP address included in the examples in this documentation may not match your network configuration. +> - If you're running NGINX on the same machine as Mattermost, and NGINX resolves `localhost` to more than one IP address (IPv4 or IPv6), we recommend using `127.0.0.1` instead of `localhost`. +> +>
+> +> ``` text +> upstream backend { +> server {ip}:8065; +> keepalive 32; +> } +> +> server { +> listen 80 default_server; +> server_name mattermost.example.com; +> +> location ~ /api/v[0-9]+/(users/)?websocket$ { +> proxy_set_header Upgrade $http_upgrade; +> proxy_set_header Connection "upgrade"; +> client_max_body_size 50M; +> proxy_set_header Host $http_host; +> proxy_set_header X-Real-IP $remote_addr; +> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +> proxy_set_header X-Forwarded-Proto $scheme; +> proxy_set_header X-Frame-Options SAMEORIGIN; +> proxy_buffers 256 16k; +> proxy_buffer_size 16k; +> client_body_timeout 60s; +> send_timeout 300s; +> lingering_timeout 5s; +> proxy_connect_timeout 90s; +> proxy_send_timeout 300s; +> proxy_read_timeout 90s; +> proxy_pass http://backend; +> } +> +> location / { +> client_max_body_size 50M; +> proxy_set_header Connection ""; +> proxy_set_header Host $http_host; +> proxy_set_header X-Real-IP $remote_addr; +> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +> proxy_set_header X-Forwarded-Proto $scheme; +> proxy_set_header X-Frame-Options SAMEORIGIN; +> proxy_buffers 256 16k; +> proxy_buffer_size 16k; +> proxy_read_timeout 600s; +> proxy_http_version 1.1; +> proxy_pass http://backend; +> } +> } +> ``` + +3. Remove the existing default sites-enabled file by running `sudo rm /etc/nginx/sites-enabled/default` (Ubuntu) or `sudo rm /etc/nginx/conf.d/default` (RHEL 8). +4. Enable the Mattermost configuration by running `sudo ln -s /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/mattermost` (Ubuntu) or `sudo ln -s /etc/nginx/conf.d/mattermost /etc/nginx/conf.d/default.conf` (RHEL 8). +5. Run `sudo nginx -t` to ensure your configuration is done properly. If you get an error, look into the NGINX config and make the needed changes to the file under `/etc/nginx/sites-available/mattermost`. +6. Restart NGINX by running `sudo systemctl start nginx`. +7. Verify that you can see Mattermost through the proxy by running `curl http://localhost`. + +> If everything is working, you will see the HTML for the Mattermost signup page. You will see invalid certificate when accessing through the IP or localhost. Use the full FQDN domain to verify if the SSL certificate has pinned properly and is valid. + +8. Install and update Snap by running `sudo snap install core; sudo snap refresh core`. +9. Install the Certbot package by running `sudo snap install --classic certbot`. +10. Add a symbolic link to ensure Certbot can run by running `sudo ln -s /snap/bin/certbot /usr/bin/certbot`. +11. Run the Let's Encrypt installer dry-run to ensure your DNS is configured properly by running `sudo certbot certonly --dry-run`. + +> This will prompt you to enter your email, accept the TOS, share your email, and select the domain you're activating certbot for. This will validate that your DNS points to this server properly and you are able to successfully generate a certificate. If this finishes successfully, proceed to step 12. + +12. Run the Let's Encrypt installer by running `sudo certbot`. This will run certbot and will automatically edit your NGINX config file for the site(s) selected. +13. Ensure your SSL is configured properly by running `curl https://{your domain here}` +14. Finally, we suggest editing your config file again to increase your SSL security settings above the default Let's Encrypt. This is the same file from Step 2 above. Edit it to look like the below: + +> ``` text +> upstream backend { +> server {ip}:8065; +> keepalive 32; +> } +> +> proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=120m use_temp_path=off; +> +> server { +> server_name mattermost.example.com; +> +> location ~ /api/v[0-9]+/(users/)?websocket$ { +> proxy_set_header Upgrade $http_upgrade; +> proxy_set_header Connection "upgrade"; +> client_max_body_size 50M; +> proxy_set_header Host $http_host; +> proxy_set_header X-Real-IP $remote_addr; +> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +> proxy_set_header X-Forwarded-Proto $scheme; +> proxy_set_header X-Frame-Options SAMEORIGIN; +> proxy_buffers 256 16k; +> proxy_buffer_size 16k; +> client_body_timeout 60s; +> send_timeout 300s; +> lingering_timeout 5s; +> proxy_connect_timeout 90s; +> proxy_send_timeout 300s; +> proxy_read_timeout 90s; +> proxy_http_version 1.1; +> proxy_pass http://backend; +> } +> +> location / { +> client_max_body_size 50M; +> proxy_set_header Connection ""; +> proxy_set_header Host $http_host; +> proxy_set_header X-Real-IP $remote_addr; +> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +> proxy_set_header X-Forwarded-Proto $scheme; +> proxy_set_header X-Frame-Options SAMEORIGIN; +> proxy_buffers 256 16k; +> proxy_buffer_size 16k; +> proxy_read_timeout 600s; +> proxy_http_version 1.1; +> proxy_pass http://backend; +> } +> +> listen 443 ssl http2; # managed by Certbot +> ssl_certificate /etc/letsencrypt/live/mattermost.example.com/fullchain.pem; # managed by Certbot +> ssl_certificate_key /etc/letsencrypt/live/mattermost.example.com/privkey.pem; # managed by Certbot +> # include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot +> ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +> +> ssl_session_timeout 1d; +> +> # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC). +> ssl_protocols TLSv1.2 TLSv1.3; +> +> # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to +> # prevent replay attacks. +> # +> # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data +> ssl_early_data on; +> +> ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA; +> ssl_prefer_server_ciphers on; +> ssl_session_cache shared:SSL:50m; +> # HSTS (ngx_http_headers_module is required) (15768000 seconds = six months) +> add_header Strict-Transport-Security max-age=15768000; +> # OCSP Stapling --- +> # fetch OCSP records from URL in ssl_certificate and cache them +> ssl_stapling on; +> ssl_stapling_verify on; +> } +> +> +> server { +> if ($host = mattermost.example.com) { +> return 301 https://$host$request_uri; +> } # managed by Certbot +> +> +> listen 80 default_server; +> server_name mattermost.example.com; +> return 404; # managed by Certbot +> +> } +> ``` + +15. Check that your SSL certificate is set up correctly. + +> - Test the SSL certificate by visiting a site such as [https://www.ssllabs.com/ssltest/index.html](https://www.ssllabs.com/ssltest/index.html). +> - If there’s an error about the missing chain or certificate path, there is likely an intermediate certificate missing that needs to be included. + +## High-performance scaling configuration + +For high-scale deployments with multiple Mattermost servers and heavy traffic loads, additional NGINX optimizations are recommended. This configuration is based on performance testing with large-scale Mattermost deployments. + + + +These settings are designed for high-performance environments. For standard deployments, the basic configuration above should be sufficient. + + + +### NGINX main configuration optimizations + +Update your main NGINX configuration file (`/etc/nginx/nginx.conf`) with the following performance optimizations: + +``` text +user www-data; +worker_processes auto; +worker_rlimit_nofile 100000; +pid /run/nginx.pid; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 20000; + use epoll; +} + +http { + map $status $loggable { + ~^[23] 0; + default 1; + } + + sendfile on; + tcp_nopush on; + tcp_nodelay off; + keepalive_timeout 75s; + keepalive_requests 16384; + types_hash_max_size 2048; + include /etc/nginx/mime.types; + default_type application/octet-stream; + ssl_prefer_server_ciphers on; + access_log /var/log/nginx/access.log combined if=$loggable; + error_log /var/log/nginx/error.log; + gzip on; + include /etc/nginx/sites-enabled/*; +} +``` + +Key optimizations in this configuration: + +- **worker_processes auto**: Automatically sets worker processes based on CPU cores +- **worker_rlimit_nofile 100000**: Increases file descriptor limit for high-concurrency +- **worker_connections 20000**: Allows each worker to handle more concurrent connections +- **use epoll**: Enables efficient connection handling on Linux +- **keepalive_timeout 75s** and **keepalive_requests 16384**: Optimizes connection reuse +- **Conditional logging**: Reduces log volume by only logging errors and non-2xx/3xx responses + +### Multi-node backend configuration + +For deployments with multiple Mattermost application servers, configure your site file (`/etc/nginx/sites-available/mattermost`) with load balancing: + +``` text +upstream backend { + server 172.27.205.186:8065 max_fails=0; + server 172.27.213.167:8065 max_fails=0; + # Add additional Mattermost servers as needed + + keepalive 256; +} + +proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=60m use_temp_path=off; + +server { + listen 80 reuseport; + server_name _; + + location ~ /api/v[0-9]+/(users/)?websocket$ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + include /etc/nginx/snippets/proxy.conf; + } + + location ~ /api/v[0-9]+/users/[a-z0-9]+/image$ { + proxy_set_header Connection ""; + include /etc/nginx/snippets/proxy.conf; + include /etc/nginx/snippets/cache.conf; + proxy_ignore_headers Cache-Control Expires; + proxy_cache_valid 200 24h; + } + + location / { + proxy_set_header Connection ""; + include /etc/nginx/snippets/proxy.conf; + include /etc/nginx/snippets/cache.conf; + } +} +``` + +### NGINX proxy configuration snippets + +Create optimized proxy configuration snippets for reuse across different locations. + +Create `/etc/nginx/snippets/proxy.conf`: + +``` text +client_max_body_size 50M; +proxy_set_header Host $http_host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Frame-Options SAMEORIGIN; +proxy_buffers 256 16k; +proxy_buffer_size 16k; +client_body_timeout 60s; +send_timeout 300s; +lingering_timeout 5s; +proxy_connect_timeout 30s; +proxy_send_timeout 90s; +proxy_read_timeout 90s; +proxy_http_version 1.1; +proxy_pass http://backend; +``` + +Create `/etc/nginx/snippets/cache.conf`: + +``` text +proxy_cache mattermost_cache; +proxy_cache_revalidate on; +proxy_cache_min_uses 2; +proxy_cache_use_stale timeout; +proxy_cache_lock on; +``` + +### Key performance optimizations + +The high-performance configuration includes several critical optimizations: + +**Load Balancing**: + +- **max_fails=0**: Prevents servers from being marked as unavailable +- **keepalive 256**: Maintains persistent connections to backend servers +- **reuseport**: Allows multiple worker processes to bind to the same port + +**Caching Strategy**: + +- **User images cached for 24 hours**: Reduces load on application servers for static content +- **Cache revalidation**: Ensures fresh content while maintaining performance +- **Cache locking**: Prevents cache stampede scenarios + +**Buffer and Timeout Optimization**: + +- **proxy_buffers 256 16k**: Handles high-throughput data transfer efficiently +- **Optimized timeouts**: Balances responsiveness with resource usage +- **HTTP/1.1 keepalive**: Reduces connection overhead + +**Resource Limits**: + +- **50M client_max_body_size**: Accommodates large file uploads +- **Increased file descriptor limits**: Supports high-concurrency scenarios + +### Implementation notes + +1. **Replace IP addresses**: Update the backend server IPs (172.27.205.186, 172.27.213.167) with your actual Mattermost server addresses. + +2. **Create cache directory**: Ensure the cache directory exists and has proper permissions: + + ``` sh + sudo mkdir -p /var/cache/nginx + sudo chown -R www-data:www-data /var/cache/nginx + ``` + +3. **Test configuration**: Always test your configuration before applying: + + ``` sh + sudo nginx -t + ``` + +4. **Monitor performance**: Use NGINX access logs and monitoring tools to verify the performance improvements. + +5. **Scale incrementally**: Apply these optimizations gradually and monitor their impact on your specific deployment. + +## NGINX configuration FAQ + +### Why am I seeing the error "Too many redirects?" + +You may see this error if you're setting Mattermost in a sub-path. To resolve this error, add the following block to the HEAD request: + +``` text +location ~* ^/sub-path { + client_max_body_size 250M; + proxy_set_header Connection ""; + + if ($request_method = HEAD) { + return 200; + } +} +``` + +### Why are Websocket connections returning a 403 error? + +This is likely due to a failing cross-origin check. A check is applied for WebSocket code to see if the `Origin` header is the same as the host header. If it's not, a 403 error is returned. Open the file `/etc/nginx/sites-available/mattermost` as *root* in a text editor and make sure that the host header being set in the proxy is dynamic: + +``` text +location ~ /api/v[0-9]+/(users/)?websocket$ { + proxy_pass http://backend; + (...) + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; +} +``` + +Then in `config.json` set the `AllowCorsFrom` setting to match the domain being used by clients. You may need to add variations of the host name that clients may send. Your NGINX log will be helpful in diagnosing the problem. + +``` text +"EnableUserAccessTokens": false, +"AllowCorsFrom": "domain.com domain.com:443 im.domain.com", +"SessionLengthWebInDays": 30, +``` + +### How do I setup an NGINX proxy with the Mattermost Docker installation? + +1. Find the name of the Mattermost network and connect it to the NGINX proxy. + +``` sh +docker network ls +# Grep the name of your Mattermost network like "mymattermost_default". +docker network connect mymattermost_default nginx-proxy +``` + +2. Restart the Mattermost Docker containers. + +``` sh +docker-compose stop app +docker-compose start app +``` + + + +You don't need to run the 'web' container, since NGINX proxy accepts incoming requests. + + + +3. Update your `docker-compose.yml` file to include a new environment variable `VIRTUAL_HOST` and an `expose` directive. + +``` text +environment: + # set same as db credentials and dbname + - MM_USERNAME=mmuser + - MM_PASSWORD=mmuser-password + - MM_DBNAME=mattermost + - VIRTUAL_HOST=mymattermost.tld +expose: + - "80" + - "443" +``` + +### Why does NGINX fail when installing GitLab CE with Mattermost on Azure? + +You may need to update the Callback URLs for the Application entry of Mattermost inside your GitLab instance. + +1. Log in to your GitLab instance as the admin. +2. Go to **Admin \> Applications**. +3. Select **Edit** on GitLab-Mattermost. +4. Update the callback URLs to your new domain/URL. +5. Save the changes. +6. Update the external URL for GitLab and Mattermost in the `/etc/gitlab/gitlab.rb` configuration file. + +### Why does Certbot fail the http-01 challenge? + +``` text +Requesting a certificate for yourdomain.com +Performing the following challenges: +http-01 challenge for yourdomain.com +Waiting for verification... +Challenge failed for domain yourdomain.com +http-01 challenge for yourdomain.com +Cleaning up challenges +Some challenges have failed. +``` + +If you see the above errors this is typically because Certbot wasn't able to access port 80. This can be due to a firewall or other DNS configuration. Make sure that your A/AAAA records are pointing to this server and your `server_name` within the NGINX config doesn't have a redirect. + + + +If you're using Cloudflare you'll need to disable `force traffic to https`. + + + +#### Certbot rate limiting + +If you're running certbot as stand-alone you'll see this error: + +``` text +Error: Could not issue a Let's Encrypt SSL/TLS certificate for example.com. +One of the Let's Encrypt rate limits has been exceeded for example.com. +See the related Knowledge Base article for details. +Details +Invalid response from https://acme-v02.api.letsencrypt.org/acme/new-order. +Details: +Type: urn:ietf:params:acme:error:rateLimited +Status: 429 +Detail: Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/ +``` + +If you're running Let's Encrypt within Mattermost you'll see this error: + +``` json +{"level":"error","ts":1609092001.752515,"caller":"http/server.go:3088","msg":"http: TLS handshake error from ip:port: 429 urn:ietf:params:acme:error:rateLimited: Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/","source":"httpserver"} +``` + +This means that you've attempted to generate a cert too many times. You can find more information [here](https://letsencrypt.org/docs/rate-limits). diff --git a/docs/main/deployment-guide/server/setup-tls.mdx b/docs/main/deployment-guide/server/setup-tls.mdx new file mode 100644 index 000000000000..8a05a1de7e73 --- /dev/null +++ b/docs/main/deployment-guide/server/setup-tls.mdx @@ -0,0 +1,72 @@ +--- +title: "(Optional) Set up TLS" +--- +You have two options if you want users to connect with HTTPS: + +[Install a proxy such as NGINX](/deployment-guide/server/setup-nginx-proxy) and then [set up TLS on the proxy](#Use-TLS-on-NGINX-as-a-proxy). This is our recommended option if you have a large number of users (more than 200), or if you want to use a reverse proxy for other reasons, such as load balancing or caching. A proxy server delivers better performance and provides standard HTTP request logs. + +Alternatively, if you have fewer than 200 users, you can set up TLS on Mattermost server. This is the easiest option when you don't need to use a reverse proxy. + +> - You can use [Let's Encrypt](https://letsencrypt.org/) to automatically install and set up the certificate. +> - You can also specify your own certificate. +> - You can use a self-signed certificate, but this is not recommended for production environments. + +## Configure TLS on the Mattermost server + +1. In **System Console \> Environment \> Web Server**: + +> 1. Change the **Listen Address** setting to `:443`. +> 2. Change the **Connection Security** setting to `TLS`. +> 3. Change the **Forward port 80 to 443** setting to `true`. + +2. Activate the `CAP_NET_BIND_SERVICE` capability to allow Mattermost to bind to low ports: + + > ``` sh + > sudo setcap cap_net_bind_service=+ep /opt/mattermost/bin/mattermost + > ``` + +3. Install the security certificate. Use Let's Encrypt to automatically install and setup the certificate, or specify your own certificate. + +## Use a Let's Encrypt certificate + +The certificate is retrieved the first time that a client tries to connect to the Mattermost server. Certificates are retrieved for any hostname a client tries to reach the server at. + +1. Change the **Use Let's Encrypt** setting to `true`. +2. Restart the Mattermost server for these changes to take effect. + + + +- If Let's Encrypt is enabled, forward port 80 through a firewall, with [Forward80To443](/administration-guide/configure/environment-configuration-settings#forward-port-80-to-443) `config.json` setting set to `true` to complete the Let's Encrypt certification. +- Your Mattermost server must be accessible from the Let's Encrypt CA in order to verify your domain name and issue the certificate. Be sure to open your firewall and configure any reverse proxies to forward traffic to ports 80 and 443. More information can be found [at Let's Encrypt](https://letsencrypt.org/how-it-works/). + + + +## Use your own certificate + +1. Change the **Use Let's Encrypt** setting to `false`. +2. Change the **TLS Certificate File** setting to the location of the certificate file. +3. Change the **TLS Key File** setting to the location of the private key file. +4. Restart the Mattermost server for these changes to take effect. + + + +Password-protected certificates aren't supported. + + + +## Use TLS on NGINX (as a proxy) + + + +Do not set up TLS on Mattermost before doing so for NGINX. It breaks the connection as the TLS prevents it from successfully communicating with the Mattermost server. + + + +- NGINX will act as a forward proxy to encrypt the traffic between the client and Mattermost server. After installing the SSL certificate, the incoming traffic will be handled via NGINX on port 443 exposed to the internet, proxy to the Mattermost server running on port 80. +- (Optional) Upstream encryption between NGINX to Mattermost server is allowed. +- Follow [NGINX's guide on setting up SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/). + +More helpful resources: + +- [NGINX's SSL blog](https://www.f5.com/company/blog/nginx/nginx-ssl/) +- [NGINX's SSL guide](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/) diff --git a/docs/main/deployment-guide/server/trouble-postgres.mdx b/docs/main/deployment-guide/server/trouble-postgres.mdx new file mode 100644 index 000000000000..88301cafd115 --- /dev/null +++ b/docs/main/deployment-guide/server/trouble-postgres.mdx @@ -0,0 +1,24 @@ +--- +title: "PostgreSQL installation troubleshooting" +--- +From Mattermost v8.0, [PostgreSQL](/deployment-guide/software-hardware-requirements#database-software) is our database of choice for Mattermost to enhance the platform’s performance and capabilities. + +PostgreSQL v15 introduces changes that may affect compatibility with previous releases. If you're deploying a fresh installation of PostgreSQL v15, run this command: `GRANT CREATE ON SCHEMA public TO PUBLIC` to ensure that you can use Mattermost. + +## PostgreSQL full-text search fails to use indexes with non-English `default_text_search_config` + +Mattermost uses `default_text_search_config` for full-text search in PostgreSQL databases, as opposed to a hardcoded text search config. However, indexes are still created with a hardcoded text search config (english) and as a result, full-text search may never use the indexes. + +Some of the tables in Mattermost, like `Posts` or `Users`, contain GIN indexes to improve the database full-text search feature in PostgreSQL. + +These indexes need to be built against a specific language, and when they're created they're hard-coded to English. Full-text search queries are always performed using the `default_text_search_config` database setting. In order for the full-text search feature to leverage the indexes, the language specified in the query needs to match the language specified in the index. + +If the `default_text_search_config` is not set to `english`, the GIN indexes will not be used. Database administrators can work around this by dropping the specific GIN index they're interested in and rebuilding it with the value of `default_text_search_config`. + +For example, if the default language of your server is Spanish: + +`` `sql # Create the new index with a new name before dropping the old one CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_posts_message_txt_spanish ON posts USING gin(to_tsvector('spanish', message)); # Check that the new index does work. If it does, drop the old one and rename the new one: DROP INDEX CONCURRENTLY IF EXISTS idx_posts_message_txt; ALTER INDEX idx_posts_message_txt_spanish RENAME TO idx_posts_message_txt; ``\` + +## Change the PostgreSQL username and password + +We recommend changing the PostgreSQL username and password in the `.env` file. diff --git a/docs/main/deployment-guide/server/trouble_mysql.mdx b/docs/main/deployment-guide/server/trouble_mysql.mdx new file mode 100644 index 000000000000..e870f8213aca --- /dev/null +++ b/docs/main/deployment-guide/server/trouble_mysql.mdx @@ -0,0 +1,214 @@ +--- +title: "MySQL installation troubleshooting" +--- + + +- From Mattermost v11, Mattermost completely stops support MySQL as a database driver. MySQL support has been completely removed from the codebase, and the product will throw an invalid configuration error. +- PostgreSQL is our preferred database of choice. See the [database software](/deployment-guide/software-hardware-requirements#database-software) documentation for details on database version support, and see the [Migrate from MySQL to PostgreSQL](/deployment-guide/postgres-migration) documentation for details on migrating from MySQL to PostgreSQL. + + + +Before you can run the Mattermost server, you must first install and configure a database. You can start Mattermost by navigating to the `/opt/mattermost` directory and entering the command `sudo -u mattermost bin/mattermost`. If the Mattermost server can't connect to the database, it will fail to start. This section deals with MySQL database issues that you may encounter when you start up Mattermost for the first time. + + + +- Additional database tuning guidance is available for specific Mattermost releases. See the [important upgrade notes](/administration-guide/upgrade/important-upgrade-notes) documentation for more details. +- See the [database configuration settings](/administration-guide/configure/environment-configuration-settings#database) documentation for details on configuration options specific to MySQL databases. + + + +How you install MySQL varies depending upon which Linux distribution you use. However, once MySQL is installed, the configuration instructions are the same. For all distributions you must create a `mattermost` database and a `mattermost` database user. Failure to create these database objects or improperly referencing them from the Mattermost configuration file, `/opt/mattermost/config/config.json`, causes Mattermost to fail. The troubleshooting tips given here deal with these specific issues. + +Before proceeding, confirm that your MySQL server is running. You can do this by issuing the command `mysqladmin -u root -p status`. When prompted, enter your password. If MySQL is running you should see output like the following: + +> Uptime: 877134 Threads: 1 Questions: 9902 Slow queries: 0 Opens: 522 +> Flush tables: 1 Open tables: 371 Queries per second avg: 0.011 + +If MySQL is not running, review the instructions for installation on your distribution. + + + +Some of the commands used in this section alter the database. **Use these commands only if your Mattermost installation has failed.** Do not directly manipulate the MySQL database for a working Mattermost installation. + + + +## The `mattermost` database + +The database created during installation is named `mattermost`. If you fail to create this database or you misname it, you will see an error such as the following when you attempt to start the Mattermost server: + +> [2017/09/20 17:11:37 EDT] [INFO] Pinging SQL master database +> [2017/09/20 17:11:37 EDT] [ERROR] Failed to ping DB retrying in 10 seconds +> err-Error 1044: Access denied for user 'mmuser'@'%' to database 'mattermost' + +Note that MySQL is specifically denying access to the `mattermost` database. This may mean that you have failed to create a database named `mattermost` or you may have incorrectly referenced this database from the `/opt/mattermost/config/config.json` file. + +**Checking that the Database Exists** + +To confirm that the `mattermost` database exists, open MySQL as *root* by executing `mysql -u root -p`. When prompted, enter your password and then issue the command `show databases;`. This command displays all the databases. You should see something similar to the following: + +> +--------------------+ +> | Database | +> +--------------------+ +> | information_schema | +> | mattermost | +> | mysql | +> | performance_schema | +> | sys | +> +--------------------+ +> 5 rows in set (0.03 sec) + +**No mattermost Database** + +If the `mattermost` database doesn't exist, create a database named `mattermost` by opening MySQL as root and issuing the command: `create database mattermost;`. + +If you accidentally created a database with the wrong name, you can remove it by issuing the command: `drop database {misnamed};`. + +After creating the database, attempt to restart the Mattermost server by navigating to the `/opt/mattermost` directory and entering the command `sudo -u mattermost bin/mattermost`. + +**The mattermost Database Exists** + +If the `mattermost` database does exist, confirm that you have defined the database driver correctly in the `/opt/mattermost/config/config.json` file. Open this file in a text editor, and review the value of `"DataSource"`. It should be: + +> "mmuser:*mmuser-password*@tcp(*host-name-or-IP*:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s" + +You should also confirm that `DriverName` element (found immediately above the `DataSource` element) is set to `mysql`. + +If you correct an error, restart the Mattermost server by navigating to the `/opt/mattermost` directory and entering the command `sudo -u mattermost bin/mattermost`. + +## The Database User + +During the installation you should create a MySQL database user from the *mysql* prompt by issuing the command + +samp +create user 'mmuser'@'%' identified by '{mmuser-password}';. + +The `mmuser-password` value is a placeholder for the password you chose. You may also have specified an IP address rather than the wild card `%`. + + + +A MySQL user is fully defined by their username and the host that they access MySQL from. These elements are separated by the `@` sign. The `%` character is a wild card indicating that the user can access MySQL from any IP address. If the user you created accesses MySQL from a specific IP address such as `10.10.10.2`, please adjust your actions accordingly. + + + +If the user and host combination that you created does not exist, you will see an error such as: + +> [2017/09/20 17:06:18 EDT] [INFO] Pinging SQL master database +> [2017/09/20 17:06:18 EDT] [ERROR] Failed to ping DB retrying in 10 seconds +> err-Error 1045: Access denied for user 'mmuser'@'localhost' (using password: YES) + +**Checking that mmuser Exists** + +To check that this user exists, log in to MySQL as *root*: `mysql -u root -p`. + +When prompted, enter the root password that you created when installing MySQL. From the `mysql` prompt enter the command `select User, Host from mysql.user;`. You should see something like the following: + +> +------------------+-----------+ +> | User | Host | +> +------------------+-----------+ +> | mmuser | % | +> | debian-sys-maint | localhost | +> | mysql.session | localhost | +> | mysql.sys | localhost | +> | root | localhost | +> +------------------+-----------+ +> 5 rows in set (0.00 sec) + +**User Doesn't Exist** + +If `'mmuser'@'%'` does not exist, create this user by logging into MySQL as *root* and issuing the command: + +samp +create user 'mmuser'@'%' identified by '{mmuser-password}';. + +After creating a user, ensure that this user has rights to the `mattermost` database. + +**User Exists** + +If the user `mmuser` exists, the DataSource element of the `/opt/mattermost/config/config.json` file may be incorrect. Open this file and search for `DataSource`. Its value should be: + +> "mmuser:*mmuser-password*@tcp(*host-name-or-IP*:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s" + +If you correct an error, restart the Mattermost server by navigating to the `/opt/mattermost` directory and issuing the command: `sudo -u mattermost bin/mattermost`. + +## The user password + +Mattermost will fail if you use an incorrect password for `mmuser`. An incorrect password displays an error message such as the following: + +> [2017/09/20 17:09:10 EDT] [INFO] Pinging SQL master database +> [2017/09/20 17:09:10 EDT] [ERROR] Failed to ping DB retrying in 10 seconds +> err-Error 1045: Access denied for user 'mmuser'@'localhost' (using password: YES) + +**The password in \`\`config.json\`\`** + +The DataSource element of the `/opt/mattermost/config/config.json` file references the `mmuser` password. Open this file and search for `DataSource`. It's value should be: + +> "mmuser:*mmuser-password*@tcp(*host-name-or-IP*:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s" + +Check that the password is correct. If you correct an error, restart the Mattermost server by navigating to `/opt/mattermost` and issuing the command: `sudo -u mattermost bin/mattermost`. + +**Unsure of Password** + +If you are not sure that the `mmuser` password is correct, attempt to log in to MySQL as `mmuser` by issuing the command `mysql -u mmuser -p`. You will be prompted for your password. If your login fails, you are not using the correct password. + +With a new database installation, the easiest solution for an unknown password is to remove the existing `mmuser` and then recreating that user. You can do this by logging in to MySQL as `root` and issuing the following commands: + +- `drop user mmuser;` + +- `flush privileges;` + +- samp + create user 'mmuser'@'%' identified by '{mmuser-password}'; + +If you recreate `mmuser`, ensure that this user has rights to the `mattermost` database by following the instructions in the [granting privileges to mmuser](#granting-privileges-to-mmuser) section below. + +## Insufficient user privileges + +If the database exists and the username and password are correct, the `mmuser` may not have sufficient rights to access the `mattermost` database. If this is the case, you may see an error message such as: + +> [2017/09/20 17:20:53 EDT] [INFO] Pinging SQL master database +> [2017/09/20 17:20:53 EDT] [ERROR] Failed to ping DB retrying in 10 seconds +> err-Error 1044: Access denied for user 'mmuser'@'%' to database 'mattermost + + + +Examine the error message closely. The user name displayed in the error message is the user identified in the `DataSource` element of the `/opt/mattermost/config/config.json` file. For example, if the error message reads `Access denied for user 'muser'@'%' ...`, you will know that you have misidentified the user as `muser` in the `config.json` file. + + + +You can check if the user `mmuser` has access to the `mattermost` database by logging in to MySQL as `mmuser` and issuing the command: `show databases;`. If this user does not have rights to view the `mattermost` database, you will not see it in the output. + +> +--------------------+ +> | Database | +> +--------------------+ +> | information_schema | +> +--------------------+ +> 1 rows in set (0.00 sec) + +
+ +**Granting privileges to mmuser** + +
+ +If the `mattermost` database exists and `mmuser` cannot view it, exit from MySQL and then log in again as root. Issue the command `grant all privileges on mattermost.* to 'mmuser'@'%';` to grant all rights on `mattermost` to `mmuser`. + +Restart the Mattermost server by navigating to the `/opt/mattermost` directory and entering the command `sudo -u mattermost bin/mattermost`. + +## Server is set to SYSTEM timezone + +Mattermost customers using v7.7 or earlier may see an errors occur on servers using MySQL in cases where the server is set to SYSTEM timezone and doesn’t support named timezones. These errors can be fixed by populating the `timezone` tables on the server. Refer to the following docs for more information on loading the timezone table: + +- [Linux](https://dev.mysql.com/doc/refman/5.7/en/mysql-tzinfo-to-sql.html) +- [Windows](https://dev.mysql.com/downloads/timezones.html) + + + +This issue has been addressed from Mattermost v7.8. + + + +## Maximum allowed packet + +The Go MySQL driver has changed the `maxAllowedPacket` size from 4MiB to 64MiB. This is to make it consistent with the change in the server-side default value from MySQL 5.7 to MySQL 8.0. + +If your `max_allowed_packet` setting is not 64MiB, update the MySQL configuration DSN with an additional parameter of `maxAllowedPacket` to match with the server-side value. Alternatively, set a value of `0` to fetch the server-side value automatically on every new connection which has a performance overhead. diff --git a/docs/main/deployment-guide/server/troubleshooting.mdx b/docs/main/deployment-guide/server/troubleshooting.mdx new file mode 100644 index 000000000000..cff80b14aa3d --- /dev/null +++ b/docs/main/deployment-guide/server/troubleshooting.mdx @@ -0,0 +1,415 @@ +--- +title: "General deployment troubleshooting" +--- +This document summarizes common deployment troubleshooting issues and resolutions. Some of these suggestions can be done directly, and others may need consultation from your network administrator. + +## Start Mattermost at system boot + +To have the Mattermost Server start at system boot, the systemd unit file needs to be enabled. Run the following command: + +``` sh +sudo systemctl enable mattermost.service +``` + +If your database is on the same system as your Mattermost Server, we recommend editing the default `/lib/systemd/system/mattermost.service` systemd unit file to add `After=postgresql.service` and `BindsTo=postgresql.service` to the `[Unit]` section. + +## Run Mattermost without a proxy + +Mattermost binds to 443 instead of 8065. The Mattermost binary requires the correct permissions to do that binding. You must activate the `CAP_NET_BIND_SERVICE` capability to allow the new Mattermost binary to bind to ports lower than 1024 by running the following command: + +``` sh +sudo setcap cap_net_bind_service=+ep ./mattermost/bin/mattermost +``` + + + +We highly recommend using a proxy in front of Mattermost server for up to 200 concurrent users. If you have fewer than 200 concurrent users, you can [set up TLS](/deployment-guide/server/setup-tls). If you're exceeding 200 concurrent users, you'll need [a proxy](/deployment-guide/server/setup-nginx-proxy), such as NGINX, in front of Mattermost to manage the traffic. + + + +## Review Mattermost logs + +You can access logs for Mattermost and use them for troubleshooting. These steps assume that you have appropriate [system admin permissions](/administration-guide/onboard/advanced-permissions) to do so. + +### Mattermost Server logs + +- Ensure that log files are being created: Navigate to **System Console \> Environment \> Logging**, confirm that **Output logs to file** is set to **true**. +- You can obtain the path for the log files in **System Console \> Environment \> Logging \> File Log Directory**. + +The resulting server log file is called `mattermost.log` and can be opened with a standard text editor or shared directly. + + + +For a more complete log open **System Console \> Environment \> Logging**, set **File Log Level** to **DEBUG**, then replicate the issue to log it again. Make sure to revert the file log level to **INFO** after troubleshooting to save disk space. + + + +If filesystem access is not possible, navigate to **System Console \> Reporting \> Server Logs** to locate the current system logs which can be copied to a file. + +You can find more on logging settings [here](/administration-guide/configure/environment-configuration-settings#logging). + +#### Log files not accessible + +From Mattermost v11.4, log file paths are validated to ensure they remain within a designated logging root directory. + +1. If log files aren't appearing in **System Console \> Reporting \> Server Logs** or support packets, check error messages in server console to see if the log file path is outside the allowed directory: `"Blocked attempt to read log file outside allowed root"` Log file paths outside the directory specified by the `MM_LOG_PATH` environment variable generate errors and are excluded from support packet downloads. If `MM_LOG_PATH` is not set, the default `logs` directory is used. + + The error message will identify which configuration setting has an invalid path: + + - `LogSettings.FileLocation` - main server log file + - `LogSettings.AdvancedLoggingJSON` - advanced logging file targets + - `ExperimentalAuditSettings.AdvancedLoggingJSON` - audit logging file targets + +2. Choose one of these solutions: + + **Option A - Use default logging directory**: + + - Update your configuration to use the default `logs` directory + - Remove or update the `MM_LOG_PATH` environment variable + - Restart Mattermost server + + **Option B - Configure logging root to match your log paths**: + + - Set the `MM_LOG_PATH` environment variable to a directory that contains all your log files + - Ensure all configured log file paths are within this root directory + - Restart Mattermost server + +3. Verify logs are accessible: + + - Navigate to **System Console \> Reporting \> Server Logs** + - Confirm log entries are visible + - Generate a test support packet to verify logs are included + +See the [log path restrictions](/administration-guide/manage/logging#log-path-restrictions) documentation for detailed configuration examples. + +### Mattermost Desktop App logs + +Access desktop app logs by going to **Help \> Show logs** from the menu bar. + +Alternatively, you can access desktop app log files in the following directory: + +- **Windows:** `%userprofile%\AppData\Roaming\Mattermost\logs` +- **Linux:** `~/.local/share/Mattermost/logs` OR `~/.config/Mattermost/logs` +- **MacOS:** `~/Library/Logs/Mattermost` (DMG installation) OR `~Library/Containers/Mattermost.Desktop/Data/Library/Logs/Mattermost` (Appstore installation only) + +### Mattermost web logs + +The browser-based app does not produce additional log files. If the app has to be debugged, use the development tools integrated in your browser for action history. + +### Mattermost Push Notification Service logs + +Logging for the Mattermost Push Notification Service is handled via system log with logger and is appended to `/var/log/syslog`. + +## Review Mattermost environment + +Put together a timeline to eliminate events prior to the error/problem occurring. For example, if you recently reconfigured your firewall and are now having connection issues it might be worth reviewing the settings or rolling back to see whether that resolves the problem. + +- If the problem occurred subsequent to some period of normal operation, did anything change in the environment? + + > - Was the client, host, or server upgraded? + > - Was an operating system update applied? + > - Did the network environment change? For example, was a server moved or a domain migrated? + > - Did the system (client or server) recently fail or abnormally terminate? + +- How many users are impacted? + + > - Is this problem affecting one, some, or all users? + > - Is the problem occurring only for a user who was recently added to the environment, such as a new employee? + > - Do differences exist between the users who are affected and the users who are not affected? + +You can also search the error messages online. Existing solutions from our [forum](https://forum.mattermost.com/t/how-to-use-the-troubleshooting-forum/150) can often be found and applied. + +## Connect to another server + +1. Create an account at [https://community.mattermost.com](https://community.mattermost.com). +2. Erase your mobile application and reinstall it. +3. In your mobile app, enter the server URL [https://community.mattermost.com](https://community.mattermost.com) and then your login credentials to test whether the connection is working. + +## Connect with another device + +- If you have another mobile device available, try connecting with that to see if your issue still reproduces. +- If you don’t have another device available, check with other teammates to see if they are having the same issue. + +## Opening a support ticket for self-hosted deployments + +If you have a [paid subscription to a Mattermost offering](/product-overview/editions-and-offerings), such as Mattermost Professional or Mattermost Enterprise, you're entitled to open support tickets via our [online support portal](https://support.mattermost.com/hc/en-us/requests/new). + +When opening a Support ticket as part of your paid subscription, it's important that you provide us with as much information as you can in a timely manner. Knowing what information is relevant can be confusing. We use the anagram C.L.U.E.S. to remember what we need: + +- Configurations +- Logs +- Users affected +- Environment +- Steps to reproduce + +C.L.U.E.S. represents all of the information that can clarify your issue. With these details, we can begin searching for a cause, whether it's a simple configuration change or a product bug. It also helps us when we need to escalate the issue to our developers so they can spend as much time as possible improving our product. + +### General guidelines for information + +Follow these guidelines when providing diagnostic data to us: + +- Make sure the files you provide are as complete as possible, rather than providing a few lines. Entire log files and configurations provide us with important context. +- Provide configuration and log files in plaintext format if possible, as these are far easier for us to search than screenshots. +- Be sure to sanitize configuration and log files to remove usernames, passwords, and LDAP groups. Replace these details with example strings that contain the same special characters if possible, as special characters are common causes of configuration errors. +- Provide screenshots or screen recordings of unexpected product behavior so that we know exactly what your users are seeing. + +### Configuration + +#### Why we need your configuration data + +On Linux systems, settings are generally stored in configuration files. Many issues can be resolved by enabling or disabling a configuration setting. In order to find a resolution, we need to have as complete a picture of your system setup as possible. This also helps us to reproduce bugs so our developers can fix them. + +#### What configuration data includes + +Configuration includes (but is not limited to): + +- The Mattermost `config.json` file. +- The configuration for the reverse proxy, e.g. NGINX, HAProxy, AWS. +- The database configuration. +- SAML configuration when the issue is regarding SAML authentication. The configuration for the Mattermost service is in the SAML IdP. +- Any other systems that Mattermost connects to or systems that exist between the user and the Mattermost server. + +#### How to access your configuration data + +**Mattermost configuration** + +The Mattermost configuration is usually stored at `/opt/mattermost/config/config.json`. If you've migrated the Mattermost configuration to the database, you can get the configuration using `mmctl` or by running this database query: + +``` SQL +SELECT Value FROM Configurations WHERE Active = 1; +``` + +**Reverse Proxy configuration** + +NGINX usually splits its configuration into two parts: the main server configuration at `/etc/nginx/nginx.conf`, and a virtual server configuration. On Ubuntu, this is stored in `/etc/nginx/sites-available`. Providing both of these configuration files is helpful, but providing the latter is more important. + +**SAML configuration** + +If the issue you're seeing is with SAML login, we will need to see the full configuration for the Mattermost service in the SAML provider. The configuration for the Mattermost service is in the SAML IdP. Providing screenshots similar to the ones in the setup documentation is sufficient because most SAML providers are configured using a web interface. + +**LDAP configuration** + +The LDAP administrator should confirm the correct values for the following Mattermost LDAP settings: + +- LDAP server hostname. +- LDAP connection port, security, and certificates. +- BaseDN, bind username, and bind password. +- User, Group, Guest, and Admin filters. +- Display attributes. + +These can be provided as a text file or as screenshots from the LDAP server. + +**Other configurations** + +If you're experiencing an issue on mobile, and you're using an MDM or VPN to connect to the server, those configurations will be necessary to diagnose the problem. A system admin for the external system should be able to provide you with the configuration. + +### Logs + +#### Why we need them + +Nearly all computer systems have logs of errors and application behavior that can show us what's happening when an application is running. Error logs are invaluable when diagnosing a problem, but only if they're as complete as possible. + +#### What logs are available + +**Mattermost** + +Mattermost has two log files, one for general messages and the other for notification-related messages. These are found at: + +- `/opt/mattermost/logs/mattermost.log` +- `/opt/mattermost/logs/notification.log` + +**Proxy** + +The location of these depend on your proxy configuration, but a good place to start looking is in `/var/log`. Your proxy administrator should be able to help you find the logs. + +**Database** + +PostgreSQL and MySQL have different logs, and their location varies based on your configuration. If the issue is related to database connectivity, check the database documentation to locate the logs. + +**SAML, LDAP, and other systems** + +Your organization's system admin should be able to find these for you. + +#### How to access logs + +**Mattermost** + +Make sure [debug logging is enabled](/administration-guide/manage/logging#how-do-i-enable-debug-logging) so that we can get the most information from the logs. To do this, go to **System Console \> Environment \> Logging**, then set both **Console File Level** and **File Log Level** to **DEBUG**. Remember to save your changes. + +If the behavior started at a known time or date, use `journalctl` to get the logs like this: + +``` sh +sudo journalctl -u mattermost --since "2020-08-23 17:15:00" > mattermost_journalctl.log +``` + +Replace 2020-08-23 17:15:00 with the date and time (relative to the server) when the behavior started. To get the server time, use the `date` command. If the log files generated are too large to send, compress them with this command: + +``` sh +tar -czf /tmp/mattermost.log.tgz +``` + +The compressed logs will be located on the server at `/tmp/mattermost.log.tgz`. + +If the compressed file is still too big, use these commands to split the compressed file into two or more 20MB files: + +``` sh +mkdir -p /tmp/mattermost-logs +cd /tmp/mattermost-logs +tar czf - /opt/mattermost/logs/mattermost.log | split -b 20m - mattermost.log.tgz. +``` + +The compressed files will be located on the server at `/tmp/mattermost-logs` and be named `mattermost.log.tgz.aa`, `mattermost.log.tgz.ab`, and so on. Use a file transfer client that supports SSH/SFTP, such as Cyberduck, to copy these files from the server. + +If you are experiencing issues with Elasticsearch, LDAP, or the database, you can enable trace logging in `config.json` by setting `Trace` to `true` under their respective settings. Combining this with `DEBUG` level file log output will result in huge log files, so only leave trace logging on long enough to replicate the behavior. The resulting logs will also contain a lot more sensitive data, including user data, so be sure to sanitize it completely before sharing it with us. + +**System logs** + +The location of log files for other systems varies, but a good way to get the logs for all processes on the Mattermost server is to use `journalctl` like this: + +``` sh +sudo journalctl --since "2020-08-23 17:15:00" > mattermost_journalctl.log +``` + +Replace 2020-08-23 17:15:00\` with the date and time (relative to the server) when the error occurred. You can use `--until` with the same timestamp format to get the logs between two times: + +``` sh +sudo journalctl --since "2020-08-23 17:15:00" --until "2020-08-23 16:30:00" > mattermost_journalctl.log +``` + +### Users affected + +#### Why we need it + +Mattermost servers are chaotic places. Thousands of posts, websocket actions, and webhook calls happen every second while users can be in dozens of channels across multiple teams. Knowing which users are affected by a problem can help us sift through all this information to find the root cause. + +#### What information to include + +This should be a detailed explanation of anything the end users who are reporting the unexpected behavior have in common. This includes (but is not limited to): + +- Team and Channel memberships, including Direct and Group Messages. +- Authentication methods. +- Client operating system and app versions. +- How users connect to the Mattermost server. +- Any other things these users have in common such as when they joined, whether their login information recently changed, or if they are being synchronized via LDAP. + +Note for Agents: This information is also required: + +- Customer name +- Customer contacts +- Customer license, e.g. Enterprise/Professional +- Customer tier + +### Environment + +Where the Mattermost server sits in your architecture has a lot of impact on potential issues. For example, a misconfigured proxy server can prevent users from connecting even if there's nothing wrong with Mattermost. + +#### What information to include + +Because of this, having a complete picture of the servers and network that the Mattermost server operates in is key to solving problems. This includes (but is not limited to): + +- Mattermost version (e.g. 7.3.0, 7.8.3) +- Server OS and version (e.g. RHEL7, Ubuntu 20.04) +- Any orchestration/automation used like Docker or Kubernetes +- Reverse proxy and version (e.g. NGINX 1.16) +- Database type and version (e.g. PostgreSQL 14) +- SAML provider (e.g. Windows Server 2012 Active Directory, Okta, KeyCloak) +- LDAP provider (e.g. Windows Server 2016 Active Directory, Okta, OpenLDAP) +- The type and version of any proxies or VPNs on the network that the Mattermost server is connecting through + +Be as specific as possible when describing the environment. If you are seeing errors like **Connection Refused** be sure to include any firewalls or filtering proxies that may be on your network, either inbound or outbound. + +**Examples** + +Mattermost server + +> - External hostname: mattermost.example.com +> - Internal hostname: mattermost.lan +> - Mattermost v7.3.0 +> - Zoom plugin v1.4.1 +> - NGINX v1.18.0 + +Database server + +> - Internal hostname: postgresql.lan +> - PostgreSQL v13 +> - LDAP Provider - 192.168.1.102 +> - Internal hostname: ldap.lan +> - OpenLDAP 2.4.54 (Docker container) + +Mattermost servers + +> - Hostnames: mm1.local.lan, mm2.local.lan, mm3.local.lan, mm4.local.lan + +Mattermost server versions + +> - mm1-3: 5.25.4 +> - mm4: 5.21.0 + +Proxy server + +> - External hostname: mattermost.example.com +> - Internal hostname: proxy.local.lan +> - NGINX v1.16.0 + +Database servers + +> - Hostnames: db1.local.lan, db2.local.lan, db3.local.lan +> - Primary: db1.local.lan +> - Read-Only: db2.local.lan, db3.local.lan +> - PostgreSQL v13 + +Elasticsearch server + +> - Hostname: elastic.local.lan +> - Elasticsearch v7.9 with these plugins +> - analysis-icu + +### Steps to reproduce + +#### What it is + +If the behavior only happens when the user performs a specific action, providing detailed steps to reproduce it will help us make sure we find and fix the right bug. These details should be as descriptive as possible, but nothing is better than a screenshot or a screen recording of the behavior. + +A short summary of the steps to reproduce is also helpful. If you want some examples, look at the bug tickets on some Mattermost Jira tickets. + +#### How to provide these details + +**macOS** + +Press 5 to open the screen recording tool and select the region of the screen you want to record. To take a screenshot, press 4 and select the region to take a screenshot. The screenshot files are placed on the desktop by default. + +**Windows** + +Press Ctrl Shift S to open the snipping tool to take a screenshot. If you want to take a screen recording you'll need to install third-party software such as [OBS](https://obsproject.com/). + +**iOS** + +Take a screenshot or screen recording [on iPhone](https://support.apple.com/guide/iphone/take-a-screenshot-iphc872c0115/ios). + +**Android** + +Take a screenshot or record your screen on your [Android device](https://support.google.com/android/answer/9075928?hl=en). + +## Appendix + +**A note on mobile issues** + +Because the mobile app doesn't have a debug mode, diagnosing issues stemming from user data requires a proxy like Charles or mitmproxy. These will intercept and record traffic from the client which can then be replayed to reproduce issues. Talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) for help setting these up. + +**SAML login issues** + +If the issue is with SAML login, one important piece of context is the SAML login flow. This contains headers and authentication information that can reveal issues that are easy to fix. Follow these instructions to view the SAML login flow if you are experiencing SAML authentication. + +### Checking keys and certificates + +Key and certificate files should never be shared, but if the error indicates a problem with the format of a key or certificate, then you should verify the format of the keys and certificates by running this command: + +``` sh +cat -A /path/to/key-or.cert +``` + +The output must meet these criteria exactly to be valid: + +- Start with `-----BEGIN CERTIFICATE-----$`. +- All lines must end with `$`. If they end with `^M$` then convert them to UNIX line endings with `dos2unix`. +- End with `-----END CERTIFICATE-----$`. diff --git a/docs/main/deployment-guide/software-hardware-requirements.mdx b/docs/main/deployment-guide/software-hardware-requirements.mdx new file mode 100644 index 000000000000..6018c54c2389 --- /dev/null +++ b/docs/main/deployment-guide/software-hardware-requirements.mdx @@ -0,0 +1,317 @@ +--- +title: "Software and hardware requirements" +sidebar_label: "Software & hardware requirements" +--- +This guide outlines minimum software and hardware requirements for deploying Mattermost. Requirements may vary based on utilization and observing performance of pilot projects is recommended prior to scale out. + +## Deployment overview + +Please see the [Application architecture](/deployment-guide/reference-architecture/application-architecture) documentation for a summary of software systems and components whose requirements are described in this document. + +## Software requirements + +### Client software + +#### Desktop apps + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operating SystemSelf-Hosted Technical RequirementCloud Technical Requirement
WindowsWindows 11+Windows 11+
MacmacOS 14+macOS 14+
LinuxUbuntu LTS releases 22.04 or laterUbuntu LTS releases 22.04 or later
+ +Though not officially supported, the Linux desktop app also runs on RHEL/CentOS 7+. + +##### Flatpak package requirements (Linux) + +From Mattermost Desktop v6.1, Flatpak packages are available for Linux (currently in beta). The Flatpak version requires: + +- Flatpak runtime installed on the system +- Freedesktop Platform/SDK 25.08 +- Electron BaseApp 25.08 +- Access to Flathub or compatible Flatpak repository for dependencies + +Flatpak packages are available for x86_64 (Intel/AMD) and aarch64 (ARM) architectures. The Flatpak version includes Wayland display server support enabled by default. + + + +- \* Integrated Windows Authentication is not supported by Mattermost desktop apps. If you use ADFS we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). +- From Windows Desktop v6.1.0, the MSI installer installs per-machine (system-wide) by default and requires administrator privileges for installation. This meets enterprise compliance requirements. +- The minimum content size is 800 x 600 pixels. + + + +#### PC web + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BrowserSelf-Hosted Technical RequirementCloud Technical Requirement
Chromev144+v144+
Firefoxv140+v140+
Safariv26.2+v26.2+
Edgev144+v144+
+ +\* Internet Explorer (IE11) is no longer supported. We recommend using the [Mattermost desktop app](https://mattermost.com/apps/) or another supported browser. See [this forum post](https://forum.mattermost.com/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575) to learn more. + +#### Mobile apps + + + + + + + + + + + + + + + + + + +
Operating SystemTechnical Requirement
iOSiPhone 8+ devices and later with iOS 16.0+
AndroidAndroid devices with Android 7+
+ + + +- \* Integrated Windows Authentication is not supported by Mattermost mobile apps. If you use ADFS we recommend [configuring intranet forms-based authentication for devices that do not support WIA](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-intranet-forms-based-authentication-for-devices-that-do-not-support-wia). +- The minimum and target content size is 320 x 460 pixels, matching the available space when the mobile app is opened in Safari on the minimum supported iOS device. +- The Mattermost mobile app for Android isn't supported on Chromebooks. Access Mattermost using the Chrome web browser, or install the web app as a Progressive Web App (PWA) directly from the browser for an app-like experience with a desktop icon and windowed view. + + + +#### Mobile web + + + + + + + + + + + + + + + + + + +
BrowserTechnical Requirement
iOSiOS 16.0+ with Safari 26.2+ or Chrome 144+
AndroidAndroid 7+ with Chrome 144+
+ +#### Email client + +- *Desktop clients:* Outlook 2010+, Apple Mail version 7+, Thunderbird 38.2+ +- *Web based clients:* Entra ID, Outlook, Gmail, Yahoo, AOL +- *Mobile clients:* iOS Mail App (iOS 7+), Gmail Mobile App (Android, iOS) + +### Server software + +#### Mattermost server operating system + +- Ubuntu, Debian Buster, CentOS 6+, CentOS 7+, RedHat Enterprise Linux 7+, Oracle Linux 6+, Oracle Linux 7+. +- Using the Mattermost [Docker deployment](https://github.com/mattermost/docker) on a Docker-compatible operating system (Linux-based OS) is still recommended. + +While community support exists for Fedora, FreeBSD, and Arch Linux, Mattermost does not currently include production support for these platforms. + +#### Database software + +- PostgreSQL 14.0+ + +Amazon Aurora equivalents of PostgreSQL is also supported. Our [Migration Guide](https://docs.mattermost.com/deployment-guide/postgres-migration.html) outlines the steps, tools and support available for migrating from MySQL to PostgreSQL. + + + +- MariaDB v10+ no longer functions as a MySQL drop-in replacement, and it's not supported for Mattermost due to the requirement of MySQL 5.7.12. Prior versions of MariaDB were not officially supported but may have functioned in older Mattermost releases. If you are running MariaDB now, migrating from MariaDB to the MySQL equivalent is recommended. +- MySQL deployments requiring searching in Chinese, Japanese, and Korean languages require the configuration of [ngram Full-Text parser](https://dev.mysql.com/doc/refman/8.4/en/fulltext-search-ngram.html). For searching two characters, you will also need to set `ft_min_word_len` and `innodb_ft_min_token_size` to `2` and restart MySQL. See [CJK discussion](https://github.com/mattermost/mattermost/issues/2033#issuecomment-183872616) for details. + + + +##### Minimum PostgreSQL database support policy + +To make planning easier and ensure your Mattermost deployment remains fast and secure, we are introducing a policy for updating the minimum supported version of PostgreSQL. The oldest supported PostgreSQL version Mattermost supports will match the oldest version supported by the PostgreSQL community. This ensures you benefit from the latest features and security updates. + +This policy change takes effect from Mattermost v10.6, where the minimum PostgreSQL version required will be PostgreSQL 13. This aligns with the PostgreSQL community's support policy, which provides 5 years of support for each major version. + + + +Mattermost v10.6 is not an [Extended Support Release (ESR)](/product-overview/release-policy#extended-support-releases). Going forward, this database version support policy will only apply to ESR releases. + + + +When a PostgreSQL version reaches its end of life (EOL), Mattermost will require a newer version starting with the next scheduled ESR release. This means the following future PostgreSQL minimum version increases as follows: + + ++++++ + + + + + + + + + + + + + + + + + + + + +
+

Mattermost Version | Release Date | Minimum PostgreSQL Version |

+
+
+
============================================================+==================+================================+
+
+

v9.11 ESR | 2024-8-15 | 11.x

+
+
v10.5 ESR | 2025-2-15 | 11.x
v10.6 | 2025-3-15 | 13.x
v10.11 ESR| 2025-8-15 | 13.x
v11.7 ESR *2026-5-1514.x (EOL 2026-11-12)
+ +`*` Forcasted release version and date. + +Customers will have 9 months to plan, test, and upgrade their PostgreSQL version before the new requirement takes effect. This policy aims to provide clarity and transparency so you can align database upgrades with the Mattermost release schedule. Contact a [Mattermost Expert](https://mattermost.com/contact-sales/). to discuss your options. + +##### Database Search limitations + +Common limitations: + +- Only the initial **1 MB** of the file content is available for search, even though much bigger files can be uploaded. + +Search limitations on PostgreSQL: + +- Email addresses do not return results. +- Hashtags or recent mentions of usernames containing a dash do not return search results. +- Terms containing a dash return incorrect results as dashes are ignored in the search query. +- Limitations set by [PostgreSQL itself](https://www.postgresql.org/docs/current/textsearch-limitations.html): + - One of them is: `The length of a tsvector (lexemes + positions) must be less than 1 megabyte`, which means that, based on the file content, even files with content less than 1 MB won't be searchable if they hit the `tsvector` limit of 1 MB. +- If any of the above is an issue, you can [set up and enable enterprise search](/administration-guide/scale/enterprise-search). + +##### MySQL Support + +[MySQL database support](/deployment-guide/server/prepare-mattermost-mysql-database) is being deprecated starting with Mattermost v11. See the [PostgreSQL migration](/deployment-guide/postgres-migration) documentation for guidance on migrating from MySQL to PostgreSQL. + +- Search limitations on MySQL: Hashtags or recent mentions of usernames containing a dot do not return search results. +- The migration system requires the MySQL database user to have additional EXECUTE, CREATE ROUTINE, ALTER ROUTINE and REFERENCES privileges to run schema migrations. +- MariaDB v10+ no longer functions as a MySQL drop-in replacement, and it's not supported for Mattermost due to the requirement of MySQL 5.7.12. Prior versions of MariaDB were not officially supported but may have functioned in older Mattermost releases. If you are running MariaDB now, migrating from MariaDB to the MySQL equivalent is recommended. +- Deployments requiring searching in Chinese, Japanese, and Korean languages require MySQL 5.7.6+ and the configuration of [ngram Full-Text parser](https://dev.mysql.com/doc/refman/5.7/en/fulltext-search-ngram.html). For searching two characters, you will also need to set `ft_min_word_len` and `innodb_ft_min_token_size` to `2` and restart MySQL. See [CJK discussion](https://github.com/mattermost/mattermost/issues/2033#issuecomment-183872616) for details. + + + +MySQL 8.0.22 contains an [issue with JSON column types](https://bugs.mysql.com/bug.php?id=101284) changing string values to integers which is preventing Mattermost from working properly. Users are advised to avoid this database version. + + + +In MySQL 8.0.4, the default authentication plugin was changed from `mysql_native_password` to `caching_sha2_password`. Therefore, you will need to enable `mysql_native_password` by adding the following entry in your MySQL configuration file: + +> ``` text +> [mysqld] +> default-authentication-plugin=mysql_native_password +> ``` + +In MySQL 8, the default collation changed to `utf8mb4_0900_ai_ci` ([https://dev.mysql.com/doc/mysqld-version-reference/en/optvar-changes-8-0.html](https://dev.mysql.com/doc/mysqld-version-reference/en/optvar-changes-8-0.html)). Therefore, if you update your MySQL installation to version 8, you'll need to convert your database tables to use the new default collation: + +``` sql +ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +``` + +If this change isn't made, tables in the database may end up having different collations which will cause errors when executing queries. + +In MySQL versions 8.0.0 - 8.0.11 `ADMIN` is a [reserved keyword](https://dev.mysql.com/doc/refman/8.0/en/keywords.html), which is why our requirement for MySQL is version 8.0.12. + +MySQL 8.0.22 contains an [issue with JSON column types](https://bugs.mysql.com/bug.php?id=101284) changing string values to integers which is preventing Mattermost from working properly. Users are advised to avoid this database version. + +## Hardware requirements + +Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on traditional deployments and may grow or shrink depending on how active your users are. + +Moreover, memory requirements can be driven by peak file sharing activity. Recommendation is based on default 50 MB maximum file size, which can be [adjusted from the System Console](/administration-guide/configure/environment-configuration-settings#maximum-file-size). Changing this number may change memory requirements. + +For deployments larger than 2,000 users, it is recommended to use the Mattermost open source load testing framework to simulate usage of your system at full scale: [https://github.com/mattermost/mattermost-load-test-ng](https://github.com/mattermost/mattermost-load-test-ng). + +Mattermost supports any 64-bit x86 processor architecture. + +### Hardware requirements for team deployments + +Most small to medium Mattermost team deployments can be supported on a single server with the following specifications based on registered users: + +- 1 - 1,000 users - 1 vCPU/cores, 2 GB RAM +- 1,000 - 2,000 users - 2 vCPUs/cores, 4 GB RAM + +### Hardware requirements for enterprise deployments (multi-server) + +#### Scale requirements + +For Enterprise Edition deployments with a multi-server setup, see [our scaling guide](/administration-guide/scale/scaling-for-enterprise). + +It is highly recommended that pilots are run before enterprise-wide deployments in order to estimate full scale usage based on your specific organizational needs. You can use the Mattermost open source load testing framework to simulate usage of your system: [https://github.com/mattermost/mattermost-load-test-ng](https://github.com/mattermost/mattermost-load-test-ng). + +Mattermost's [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) tools can be used for detailed performance measurements and to inspect the running system to ensure sizing and installation is correct. + +#### System requirements + +For Enterprise Edition deployments with a multi-server setup, we highly recommend the following systems to support your Mattermost deployment: + +- Prometheus to track system health of your Mattermost deployment, through [performance monitoring feature](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) available in Mattermost Enterprise. +- Grafana to visualize the system health metrics collected by Prometheus with the [performance monitoring feature](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). Grafana 5.0.0 and later is recommended. +- Elasticsearch to support highly efficient database searches in a cluster environment. Elasticsearch v7.17+ is supported, and Elasticsearch v8.x or AWS OpenSearch is recommended from Mattermost v9.11. [Learn more](/administration-guide/scale/enterprise-search). +- AWS S3 or any S3-compatible service. Mattermost is compatible with object storage systems which implement the S3 API. You can also use local storage or a network drive using NFS. Learn more about file storage configuration options [in our documentation](/administration-guide/configure/environment-configuration-settings#file-storage). diff --git a/docs/main/deployment-guide/transport-encryption.mdx b/docs/main/deployment-guide/transport-encryption.mdx new file mode 100644 index 000000000000..a02a7dee21e8 --- /dev/null +++ b/docs/main/deployment-guide/transport-encryption.mdx @@ -0,0 +1,448 @@ +--- +title: "Configuring transport encryption" +--- + + +The components of the Mattermost setup are shown in the following diagram, including the transport encryption used. Aside from the encryption between the nodes of the Mattermost cluster, all transports rely on TLS encryption. + + + +The transport between the Application servers is not used by default and requires additional setup steps. Enhancing the core product to include automatic encryption between cluster nodes is in progress and planned for a later release. + + + +![Components of the Mattermost setup where all transports rely on TLS encryption.](/images/transport-encryption.png) + +## Configuring proxy to Mattermost transport encryption + +Mattermost is able to encrypt the traffic between the proxy and the application server using TLS. + +### Prerequisites + +- Operational Mattermost server or cluster. +- Authentication credentials for Mattermost user on application server. + +### Example environment + +In this scenario there is one Mattermost application server and one NGINX server, both running Ubuntu 20.04, with the following IPs: + +- **transport-encryption-mattermost1:** 10.10.250.146 +- **transport-encryption-nginx:** 10.10.250.107 + +### Configuring NGINX + +On the NGINX server, connect to both servers with a sudo or root user. Open the Mattermost proxy configuration and search for the following line twice: + +``` text +proxy_pass http://backend; +``` + +Change the protocol from `http` to `https`: + +``` text +proxy_pass https://backend; +``` + +Afterwards do not reload the NGINX server yet to minimize the downtime of the service. + +### Configuring Mattermost + +On the Mattermost server, change to the config directory of Mattermost and generate a self-signed certificate that will be used to encrypt the traffic between the proxy server and the application server. + +**Note:** Alternatively you can sign a certificate from your company's CA. + +``` sh +cd /opt/mattermost/config +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +chown root:mattermost *.pem +chmod 640 *.pem +``` + +Once complete, open the file `config.json` and modify the values `ConnectionSecurity`, `TLSCertFile` and `TLSKeyFile` in the `ServiceSettings` section. + +**Before** + +``` json +{ + "ServiceSettings": { + "SiteURL": "https://transport-encryption.dev.example.com", + "WebsocketURL": "", + "LicenseFileLocation": "", + "ListenAddress": ":8065", + "ConnectionSecurity": "", + "TLSCertFile": "", + "TLSKeyFile": "", + "...":"..." + }, + "...":"..." +} +``` + +**After** + +``` json +{ + "ServiceSettings": { + "SiteURL": "https://transport-encryption.dev.example.com", + "WebsocketURL": "", + "LicenseFileLocation": "", + "ListenAddress": ":8065", + "ConnectionSecurity": "TLS", + "TLSCertFile": "/opt/mattermost/config/cert.pem", + "TLSKeyFile": "/opt/mattermost/config/key.pem", + "...":"..." + }, + "...":"..." +} +``` + +Restart the Mattermost server and ensure it's up and running: + +``` sh +sudo systemctl restart mattermost +systemctl status mattermost +``` + +``` text +● mattermost.service - Mattermost + Loaded: loaded (/lib/systemd/system/mattermost.service; static; vendor preset: enabled) + Active: active (running) since Mon 2019-10-28 16:45:29 UTC; 1h 15min ago + [...] +``` + +Finally, on the **NGINX server**, reload the configuration to ensure that requests are sent on HTTPS: + +``` sh +sudo systemctl reload nginx +``` + +## Configuring database transport encryption + +Mattermost is able to encrypt the traffic between the database and the application using TLS. This guide describes the setup steps for a single, separate MySQL server. + +### Prerequisites + +- Operational Mattermost server or cluster. +- Operational MySQL server. +- Confirmed connectivity between Mattermost and MySQL server. +- Authentication credentials for Mattermost user on MySQL server. + +### Example environment + +In this scenario there is one Mattermost application server and one MySQL server, both running Ubuntu 20.04, with the following IPs: + +- **transport-encryption-mattermost1:** 10.10.250.146 +- **transport-encryption-mysql1:** 10.10.250.148 + +### Configuring MySQL + +As a first step, connect to both servers with a sudo or root user. + +Execute the following command to prepare the server for SSL connections: + +``` sh +sudo mysql_ssl_rsa_setup --uid=mysql +``` + +This generates self-signed certificates in `/var/lib/mysql/` that the MySQL server uses to encrypt the connection. If you would like to use certificates from your company CA, please follow the MySQL documentation for configuration steps. + +**Note:** Optionally, it can be enforced that all connections must be made via a local socket connection or TLS. To do this, open `/etc/mysql/mysql.conf.d/mysqld.cnf` and append the following line to the file: + +``` text +require_secure_transport = ON +``` + +Any connection to the MySQL server must now be made with secure transport enabled. + +Last but not least, restart the server and confirm it is up and running: + +``` sh +systemctl restart mysql +systemctl status mysql +``` + +``` text +● mysql.service - MySQL Community Server + Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) + Active: active (running) since Fri 2019-10-18 16:41:25 UTC; 2s ago + Process: 8380 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS) + Process: 8360 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS) + Main PID: 8382 (mysqld) + Tasks: 27 (limit: 2361) + CGroup: /system.slice/mysql.service + └─8382 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid + +Oct 18 16:41:25 transport-encryption-mysql1 systemd[1]: Stopped MySQL Community Server. +Oct 18 16:41:25 transport-encryption-mysql1 systemd[1]: Starting MySQL Community Server... +Oct 18 16:41:25 transport-encryption-mysql1 systemd[1]: Started MySQL Community Server. +``` + +### Configuring Mattermost + +On the Mattermost server, open the file `config.json` and look for the `DataSource` value in the `SqlSettings` section. It should look similar to this: + +``` text +"DataSource": "mmuser:sad09zusaopdhsad123@tcp(10.10.250.148:3306)/mattermost?charset=utf8mb4,utf8\u0026writeTimeout=30s", +``` + +At the end of the line, we can configure that TLS must be turned on with the `tls` flag which supports the following values: + +- true (Require TLS + a trusted certificate) +- false +- skip-verify (Require TLS + accept self-signed) +- preferred (Try TLS, fallback to unencrypted) + +In our case we need to use `skip-verify` since we use a self-signed certificate. The configuration setting will now look like this: + +``` text +"DataSource": "mmuser:sad09zusaopdhsad123@tcp(10.10.250.148:3306)/mattermost?charset=utf8mb4,utf8\u0026writeTimeout=30s&tls=skip-verify", +``` + +If you're running Mattermost in a cluster, be sure to update the value on each node of the cluster. If you are using configuration in the database, be sure to update the `systemd` unit file and enable TLS for the configuration store. + +Once complete, restart the Mattermost server and ensure the system is operational: + +``` sh +sudo systemctl restart mattermost +systemctl status mattermost +``` + +``` text +● mattermost.service - Mattermost + Loaded: loaded (/lib/systemd/system/mattermost.service; static; vendor preset: enabled) + Active: active (running) since Fri 2019-10-18 16:47:08 UTC; 3s ago + Process: 3424 ExecStartPre=/opt/mattermost/bin/pre_start.sh (code=exited, status=0/SUCCESS) + Main PID: 3443 (mattermost) + Tasks: 20 (limit: 2361) + CGroup: /system.slice/mattermost.service + ├─3443 /opt/mattermost/bin/mattermost --config=mysql://mmuser:sad09zusaopdhsad123@tcp(10.10.250.148:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s&tls=skip-verify + └─3459 plugins/com.mattermost.nps/server/dist/plugin-linux-amd64 + +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.8637397,"caller":"scheduler/worker.go:36","msg":"Worker started","worker":"Plugins"} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.8639545,"caller":"jobs/jobs_watcher.go:38","msg":"Watcher Started"} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"info","ts":1571417228.8641603,"caller":"jobs/schedulers.go:72","msg":"Starting schedulers."} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.8645394,"caller":"app/web_hub.go:436","msg":"Hub for index 0 is starting with goroutine 3923"} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.8648505,"caller":"app/web_hub.go:436","msg":"Hub for index 1 is starting with goroutine 3924"} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.8656101,"caller":"web/static.go:31","msg":"Using client directory at /opt/mattermost/client"} +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"info","ts":1571417228.8681324,"caller":"commands/server.go:105","msg":"Sending systemd READY notification."} +Oct 18 16:47:08 transport-encryption-mattermost1 systemd[1]: Started Mattermost. +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.9003174,"caller":"jobs/schedulers.go:166","msg":"Next run time for scheduler","scheduler_name":"MigrationsSched +Oct 18 16:47:08 transport-encryption-mattermost1 mattermost[3443]: {"level":"debug","ts":1571417228.9025588,"caller":"jobs/schedulers.go:166","msg":"Next run time for scheduler","scheduler_name":"PluginsSchedule +``` + +## Configuring cluster transport encryption + +Mattermost is able to encrypt the messages sent within the cluster of a deployment using SSH tunneling. The guide walks through the deployment of this solution on Ubuntu 20.04, but it can be adapted for any Linux operating system. + +While this document only describes the configuration of a three-node cluster, it is by no means limited to that number. + +### Prerequisites + +- SSH port whitelisted between each node of the deployment. +- Active ufw/iptables on each node. +- Access to the root/sudo user of each node for configuration. +- A configured Mattermost cluster. +- Mattermost running with a dedicated service user. +- Mattermost service is stopped on each cluster node. + + + +Support on the application level is currently in development and, when available, will deprecate this document. + + + +### Example environment + +In this scenario there are three application nodes in our environment with the following hostname/IP mapping: + +- **transport-encryption-mattermost1:** 10.10.250.146 +- **transport-encryption-mattermost2:** 10.10.250.231 +- **transport-encryption-mattermost3:** 10.10.250.165 + +### Preparations + +- Connect to each Mattermost server with a sudo or root user. +- Make a note of the IP from each cluster member used for the internal communication. +- Ensure `AllowTcpForwarding` is enabled in `/etc/ssh/sshd_config` of each cluster node. + +### SSH authentication + +On each node, generate a SSH key-pair for the service account. In our scenario this is called `mattermost`: + +``` sh +sudo -u mattermost ssh-keygen -t rsa +``` + +``` text +Generating public/private rsa key pair. +Enter file in which to save the key (/home/mattermost/.ssh/id_rsa): +Enter passphrase (empty for no passphrase): +Enter same passphrase again: +Your identification has been saved in /home/mattermost/.ssh/id_rsa. +Your public key has been saved in /home/mattermost/.ssh/id_rsa.pub. +The key fingerprint is: +SHA256:redacted mattermost@transport-encryption-mattermost1 +``` + +The location of the SSH key itself is irrelevant if company policies require the usage of another storage location. + +Next, ensure that the SSH public key of each node is added to the `authorized_keys` file of the other nodes of the cluster. To do so, copy the contents of `/home/mattermost/.ssh/id_rsa.pub` of nodes 2 and 3, and add it to `/home/mattermost/.ssh/authorized_keys` of node 1. + +Repeat this step for each node of the cluster. As a result, each node should be able to establish an SSH connection to the other nodes of the cluster. + + + +This service account can be separate from the service account already used for the Mattermost `systemd` service itself. It's important that this service account is allowed to create a SSH tunnel with port forwarding, but it doesn't require any additional permissions. + + + +### ufw configuration + +As a next step, allow SSH access from each of the other member nodes, e.g.: + +- mattermost1 allows from mattermost2 and mattermost3 +- mattermost2 allows from mattermost1 and mattermost3 +- mattermost3 allows from mattermost1 and mattermost2 + +To do so, we add an exception in the firewall. The commands for `mattermost1` look as follows: + +``` sh +sudo ufw allow from 10.10.250.231/32 to any port ssh +sudo ufw allow from 10.10.250.165/32 to any port ssh +sudo ufw status +``` + +``` text +Rule added +Rule added +Status: active + +To Action From +-- ------ ---- +22/tcp ALLOW 10.10.250.10 +8065/tcp ALLOW Anywhere +22/tcp ALLOW 10.10.250.231 +22/tcp ALLOW 10.10.250.165 +``` + +Repeat the same steps on the other nodes, replacing the IPs with the ones from the other member nodes. Do so for each member node, excluding the node itself. + +Next, open `/etc/ufw/after.rules` and add the following block to the bottom of the file: + +``` text +*nat +:POSTROUTING ACCEPT [0:0] +:PREROUTING ACCEPT [0:0] + +-A OUTPUT -p tcp -d 10.10.250.231 --dport 8075 -j DNAT --to-destination 127.0.0.1:18075 +-A OUTPUT -p tcp -d 10.10.250.231 --dport 8074 -j DNAT --to-destination 127.0.0.1:18074 +-A OUTPUT -p tcp -d 10.10.250.165 --dport 8075 -j DNAT --to-destination 127.0.0.1:28075 +-A OUTPUT -p tcp -d 10.10.250.165 --dport 8074 -j DNAT --to-destination 127.0.0.1:28074 + +COMMIT +``` + +Two lines always belong to a single node, so in a deployment with four nodes: + +``` text +-A OUTPUT -p tcp -d ip_node_2 --dport 8075 -j DNAT --to-destination 127.0.0.1:18075 +-A OUTPUT -p tcp -d ip_node_2 --dport 8074 -j DNAT --to-destination 127.0.0.1:18074 +-A OUTPUT -p tcp -d ip_node_3 --dport 8075 -j DNAT --to-destination 127.0.0.1:28075 +-A OUTPUT -p tcp -d ip_node_3 --dport 8074 -j DNAT --to-destination 127.0.0.1:28074 +-A OUTPUT -p tcp -d ip_node_4 --dport 8075 -j DNAT --to-destination 127.0.0.1:38075 +-A OUTPUT -p tcp -d ip_node_4 --dport 8074 -j DNAT --to-destination 127.0.0.1:38074 +``` + +Please be aware that the ports on the right side must be unique, so if you have a cluster of six nodes, use 8075 and 8074 with 1 to 5 in front of it. If the cluster is of bigger size, additional ports must be used. + +Ensure that your operating system has IP forwarding enabled using the following command: + +``` sh +sysctl -w net.ipv4.ip_forward=1 +``` + +After that, reload the ufw rules and confirm that the iptable rules were successfully created: + +``` sh +iptables -t nat -L +``` + +``` text +Chain PREROUTING (policy ACCEPT) +target prot opt source destination + +Chain INPUT (policy ACCEPT) +target prot opt source destination + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +DNAT tcp -- anywhere 10.10.250.231 tcp dpt:8075 to:127.0.0.1:18075 +DNAT tcp -- anywhere 10.10.250.231 tcp dpt:8074 to:127.0.0.1:18074 +DNAT tcp -- anywhere 10.10.250.165 tcp dpt:8075 to:127.0.0.1:28075 +DNAT tcp -- anywhere 10.10.250.165 tcp dpt:8074 to:127.0.0.1:28074 +``` + +Repeat those steps for every node on the cluster. At the end of this section the following should be configured: + +- SSH access enabled in firewall from each cluster node to another. +- Per node 2 iptables rules for port 8074 and 8075. +- IP forwarding enabled. + +### SSH configuration + +As a next step, ensure that the SSH tunnels are created as part of the Mattermost service start. To do so, create a file called `pre_start.sh` in `/opt/mattermost/bin` on `mattermost1`: + +``` sh +#!/bin/bash +ssh -N -f -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 18075:10.10.250.231:8075 10.10.250.231 || true +ssh -N -f -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 18074:10.10.250.231:8074 10.10.250.231 || true +ssh -N -f -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 28075:10.10.250.165:8075 10.10.250.165 || true +ssh -N -f -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 28074:10.10.250.165:8074 10.10.250.165 || true +``` + + + +- We're ignoring the error from the SSH connection itself in case a tunnel is already active. Otherwise the Mattermost server would fail to start. +- Please make sure to back up this script in case of a version upgrade. + + + +Afterwards, set the executable bit on the shell script: + +``` sh +chmod +x /opt/mattermost/bin/pre_start.sh +``` + +Open the systemd unit file of Mattermost and search for `Type=Notify`. After this, enter a `ExecStartPre` script that will be executed before Mattermost itself is started: + +``` text +[Service] +Type=notify +ExecStartPre=/opt/mattermost/bin/pre_start.sh +``` + +Reload the systemd daemon afterwards: + +``` sh +systemctl daemon-reload +``` + +Repeat the same steps on each of the member nodes and adapt the node IPs and amount of entries for your environment. + +### Cluster start + +Once each node is configured, restart the service on each cluster and confirm that it's running using the command below: + +``` sh +systemctl start mattermost +systemctl status mattermost.service +``` + +``` text +● mattermost.service - Mattermost + Loaded: loaded (/lib/systemd/system/mattermost.service; static; vendor preset: enabled) + Active: active (running) since Fri 2019-10-04 19:44:20 UTC; 5min ago + Process: 16734 ExecStartPre=/opt/mattermost/bin/pre_start.sh (code=exited, status=0/SUCCESS) +``` + +Next, open the Mattermost System Console and confirm that each node is reporting successfully in the High Availability section. diff --git a/docs/main/end-user-guide/access/access-your-workspace.mdx b/docs/main/end-user-guide/access/access-your-workspace.mdx new file mode 100644 index 000000000000..96d144597f1a --- /dev/null +++ b/docs/main/end-user-guide/access/access-your-workspace.mdx @@ -0,0 +1,316 @@ +--- +title: "Access your workspace" +--- + + +Access your Mattermost instance with your credentials using a web browser, the desktop app, or the mobile app for iOS or Android. Depending on how Mattermost is configured, you'll log in using your email address, username, or single sign-on (SSO) username, and your password. See the [Client availability](/end-user-guide/access/client-availability) documentation to learn which features are available on different Mattermost clients. + + + +Can't find your Mattermost link? Ask your company's IT department or your Mattermost system admin for your organization's **Mattermost Site URL**. It'll look something like `https://example.com/company/mattermost`, `mattermost.yourcompanydomain.com`, or `chat.yourcompanydomain.com`. These URLs could also end in `.net`. + + + +
+ +Web/Desktop + +## Web browser + +1. Open a supported [web browser](/deployment-guide/software-hardware-requirements#pc-web). +2. Copy and paste the Mattermost server link into the browser's address field. +3. Enter your user credentials to log into Mattermost. +4. Bookmark the Mattermost URL in your web browser of choice so logging into Mattermost is easy in the future. + +## Desktop app + +1. Download and install the Mattermost desktop app from the App Store (macOS), Microsoft Store (Windows), or by [using a package manager (Linux)](/deployment-guide/desktop/linux-desktop-install). +2. When prompted, enter the Mattermost server link and a display name for the Mattermost instance. The display name is helpful in cases where you connect to multiple Mattermost instances. See the [server connections](/end-user-guide/preferences/connect-multiple-workspaces) documentation for details. +3. Enter your user credentials to log into Mattermost. +4. If the server requires an authentication secret, you'll be prompted to enter it when you connect. Enter the secret provided by your system admin and select **OK**. See the [troubleshooting](#troubleshooting-authentication-secrets) section below for help if you're having issues. +5. The team that displays first in the team sidebar opens. If you're not a member of a team yet, you're prompted to select a team to join. + + + +When you log into Mattermost using external user credentials, such as Google or Entra ID, you'll temporarily leave the desktop app during login while authenticating your credentials. Once you're successfully logged in to Mattermost, you'll be returned to the desktop app. See the [Single Sign-On (SSO)](#single-sign-on-sso) section below for details on the external providers that Mattermosts supports. + + + +
+ +
+ +Mobile + +1. Download and install the Mattermost mobile app from the [Apple App Store (iOS)](https://www.apple.com/app-store/) or [Google Play Store (Android)](https://play.google.com/store/games?hl=en). +2. When prompted, enter the Mattermost server link and a display name for the Mattermost instance. Server URLs must begin with either `http://` or `https://`. The display name is helpful in cases where you connect to multiple Mattermost instances. See the [server connections](/end-user-guide/preferences/connect-multiple-workspaces) documentation for details. +3. Enter your user credentials to log into Mattermost. +4. Optionally toggle the **Advanced Options** section to enter an **Authentication secret**. This is an additional security measure that some organizations use. Your system admin can provide you with the secret if required. See the [troubleshooting](#troubleshooting-authentication-secrets) section below for help if you're having issues. +5. The team that displays first in the team sidebar opens. If you're not a member of a team yet, you're prompted to select a team to join. + +
+ +
+ +Mobile via Microsoft Intune + +When your organization uses Microsoft Intune App Protection to secure Mattermost on iOS mobile devices, you must enroll to access Mattermost on mobile. Enrollment adds extra protection to work data while keeping your personal device and apps private. + +## What to Expect + +Each time you sign in, Mattermost checks the Intune App Protection Policy applied to your account and automatically enroll your account before you can access your workspace. After enrollment, your Mattermost experience generally stays the same, but some restrictions may be enforced. + +Intune protections apply **per Mattermost workspace** (the Mattermost server you sign in to). If you have access to multiple Mattermost workspaces, each workspace may have different protections and requirements in place. This guide explains what to expect when the workspace you are connecting to is protected by Intune. + + + +- Intune protections are based on your **user account**, not your Mattermost role or permissions. +- Intune policies are controlled by your organization, not by Mattermost. +- Intune enrollment applies only when you sign in using your organization’s **Microsoft/Entra ID** sign-in method (for example, **Sign in with Microsoft**). If you sign in using a different method (such as email/password or another SSO provider), Intune App Protection may not be applied for that workspace. +- If you’re unsure which sign-in option to use, contact your IT support team. + + + +## Sign In to Enroll + +To sign in and enroll your iOS device: + +1. Open the Mattermost mobile app on your iOS device. +2. Sign in with Microsoft (your organization’s sign-in option). +3. Enter your credentials. +4. When enrollment completes, you are notified. +5. If your organization’s Intune App Protection Policy requires it, you’ll be prompted to set a PIN to protect your work data. Once the PIN is confirmed, the Mattermost Mobile App unlocks access to your workspace. + +Enrollment happens automatically during sign-in. If you cancel the sign-in flow before it completes, return to the sign-in flow and finish signing in to continue using Mattermost on that device. + +## Mid-Session Enrollment + +If enrollment is triggered while you're already signed in, you may be prompted to confirm your Microsoft sign-in again. This is expected and typically takes only a few seconds. + +If you tap **Cancel**, you won’t be able to continue using Mattermost on that device until enrollment succeeds. You can retry immediately, or [log out](#what-happens-when-i-log-out-manually) and retry later. + +## What Changes After Enrollment? + +Your organization’s Intune App Protection Policy may restrict how you copy, capture, save, and share data from Mattermost. The exact behavior depends on the specific policy settings your organization has configured. + +### Screenshot and Screen Recording Restrictions + +Depending on your organization’s policy, you may not be able to take screenshots or record your screen while using Mattermost. If screenshot or screen recording is blocked, your device may still show the screenshot or recording UI, but the content may not be captured. + +### File Save Restrictions + +Depending on policy, you may not be able to save files from Mattermost to personal or unmanaged locations. Files may be limited to locations approved by your organization. + +### Browser and Sharing Restrictions + +Depending on policy, links may open only in an approved browser and sharing may be restricted to managed apps. If you try to open a link in an unapproved browser or share content to an unmanaged app, the action may be blocked. + +## Frequently Asked Questions + +### What Happens If I Leave the Organization or Lose My Device? + +If you leave the organization, or your device is lost or compromised, your IT support team can wipe Mattermost work data from your iOS device. This is called a **selective wipe**. + +A selective wipe means that: + +- Only Mattermost work data is removed from your device. +- Personal apps, photos, and files are untouched. +- You are logged out of the affected Mattermost workspace. +- Other Mattermost workspaces on your device remain unaffected. + +### Why Can’t I Access Mattermost After Enrollment? + +Mattermost may restrict access after enrollment if Intune detects a risk, such as: + +- Your device operating system is out of date +- The device is too old to meet security requirements +- A jailbroken device is detected +- Malware is detected +- Re-authentication is required + +If this occurs, Intune blocks access and displays an error message in the Mattermost mobile app explaining what action is required. Contact your IT support team for help. + +### What Happens When I Log Out Manually? + +When you log out of Mattermost: + +- All workspace data is securely removed from the device. +- Intune protection for that workspace is removed. + +You can sign back in with Microsoft if you need access again. + +
+ +## Reset your password + +If you've forgotten your password, you can reset it on the login screen by selecting **Forgot your password?**, or by contacting your system admin for assistance. + +## Magic link login for guests + + + +From Mattermost v11.3, guests can log in to Mattermost without a password using a secure link sent to their email address when [enabled by the system admin](/administration-guide/onboard/guest-accounts#configure-magic-links-for-guests). The magic link login provides a streamlined passwordless authentication option for guest users. + +If you've been invited as a guest to a Mattermost workspace, enter your email address on the login screen. You'll receive an email with a link to log in without a password. The link expires in 48 hours for security purposes. To log in again at a later time, enter your email address on login to receive a new login link by email that expires in 5 minutes. + + + +- Magic link security depends on your email account security. +- Never share your magic link with anyone else, as doing so would give that person full access to your account. + + + +## Email address or username + +When [account creation with email](/administration-guide/configure/authentication-configuration-settings#enable-account-creation-with-email) is enabled by your system admin, you can log in with the username or email address used to create a Mattermost account. + +![Log in to Mattermost with your username or email address, or reset your password.](/images/login-email-username.png) + +## Single Sign-On (SSO) + +When enabled by your system admin, you may log in using your GitLab, Google, Entra ID, AD/LDAP, or SAML credentials. + +
+ +GitLab + +When enabled by your system admin, you can log in with your GitLab account using a one-click login option. + +![Log in to Mattermost using your GitLab credentials.](/images/login-gitlab.png) + +
+ +
+ +Google + +When enabled by your system admin, you can log in with your Google account using a one-click login option. + +![Log in to Mattermost using your Google Apps credentials.](/images/login-google.png) + +
+ +
+ +Entra ID + +When enabled by your system admin, you can log in with your Entra ID account using a one-click login option. + +![Log in to Mattermost with your Entra ID credentials.](/images/sign-in-entraid.png) + +
+ +
+ +AD/LDAP + +When enabled by your system admin, you can log in with your AD/LDAP credentials. This lets you use the same username and password for Mattermost that you use for various other company services. + +![Log in to Mattermost with your AD/LDAP credentials.](/images/login-ad.png) + +
+ +
+ +SAML + +When enabled by your system admin, you can log in with your SAML credentials. This lets you use the same username and password for Mattermost that you use for various other company services. + +Mattermost officially supports [Okta](/administration-guide/onboard/sso-saml-okta), [OneLogin](/administration-guide/onboard/sso-saml-onelogin), and Microsoft ADFS as an identity provider (IDP) for SAML, but you may use other SAML IDPs as well. See our [SAML Single Sign-On documentation](/administration-guide/onboard/sso-saml) to learn more about configuring SAML for Mattermost. + +![Log in to Mattermost with SAML credentials, such as OneLogin.](/images/login-onelogin.png) + +
+ +## Multi-factor authentication + +If your system admin [enables multi-factor authentication](/administration-guide/onboard/multi-factor-authentication#enabling-mfa) for your Mattermost instance, you can [optionally set up multi-factor authentication](/end-user-guide/preferences/manage-your-security-preferences) for your Mattermost user account by selecting your profile picture located in the top-right corner of Mattermost, and going to **Security \> Multi-Factor Authentication**. + +If your system admin [enforces multi-factor authentication](/administration-guide/onboard/multi-factor-authentication#enforcing-mfa), you are required to [set up multi-factor authentication](/end-user-guide/preferences/manage-your-security-preferences) for your Mattermost account. When you attempt to log in to Mattermost, you're directed to the multi-factor authentication setup page. You won't be able to access Mattermost until multi-factor setup is complete. If you encounter issues setting up multi-factor authentication, contact your Mattermost system admin for assistance. + +## Troubleshooting authentication secrets + +If you're having trouble connecting to a Mattermost server that requires an authentication secret, consider the following troubleshooting tips: + +- **Authentication secrets are case-sensitive**: Ensure you're entering the secret exactly as provided, including any uppercase letters, numbers, or special characters. +- **Spaces matter**: Don't add extra spaces before or after the secret. +- **Copy/paste issues**: If copying the secret from a document, ensure you're not accidentally copying extra characters. It may be safer to type it manually. +- **Contact your administrator**: If you continue experiencing issues, contact your IT department or Mattermost system administrator. They can verify the secret is configured correctly on the server side. + +
+ +Desktop + +If you're having trouble connecting to a server with an authentication secret: + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
IssueWhat To Do
Error: Server authentication requiredYour server requires an authentication secret. Enter the secret provided by your system administrator in the modal that appears.
Error: The provided authentication secret is incorrectThe secret you entered doesn't match the server's configuration. Verify with your system admin that you have the correct secret (secrets are case-sensitive).
Connection works but then stopsYour organization may have rotated the authentication secret. Try connecting again. The app will automatically prompt you to enter the new secret.
Modal doesn't appearIf you're not seeing the authentication prompt, try removing the server and adding it again. This will reset all stored credentials.
+ +
+ +
+ +Mobile + +If you're having trouble connecting to a server with an authentication secret: + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
IssueWhat To Do
Error: "Authentication secret is invalid"Tap on the server entry, tap Edit, expand Advanced Options, verify the secret is entered correctly, and tap Save to retry.
Forgot to enter secret during setupTap on the server entry, tap Edit, expand Advanced Options, enter the secret in the Authentication secret field, and tap Save.
Need to update secret after rotationSwipe left on the server, tap Edit, expand Advanced Options, update the Authentication secret field with the new value, and tap Save.
Error persists with correct secretTry removing the server completely and adding it again with the authentication secret entered during initial setup.
+ +
diff --git a/docs/main/end-user-guide/access/client-availability.mdx b/docs/main/end-user-guide/access/client-availability.mdx new file mode 100644 index 000000000000..9ae6cd16924b --- /dev/null +++ b/docs/main/end-user-guide/access/client-availability.mdx @@ -0,0 +1,433 @@ +--- +title: "Client Availability" +draft: true +--- + + +The following tables highlight the end user features of Mattermost and their support across Web, Desktop, and Mobile applications (iOS and Android). + +## Messages + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Threaded discussions | checkmark | checkmark | checkmark |
Format messages with Markdown | checkmark | checkmark | Partial Support |
Emojis | checkmark | checkmark | checkmark |
Emoji reactions_ | checkmark | checkmark | checkmark |
File sharing | checkmark | checkmark | checkmark |
@mentions | checkmark | checkmark | checkmark |
Search hashtags | checkmark | checkmark | checkmark |
Search modifiers | checkmark | checkmark | checkmark |
Search highlightingcheckmark | checkmark | checkmark |
Pin and save messages | checkmark | checkmark | checkmark |
Preview image linksments>`__ | checkmark | checkmark | checkmark |
Preview websites | | | | | checkmark | checkmark | checkmark
Notifications | checkmark | checkmark | checkmark |
Bookmark channels | checkmark | checkmark | checkmark |
+ +## Channels + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Create a new channel | checkmark | checkmark | checkmark |
Join a channel
+ +
Leave a channel
+ +
Favorite a channel | checkmark | checkmark | checkmark |
Mute a channel | | | | | checkmark | checkmark | checkmark |
Manage members | checkmark | checkmark | checkmark |
Add members | checkmark | checkmark | checkmark
Rename channels | checkmark | checkmark | checkmark |
Deactivate members | | | | | checkmark | checkmark | |
+ +## Teams + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Multi-team support for notifications | | | | | checkmark | checkmark | checkmark
Team switching | checkmark | checkmark | checkmark |
Team-based theming | checkmark | checkmark | checkmark |
Team settings | checkmark | checkmark | |
Join existing teameam>`__ | checkmark | checkmark | checkmark |
Create a new teamteam>`__ | checkmark | checkmark | |
Share an invite link | checkmark | checkmark | checkmark |
Invite people | checkmark | checkmark | checkmark |
Manage team members | checkmark | checkmark | |
Leave team
+ +
+ +## Collaborative playbooks + + ++++++++ + + + + + + + + + + + + +
+

Feature

+
+

Web

+
DesktopMobile
Collaborative playbooks | | | | | checkmark | checkmark |
+ +## Calls + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Join call | | | | | checkmark | checkmark | checkmark |
Share screen | | | | | checkmark | checkmark | |
Chat in thread | | | | | checkmark | checkmark | checkmark
React with emoji | | | | | checkmark | checkmark | checkmark |
Record a call | | | | | checkmark | checkmark | checkmark |
+ +## Integrations + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Slash commands | checkmark | checkmark | Partial Support |
Server-side plugins | checkmark | checkmark | checkmark
Interactive dialogscheckmark | checkmark | |
OAuth 2.0checkmark | checkmark | checkmark |
Incoming webhookscheckmark | checkmark | checkmark |
Outgoing webhookscheckmark | checkmark | checkmark |
Message attachmentscheckmark | checkmark | checkmark |
Message buttonscheckmark | checkmark | checkmark |
Message menuscheckmark | checkmark | checkmark |
Message actionscheckmark | checkmark | |
Right-hand sidebarcheckmark | checkmark | |
+ +## Authentication + + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Email password login | | | | | checkmark | checkmark | checkmark
AD/LDAP | checkmark | checkmark | checkmark |
SAML SSO | checkmark | checkmark | checkmark |
GitLab SSO | checkmark | checkmark | checkmark |
Entra ID SSO | checkmark | checkmark | checkmark |
Google SSO | checkmark | checkmark | checkmark |
+ +## Other + + +++++++ + + + + + + + + + + + + + + + + + + + + + +
+

Feature

+
+

Web

+
Desktop
+

Mobile

+
Localization for 22 languages | | | | | checkmark | checkmark | checkmark |
Custom user interface themes | | | | | checkmark | checkmark | checkmark
User profile settings | | | | | checkmark | checkmark | checkmark
Channel notification settings | | | | | checkmark | checkmark | checkmark |
+ +### What feature quality levels does Mattermost have? + +We strive to release viable features. This means that we put in a significant amount of effort to ensure we solve a use case with a high bar for quality. A feature that's viable and meets our criteria for our production quality levels will be released to production. + +However, when working on large and complex features or new products, we may need to test them with a high volume of customers and users. For these scenarios, we'll release them as [Experimental](/administration-guide/manage/feature-labels#experimental) or [Beta](/administration-guide/manage/feature-labels#beta), and implement feature flags and/or A/B testing to validate the effectiveness of features prior to production-level release. Additionally, we [dogfood our features](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) on our community server, and provide many configuration options that ensure customers can opt-in when trying experimental or beta features. + +See the [Mattermost feature labels](/administration-guide/manage/feature-labels) documentation for details on the status, maturity, and support level of each feature, and what you can expect at each level. diff --git a/docs/main/end-user-guide/access/install-android-app.mdx b/docs/main/end-user-guide/access/install-android-app.mdx new file mode 100644 index 000000000000..a905ea8f96cf --- /dev/null +++ b/docs/main/end-user-guide/access/install-android-app.mdx @@ -0,0 +1,24 @@ +--- +title: "Install the Mattermost Android mobile app" +--- + + +Take Mattermost wherever you go by [installing the Mattermost mobile app](https://play.google.com/store/apps/details?id=com.mattermost.rn) on your Android mobile device running Android 7.0 or later. + +1. On your device, visit the Play Store. +2. Search for "Mattermost" and select **INSTALL** to download the app. +3. Open Mattermost from your homescreen and enter your team and account information to login: + 1. **Enter Server URL:** This is the web address you go to when you want to access Mattermost. See the [access your workspace](/end-user-guide/access/access-your-workspace) documentation for additional details. + 2. Enter your credentials as specified by your Mattermost system admin. Select **Log in**. + + + +You can set up multi-factor authentication for Mattermost if your system admin has [enabled your ability to do so](/administration-guide/configure/authentication-configuration-settings#enable-multi-factor-authentication). See the [manage security preferences](/end-user-guide/preferences/manage-your-security-preferences) documentation for details. + + + +## Mattermost on Chromebooks + +Mattermost Android mobile app for Android isn't supported on Chromebooks. While some Android applications can run on ChromeOS devices, the Mattermost app isn't optimized for this environment and may not function as expected. + +For the best experience on Chromebooks, we recommend accessing Mattermost through the web app using the Chrome browser. Alternatively, ChromeOS users can also choose to install the web app as a Progressive Web App (PWA) directly from the browser for an app-like experience with a desktop icon and windowed view. diff --git a/docs/main/end-user-guide/access/install-desktop-app.mdx b/docs/main/end-user-guide/access/install-desktop-app.mdx new file mode 100644 index 000000000000..9662a531b685 --- /dev/null +++ b/docs/main/end-user-guide/access/install-desktop-app.mdx @@ -0,0 +1,60 @@ +--- +title: "Install the Mattermost desktop app" +--- + + +Download and install the Mattermost desktop app [for macOS from the App Store](https://apps.apple.com/us/app/mattermost-desktop/id1614666244?mt=12), [for Windows from the Microsoft Store](https://apps.microsoft.com/detail/xp8br8mh3lpklt?hl=en-US&gl=US), or by [using a package manager (Linux)](/deployment-guide/desktop/linux-desktop-install). + +We strongly recommend installing the desktop app on a local drive. Network shares aren't supported. + +1. When prompted, enter the Mattermost server link and a display name for the Mattermost instance. The display name is helpful in cases where you connect to multiple Mattermost instances. See the [server connections](/end-user-guide/preferences/connect-multiple-workspaces) documentation for details. +2. Enter your user credentials to log into Mattermost. +3. The team that displays first in the team sidebar opens. If you're not a member of a team yet, you're prompted to select a team to join. + + + +When you log into Mattermost using external user credentials, such as Google or Entra ID, you'll temporarily leave the desktop app during login while authenticating your credentials. Once you're successfully logged in to Mattermost, you'll be returned to the desktop app. See the [Single Sign-On (SSO)](#single-sign-on-sso) section below for details on the external providers that Mattermosts supports. + + + +## Upgrade the desktop app + +From v6.1.0, Mattermost Desktop uses in-app notifications to alert you when new releases are available. You'll see a notification in the **Downloads** dropdown with platform-specific options: + +- **macOS (App Store)**: Select **Open Mac App Store** to update through the App Store. +- **macOS (DMG)**: Select **Download Update** to download the new DMG file from your browser. Open the DMG and drag Mattermost to your Applications folder. +- **Windows (Microsoft Store)**: Select **Use Windows Store** to update through the Microsoft Store. +- **Windows (MSI)**: Select **Download Manually** to download the MSI installer from your browser, then run the installer. +- **Linux**: Select the notification to open the GitHub releases page, download the appropriate package for your system (AppImage, deb, rpm, Flatpak), and install it. + +**Manual update check** + +You can manually check for updates at any time by: + +- Selecting **Help \> Check for Updates** from the menu bar, or +- Going to **Settings \> Updates** and selecting **Check Now** + +**Skip a version** + +If you don't want to see notifications for a specific version, select **Skip This Version** in the notification. You won't see notifications for that version, but you'll be notified when a newer version is released. + + + +In enterprise deployments, your system administrator may disable update notifications via Group Policy. If you're not seeing update notifications, contact your IT department. + + + +### Upgrading to v6.1.0 using Windows MSI installer + +If you're upgrading from a version earlier than v6.1.0 using the Windows MSI installer, you may need to recreate your taskbar shortcut once after upgrading. This one-time change improves shortcut reliability and prevents shortcuts from breaking during future upgrades. + +Prior to v6.1.0, installing over an older Desktop App version could break shortcuts. The v6.1.0 MSI installer uses a more reliable method for shortcut icons that prevents this issue in future upgrades. This only affects Windows MSI installer upgrades. The Windows Store version is not affected, and future upgrades to v6.1.1 and later won't require shortcut recreation. + +If your taskbar shortcut shows the wrong icon or fails to launch after upgrading to v6.1.0: + +1. Right-click the broken shortcut on your taskbar and select **Unpin from taskbar**. +2. Launch Mattermost Desktop from the Start Menu or desktop shortcut. +3. Right-click the Mattermost icon in the taskbar while it's running. +4. Select **Pin to taskbar**. + +Your new shortcut will work correctly for all future updates. diff --git a/docs/main/end-user-guide/access/install-ios-app.mdx b/docs/main/end-user-guide/access/install-ios-app.mdx new file mode 100644 index 000000000000..00d7cf5c5dd6 --- /dev/null +++ b/docs/main/end-user-guide/access/install-ios-app.mdx @@ -0,0 +1,23 @@ +--- +title: "Install the Mattermost iOS mobile app" +--- + + +Take Mattermost wherever you go by [installing the Mattermost mobile app](https://apps.apple.com/us/app/mattermost/id1257222717) on your iOS mobile device running iOS 12.1 or later. + +1. On your device, visit the App Store. +2. Search for "Mattermost" and select **GET** to download the app. +3. Enter your Apple ID Password or use Face or Touch ID to proceed with the installation. You may also be asked to provide an Apple Verification Code received through text/phone call, login notification, or **Settings** on your trusted device. +4. Open the Mattermost app and tap **Sign in** below the **Next** button. +5. On the next screen, tap **Allow** when prompted to approve notifications for the Mattermost app. +6. Now follow the steps below to log in: + 1. **Enter Server URL:** This is the web address you go to when you want to access Mattermost. + 2. **Display Name:** This is a name for your server so that you can identify it in case you have multiple servers set up in your app. Tap **Connect** to continue. + 3. Enter your credentials as specified by your Mattermost system admin in the next screen. Tap **Log in**. + + + +- See the [access your workspace](/end-user-guide/access/access-your-workspace) documentation for additional details. +- You can set up multi-factor authentication for Mattermost if your system admin has [enabled your ability to do so](/administration-guide/configure/authentication-configuration-settings#enable-multi-factor-authentication). See the [manage security preferences](/end-user-guide/preferences/manage-your-security-preferences) documentation for details. + + diff --git a/docs/main/end-user-guide/access/log-out.mdx b/docs/main/end-user-guide/access/log-out.mdx new file mode 100644 index 000000000000..6b21dce67afe --- /dev/null +++ b/docs/main/end-user-guide/access/log-out.mdx @@ -0,0 +1,44 @@ +--- +title: "Log out of Mattermost" +--- + + +You can log out of Mattermost from your profile picture. Select **Log Out** to log out of all teams on the server. + +
+ +Web/Desktop + +![Log out of Mattermost from your profile picture.](/images/profile-log-out.png) + +
+ +
+ +Mobile + +Log out of Mattermost from your profile picture. + +
+ +## Frequently asked questions + +### What happens when I log out of Mattermost? + +When you log out of Mattermost, all data related to your session is removed except a record in the app database of the server you accessed and general activity state information, such as the onboarding checklist. Your user data stored within the server database is deleted when you log out. If you were to delete the Mattermost desktop and the mobile app, the most recent server URL and state data would also be deleted. + +When you log out, the following additional data is also deleted: + +- All push notifications from that server. +- The websocket, network, and analytics clients stored locally in memory. +- All cookies for the server URL. +- The image cache for all servers (not just the server you've logged out of). +- All files saved in the cache directory for that server. +- All thumbnails and data saved to the clipboard for all servers (not just the server you've logged out of). +- The `image_cache` cache directory (Android mobile app) + +If you have multiple Mattermost accounts on the same server, logging out of one account will not log you out of the other accounts. + +### What happens if I log out while my device is enrolled in Intune MAM? + +If your device is enrolled in Intune MAM (Mobile Application Management), logging out of Mattermost will remove all workspace data and Intune protection for that workspace from your iOS device. You can sign back in with Microsoft if you need access again. Learn more about [accessing your workspace with Intune MAM](https://docs.mattermost.com/end-user-guide/access/access-your-workspace.html#itab--Mobile-via-Microsoft-Intune-MaM--0_1-Mobile-via-Microsoft-Intune-MaM). diff --git a/docs/main/end-user-guide/agents.mdx b/docs/main/end-user-guide/agents.mdx new file mode 100644 index 000000000000..f856fcb46434 --- /dev/null +++ b/docs/main/end-user-guide/agents.mdx @@ -0,0 +1,12 @@ +--- +title: "AI Agents" +--- + + +{/* TODO: include /agents/docs/user_guide.md could not be resolved */} + + + +Mattermost Agents is formerly known as Mattermost Copilot. + + diff --git a/docs/main/end-user-guide/collaborate/agents-context-management.mdx b/docs/main/end-user-guide/collaborate/agents-context-management.mdx new file mode 100644 index 000000000000..d773e08765ac --- /dev/null +++ b/docs/main/end-user-guide/collaborate/agents-context-management.mdx @@ -0,0 +1,62 @@ +--- +title: "Agents context management" +--- + + +Mattermost Agents are designed to handle context efficiently, ensuring that only necessary information is sent to the Large Language Model (LLM) for generating accurate responses. This document outlines how Agents process and include relevant context. The company name, the server name, and the time are always passed to the LLM to ensure accurate and contextually relevant responses. + + + +**Ensure data privacy** + +We recommend that customers with strict privacy requirements run the LLM locally to prevent sensitive data, including personally identifiable information (PII) and message content, from being shared with an external LLM hosting vendor. This ensures data privacy while enabling Agent functionality. + + + +## Direct messages to Agent bots + +When you send a direct message to an Agent bot, the context sent to the LLM includes: + +- The profile information of the user sending the prompt. +- Chat messages exchanged between the user and the bot. + +**Additional context in direct messages** + +By default, some tool use is enabled to allow for features such as integrations with JIRA, and additional context may be sent to the LLM, depending on the prompt that includes: + +- Jira tickets (public tickets) + - Example: Summarize the Jira ticket: \ +- GitHub issues + - Example: Summarize the GitHub issue: \ +- User data + - Example: What is @Bob's position? + +## @-Mentions in channels + +When you `@mention` Agents in a channel, the context sent to the LLM includes: + +**Standalone messages (@-mentions in a channel)** + +- The message containing the @-mention, including any attachments. +- The channel name and display name. +- The team name and display name. +- The profile information of the user sending the prompt. + +**Threaded messages (@-mentions in a thread)** + +- Everything sent when used in a standalone message. +- Messages within the thread, including the usernames of the users involved, as well as any attachments and their filenames. + +**Context differences between standalone and threaded messages:** + +- For @-mentions in standalone messages, the context includes only the mentioned message. +- For @-mentions in threads, the entire thread's messages are included, along with usernames of the authors of the messages. + +## Built-in ways to trigger Agents + +In addition to regular chat interactions, Agents provide specialized features where extra context is sent to the LLM. Each feature provides specialized context tailored to the task being performed. Below are the scenarios where extra context is sent to the LLM: + +- **Thread summarization**: Includes thread messages and the usernames of the authors +- **Meeting summary**: Incorporates transcriptions from calls +- **Channel summary since last visit**: Uses channel posts along with their authors to create summaries. +- **Finding action items & open questions**: Analyzes thread and channel messages to identify action items or open questions. diff --git a/docs/main/end-user-guide/collaborate/archive-unarchive-channels.mdx b/docs/main/end-user-guide/collaborate/archive-unarchive-channels.mdx new file mode 100644 index 000000000000..2d5e67003325 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/archive-unarchive-channels.mdx @@ -0,0 +1,108 @@ +--- +title: "Archive and unarchive channels" +--- + + +## Archive a channel + +Delete [public channels](/end-user-guide/collaborate/channel-types#public-channels) and [private channels](/end-user-guide/collaborate/channel-types#private-channels) when they're no longer needed by archiving them. Archiving channels removes them from the channel sidebar and marks them as read-only. Anyone can archive a public or private channel they're a member of, unless your system admin has [disabled](/administration-guide/onboard/advanced-permissions) your ability to do so. + + + +You can continue to access archived channels, unless your system admin has [disabled](/administration-guide/configure/site-configuration-settings#allow-users-to-view-archived-channels) your ability to do so. + + + +
+ +Web/Desktop + +To archive a channel, select the channel name at the top of the center pane to access the drop-down menu, then select **Archive Channel**. + +
+ +
+ +Mobile + +To archive a channel: + +1. Tap the channel you want to delete. + +![Select a channel that you want to edit.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Archive Channel**. + +![Tap on Archive channel to archive the current channel.](/images/mobile-edit-channel.jpg) + +5. Tap **Yes** to confirm. + +![Tap on Yes to confirm your choice.](/images/mobile-confirm-archive-a-channel.jpg) + +
+ + + +- When a Mattermost user is deactivated in the system, your [direct message channel](/end-user-guide/collaborate/channel-types#direct-message-channels) with that user are archived and marked as read-only. An **Archived** icon Archived channels are identified with a File Box icon. displays next to archived channels. From Mattermost v11.5, archived private channels display a distinct **Archive Lock** icon to differentiate them from other archived channels. +- [Group message channels](/end-user-guide/collaborate/channel-types#group-message-channels) can't be archived, but they can be closed to hide them from the channel sidebar. +- The default **Town Square** channel can't be archived. +- System admins can archive channels without needing to be a channel member by using the System Console. +- Because a copy of the channel exists on the server, you can't reuse the URL of an archived channel when [creating a new channel](/end-user-guide/collaborate/create-channels). + + + +## Unarchive a channel + +System admins and Team admins can restore archived channels. When a channel is unarchived, channel membership and all its content is restored, unless messages and files have been deleted based on a [data retention policy](/administration-guide/configure/compliance-configuration-settings#data-retention-policies). + +
+ +Web/Desktop + +Search for the channel if required. Then, open the channel, select the channel name at the top of the center pane to access the drop-down menu and select **Unarchive Channel**. + +![Unarchive a channel.](/images/unarchive-channel.png) + +
+ +
+ +Mobile + +To unarchive a channel: + +1. Tap the channel you want to unarchive. + +![Select a channel that you want to edit.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Unarchive Channel**. + +![Tap on Unarchive channel to unarchive the current channel.](/images/mobile-unarchive-a-channel.jpg) + +5. Tap **Yes** to confirm. + +![Tap on Yes to confirm your choice.](/images/mobile-confirm-unarchive-a-channel.jpg) + +
+ + + +Alternatively, system admins can unarchive channels [via the mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-unarchive), and Team admins can unarchive channels [via the API](https://api.mattermost.com/#operation/RestoreChannel). + + diff --git a/docs/main/end-user-guide/collaborate/audio-and-screensharing.mdx b/docs/main/end-user-guide/collaborate/audio-and-screensharing.mdx new file mode 100644 index 000000000000..5063510b6534 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/audio-and-screensharing.mdx @@ -0,0 +1,40 @@ +--- +title: "Audio and Screensharing" +--- + + +Mattermost Calls offers native real-time chat, self-hosted audio calls, and screen sharing within your own network, enabling secure, effective team communication and collaboration. Learn more about [deploying Mattermost Calls](/administration-guide/configure/calls-deployment-guide) in a self-hosted environment and [making calls](/end-user-guide/collaborate/make-calls) with Mattermost. + +With calls and screen sharing, Mattermost ensures that communications remain uninterrupted, even during maintenance or outages, and scales effortlessly to meet your team’s growing needs, safeguarding the integrity of mission-critical operations. + +Functionality includes: + +- **1:1 Audio Calls**: Initiate direct, real-time voice communication between two participants for quick resolution and sensitive discussions. +- **Audio Conference Calls**: Host multi-party voice calls to coordinate teams and resolve issues faster across distributed environments. +- **Screen Share**: Share your screen during calls to collaborate visually on tasks, review documents, or troubleshoot live issues. +- **Chat/Messaging During Calls**: Exchange messages alongside audio communication to enhance clarity, drop links, and provide visual context. +- **Search Chat History Post-Call**: Access in-call messages later to retain decision trails, links, and key points discussed. +- **Host Controls**: Manage participants, mute/unmute, and control the flow of conversations during conferences for structured engagements. +- **Call Recording**: Record voice sessions for review, compliance, or sharing with unavailable team members. *(Enterprise, Enterprise Advanced)* +- **Call Transcription**: Convert spoken content into text to support documentation, compliance, and improved accessibility. *(Enterprise, Enterprise Advanced)* +- **Live Captioning**: Provide real-time subtitles for inclusivity, accessibility, and support in noisy or multilingual environments. *(Enterprise, Enterprise Advanced)* +- **AI Call Summarization**: Automatically generate concise summaries of calls to save time and preserve key outcomes. *(Enterprise, Enterprise Advanced)* +- **Advanced Security Controls**: Enforce stricter encryption, access policies, and controls for high-assurance environments. *(Enterprise, Enterprise Advanced)* +- **High Availability**: Maintain service continuity through system failover and backup call paths. *(Enterprise, Enterprise Advanced)* + +## Video conferencing integrations + +For video conferencing, Mattermost integrates seamlessly with leading self-hosted and cloud providers, giving users the flexibility to easily transition from chat to video: + +- [Pexip](https://mattermost.com/marketplace/pexip-video-connect/): An enterprise-grade video conferencing solution with advanced security features, tailored for secure and scalable video collaboration. +- [Zoom](/integrations-guide/zoom): A widely used, cloud-based video conferencing platform known for its ease of use and wide range of collaboration tools, including screen sharing and breakout rooms. +- [Webex](https://mattermost.com/marketplace/webex-cloud/): A comprehensive video conferencing solution designed for enterprise-grade security, offering features like file sharing, virtual backgrounds, and meeting recordings. +- [Microsoft Teams](/integrations-guide/microsoft-teams-sync): A cloud-based collaboration platform that integrates with Microsoft 365, with text, voice, video, and file-sharing features. + + + +- Webex is community supported and not maintained by Mattermost. Please see the [GitHub repository](https://github.com/mattermost-community/mattermost-plugin-webex#readme) for the latest releases and documentation. +- Community supported integrations are not available to Cloud deployments of Mattermost. +- Looking for a [Skype for Business replacement](https://mattermost.com/skype-for-business-datasheet/)? Learn why Mattermost is the best solution to upgrade your collaboration strategy. + + diff --git a/docs/main/end-user-guide/collaborate/autotranslate-messages.mdx b/docs/main/end-user-guide/collaborate/autotranslate-messages.mdx new file mode 100644 index 000000000000..11cc2ca75c6c --- /dev/null +++ b/docs/main/end-user-guide/collaborate/autotranslate-messages.mdx @@ -0,0 +1,48 @@ +--- +title: "Auto-translate messages (Beta)" +--- + + +From Mattermost v11.5, messages in channels with auto-translation enabled are automatically translated into your preferred language. This enables seamless multilingual collaboration — you can read and respond in your own language while teammates do the same in theirs. + +## How auto-translation works + +Your system admin must first [enable auto-translation](/administration-guide/manage/admin/autotranslation) for your Mattermost instance. Then, a system admin or channel admin can enable it for individual channels. When autotranslation is enabled in a channel: + +- The language of each message is automatically detected. +- Messages are translated into your preferred display language and shown in place of the original text. +- Code blocks, URLs, and @mentions are preserved and not translated. +- Translations happen asynchronously — there may be a brief delay before the translated text appears. +- Messages written in your preferred language are not translated. + +## View translated messages + +Translated messages display in place of the original text. To view the original untranslated message, select the **translation** icon on the message. + +## Set your preferred language + +Auto-translation translates messages into your Mattermost display language. To change your display language: + +1. Select the gear icon to open **Settings**. +2. Select **Display \> Language**. +3. Choose your preferred language. +4. Select **Save**. + +See the [language](/end-user-guide/preferences/manage-your-display-options#language) documentation for more details. + +## Opt out of auto-translation in a channel + +You can opt out of auto-translation on a per-channel basis if you prefer to see original messages in a specific channel. To opt out: + +1. Open the channel where you want to disable auto-translation. +2. Select the channel name at the top to open the channel menu. +3. Disable the auto-translation option for this channel. + +You'll see original, untranslated messages in that channel going forward. You can re-enable auto-translation at any time using the same steps. + +## Limitations + +- **Direct and group messages**: Your system admin may have restricted auto-translation in direct and group messages. If auto-translation isn't available in a direct or group message, contact your system admin. +- **Short or mixed-language messages**: Very short messages or messages that mix multiple languages may not be reliably detected and translated. +- **Code-only messages**: Messages that contain only code blocks are not translated, as code is preserved in its original form. +- **Translation accuracy**: Translation quality depends on the translation provider configured by your system admin. Some languages or specialized terminology may produce less accurate results. diff --git a/docs/main/end-user-guide/collaborate/browse-channels.mdx b/docs/main/end-user-guide/collaborate/browse-channels.mdx new file mode 100644 index 000000000000..452267150719 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/browse-channels.mdx @@ -0,0 +1,60 @@ +--- +title: "Browse channels" +--- + + +
+ +Web/Desktop + +1. Select the **Plus** The Plus icon provides access to channel and direct message functionality. icon at the top of the channel sidebar to see all available public channels you can join that you're not already a member of. +2. Select **Browse Channels**. +3. Search for channels by name or scroll through the list. +4. Select **Join** next to any channel to become a member of that channel. + + + +From Mattermost v9.1, you can filter the list of channels by public, private, or archived channels, and you can hide all channels you're already a member of. + + + +
+ +
+ +Mobile + +1. Tap the **Plus** The Plus icon provides access to channel and direct message functionality. icon located in the top right corner of the app. + +![Tap the plus icon to view additional options.](/images/mobile-select-a-channel.jpg) + +2. Tap **Browse Channels**. + +![Click on Browse Channels to view the list of public channels.](/images/create-channel-or-open-direct-message-on-mobile.jpg) + +3. Search for channels by name or filter the list of channels to show only public, archived or shared channels. + +![Type the name of a channel in search to find it from the list.](/images/mobile-browse-public-channels-using-search.jpg) + +![Tap on Show to select from available filters such as Public channels, Archived channels, etc.](/images/mobile-browse-public-channels-using-filters.jpg) + +4. Tap a channel to become a member of that channel. + +![Tap on the public channel name that you want to join.](/images/mobile-browse-public-channels.jpg) + + + +You can filter the list of channels by public, archived, or shared channels. + + + +
+ +Want to see all of the channels you're already a member of, or can't find a specific private channel? Using a browser or the desktop app, select **Find Channel** in the channel sidebar to see all of the channels you're currently a member of across all of your teams, including public and private channels, direct and group messages, channels with unread messages, and threads. Channels you have muted aren't included in results. + +## Revisit recent channels + +Using a browser or the desktop app, use the **History** arrows at the top of the sidebar to move back and forth through your channel history. + +- Select the left arrow to go back one page. +- Select the right arrow to go forward one page. diff --git a/docs/main/end-user-guide/collaborate/channel-header-purpose.mdx b/docs/main/end-user-guide/collaborate/channel-header-purpose.mdx new file mode 100644 index 000000000000..674e22e29af1 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/channel-header-purpose.mdx @@ -0,0 +1,109 @@ +--- +title: "Communicate a channel's focus and scope" +--- + + +Every channel in Mattermost serves a purpose and exists for a reason. You can communicate a channel's focus and scope in 3 ways: + +- a descriptive [channel name](#channel-name) +- a [channel purpose](#channel-purpose) description +- [channel header](#channel-header) details + +## Channel name + +You're prompted to provide a channel name when [creating a new channel in Mattermost](/end-user-guide/collaborate/create-channels). Channel names must be at least 2 characters, and can be up to 64 characters in length. See the [channel naming conventions](/end-user-guide/collaborate/channel-naming-conventions) documentation for additional details and guidance on why channel naming is important. + + + +[Some unicode characters](https://www.w3.org/TR/unicode-xml/#Charlist) aren't supported in channel names. + + + +Looking to rename an existing channel? See the [rename channels](/end-user-guide/collaborate/rename-channels) documentation for details. + +## Channel purpose + +You're prompted to provide an optional channel purpose description when [creating a channel](/end-user-guide/collaborate/create-channels) or [renaming a channel](/end-user-guide/collaborate/rename-channels). A channel purpose can be up to 250 characters in length, and is often used to help users decide whether to join that channel. + +A channel's purpose is visible in the right pane when you select the **View Info** Use the Channel Info icon to access additional channel management options. icon for the channel. Any member of a channel can change a channel's purpose description, unless the system admin has [disabled the ability to do so](/administration-guide/onboard/advanced-permissions). + +
+ +Web/Desktop + +![Channel purpose helps users decide if they want to join the channel based on its scope or focus.](/images/channel-purpose-info.png) + +1. Select the channel name at the top of the center pane to access the drop-down menu, then select **Channel Settings**. +2. Enter or update the channel purpose. +3. Select **Save**. + +
+ +
+ +Mobile + +1. Tap the channel you want to edit. + +![Select a channel that you want to edit.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Edit Channel**. + +![Click on Edit channel to update the purpose of the channel.](/images/mobile-edit-channel.jpg) + +5. Type the new purpose of the channel and tap on **Save** to update the purpose. + +![Click on Edit channel to rename the channel.](/images/mobile-update-channel-purpose.jpg) + +
+ +## Channel header + +A channel header is text that displays directly under a channel name at the top of the channel. Any channel member can change a channel header, unless the system admin has [disabled the ability to do so](/administration-guide/onboard/advanced-permissions) + +A channel header can be up to 1024 characters in length, include Markdown formatting, and is often used to summarize the channel's focus or to provide links to frequently accessed documents, tools, or websites. + +
+ +Web/Desktop + +1. Select the channel name at the top of the center pane to access the drop-down menu, then select **Channel Settings**. +2. Enter or change channel header details. You can use the same [Markdown formatting](/end-user-guide/collaborate/format-messages#use-markdown) in the channel header as you would when composing a message. + +![Channel headers can include links to documents, tools, or websites.](/images/channel-header.png) + +
+ +
+ +Mobile + +1. Tap the channel you want to edit. + +![Select a channel that you want to edit.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Edit Channel**. + +![Click on Edit channel to to update the header of the channel.](/images/mobile-edit-channel.jpg) + +5. Type the new header of the channel and tap on **Save** to update the header. + +![Click on Edit channel to rename the channel.](/images/mobile-update-channel-header.jpg) + +
diff --git a/docs/main/end-user-guide/collaborate/channel-naming-conventions.mdx b/docs/main/end-user-guide/collaborate/channel-naming-conventions.mdx new file mode 100644 index 000000000000..52d92610a2d6 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/channel-naming-conventions.mdx @@ -0,0 +1,176 @@ +--- +title: "Channel naming conventions" +--- + + +All organizations are different and have different communication needs. The importance of organizing your conversations increases as your user base grows. The following are ideas for how you might want to name, group, and structure your channels. If you change your mind about a channel's name, you can [rename it](/end-user-guide/collaborate/rename-channels). + +## Basic structure + +- Channel names appear in menus where users select which conversations to join. +- Channel names are unique. +- Channel names have a 64-character limit to ensure readability on both desktop and mobile devices. +- An additional 1024 characters are available for describing the channel's focus in the channel header and channel information pane. +- An additional 128 characters are available for a **Channel Purpose** that's visible in the channel header and the channel information pane. +- Channel names can include standard Unicode emojis that are universally supported emojis that look the same (or similar) across platforms. Specify a Unicode emoji by positioning your cursor in the channel **Display Name** field and accessing the Unicode emoji picker for your operating system, as follows: + +> - On Windows press Windows + . or ; to open the Unicode emoji picker. +> - On macOS, press Ctrl + + Space to open the Unicode emoji picker. + +We recommend prefixing channel names with emojis for the following reasons: + +> - Emojis can make it easier for users to quickly identify and manage channels, particularly in large workspaces with many channels. +> - Sharing the same emoji across channels related to a specific category or function helps maintain organization and consistency across the workspace. +> - Making channels more visually distinct with emojis helps users find the channels they need more quickly and easily at a glance, reducing the time spent searching for the right channel. +> - New users can quickly understand the purpose of various channels based on their emoji prefixes without needing extensive explanations. +> - As users grasp channel structure through emojis, the time and effort needed to train new members on navigating the workspace is reduced. +> - A well-organized and visually appealing workspace can encourage users to participate more actively, which can lead to more effective communication and collaboration. + +## Scope channel names + +It's natural to start with broadly defined channels and let them divide into narrower topics as discussions progress. + +For example, you might begin with a general "Marketing" channel. As conversations progress, you might divide that channel into: "Marketing: Website", "Marketing: Social Media", "Marketing: General". + + + +Use colons to separate sections of channel names, rather than `-` or `>` which require more spaces to display. + + + +As the organization grows, disciplines might split across business units, products and geographies, with channel names like "US: Marketing" and "UK: Marketing". + + + +If you need to shorten country names, use standard [2-letter country codes](https://www.nationsonline.org/oneworld/country_code_list.htm). + + + +You can combine the hierarchies, with formats like `[SUB-TEAM]: [TOPIC]: [SUB-TOPIC]`. For example: `US: Mrkt: Website` and `UK: Mrkt: Social Media`. + + + +Shorten words, particularly categories, by removing vowels, endings, and redundant letter sounds. Example: Turn "Marketing" into "Mrkt", and "Project" into "Prjt". + + + +Good naming can take a team up to several thousand channels without significant confusion. Eventually every organization hits a limit and an additional team might need to be created on the server to accommodate the large number of channels. Keeping names clear and short lets users navigate large collections of channels quickly. + +Here are different navigation options and types of channels to consider. + +### Navigate channels using the keyboard + +Keyboard shortcuts allow users to jump between channels. See the [keyboard shortcuts](/end-user-guide/collaborate/keyboard-shortcuts) documentation for all available keyboard shortcuts. + +### Topic channels + +Topics are broad categories for organizing discussions. Topics are similar to how a user might create a folder for organizing emails or documents. Examples: Recruiting, Interviews, Legal Reviews, Documentation. + +Users can join and leave topic-based channels, as well as add colleagues to have topic-based discussions. + +As teams get larger and the number of channels increase, you may start naming topics in a hierarchy to make them easier to find. Examples: Legal: Trademarks, Legal: Contracts, Legal: Licensing. + +### Meeting channels + +Meeting channels are often used to organize regular meetings. Members can add topics as messages to be discussed during the regular meeting time. Examples: Monday Sales Update, All Hands Meeting. + +There are three built-in features to make meetings easier: + +1. Numbered agenda items in title text + +You can number and format messages as agenda items to discuss for the next meeting. + + + +Try pasting the following as an example in a channel designated for meetings: + + #### 1) Agenda item example + #### Commentary about agenda item to be discussed. + + + +2. Threaded messaging + +On an agenda item message, you can select `[...] > Reply` to leave comments about an agenda item before or after a meeting to extended discussion. + +3. Header links + +When meeting remotely, add persistent links to your video or audio conferencing solution, like Zoom, Google Hangouts, or BlueJeans in the channel header. See our [documentation](/end-user-guide/collaborate/channel-header-purpose) to learn more about working with channel headers. + +When it's time to meet, your team can select the conference link to connect. + +### Sub-team channels + +Sub-teams can include people from the same discipline, project teams, people with the same manager or other groups brought together for a shared purpose. Examples: Developers, Marketers, Offsite Organizing Committee, SusanK's Directs + +As sub-teams grow beyond a manageable size for one channel, they can sub-divide. Examples: US: Developers, UK: Developers, SusanK's Directs, SusanK's Extended Directs. + +### Project channels + +Project channels discuss how groups of people come together to achieve specific outcomes. Examples: Logo Design, Localization, Product Launch. + +Projects are often private channels rather than public channels and are used to organize a small team around a project brought up in a larger channel. The Project Channel is used to do detailed work, and updates are typically communicated back to larger channels. + +### Location channels + +If your teams are in different buildings, cities or regions, you can create Location channels to help people coordinate meetings and get-togethers. Examples: Building 10, Palo Alto, Toronto, Delaware. + +This helps share announcements and discussions relevant to only those locations. + +### Data channels + +Data channels allow automatic integration. Information like new or updated support tickets or bug reports, Twitter updates or mentions of your company name in the news can all be made available in channels your team chooses to monitor. There is a wide array of options. Examples: Bugs, Support Tickets, Twitter, News Mentions. + +People might use these channels like a daily newspaper, reading about everything that's happened in the last day, while other configurations allow notifications to alert only when their username or certain key words are mentioned. + +## Channel naming examples + +Here is an example of what a marketer's channels might look like in a small team: + +CHANNELS + +- Recruiting +- Interviews +- Marketing +- Sales +- All Hands Meeting +- Town Square +- Off-Topic + +PRIVATE CHANNELS + +- Website +- Twitter Marketing +- Logo Design + +DIRECT MESSAGES + +- \[Sales People\] +- \[Marketers\] +- \[Recruiter\] +- \[Manager\] + +Here's an example of what a marketer's channels might look like if she was working in the Palo Alto, California office of a large enterprise, working on a product called "Pontoon": + +CHANNELS + +- Geo: PA: Recruiting +- Geo: PA: Interviews +- US: Mrkt: General +- US: Sales: West Coast +- US: All Hands +- Town Square +- Off-Topic + +PRIVATE CHANNELS + +- Pontoon: Mkrt: Website +- Pontoon: Mkrt: Twitter +- Pontoon: Mkrt: Logo Design + +DIRECT MESSAGES + +- \[West Coast Sales People\] +- \[Marketing Peers\] +- \[Recruiter for PA office\] +- \[Manager\] diff --git a/docs/main/end-user-guide/collaborate/channel-types.mdx b/docs/main/end-user-guide/collaborate/channel-types.mdx new file mode 100644 index 000000000000..a9f076b0d602 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/channel-types.mdx @@ -0,0 +1,72 @@ +--- +title: "Channel types" +--- + + +Channels are used to organize conversations across different topics. The channels you're a member of display in the left pane. Learn how to create channels by visiting the [create channels](/end-user-guide/collaborate/create-channels) documentation. + +There are 5 types of channels in Mattermost: + +- [Public channels](#public-channels) +- [Private channels](#private-channels) +- [Direct message channels](#direct-message-channels) +- [Group message channels](#group-message-channels) +- [Archived channels](#archived-channels) + + + +Enterprise customers can additionally configure [read-only](/administration-guide/onboard/advanced-permissions#read-only-channels) broadcast channels. + + + +## Public channels + +Public channels are open to everyone on a team and are identified with a **Globe** Public channels are identified with a Globe icon. icon. New team members are automatically added to the **Town Square** channel. + +See the [Join and leave channels](/end-user-guide/collaborate/join-leave-channels) documentation for details on discovering, joining, and leaving other channels. + +## Private channels + +Private channels are channels for sensitive topics and are only visible to selected team members. Private channels are identified with a **Lock** Private channels are identified with a Lock icon. icon. Channel members can choose to leave private channels at any time. + + + +- Mattermost Enterprise and Professional customers can restrict channel management to system and channel admins. +- In a Mattermost Team Edition instance, any member of a private channel can add or remove other members from private channels. + + + +## Direct message channels + +Direct message channels are for conversations between 2 people. Only members of the conversation can see direct messages and channel heading information, including the last active status of the other user. + +You can start a direct message with people on other teams [unless the system admin has disabled your ability to do so](/administration-guide/configure/site-configuration-settings#enable-users-to-open-direct-message-channels-with). + +Direct messages update the numbered badge count and trigger a notification unless the direct message is muted, or your notifications are disabled. See the [notification documentation](/end-user-guide/preferences/manage-your-notifications) for details on customizing notifications based on your preferences. + + + +- From Mattermost v10, when sending a direct message, Mattermost warns you that the recipient's availability is set to [Do Not Disturb](/end-user-guide/preferences/set-your-status-availability#set-your-availability), and when the recipient's local time is outside of regular business hours (between 10PM and 6AM). This warning displays directly above the message text field. +- When a Mattermost user is deactivated in the system, your [direct message channel](/end-user-guide/collaborate/channel-types#direct-message-channels) with that user are [archived](#archived-channels) and marked as read-only. An **Archived** icon Archived channels are identified with a File Box icon. displays next to archived channels. + + + +## Group message channels + +Group message channels are for conversations between 3 to 7 people. Only members of the conversation can see group messages. Group messages always display a new message badge. + +Want to have a group conversation with more than 7 people? [Create a private channel](/end-user-guide/collaborate/create-channels). Alternatively, from Mattermost v9.1, you can [convert group messages to a private channel](/end-user-guide/collaborate/convert-group-messages). + + + +- You can start a group message with people on other teams when [unless the system admin has disabled your ability to do so](/administration-guide/configure/site-configuration-settings#enable-users-to-open-direct-message-channels-with). +- From Mattermost v9.1, group messages increase the numbered badge count and trigger a notification unless the direct message is muted, or your notifications are disabled. Control how you're notified about group message conversations by going to **Settings \> Notifications**. See the [notification documentation](/end-user-guide/preferences/manage-your-notifications) to learn more. +- Any group message history you have with a deactivated user remains available [unless your system admin disables your ability to do so](/administration-guide/configure/site-configuration-settings#allow-users-to-view-archived-channels). + + + +## Archived channels + +Archived channels are deactivated public, private, direct message, or group message channels that are no longer used. Archived channels are identified with a **File Box** Archived channels are identified with a File Box icon. icon. From Mattermost v11.5, archived private channels are identified with a distinct **Archive Lock** icon to visually differentiate them from archived public channels. + +[Archiving a channel](/end-user-guide/collaborate/archive-unarchive-channels#archive-a-channel) marks it read-only to prevent new messages from being sent and preserve channel history. You can continue to access archived channels, unless your system admin has [disabled](/administration-guide/configure/site-configuration-settings#allow-users-to-view-archived-channels) your ability to do so. diff --git a/docs/main/end-user-guide/collaborate/collaborate-within-channels.mdx b/docs/main/end-user-guide/collaborate/collaborate-within-channels.mdx new file mode 100644 index 000000000000..e466091f4408 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/collaborate-within-channels.mdx @@ -0,0 +1,44 @@ +--- +title: "Collaborate within channels" +--- + + +Channels are where you connect, collaborate, and communicate with your team about various topics or projects. Use channels to organize conversations across different topics. as you're [sending messages](/end-user-guide/collaborate/send-messages), [replying to messages](/end-user-guide/collaborate/reply-to-messages), and [participating in conversation threads](/end-user-guide/collaborate/organize-conversations#start-or-reply-to-threads). + +## You're added to default channels automatically + +Everyone who joins a Mattermost [workspace](/end-user-guide/end-user-guide-index) is automatically added to the **Town Square** channel. See our [Channel Types](/end-user-guide/collaborate/channel-types) documentation for details. + + + +The Town Square channel can't be [archived](/end-user-guide/collaborate/archive-unarchive-channels#archive-a-channel) or [converted to a private channel](/end-user-guide/collaborate/convert-public-channels), and users can't [leave](/end-user-guide/collaborate/join-leave-channels#leave-a-channel) this default channel. However, [guests](/administration-guide/onboard/guest-accounts) who are manually invited to **Town Square** can leave the channel. + + + +## Channel sidebar + +In the channel sidebar on the left, you'll find all of the the channels you're a member of as well as useful channel management tools. See the [channel types](/end-user-guide/collaborate/channel-types) to learn about the types of channels available, how they work, and how to identify them in the channel sidebar. Learn how to create channels by visiting the [create channels](/end-user-guide/collaborate/create-channels) documentation. + +As your channel sidebar fills up with channels you've joined, you can organize your channels into categories based on how you work. See the [customize your channel sidebar](/end-user-guide/preferences/customize-your-channel-sidebar) documentation for details. + +## Learn more + +Learn more about collaborating within Mattermost channels: + +- [Channel naming conventions](/end-user-guide/collaborate/channel-naming-conventions) - Learn why channel names are important. +- [Communicate a channel's focus and scope](/end-user-guide/collaborate/channel-header-purpose) - Learn how to communicate a channel's scope and focus. +- [Browse channels](/end-user-guide/collaborate/browse-channels) - Browse all available public channels you can join, and all channels you're a member of. +- [Join and leave channels](/end-user-guide/collaborate/join-leave-channels) - Learn how to start or stop being a channel member. +- [Make calls in Mattermost](/end-user-guide/collaborate/make-calls) - Learn how to start, join, and attend calls in Mattermost, as well as screen share. +- [Navigate between channels](/end-user-guide/collaborate/navigate-between-channels) - Learn how to navigate between channels. +- [Create channels](/end-user-guide/collaborate/create-channels) - Create channels to organize discussion by topic, project, or focus. +- [Rename a channel](/end-user-guide/collaborate/rename-channels) - Rename channels to make them more discoverable. +- [Display channel banners](/end-user-guide/collaborate/display-channel-banners) - Display a fixed banner at the top of channels to warn users about the presence of classified or sensitive information. +- [Auto-translate messages](/end-user-guide/collaborate/autotranslate-messages) - Automatically translate channel messages into your preferred language. +- [Convert public channels to private channels](/end-user-guide/collaborate/convert-public-channels) - Learn how to convert channel access and visibility. +- [Convert group messages to private channels](/end-user-guide/collaborate/convert-group-messages) - Learn how to convert group messages to private channels. +- [Manage channel members](/end-user-guide/collaborate/manage-channel-members) - Add and remove users from channels. +- [Mark channels as favorites](/end-user-guide/collaborate/favorite-channels) - Mark commonly visited channels as favorites. +- [Manage channel bookmarks](/end-user-guide/collaborate/manage-channel-bookmarks) - Manage quick access links or files pinned to the top of channels. +- [Mark channels as unread](/end-user-guide/collaborate/mark-channels-unread) - Mark channels unread to return to messages later. +- [Archive and unarchive channels](/end-user-guide/collaborate/archive-unarchive-channels) - Keep the number of available channels manageable. diff --git a/docs/main/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams.mdx b/docs/main/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams.mdx new file mode 100644 index 000000000000..c63c96659b92 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams.mdx @@ -0,0 +1,58 @@ +--- +title: "Collaborate within Microsoft Teams" +--- + + +The Mattermost for Microsoft Teams integration enables you to break through siloes in a mixed Mattermost and Teams environment by forwarding real-time chat notifications from Teams to Mattermost. + +![Mattermost for Microsoft Teams integration forwards real-time chat notifications from Teams to Mattermost.](/images/microsoft-teams-chat-notifications.gif) + + + +## Connect your Mattermost account to your Microsoft Teams account + + + +Your System Administrator must install and enable the [Mattermost for Microsoft Teams integration](/integrations-guide/microsoft-teams-sync) and ensure [support for notifications is enabled](/administration-guide/configure/plugins-configuration-settings#sync-notifications) in order for you to connect your account and recieve chat notifications. + + + +Once the integration is installed and configured by a System Administrator, you can connect your Mattermost user account to your Microsoft Teams account. You only need to complete this step once. + +1. Log into Mattermost using your credentials. +2. In any channel, run the `/msteams connect` slash command, and select the resulting link. +3. Authenticate with Microsoft Teams using the email address matching your account in Mattermost. + +Mattermost will confirm when your account is connected. + +Once you've connected your Mattermost account to your Microsoft Teams account, when you're offline or away from Microsoft Teams, any messages you receive in a chat or group chat in Microsoft Teams will display in Mattermost as a notification and include a link to open the chat in Microsoft Teams to continue the conversation. These notifications won't appear if you've been recently active in Teams. + +![An example of a chat message notification.](/images/microsoft-teams-chat-notifications.png) + +### Manage notification settings + +Manage your Mattermost notification settings for the Microsoft Teams integration at any time in **Settings** \> **Plugin Preferences** + +![Manage notification settings for the Microsoft Teams integration in Account Settings \> Plugin Preferences](/images/teams_plugin_notification_settings.png) + + + +You can run the following [slash commands](/integrations-guide/run-slash-commands#run-slash-commands) to manage your integration settings by typing the commands into the Mattermost message text box, and selecting **Send**: + +- `/msteams connect`: Connect your Mattermost account to Microsoft Teams account. +- `/msteams disconnect`: Disconnect your Mattermost account from Microsoft Teams account. +- `/msteams status`: Show your current connection status. +- `/msteams notifications on|off`: Change your current notifications settings. + + + +## Frequently asked questions + +### How does the integration determine when to send chat notifications? + +Chat notifications are sent in real-time whenever you're not active in Microsoft Teams and receive a chat or group chat. Mattermost uses your online status in Teams to determine if a chat notification should be delivered. Mattermost delivers notifications if you appear **Away** or **Offline** in Microsoft Teams, so the default behavior for when notifications will be delivered depends on the client you typically use to access Microsoft Teams: + +- Web browser: Mattermost delivers notifications when you've not had activity in your Microsoft Teams browser tab for 5 minutes or more, when the browser tab is closed, or when you mark yourself as **Offline** in Microsoft Teams. +- Desktop app: Mattermost delivers notifications when you've not had activity at your computer for 5 minutes or more, when the Microsoft Teams desktop app is closed, or when you mark yourself as **Offline** in Microsoft Teams. + +In order to avoid double notifications, Mattermost won't deliver chat notifications when your availability is set to **Available**, **Busy**, **Do not disturb**, or **Be right back** in Microsoft Teams. diff --git a/docs/main/end-user-guide/collaborate/communicate-with-messages.mdx b/docs/main/end-user-guide/collaborate/communicate-with-messages.mdx new file mode 100644 index 000000000000..2e2541c422b8 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/communicate-with-messages.mdx @@ -0,0 +1,32 @@ +--- +title: "Communicate with messages and threads" +--- + + +[Sending messages](/end-user-guide/collaborate/send-messages), [replying to messages](/end-user-guide/collaborate/reply-to-messages), and [participating in discussion threads](/end-user-guide/collaborate/organize-conversations#start-or-reply-to-threads) are important ways to keep conversations active with your team. + +## Work with messages and threads + +Learn more about messages and threads: + +- [Send messages](/end-user-guide/collaborate/send-messages) - Send messages to other Mattermost users. +- [Reply to messages](/end-user-guide/collaborate/reply-to-messages) - Communicate with your team in Mattermost. +- [React with emojis and GIFs](/end-user-guide/collaborate/react-with-emojis-gifs) - Use emojis and GIFs to react to messages and to express concepts, humor, emotions, and physical gestures in your own messages. +- [Organize conversations with threaded discussions](/end-user-guide/collaborate/organize-conversations) - An enhanced communication thread experience is available in Mattermost. +- [Mark messages as unread](/end-user-guide/collaborate/mark-messages-unread) - Change messages to an unread state for easy follow-up. +- [Forward messages](/end-user-guide/collaborate/forward-messages) - Quickly and easily forward messages with previews. +- [Share links to messages](/end-user-guide/collaborate/share-links) - Share links to messages across channels. +- [Save and pin messages](/end-user-guide/collaborate/save-pin-messages) - Mark useful messages for easy retrieval in the future. +- [Set message reminders](/end-user-guide/collaborate/message-reminders) - Set reminders to follow up on messages. +- [Search for messages](/end-user-guide/collaborate/search-for-messages) - Use search to find messages, replies, and file contents across Mattermost channels. +- [Schedule messages](/end-user-guide/collaborate/schedule-messages) - Schedule messages to be sent in the future. +- [Flag messages](/end-user-guide/collaborate/flag-messages) - Flag messages that may contain sensitive or restricted information for review by authorized moderators. + +## Make your messages stand out + +Learn more about making your messages stand out: + +- [Format messages](/end-user-guide/collaborate/format-messages) - Use markdown to format message content. +- [Set message priority](/end-user-guide/collaborate/message-priority) - Ensure important and urgent messages stand out clearly by adding priority labels, and requesting message acknowledgements. +- [Mention people](/end-user-guide/collaborate/mention-people) - Get the attention of specific people. +- [Share files in messages](/end-user-guide/collaborate/share-files-in-messages) - Share videos, voice recordings, and images in your Mattermost messages. diff --git a/docs/main/end-user-guide/collaborate/convert-group-messages.mdx b/docs/main/end-user-guide/collaborate/convert-group-messages.mdx new file mode 100644 index 000000000000..4975a74a4bed --- /dev/null +++ b/docs/main/end-user-guide/collaborate/convert-group-messages.mdx @@ -0,0 +1,53 @@ +--- +title: "Convert group messages to private channels" +--- + + +From Mattermost v9.1, you can change the members of your group conversation by converting the group message to a private channel. When a group message is converted to private, its history and membership are preserved. Membership in a private channel remains as invitation only. + + + +- Any member of an existing group message, except [guests](/administration-guide/onboard/guest-accounts), can convert that group message to a private channel. +- Conversation history will be visible to all channel members. +- All group message participants must share at least one team membership. + + + +
+ +Web/Desktop + +1. Select the group message name at the top of the center pane to access the drop-down menu, then select **Convert to Private Channel**. +2. Specify the team where the new private channel will be created. You're prompted to specify a team when all group message members share more than one team membership. +3. Enter a channel name. +4. Select **Convert to private channel**. + +
+ +
+ +Mobile + +1. Tap the group message you want to convert to a private channel. + +![Select a group that you want to convert.](/images/mobile-select-a-group-message.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the group.](/images/mobile-select-more-options-for-a-group.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic group info.](/images/mobile-select-view-info-for-a-group.jpg) + +4. Tap **Convert to a Private Channel**. + +![Tap on Convert to a Private Channel to convert the group.](/images/mobile-convert-group-to-private-channel.jpg) + +5. Enter the private channel name. + +![Type a name for the Private channel.](/images/mobile-provide-private-channel-name-for-the-group.jpg) + +6. Tap **Convert to Private Channel** to confirm. + +
diff --git a/docs/main/end-user-guide/collaborate/convert-public-channels.mdx b/docs/main/end-user-guide/collaborate/convert-public-channels.mdx new file mode 100644 index 000000000000..5676f749aabe --- /dev/null +++ b/docs/main/end-user-guide/collaborate/convert-public-channels.mdx @@ -0,0 +1,67 @@ +--- +title: "Convert public channels to private channels" +--- + + +You must be a system admin or team admin to convert public channels to private channels. When a channel is converted from public to private, its history and membership are preserved. Membership in a private channel remains as invitation only. Publicly-shared files remain accessible to anyone with the link. + + + +The default channel `Town Square` can't be converted to a private channel. + + + +
+ +Web/Desktop + +To convert a public channel to a private channel, select the public channel name at the top of the center pane to access the drop-down menu, then select **Convert to Private Channel**. + +![From the channel name, you can convert a public channel to a private channel if you're an admin.](/images/convert-public-channel-to-private.png) + +
+ +
+ +Mobile + +To convert a public channel to a private channel: + +1. Tap the channel you want to convert. + +![Select a channel that you want to rename.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Convert to private channel**. + +![Tap on Convert to private channel to make the channel private.](/images/mobile-convert-to-private-channel.jpg) + +5. Tap **Yes** to confirm. + +![Tap on Yes to confirm your choice.](/images/mobile-confirm-convert-to-private-channel.jpg) + +
+ +## Convert private channels to public channels + +Due to potential security concerns with sharing private channel history, only system admins can convert private channels to public channels using the System Console. + + + +- The ability to convert private channels to public channels using the [API](https://api.mattermost.com/#tag/channels/operation/UpdateChannelPrivacy) or [mmctl channel modify command](/administration-guide/manage/mmctl-command-line-tool#mmctl-channel-modify) is limited to system admins, team admins, and users with specific granular admin roles. Team admins have this permission by default, but system admins can restrict it or assign it to other roles. +- Granular roles require permissions for managing User Management Channels and Groups, including `sysconsole_write_user_management_channels` and `sysconsole_write_user_management_groups`. Manage permissions through the [permission scheme](/administration-guide/onboard/advanced-permissions#permissions-structure). +- If [Sync Group channel management](/administration-guide/manage/team-channel-members#channel-management) is enabled, private channels can't be converted to public channels. + + + +1. Go to **System Console \> Channels**. +2. Select **Edit** for an existing private channel. You can also filter the list of channels to private channels only. +3. Under **Channel Management \> Public channel or private channel**, select **Private**. +4. Select **Save**. diff --git a/docs/main/end-user-guide/collaborate/create-channels.mdx b/docs/main/end-user-guide/collaborate/create-channels.mdx new file mode 100644 index 000000000000..068607b72f4a --- /dev/null +++ b/docs/main/end-user-guide/collaborate/create-channels.mdx @@ -0,0 +1,74 @@ +--- +title: "Create channels" +--- + + +Anyone can create public channels, private channels, direct messages, and group messages unless the system admin has [restricted permissions to do so using advanced permissions](/administration-guide/onboard/advanced-permissions). Enterprise system administrators can also configure channels as [read-only](/administration-guide/onboard/advanced-permissions#read-only-channels). + +
+ +Web/Desktop + +## Create a public or private channel + +1. Select the **Add channels** button in the channel sidebar, then select **Create New Channel**. Alternatively, you can select The Plus icon provides access to channel and direct message functionality. at the top of the channel sidebar, then select **Create New Channel**. + +> You can create a channel using the Add channels button + +2. Enter a channel name. +3. Choose whether this is a public or private channel. See the [channel types](/end-user-guide/collaborate/channel-types) documentation to learn more about public and private channels. +4. (Optional) Describe the channel's focus or purpose. This text is visible to all channel members in the channel header. +5. (Optional) Assign the channel to a category. If your system admin has enabled [channel category sorting](/administration-guide/configure/experimental-configuration-settings#enable-channel-category-sorting), you can assign the new channel to a new or existing channel category. If this option isn't available, you can customize your channel sidebar \. + +## Start a direct or group message + +1. Select the The Plus icon provides access to channel and direct message functionality. next to the **Direct Messages** category in the channel sidebar. + +> ![Access recent direct messages and group messages.](/images/write-dm.png) + +2. Select up to seven users by searching or browsing. If your organization uses [connected workspaces](/administration-guide/onboard/connected-workspaces), you can also select remote users from shared channels for direct and group messages. + + + +- Alternatively, select The Plus icon provides access to channel and direct message functionality. at the top of the channel sidebar, then select **Open a Direct Message**. In the **Direct Messages** list, you'll see your most recent conversations. +- To add more people to the conversation select the channel name, then select **Add Members**. Adding members to a group message creates a new channel and starts a new conversation. +- You can't remove members of a group message; however, you can start a new group channel and conversation with different members. +- If you want to add more than 7 users to a group message, create a private channel instead. + + + +
+ +
+ +Mobile + +## Create a public or private channel + +Tap The Plus icon provides access to channel and direct message functionality. in the top right corner of the app, then select **Create New Channel**. Channels are created as public by default. If you want to create a private channel, tap the **Make Private** option. + +> ![You can create a new channel by tapping the plus in the top right corner.](/images/create-channel-or-open-direct-message-on-mobile.jpg) +> +> ![You can make a channel private by tapping the Make Private option.](/images/private-channel-create.jpg) + +## Start a direct or group message + +Tap The Plus icon provides access to channel and direct message functionality. in the top right corner of the app, then select **Open a Direct Message**. You can select one person for a direct message or up to seven people for a group message. If your organization uses [connected workspaces](/administration-guide/onboard/connected-workspaces), remote users from shared channels are also available to select. Tap **Start** to start the conversation. + +> ![You can start a direct or group message by tapping the plus in the top right corner.](/images/create-channel-or-open-direct-message-on-mobile.jpg) +> +> ![You can stat a group conversation by selecting up to 7 members.](/images/start-group-conversation.jpg) + +
+ +## Automate with channel actions + +The person who creates a channel automatically becomes the channel admin. Channel admins using Mattermost in a web browser or the desktop app can access **Channel Actions** from the channel name drop-down menu in the center pane to set up automatic actions when users [join the channel](/end-user-guide/collaborate/join-leave-channels#join-a-channel) or [post a message](/end-user-guide/collaborate/send-messages) to the channel. + +Automatic actions include: + +- Displaying a temporary welcome message for new channel members. +- Automatically adding the channel to a [category in the user's channel sidebar](/end-user-guide/preferences/customize-your-channel-sidebar). +- Prompting to run a playbook based on the contents of a message. + +The [collaborative playbooks must be enabled](/administration-guide/configure/plugins-configuration-settings#collaborative-playbooks) for channel admins to use channel actions. diff --git a/docs/main/end-user-guide/collaborate/display-channel-banners.mdx b/docs/main/end-user-guide/collaborate/display-channel-banners.mdx new file mode 100644 index 000000000000..467eae2c053a --- /dev/null +++ b/docs/main/end-user-guide/collaborate/display-channel-banners.mdx @@ -0,0 +1,37 @@ +--- +title: "Display channel banners" +--- + + +From Mattermost v10.9, users with admin permissions can enable channel banners to remind channel members about being diligent to avoid data spillage in channels that aren't intended for classified or sensitive information. These non-dismissible banners can be styled using Markdown and are visible across all Mattermost clients, including web browsers, the desktop app, and the mobile app. + +Channel banner use cases include the following: + +- Security classifications, such as **SENSITIVE INFORMATION: IMPACT LEVEL 5** with a distinctive color to alert members of the required security level. +- Important notices, such as **Reminder: Code complete deadlines are Fridays at 3 PM**, for recurring reminders. +- Policy or terms, such as **All discussion in this channel is private and restricted** with a red color to signal caution. + +Mattermost [channel admins](/end-user-guide/collaborate/learn-about-roles#channel-admin), [team admins](/end-user-guide/collaborate/learn-about-roles#team-admin), and [system admins](/end-user-guide/collaborate/learn-about-roles#system-admin) can enable a banner with custom text at the top of Mattermost public or private channels. + +Create a channel banner: + +1. Open a channel where you have administrative permissions. +2. Select the channel name at the top of the center pane to access the drop-down menu, then select **Channel Settings**. +3. Select **Configuration** and enable the **Channel Banner** option. +4. Specify the banner text you want to display at the top of the channel. You can style the text using [Markdown](/end-user-guide/collaborate/format-messages#use-markdown), if desired. +5. Select the banner color. +6. Select **Save** to apply the changes. The banner displays immediately. + +## Change a channel banner + +You can change the banner text or color at any time by following the same steps above. The new banner text or color displays immediately. + +## Remove a channel banner + +Disable the **Channel Banner** option in the channel settings to remove the banner from the channel. + + + +System admins can grant any user the ability to create and manage channel banners by assigning the **Manage Channel Banners** permission in the System Console. See the [advanced permissions](/administration-guide/onboard/advanced-permissions) documentation for details. + + diff --git a/docs/main/end-user-guide/collaborate/extend-mattermost-with-integrations.mdx b/docs/main/end-user-guide/collaborate/extend-mattermost-with-integrations.mdx new file mode 100644 index 000000000000..2682412bc767 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/extend-mattermost-with-integrations.mdx @@ -0,0 +1,31 @@ +--- +title: "Extend Mattermost with integrations" +--- +Ensure your teams are are always informed about important events, status changes, deadlines, or priorities with Mattermost operational and DevOps integrations. Enhance communication, streamline Mattermost with external workflows, ensure security and compliance, and foster a more efficient and collaborative work environment with major communication tools and services featuring real-time alerts, updates, and notifications directly within channels. + +## Interoperability with pre-built integrations + +Your system admin can install the following pre-packaged integrations through the Mattermost Marketplace, and enable and configure them in the Mattermost System Console. + +### Mattermost features + +- [AI Agents](/end-user-guide/agents#access-ai-features) +- [Export Mattermost channel data](/administration-guide/comply/export-mattermost-channel-data#usage) +- [Monitor performance metrics](/administration-guide/scale/collect-performance-metrics#usage) +- [Perform legal holds](/administration-guide/comply/legal-hold) + +### Mattermost interoperability + +- [GitHub](/integrations-guide/github#use) +- [GitLab](/integrations-guide/gitlab#use) +- [Jira](/integrations-guide/jira#use) +- [Microsoft Teams](/integrations-guide/microsoft-teams-sync#use) +- [ServiceNow](/integrations-guide/servicenow#use) +- [Zoom](/integrations-guide/zoom#use) + + + +- [Visit the Mattermost Marketplace](https://mattermost.com/marketplace/) to find open source, community-supported integrations to common developer tools like [CircleCI](https://mattermost.com/marketplace/circleci/), [Opsgenie](https://mattermost.com/marketplace/opsgenie/), [PagerDuty Notifier](https://mattermost.com/marketplace/pagerduty/); productivity tools like [Autolink](https://mattermost.com/marketplace/autolink-plugin/), [ToDo](https://mattermost.com/marketplace/todo/), and [WelcomeBot](https://mattermost.com/marketplace/welcomebot-plugin/); as well as social tools like [Memes](https://mattermost.com/marketplace/memes-plugin/) and [GIFs](https://mattermost.com/marketplace/giphy-plugin/) that are freely available for use and customization. +- Looking for a way to get notifications of new Mattermost Marketplace integrations in your Mattermost channels? See the [integrations FAQ](/integrations-guide/faq) documentation for details. + + diff --git a/docs/main/end-user-guide/collaborate/favorite-channels.mdx b/docs/main/end-user-guide/collaborate/favorite-channels.mdx new file mode 100644 index 000000000000..a9ef1cfbbbbb --- /dev/null +++ b/docs/main/end-user-guide/collaborate/favorite-channels.mdx @@ -0,0 +1,61 @@ +--- +title: "Mark channels as favorites" +--- + + +You can mark public and private channels, as well as direct and group messages as favorites so they're easy to access later. Favorite channels display in the **Favorites** category in the channel sidebar. + +![Favorite channels display in the channel sidebar.](/images/favorites-list-sidebar.png) + +To mark a channel as a **Favorite**: + +
+ +Web/Desktop + +1. Open a channel. +2. Select on the star icon next to the channel name. + +At the top of the page, select the Use the Star icon to mark a channel as a favorite. icon next to the channel name. + +![Mark a channel as a favorite.](/images/favorite-channel-desktop.png) + +To remove a channel from your **Favorites** list, select the Use the Star icon to mark a channel as a favorite. icon again. + +Alternatively to mark channels as favorites, select the channel name, select the **View Info** Use the Channel Info icon to access additional channel management options. icon, then select **Favorite** in the right pane. Select **Favorited** to remove the channel from your list of favorites. + +
+ +
+ +Mobile + +1. Tap the channel you want to mark as a favorite. + +![Select a channel that you want to mark as favorite.](/images/mobile-select-a-channel.jpg) + +2. Tap the Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **Favorite**. + +![Tap on Favorite to mark the channel as one of the favorites.](/images/mobile-select-view-info-for-a-channel.jpg) + +Alternatively, you can mark a favorite channel as follows: + +1. In a channel, tap the channel name at the top of the screen. + +![Tap on the channel name to view available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +2. Tap on **Favorite** + +![Tap on Favorite to mark the channel as one of the favorites.](/images/mobile-favorite-a-channel-within-channel.jpg) + +
+ +To remove a channel from the **Favorites** list, tap the **Favorited** option. + +![Tap on Favorited to unfavorite the channel.](/images/mobile-unfavorite-a-channel.jpg) + +![Tap on Favorited to unfavorite the channel.](/images/mobile-unfavorite-a-channel-from-within-the-channel.jpg) diff --git a/docs/main/end-user-guide/collaborate/flag-messages.mdx b/docs/main/end-user-guide/collaborate/flag-messages.mdx new file mode 100644 index 000000000000..c73e3b97f86e --- /dev/null +++ b/docs/main/end-user-guide/collaborate/flag-messages.mdx @@ -0,0 +1,29 @@ +--- +title: "Quarantine for Review" +--- + + +Every Mattermost user contributes to data security. From Mattermost v11.1, you can help keep your workspace secure and prevent data spillage by quarantining messages that may contain sensitive or restricted information for review by authorized moderators. Your quick actions can prevent accidental leaks before they spread, and build a culture of shared responsibility for secure communication. + +## Quarantine a message + +For example, you notice a public post in a channel that contains internal project details that not all users should have access to. You can quarantine that message as **Sensitive data** to alert designated content reviewers right away. + +1. Hover over the message, select the **More actions** Use the More icon to access additional message options. icon, and then select **Quarantine for Review**. +2. Select a **reason** for quarantining the message, and add a comment explaining why you're quarantining it, when required. +3. Select **Submit**. + +You’ll see a confirmation that your message was quarantined. Mattermost may hide the quarantined message based on how your system admin has configured Data Spillage Handling workflows. You can’t quarantine the same message twice. + +## If your message is quarantined + +A message being quarantined isn’t a disciplinary action. Quarantined messages help to protect sensitive data across your organization. + +If another user quarantines one of your messages, you’ll receive a direct message from the **Data Spillage Bot** explaining which message was quarantined and why. If Mattermost has hidden your message, the direct message won’t contain the quarantined message content. + +You'll receive another direct message once reviewers take action. + +- If your message is removed, review the reason why it was quarantined, and adjust how you share information in the future. +- If your message is kept, no further action is required of you. + +Contact your reviewer or system admin if you need clarification about actions taken or next steps. diff --git a/docs/main/end-user-guide/collaborate/format-messages.mdx b/docs/main/end-user-guide/collaborate/format-messages.mdx new file mode 100644 index 000000000000..f8b03d2b30cb --- /dev/null +++ b/docs/main/end-user-guide/collaborate/format-messages.mdx @@ -0,0 +1,665 @@ +--- +title: "Format messages" +draft: true +--- + + +## Use the messaging formatting toolbar + +From Mattermost v7.0, you can format your messages in Mattermost using the message formatting toolbar without having to specify any Markdown syntax. + +![The message formatting toolbar, available from Mattermost v7.0, doesn't require Markdown syntax, and makes formatting message text fast and easy.](/images/message-formatting-toolbar.gif) + +The message formatting toolbar offers the following formatting options: + + ++++ + + + + + + + + + + + + + + + + + + + + + + +
+

Formatting option

+
+
+
==================================================================================
+
+

Bold, italicize, or strike out text

+
+
+

Icon |

+
+
+
=========================+
+
+

bold-icon | italics-icon | strikeout-icon |

+
+
Add headings, links, or attachmentsheadings-icon | copy-link-icon | attachments-icon |
Format a numbered list, a bulleted list, quoted text, or text as codenumbered-icon | bullets-icon | quotes-icon | code-icon |
Add emojis or GIFs | emoji-icon |
Set message priority | message-priority-icon
+ +Review how your message formatting will look when the message is sent by selecting the **Show/Hide Preview** Review your message text formatting using the Show/Hide preview icon in the message formatting toolbar. icon. Return to your draft message by selecting the icon again. + + + +- Hide the formatting options by selecting the **Show/Hide Formatting** Hide formatting options in the message formatting toolbar using the Show/Hide Formatting icon. icon. Select the icon again to show the formatting options. +- You can control whether post formatting is rendered within the message formatting editor. When disabled, raw text is shown. See the [Channels customization](/end-user-guide/preferences/manage-advanced-options) documentation for details. + + + +## Use Markdown + +You can also format your messages in Mattermost using Markdown to control [text styling](#text-style), [links](#links), [headings](#headings), [lists](#lists), [code blocks](#code-blocks), [in-line code](#in-line-code), [in-line images](#in-line-images), [horizontal lines](#horizontal-lines), [block quotes](#block-quotes), [tables](#tables), and [math formulas](#math-formulas). Markdown makes it easy to format messages: type a message as you normally would, then use formatting syntax to render the message a specific way. For a guide to using Markdown in Mattermost, [see this blog post](https://mattermost.com/blog/laymans-guide-to-markdown-on-mattermost/). + +![Formatting markdown controls the look and feel of text messages.](/images/messagesTable1.png) + +### Text style + +You can use either `_` or `*` around a word or phrase to make it italic, or `__` or `**` around a word or phrase to make it bold. + + + +Common formatting keyboard shortcuts are supported. Bold text by pressing Ctrl B on Windows and Linux, or B on Mac. Italicize text by pressing Ctrl I on Windows or Linux, or I on Mac. + + + +- `*italics*` (or `_italics_`) renders as *italics* +- `**bold**` renders as **bold** +- `***bold-italic***` renders as Bold Italics +- `~~strikethrough~~` renders as Strike Through + +### Links + + + +Format selected message text as a link by pressing Ctrl K on Windows and Linux, or by pressing K on Mac. + + + +#### Channel links + +Create a link to a public channel in a message by typing `~` followed by the channel name (e.g. `~roadmap`). Channel members see private channel names returned. + +#### Labeled links + +Create labeled links by putting the desired text in square brackets `[ ]` and the associated link in round brackets `( )`. + +`[Check out Mattermost!](https://.mattermost.com/)` + +Renders as: [Check out Mattermost!](https://mattermost.com/) + +### Headings + +Make a heading by typing `#` and a space before your title. For smaller headings, use more `#`'s. + +``` text +## Large Heading +### Smaller Heading +#### Even Smaller Heading +``` + +Renders as: + +![Large Heading](/images/Headings1.png) + +Alternatively, you can underline the text using equal signs `===` or hyphens `---` to create headings. + +``` text +Large Heading +------------- +``` + +Renders as: + +![Smaller Heading](/images/Headings2.png) + +### Lists + +Create a list by using asterisks `*`, hyphens `-`, and/or plus signs `+` interchangeably as bullets. Indent bullet points by adding two spaces in front each one. + +``` text +* item one +- item two + + item two sub-point +``` + +Renders as: + +- item one +- item two + - item two sub-point + +Make an ordered list by using numbers instead: + +``` text +1. Item one +1. Item two +1. item three +``` + +Renders as: + +1. Item one +2. Item two +3. Item three + +You can also start a list at any number: + +``` text +4. The first list number is 4. +1. The second list number is 5. +1. The third list number is 6. +``` + +Renders as: + +4. The first list number is 4. +5. The second list number is 5. +6. The third list number is 6. + +Make a task list by including square brackets `[ ]`. Mark a task as complete by adding an `x`. + +``` text +- [ ] Item one +- [ ] Item two +- [x] Completed item +``` + +Renders as: + +![List](/images/checklist.png) + +### Code blocks + +Creating a fixed-width code block is recommended for pasting multi-line blocks of code or other text output because it's easier to read with fixed-width font alignment. Examples include block text snippets, ASCII tables, and log files. Rendered code blocks include a **Copy** option to copy the contents of the code block. + +This can be accomplished by placing three backticks ```` ` on the line directly above and directly below your code: .. code-block:: text `` this is my code block `.. tip:: Type three backticks```, press \`Shift \\_\_ Enter on Windows or Linux, or on Mac, ``, press Shift Enter on Windows or Linux, or on Mac again, then type three more backticks ```` `. Or by indenting each line by four spaces: .. code-block:: text this is my code block ^^^^ 4x spaces Syntax highlighting ^^^^^^^^^^^^^^^^^^^^ To add syntax highlighting, type the language to be highlighted after the ````\` at the beginning of the code block. Mattermost also offers four different code themes (GitHub, Solarized Dark, Solarized Light, and Monokai) that can be changed in **Settings \> Display \> Theme \> Custom Theme \> Center Channel Styles**. + +Supported languages and their aliases include: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LanguageAliases
ActionScriptactionscript, as, as3
AppleScriptapplescript
Bashbash, sh
Clojureclojure
CoffeeScriptcoffescript, coffee, coffee-script
C/C++cpp, c++, c
C#cs, c#, csharp
CSScss
Dd, dlang
Dartdart
Delphidelphi
Diffdiff, patch, udiff
Djangodjango
Dockerfiledockerfile, docker
Elixirelixir, ex, exs
Erlangerlang, erl
Fortranfortran
F#fsharp
G-Codegcode
Gogo, golang
Groovygroovy
Handlebarshandlebars, hbs, mustache
Haskellhaskell, hs
Haxehaxe
Javajava
JavaScriptjavascript, js
JSONjson
Juliajulia, jl
Kotlinkotlin
LaTeXlatex, tex
Lessless
Lisplisp
Lualua
Makefilemakefile, make, mf, gnumake, bsdmake
Markdownmarkdown, md, mkd
Matlabmatlab, m
Objective Cobjectivec, objective_c, objc
OCamlocaml
Perlperl, pl
Pascalpascal, pas
PostgreSQLpgsql, postgres, postgresql
PHPphp, php3, php4, php5
PowerShellpowershell, posh
Puppetpuppet, pp
Pythonpython, py
Rr, s
Rubyruby, rb
Rustrust, rs
Scalascala
Schemescheme
SCSSscss
Smalltalksmalltalk, st, squeak
SQLsql
Stylusstylus, styl
Swiftswift
Texttext
TypeScripttypescript, ts, tsx
VB.Netvbnet, vb, visualbasic
VBScriptvbscript
Verilogverilog
VHDLvhdl
HTML, XMLhtml, xml
YAMLyaml, yml
+ +Example: + +```` text +``` go +package main +import "fmt" +func main() { + fmt.Println("Hello, 世界") +} +``` +```` + +Renders as: + +**GitHub Theme** + +![Syntax Highlighting in GitHub](/images/syntax-highlighting-github.png) + +**Solarized Dark Theme** + +![Syntax Highlighting Dark](/images/syntax-highlighting-sol-dark.png) + +**Solarized Light Theme** + +![Syntax Highlighting Light](/images/syntax-highlighting-sol-light.png) + +**Monokai Theme** + +![Syntax Highlighting Monokai](/images/syntax-highlighting-monokai.png) + +### In-line code + +Create in-line monospaced code text by surrounding it with backticks ``. Don't use single quotes '\`. + +``` text +`monospace` +``` + +Renders as: `monospace`. + +### In-line images + +In-line images are images added within lines of text. You can control whether all in-line images over 100px in height are automatically collapsed or expanded in messages by setting a [user preference](/end-user-guide/preferences/manage-your-display-options), or by using the `/collapse` and `/expand` slash commands. + +To add in-line images to text, use an exclamation mark `!` followed by the `alt text` in square brackets `[ ]`, then the `image URL` in round brackets `( )`. You can add hover text after the link by placing the text in quotes `" "`. + +Example: + +``` text +![alt text](URL of image "Hover text") +``` + +If the height of the original image is more than 500 pixels, Mattermost sets the image height at 500 pixels and adjusts the width to maintain the original aspect ratio. + +You can set the width and height of the displayed image after the URL of the image by using an equals sign `=` followed by values for both width and height `##x##`. If you set only the width, Mattermost adjusts the height to maintain the original aspect ratio. + + + +The native apps do not support fixed width and height and will display the full-size image. + + + +Examples: + +``` text +.. |mattermost-icon-76x76| image:: ../images/icon-76x76.png +.. |mattermost-icon-50x76| image:: ../images/icon-50x76.png +``` + +#### In-line image with hover text + +``` text +![Mattermost](/images/icon-76x76.png "Mattermost Icon") +``` + +Renders as: + +> ![Mattermost](/images/icon-76x76.png) + +#### In-line image with link + + + +An extra set of square brackets `[ ]` is required around the alt text, and round brackets `( )` are required around the image link. + + + +``` text +[![Mattermost](/images/icon-76x76.png)](https://github.com/mattermost/mattermost) +``` + +Renders as: + +> [![image](/images/icon-76x76.png)](https://github.com/mattermost/mattermost) + +#### In-line image displayed with fixed width and height + +Example: An in-line image that's 50 pixels wide and 76 pixels high. + +``` text +![Mattermost](/images/icon-76x76.png =50x76 "Mattermost Icon") +``` + +Renders as: + +> Mattermost + +#### In-line image displayed with fixed width + +Example: An in-line image that's 50 pixels wide where the system adjusts the height to maintain the original aspect ratio. + +``` text +![Mattermost](/images/icon-76x76.png =50 "Mattermost Icon") +``` + +Renders as: + +> Mattermost + +### Horizontal lines + +Create a line by using three `*`, `_`, or `-`. + +`***` + +Renders as: + +------------------------------------------------------------------------------------------------------------------------ + +### Block quotes + +Create block quotes using `>`. + +`> block quotes` renders as: + +![image](/images/blockQuotes.png) + +### Tables + +Create a table by placing a dashed line `---` under the header row, then separating each column with using pipes `|`. The columns don’t need to line up exactly. Choose how to align table columns by including colons `:` within the header row. + +``` text +| Left-Aligned | Center Aligned | Right Aligned | +| :------------ |:---------------:| -----:| +| Left column 1 | this text | $100 | +| Left column 2 | is | $10 | +| Left column 3 | centered | $1 | +``` + +Renders as: + +![Markdown Table Sample](/images/markdownTable1.png) + + + +Multi-line text in a table cell isn't supported using HTML tags such as `
` or `
`. + +
+ +### Math Formulas + +
+ +Using Inline LaTeX + +You can create formulas that display inline using LaTeX. Use the dollar sign ($) symbol at the beginning and end of each formula. + + + +This feature is [disabled by default](/administration-guide/configure/site-configuration-settings#enable-inline-latex-rendering). Contact your system admin to enable this setting in **System Console \> Site Configuration \> Posts** to use this feature. + + + +``` text +$X_k = \sum_{n=0}^{2N-1} x_n \cos \left[\frac{\pi}{N} \left(n+\frac{1}{2}+\frac{N}{2}\right) \left(k+\frac{1}{2}\right) \right]$ +``` + +Renders as: + +![An inline LaTeX math equation sample.](/images/latex-inline.png) + +
+ +
+ +Using LaTeX in Code Blocks + +Create formulas as code blocks by using LaTeX in a `latex` [code blocks](#code-blocks). + + + +This feature is [disabled by default](/administration-guide/configure/site-configuration-settings#enable-latex-code-block-rendering). Contact your system admin to enable this setting in **System Console \> Site Configuration \> Posts** to use this feature. + + + +```` text +```latex +X_k = \sum_{n=0}^{2N-1} x_n \cos \left[\frac{\pi}{N} \left(n+\frac{1}{2}+\frac{N}{2}\right) \left(k+\frac{1}{2}\right) \right] +``` +```` + +Renders as: + +![A LaTeX code block math equation sample.](/images/latex-codeblock.png) + +
+ + diff --git a/docs/main/end-user-guide/collaborate/forward-messages.mdx b/docs/main/end-user-guide/collaborate/forward-messages.mdx new file mode 100644 index 000000000000..a7ce14f379b4 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/forward-messages.mdx @@ -0,0 +1,30 @@ +--- +title: "Forward messages" +--- + + +From Mattermost v7.2, using a web browser or the desktop app, you can forward messages in public channels to other public channels. From Mattermost v7.5, you can also forward messages from bots and webhooks. + + + +Private channels, direct messages, and group messages intended for specific people can't be forwarded. + + + +To forward a message: + +1. Select the **More** Use the More icon to access additional message options. icon next to a message, then select **Forward**. + +> ![You can forward messages to others using the More option.](/images/forward-message.png) + +2. Specify where you want to forward the message, and include an optional comment. + +Forwarding a message also generates a preview of the message. + +![Mattermost generates previews of links shared in Channels.](/images/permalink-previews.png) + + + +Previews respect channel membership permissions, so they’re only visible to users who have access to the original message. If the link is to a message in a public channel, any member of the team can see the message preview. If the link is to a message in a private channel or direct message, only members in that channel can see the message preview. + + diff --git a/docs/main/end-user-guide/collaborate/invite-people.mdx b/docs/main/end-user-guide/collaborate/invite-people.mdx new file mode 100644 index 000000000000..c19d4db571b3 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/invite-people.mdx @@ -0,0 +1,57 @@ +--- +title: "Invite people to your workspace" +--- + + +Anyone can invite people to Mattermost teams and channels, unless your system admin has [disabled](/administration-guide/onboard/advanced-permissions) your ability to do so. + +
+ +Web/Desktop + +1. Select the team name at the top of the channel sidebar, and then select **Invite People**. + +> ![Select the team name in the sidebar and select Invite People.](/images/invite-people.png) + +2. Choose how to invite people: + +> - **Copy invite link**: Share an invitation link with others using apps on your mobile device. +> - **Invite as member**: Send an invitation by email to people who don't have an account on your Mattermost workspace by specifying their email address and selecting **Invite**. +> - **Add existing users**: Add existing workspace users as members of the current team by specifying their username and selecting **Invite**. +> - **Invite as guest**: Invite a guest temporarily with limited workspace access. Specify their email address, select the channels they can access, and optionally add a custom message. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation to learn more about guest accounts. +> - **Use magic link**: Invite guests to log in without a password using a magic link when [enabled by your system admin](/administration-guide/onboard/guest-accounts#configure-magic-links-for-guests). See the [magic link login for guests](/end-user-guide/access/access-your-workspace#magic-link-login-for-guests) documentation for login details. +> +> ![You can invite users through the web or desktop app in a number of ways.](/images/web-desktop-invite-people-to-the-team.png) + +
+ +
+ +Mobile + +1. Tap the The Plus icon provides access to channel and direct message functionality. icon in the top right corner of the screen and tap **Invite people to the team**. + +> ![When you select +, you can access more options from the popup window.](/images/mobile-invite-people-to-the-team.png) + +2. Choose how to invite people: + +> - **Share link**: Share an invitation link with others using apps on your mobile device. +> - **Invite as member**: Send an invitation by email to people who don't have an account on your Mattermost workspace by specifying their email address and tap **Send**. +> - **Add existing users**: Add existing workspace users as members of the current team by specifying their username and tap **Send**. +> - **Invite as guest**: Invite a guest temporarily with limited workspace access. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation to learn more about guest accounts. Specify their email address, select the channels they can access, and optionally add a custom message. Tap **Send** when ready. +> - **Use magic link**: Invite guests to log in without a password using a magic link when [enabled by your system admin](/administration-guide/onboard/guest-accounts#configure-magic-links-for-guests). See the [magic link login for guests](/end-user-guide/access/access-your-workspace#magic-link-login-for-guests) documentation for login details. +> +> ![You can invite users through the mobile app in a number of ways.](/images/mobile-send-invite-to.png) + +
+ + + +- Can't share invitation links? Contact your Mattermost system admin for assistance. An [SSL certificate (or a self-signed certificate)](/administration-guide/onboard/ssl-client-certificate) may be required for link-based invitations to work. +- When inviting guests, you must select at least one channel they can access. Guests are limited to the channels you specify and cannot discover other channels. +- An invite link can be used by anyone and doesn’t change unless it’s re-generated or revoked by a system admin or team admin via **Team Settings \> Access \> Invite Code**. +- Your system admin must [enable email invitations](/administration-guide/configure/authentication-configuration-settings#enable-email-invitations) and configure [email](/administration-guide/configure/environment-configuration-settings#smtp) for Mattermost to send email-based invitations. + - Invitation links sent by email expire after 48 hours and can only be used once. +- Your system admin can [cancel all email invitations](/administration-guide/configure/authentication-configuration-settings#invalidate-pending-email-invites) that haven't yet been accepted within the System Console. + + diff --git a/docs/main/end-user-guide/collaborate/join-leave-channels.mdx b/docs/main/end-user-guide/collaborate/join-leave-channels.mdx new file mode 100644 index 000000000000..783fea64726c --- /dev/null +++ b/docs/main/end-user-guide/collaborate/join-leave-channels.mdx @@ -0,0 +1,109 @@ +--- +title: "Join and leave channels" +--- + + +## Join a channel + +Channels are either **public** or **private**. + +- **Public** channels are identified with a **Globe** Public channels are identified with a Globe icon. icon. Anyone on the team can join a public channel. +- **Private** channels are typically used for sensitive topics, and are identified with a **Lock** Private channels are identified with a Lock icon. icon. You must be invited to private channels by another channel member. + + + +To join a private channel, you need to be added to the channel by a member of that channel. + + + +To join a public channel: + +
+ +Web/Desktop + +1. Select the **Add channels** button in the channel sidebar, then select **Browse Channels**. + +> You can browse channels using the Add channels button +> +> Alternatively, you can select The Plus icon provides access to channel and direct message functionality. at the top of the channel sidebar, then select **Browse Channels**. +> +> ![You can browse available channels to join using the + option at the top of the channel sidebar.](/images/browse-channels.png) + +2. Select **Join** next to the public channel you want to join. + +> ![When browsing available channels, select the join option next to any channel to become a member.](/images/join-channels.png) + +
+ +
+ +Mobile + +1. Tap The Plus icon provides access to channel and direct message functionality. located in the top right corner the app. + +![Tap the plus icon to view additional options.](/images/mobile-select-a-channel.jpg) + +2. Tap **Browse Channels**. + +![Click on Browse Channels to view the list of public channels.](/images/create-channel-or-open-direct-message-on-mobile.jpg) + +3. Tap the public channel you want to join. + +![Tap on the public channel name that you want to join.](/images/mobile-browse-public-channels.jpg) + +
+ + + +When you join channels, depending on the [channel actions configured](/end-user-guide/collaborate/create-channels), you may see a welcome message, and channels may be added to [a category in your channel sidebar](/end-user-guide/preferences/customize-your-channel-sidebar) automatically. Using Mattermost in a web browser or the desktop app, access **Channel Actions** from the channel name drop-down menu in the center pane to see what automatic actions have been configured. + + + +See the following documentation to learn more about working with channels: + +- [Create channels](/end-user-guide/collaborate/create-channels) +- [Browse channels](/end-user-guide/collaborate/browse-channels) +- [Customize your channel sidebar](/end-user-guide/preferences/customize-your-channel-sidebar) + +## Leave a channel + +When you leave a private channel, you must be re-added by another channel member to rejoin. You won't receive mention notifications from a channel if you're not a member of that channel. + + + +All users are added to the **Town Square** channel automatically. This means that users can't [archive](/end-user-guide/collaborate/archive-unarchive-channels#archive-a-channel), [unarchive](/end-user-guide/collaborate/archive-unarchive-channels#unarchive-a-channel), or leave the **Town Square** channel. However, [guests](/administration-guide/onboard/guest-accounts) who are manually invited to **Town Square** can leave the channel. + + + +
+ +Web/Desktop + +Select the channel name at the top of the center pane to access the drop-down menu, then select **Leave Channel**. + +![You can use channel options available from the channel name to leave a channel.](/images/leave-channels.png) + +
+ +
+ +Mobile + +1. Tap the channel you want to leave. + +![Select the channel that you want to leave.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel you want to leave.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **Leave channel**. + +![Tap on Leave channel to leave the current channel.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap on **Leave** to confirm you choice. + +![Tap on Leave to confirm your choice.](/images/mobile-confirm-leave-a-channel.jpg) + +
diff --git a/docs/main/end-user-guide/collaborate/keyboard-accessibility.mdx b/docs/main/end-user-guide/collaborate/keyboard-accessibility.mdx new file mode 100644 index 000000000000..bbe42d82f2fe --- /dev/null +++ b/docs/main/end-user-guide/collaborate/keyboard-accessibility.mdx @@ -0,0 +1,76 @@ +--- +title: "Keyboard accessibility" +draft: true +--- + + +Navigational keyboard shortcuts help you use Mattermost in a web browser or the desktop app without needing a mouse. Below is a list of supported accessibility shortcuts. + + +++ + + + + + + + + + + + + + + + + + + + + +

Keyboard shortcut | Description |

==============================================+==================================================================================+ | Desktop App: F6 || Move focus to the next section | | Browser: Ctrl F6 || |

Desktop App: Shift F6 || Move focus to the previous section |
Browser: Ctrl Shift F6 |
Tab | Move focus to the next element |
Shift Tab | Move focus to the previous element |
or | Move focus between messages in the post list or sections in the channel sidebar |
Enter | Take action on the focused element |
+ +## Region navigation + +Mattermost has eight regions that can be focused for navigation. Use F6 in the desktop app, or use Ctrl F6 in a browser repeatedly to move focus and loop through the regions in this order: + +1. Message list region +2. Message input region +3. Right-hand side message list region +4. Right-hand side message input region +5. Team menu region +6. Channel sidebar region +7. Channel header region +8. Search + +![Navigate through the sections of Mattermost using a keyboard.](/images/navigation.gif) + +## Message navigation + +When the message list region is focused, use the or arrow keys to navigate through messages and reply threads. Press Tab to navigate through message actions. + +![Navigate through Mattermost messages using a keyboard.](/images/message-navigation.gif) + +### Message composition + +Mattermost is compatible with most popular screen readers, such as [Apple VoiceOver](https://www.apple.com/ca/accessibility/vision/) or [JAWS for Windows](https://www.freedomscientific.com/products/software/jaws/). A custom readout is composed for each message by combining the message elements and reading them together in full sentences. Message elements will read in the following order: + +1. Header: Author, timestamp, message type (i.e. parent post or reply) +2. Main Content: The message content typed by the author +3. Attachments: The number of attachments (if applicable) +4. Emoji Reactions: The number of unique emoji reactions (if applicable) +5. Saves/Pins: If a message is saved or pinned (if applicable) + +For example, a message read by a screen reader may sound like the following: + +``` text +Eric Sethna at 12:57pm Thursday June 13th wrote a reply "Thanks for the review", 3 attachments, 2 reactions, message is saved and pinned. +``` + +## Channel sidebar navigation + +When the channel sidebar region is focused, use the or arrow keys to focus individual sidebar sections, such as Insights, Threads, Favorites, custom categories, public channels, private channels, and direct messages. Press Tab to navigate through channels or other buttons within a sidebar section. + +![Navigate the Mattermost channel sidebar using a keyboard.](/images/channel-sidebar-navigation.gif) diff --git a/docs/main/end-user-guide/collaborate/keyboard-shortcuts.mdx b/docs/main/end-user-guide/collaborate/keyboard-shortcuts.mdx new file mode 100644 index 000000000000..31bf38666233 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/keyboard-shortcuts.mdx @@ -0,0 +1,440 @@ +--- +title: "Mattermost keyboard shortcuts" +draft: true +--- + + +Mattermost keyboard shortcuts help you make a more efficient use of your keyboard when using Mattermost in a web browser or the desktop app. + + + +- More keyboard shortcuts are available. See the [team keyboard shortcuts](/end-user-guide/collaborate/team-keyboard-shortcuts) and [text style](/end-user-guide/collaborate/format-messages#text-style) documentation for details. +- In Mattermost, display a list of available keyboard shortcuts by pressing Ctrl / on Windows or Linux, pressing / on macOS, or using the `/shortcuts` slash command. + +![Review a list of available keyboard shortcuts by using the \`\`/shortcuts\`\` slash command.](/images/keyboard-shortcuts.png) + + + +## Channel navigation + +The following keyboard shortcuts for channels are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
=====================================+==============================+==================================================================================+
+
+

Alt | | Previous channel or direct message in the channel sidebar. |

+
+
Alt | | Next channel or direct message in the channel sidebar. |
Alt Shift | | Previous channel or direct message in the channel sidebar with unread messages.
Alt Shift | | Next channel or direct message in the channel sidebar with unread messages.
Alt + select channel | + select channel | Mark the last post in the channel as unread. |
+
Ctrl K | K | - If text isn't selected: Open the Find Channels dialog. |
+
+
                             | - If text is selected: Create a hyperlink in the format [linktext](URL). |
+
+
Ctrl Shift K | K | Open the Direct Messages dialog.
Ctrl Shift A | A | Open the Settings dialog.
Ctrl Shift M | M | Open recent mentions.
Ctrl Shift L | L | Set focus to center channel input field.
Ctrl . | . | Open or close the right-hand sidebar. |
Ctrl Shift . | . | Expand or shrink the width of the open right-hand sidebar.
Ctrl Shift F | F | Move focus to the Search field and search the current channel.
Ctrl Shift U | U | Find unread channels or search through all channels.
Ctrl Shift I | I | Open or close Channel Info details in the right-hand sidebar.
+ +## File uploads + +The following keyboard shortcuts are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
=======================+====================+=================+
+
+

Ctrl U | U | Upload a file.

+
+
+ +## Messages + +The following keyboard shortcuts are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
===============================================+============================================+===========================================================+
+
+

Ctrl (in empty input field) | (in empty input field) | Reprint previous message or slash command you entered. |

+
+
Ctrl (in empty input field) | (in empty input field) | Reprint next message or slash command you entered. |
Shift (in empty input field) | (in empty input field) | Reply to the most recent message in the current channel. |
(in empty input field) | (in empty input field) | Edit your last message in the current channel. |
@[character] Tab | @[character] Tab | Autocomplete @username beginning with [character]. |
\~[character] Tab | \~[character] Tab | Autocomplete channel beginning with [character]. |
:[character] Tab | :[character] Tab | Autocomplete emoji beginning with [character]. |
Ctrl Shift \ | \ | React to last message in channel or thread.
+ +## Message formatting + +The following keyboard shortcuts are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
===================================+=============================+========================+
+
+

Ctrl B | B | Bold text. |

+
+
Ctrl I | I | Italicize text. |
Ctrl Alt K | K | Format text as a link.
+ +## Accessibility nagivation + +The following keyboard shortcuts work in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
==============================================+==========================================+==================================================+
+
+

Alt | [ | Go to the previous channel in your history.

+
+
Alt | ] | Go to the next channel in your history.
Shift (in input field) | (in input field) | Highlight text to the previous line.
Shift (in input field) | (in input field) | Highlight text to the next line.
Shift Enter (in input field) | Enter (in input field) | Create a new line.
+ + + +Though Mattermost keyboard shortcuts support standard languages and keyboard layouts, they may not work if you use keymapping that overwrites default browser shortcuts. + + + +## Calls + +The following keyboard shortcuts are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app when [calls](/end-user-guide/collaborate/make-calls) are enabled. + + +++ + + + + + + + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
===========================================================+==================================================+=========================================================================================+
+
+

Ctrl Alt S | S | Start or join call in current channel. |

+
+
Ctrl Shift Space | Space | Mute or unmute. |
Ctrl Shift Y | Y | Raise or lower hand. |
Ctrl Shift E | E | Share or unshare screen. |
Alt P or Ctrl Shift P | P or P | Show or hide participants list.
Ctrl Shift L | L | Leave current call. |
Space | Space | Hold to unmute (push to talk) Note: works in the expanded view/popout window only. |
+ +## Navigation in the desktop app + +The following navigation keyboard shortcuts are supported only in the Mattermost desktop app. + +
+ +Desktop app v6.x + +Mattermost desktop app v6.0 introduces the ability to keep multiple workspaces open at the same time and work across them without constant switching contexts. The following keyboard shortcuts help you navigate multiple views: + + +++ + + + + + + + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On macOS | Description |

+
+
+
======================================+===============================+=================================================================================================+
+
+

Ctrl N | N | Open a new window for the current server |

+
+
Ctrl T | T | Open a new tab for the current server |
Ctrl Tab | Tab | Go to the next tab |
Ctrl Shift Tab | Tab | Go to the previous tab
Ctrl 1-9 | 1-9 | Jump to a specific tab based on its position |
Ctrl W | W | Close current tab when multiple tabs are open |
Ctrl Shift W | W | Close main window
+ +
+ +
+ +Desktop app v5.x + +Mattermost desktop app v5.0 introduces additional ways to navigate your Mattermost interface, including server selections, as well as tabs for channels, collaborative playbooks, and boards. + + +++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On macOS | Description |

+
+
+
======================================+===============================+=================================================================================================+
+
+

Ctrl F | F | Move focus to the Search field and search the current channel. |

+
+
+
Ctrl Shift S | S | Open the Servers selector, press or to navigate between
+
+
                              | servers, then press Enter on Windows or Linux, or on macOS, to select a server. |
+
+
Ctrl Shift 1 || 1 || Navigate to the first server in the Servers list. |
+Ctrl Shift 2 || 2 || Replace the number with the server's position within the server in the list. |
Ctrl Tab | Tab | Navigate to the next product tab based on the current product selected. |
Ctrl Shift Tab | Tab | Navigate to the previous product tab based on the current product selected. |
Ctrl 1 | 1 | Navigate to the Channels tab. |
Ctrl 2 | 2 | Navigate to the Boards tab. |
Ctrl 3 | 3 | Navigate to the Playbooks tab. |
+ +
+ +
+ +Desktop app v4.7 and earlier + +Mattermost desktop app v4.7 and earlier releases support the following navigation keyboard shortcuts: + + +++ + + + + + + + + + + + + + + + + + +
+

On Windows & Linux | On macOS | Description |

+
+
+
======================================+==============================+================================================================================+
+
+

Ctrl F | F | Move focus to the Search field and search the current channel. |

+
+
Ctrl 1 || 1 | Navigate to the first server in the Servers list. |
+Ctrl 2 || 2 | Replace the number with the server's tab position. |
+Ctrl 3 || 3 | |
Ctrl Tab | Tab | Navigate to the next server tab based on the current server selected. |
Ctrl Shift Tab | Tab | Navigate to the previous server tab based on the current server selected.
Alt | | Next channel or direct message in the channel sidebar. |
+ +
+ +## Zoom in & zoom out display + +The following display keyboard shortcuts work in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost desktop app. + + +++ + + + + + + + + +
+

On Windows & Linux | On macOS | Description |

+
+
+
=====================================+==============================+========================================+
+
+

Ctrl Shift + | + | Increase font size (zoom in).

+
+
Ctrl Shift - | - | Decrease font size (zoom out).
+ + + +Though Mattermost keyboard shortcuts support standard languages and keyboard layouts, they may not work if you use keymapping that overwrites default browser shortcuts. + + diff --git a/docs/main/end-user-guide/collaborate/learn-about-roles.mdx b/docs/main/end-user-guide/collaborate/learn-about-roles.mdx new file mode 100644 index 000000000000..825a7df249ee --- /dev/null +++ b/docs/main/end-user-guide/collaborate/learn-about-roles.mdx @@ -0,0 +1,80 @@ +--- +title: "Learn about Mattermost roles" +--- + + +There are 6 types of user roles with different permission levels in Mattermost: [system admin](#system-admin), [team admin](#team-admin), [channel admin](#channel-admin), [member](#member), [guest](#guest), and [deactivated](#deactivated). + + + +To view a list of users on the team and what their roles are, you need to be A team admin using Mattermost in a web browser or the desktop app. Open the Team menu and select **Manage Members**. + + + +## System admin + +The first user added to a newly-installed Mattermost system is assigned the system admin role. System admins are allowed to perform any actions on the system, and only a system admin can make changes to another system admin user account in Mattermost. + +The system admin is typically a member of the IT staff and has all the privileges of a team admin, along with the following additional privileges: + +- Access to the System Console in any team site. +- Ability to change any setting on the Mattermost server available in the System Console. +- Ability to promote and demote other users from Member role to system admin role (and vice versa). +- Ability to promote and demote other users to and from Guest role. +- Ability to deactivate user accounts and to reactivate them. +- Access to private channels, but only if given the link to the private channel. + +A system admin can view and manage users in **System Console \> User Management \> Users**. They can search users by name, filter users by teams, and filter to view other system admins, guests, as well as activated and deactivated users. + +### Grant personal access tokens + +System admin also can enable [personal access tokens](https://developers.mattermost.com/integrate/admin-guide/admin-personal-access-token/) for user accounts. This gives specific users permissions to create personal access tokens via **System Console \> Users**. + +In addition, a system admin can optionally set the following permissions for the account, which are useful for integrations and bot accounts: + +- **post:all**: Allows the account to post to all Mattermost channels including direct messages. +- **post:channels**: Allows the account to post to all Mattermost public channels. + +## Team admin + +When a team is first created, the person who set it up is made a team admin. It is a team-specific role, meaning that someone can be a team admin for one team but only a member on another team. Team admins have the following privileges: + +- Access to the **Team Settings** menu. +- Ability to change the team name and import data from Slack export files. +- Access to the **Manage Members** menu, where they can control whether team members are a **Member** or a **Team Admin**. +- Ability to manage all aspects of a team, such as joining and managing private channels they're not a member of. + +## Channel admin + +The person who creates a channel is assigned the channel admin role for that channel. People with the channel admin role have the following privileges: + +- Ability to assign the channel admin role to other members of the channel. +- Ability to remove the channel admin role from other holders of the channel admin role. +- Ability to remove members from the channel. +- Ability to configure channel actions that automate tasks based on trigger conditions, such as [joining a channel](/end-user-guide/collaborate/join-leave-channels#join-a-channel) or [sending a message](/end-user-guide/collaborate/send-messages) in a channel. + +Depending on your system configuration, channel admins can be granted special permissions by the system admin to rename and delete channels. + +## Member + +This is the default role given to users when they join a team. Members have basic permissions on a Mattermost team. See the [advanced permissions backend infrastructure](/administration-guide/onboard/advanced-permissions-backend-infrastructure) documentation for details. + +## Guest + +A guest is a role with restricted permissions. Guests enable organizations to collaborate with users outside of their organization, and control what channels they are in and who they can collaborate with. See the [guest accounts](/administration-guide/onboard/guest-accounts) documentation for details on working with guest accounts. + +## Deactivated + +A system admin can deactivate user accounts via **System Console \> Users**. A list of all users on the server can be searched and filtered to make finding users easier. Select the user's role and in the menu that opens, then select **Deactivate**. See the [deactivate user accounts admin](/administration-guide/configure/user-management-configuration-settings#deactivate-users) documentation for details. + +When **Deactivate** is selected, the user is logged out of the system, and receives an error message if they try to log back in. The user no longer appears in channel member lists, and they are removed from the team members list. A deactivated account can also be reactivated from the System Console, in which case the user rejoins channels and teams that they previously belonged to. + +Direct message channels with deactivated users are hidden in users' sidebars, but can be reopened using the **More...** button or by pressing Ctrl K on Windows or Linux, or K on Mac. + +Mattermost is designed as a system-of-record, so there isn't an option to delete users from the Mattermost system, as such an operation could compromise the integrity of message archives. + + + +AD/LDAP user accounts can't be deactivated from Mattermost; they must be deactivated from your Active Directory. + + diff --git a/docs/main/end-user-guide/collaborate/make-calls.mdx b/docs/main/end-user-guide/collaborate/make-calls.mdx new file mode 100644 index 000000000000..c0058a412b16 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/make-calls.mdx @@ -0,0 +1,369 @@ +--- +title: "Make calls" +draft: true +--- + + +Using a web browser, the desktop app, or the mobile app, you can [join a call](#join-a-call) or [start a call](#start-a-call), [share your screen](#share-screen), raise your hand, [react using emojis](#react-using-emojis) during a call, [chat in a thread](#chat-in-a-call), and continue working in Mattermost during a call. + + + +- All Mattermost customers can start, join, and participate in 1:1 audio calls with optional screen sharing. +- For group calls up to 50 concurrent users, Mattermost Enterprise, Professional, or Mattermost Cloud is required. +- Enterprise customers can also [record calls](#record-a-call), enable [live text captions](/end-user-guide/collaborate/make-calls#live-captions-during-calls) during calls, and [transcribe recorded calls](#transcribe-recorded-calls). We recommend that Enterprise self-hosted customers looking for group calls beyond 50 concurrent users consider using the [dedicated RTCD service](/administration-guide/configure/calls-deployment-guide). +- Mattermost Cloud users can start calling right out of the box. For Mattermost self-hosted deployments, System admins need to enable and configure the plugin [using the System Console](/administration-guide/configure/plugins-configuration-settings#calls). + + + + + +## Join a call + +To join a call, select **Join call** in a channel, group message, or direct message. Any active team member in a channel or message can join a call, whether it's a public or private channel, or a group or direct message. + + + +- You can share a call's link to use in a meeting request or share with other people. The link is unique to each channel, and contains the channel's ID, so it doesn't change between calls. Use the `/call link` slash command to generate a shareable link. The call link is valid for long as the channel is active. When a channel is archived or deleted, the share link becomes invalid. +- If someone from outside of the organization wants to join a call, you need to provide them with a guest account, and add them to the channel. Users who are archived or not registered can't join a call. + + + +From Mattermost v9.4: + +- You can join the same call using a web browser, the desktop app, and the mobile app. You can mute, unmute, react, share your screen, and configure voice settings independently for each Mattermost client you're using. You'll appear multiple times as a call participant in the call widget when you join one call on multiple clients. +- You'll see incoming call notifications for direct and group messages when a new call is started. Multiple calls will result in multiple incoming call notifications. If you're already in a call, and you receive a new incoming call notification, Mattermost prompts you to **Join** the incoming call, or dismiss the notification. + +## Start a call + +
+ +Web/Desktop + +To start a call, select **Start call** in the channel header. When you start a call, you become the call host by default. See the [host controls](#host-controls) section below for details on host controls available to ensure calls run smoothly. + + + +- When you start a call in a channel, you're muted by default. In a direct or group message you're unmuted by default. +- You can move the call widget to a different area of your screen. +- Alternatively, you can start a call using the `/call start` slash command. + + + +
+ +
+ +Mobile + +To start a call, go the channel info menu. Then tap **Start Call**. + +![Tap on Start Call to start a call in the channel.](/images/mobile-start-a-call-in-a-channel.gif) + +After starting the call, audio will come through the device's speaker or a Bluetooth device, if connected. On Android, audio output will automatically switch to a Bluetooth device if one is connected during a call. You can tap the **Speaker** icon to manually select the output device. + +On iOS, audio will automatically come through a connected device. You can override this behavior by tapping the **Speaker** button. Audio will then come through the speaker. However, you cannot manually select an output device on iOS at this time. + +
+ +## Host controls + +From Mattermost v9.9, and Mattermost mobile v2.17, call host controls are available and include the ability to [transfer host duties](#transfer-host-duties), [remove call participants](#remove-call-participants), [stop a screen share](#stop-a-screen-share), [mute or unmute participants](#mute-or-nmute-participants), [lower raised hands](#lower-raised-hands), and [end the call for everyone](#end-the-call-for-everyone). + +Host controls are available to call hosts and admins in both the call widget by selecting the **More** Use the More icon to access additional message options. icon next to a participant's name, and in the expanded the call window as hosts hover over a call participant in the list. + +### Transfer host duties + +Transfer host duties to another call participant by accessing the host controls and selecting **Make host**. Once host duties are transferred to someone else, you can't access host controls unless they're transferred back to you. System admins can change the host at any time. + +### Remove call participants + +Remove a call participant from an active call by accessing the host controls and selecting **Remove from call**, then confirm by selecting **Yes, remove**. The call participant is notified that they've been removed from the call by the host. + +### Stop a screen share + +Stop a call participant's screen share by accessing the host controls and selecting **Stop screen share**. + +### Mute participants + +Invite muted participants to unmute their microphone by accessing the host controls and selecting **Ask to unmute**. The call particpant is prompted to decide whether unmute or stay muted. + +You can mute the microphone of specific particpants by accessing the host controls and toggling the particpant's mute icon. Mute all call particpants by selecting **Mute all**. + +### Lower raised hands + +Lower a raised hand by accessing the host controls and selecting **Lower hand**. The participant is notified that their hand was lowered by the host. + +### End the call for everyone + +From Mattermost v10.2 and mobile v2.19, call hosts who choose to leave a call are prompted to confirm whether they want to leave or end the call for all participants. + +## Share your screen + +During a call, call participants can share their screen with other call participants, unless your system admin has [disabled your ability to do so](/administration-guide/configure/plugins-configuration-settings#allow-screen-sharing). + + + +Screensharing is available in the Mattermost desktop app or a web browser. The ability to screenshare using the mobile app isn't supported. + + + +To share your screen: + +1. In the call widget, select **Start presenting**. +2. Select the screen you want to share. +3. To stop sharing, select the **Stop presenting** icon or the **Stop sharing** option. + +### Share audio during screen sharing + +From Mattermost Calls plugin v1.9.0, you can share audio along with your screen during screen sharing. To enable this feature, you must first turn on the **Share sound with screen** preference in your Calls settings by going to **Settings \> Plugin Preferences \> Calls**. This setting is stored locally on each client and is not synchronized across devices. + + + +Audio sharing support varies by platform and browser: + +**Web browsers:** + +- **Chrome-based browsers only** (Google Chrome, Chromium, Microsoft Edge): When sharing a browser tab, you'll have the option to include audio from that tab. On Windows only, you can also share system sounds when sharing the entire screen. +- **Other browsers**: Audio sharing is not supported. + +**Desktop app:** + +- **Windows and Linux**: System audio is shared when sharing the entire screen. +- **macOS**: Audio sharing is not supported due to system limitations. + + + +## React using emojis + +All call participants can use emojis to react during a call. + +
+ +Web/Desktop + +Expand the call window using the arrows in the top-right of the call widget. From there, select the emoji icon to access frequently-used emojis or select additional emojis from the emoji picker. + +
+ +
+ +Mobile + +Expand the call window using the arrows in the top-right of the active call banner. From there, select **React**. + +![Tap on React to use emojis reactions during a call.](/images/mobile-react-using-emojis-in-a-call.gif) + +
+ +## Chat in a call + +A chat thread is created automatically for every new call. + +
+ +Web/Desktop + +Open the chat thread in the widget by selecting the **Gear** Use the Settings icon to customize your Mattermost user experience. icon, then select **Show chat thread**. Alternatively, expand the call window using the arrows in the top-right of the call widget. From there, select the chat icon to access the chat thread. + +
+ +
+ +Mobile + +Expand the call window using the arrows in the top-right of the active call banner. Then select **More \> Call Thread**. + +![Tap on Call Thread to chat while being in a call.](/images/mobile-chat-in-a-call.gif) + +
+ +## Record a call + + + +From Mattermost v7.7, if you're the host of a meeting, you can record the call, unless your system admin has [disabled the host's ability to do so](/administration-guide/configure/plugins-configuration-settings#enable-call-recordings). + +Call recordings include audio, any screen sharing during the call, and text transcriptions, when [enabled](/administration-guide/configure/plugins-configuration-settings#enable-call-transcriptions). + +The default setting for a recording is 60 minutes, but your system admin may [change the recording duration](/administration-guide/configure/plugins-configuration-settings#maximum-call-recording-duration) as needed. You'll receive a reminder 10 minutes before the recording limit is reached. If your call is going to continue beyond the recording limit, allow the first recording to complete, then start a new recording immediately after. + +When you stop recording, the recording file is posted in the call thread as an MP4 file attachment. It's available to all users in the channel both during the call, and after the call has ended. + +To record a call: + +
+ +Web/Desktop + +1. Select **Start call** in the header of the channel, group message, or direct message. +2. Select the pop-out icon. +3. In the call widget, select the **Record** button. +4. To stop recording, select the **Record** button again. + +
+ +
+ +Mobile + +To start recording, use the `/call recording start` slash command. When you're finished recording, use the `/call recording stop` slash command. + +![Use '/call recording start' to start recording a call](/images/mobile-start-a-call-recording-using-slash-commands.gif) + +![Use '/call recording stop' to stop recording the call.](/images/mobile-stop-a-call-recording-using-slash-commands.gif) + +Alternatively, expand the call window using the arrows in the top-right of the active call banner. Then select the **Record** button. To finish, tap on **Stop Recording** button. + +![Tap on Record to start recording a call.](/images/mobile-start-a-call-recording-using-call-banner.gif) + +![Tap on Stop Recording to stop recording the call.](/images/mobile-stop-a-call-recording-using-call-banner.gif) + +
+ +## Live captions during calls + + + +From Mattermost v9.7, and Mattermost mobile app v.2.16, all call participants can display real-time text captions by selecting the **More** Use the More icon to access additional message options. icon and **Show live captions** when the call is being recorded, and when [live captions are enabled](/administration-guide/configure/plugins-configuration-settings#enable-live-captions). Live captions can be helpful in cases where noise is preventing you from hearing the audio of participants clearly. + +By default, live captions display in English. Your Mattermost system admin can [specify a different language for live captions](/administration-guide/configure/plugins-configuration-settings#live-captions-language) in the System Console. + + + +- The ability to enable live captions during Mattermost calls is currently in [Beta](/administration-guide/manage/feature-labels#beta). +- Your system admin must enable [call recordings](/administration-guide/configure/plugins-configuration-settings#enable-call-recordings) to enable live captions. + + + +## Transcribe recorded calls + + + +From Mattermost v9.4, and Mattermost mobile app v.2.13, call recordings can include text captions, and a transcription text file can be generated, unless your system admin has [disabled the ability to transcribe call recordings](/administration-guide/configure/plugins-configuration-settings#enable-call-transcriptions). + +When call recording stops, the transcription file is posted in the call thread as a TXT file attachment. It's available to all users in the channel both during the call, and after the call has ended. Additionally, users viewing the call recording can show or hide text captions using the Closed Captioning option in the video player. + + + +- The ability to enable recorded call transcriptions is currently in [Beta](/administration-guide/manage/feature-labels#beta). +- Your system admin must enable [call recordings](/administration-guide/configure/plugins-configuration-settings#enable-call-recordings) to enable recorded call transcriptions. + + + +## Frequently asked questions + +### Can I set a ring tone for incoming calls? + +Yes! From Mattermost v8.0 and Calls v0.17.0, desktop app and web users can go to **Settings \> Notifications \> Desktop Notifications** to enable Mattermost to alert you to incoming calls through direct or group messages with a specific ring tone and a desktop notification, unless the system admin has [disabled your ability to do so](/administration-guide/configure/plugins-configuration-settings#enable-call-ringing). + +### Is video supported? + +The integration currently supports only voice calling and screen sharing. We're considering video support in the future. + +### Can I password-protect a call? + +No. Any member with sufficient permission to access the channel can join the call. + +### Is there encryption? + +Media (audio/video) is encrypted using security standards as part of WebRTC. It's mainly a combination of DTLS and SRTP. It's not e2e encrypted in the sense that in the current design all media needs to go through Mattermost which acts as a media router and has complete access to it. Media is then encrypted back to the clients so it's secured during transit. In short: only the participant clients and the Mattermost server have access to unencrypted call data. + +### Are there any third-party services involved? + +The only external service used is Mattermost official STUN server (`stun.global.calls.mattermost.com`) which is configured as default. This is primarily used to find the public address of the Mattermost server. The only information sent to this service is the IP addresses of clients connecting as no other traffic goes through it. It can be removed in the System Console if you want to provide an `ICE Host Override` setting instead. + +## Troubleshooting + +### My audio doesn't work when I join a call + +If you can hear the other participants in the call but they can't hear you, select the Gear icon Use the Settings icon to customize your Mattermost user experience. next to the call end button in the widget. From there, you can check and change your audio output and microphone settings. Select Use the Settings icon to customize your Mattermost user experience. again to close the menu. Alternatively, you can [manage your audio and microphone preferences](/end-user-guide/preferences/manage-your-plugin-preferences) in **Settings**. + +### My call is disconnected after a few seconds + +This is usually a sign that the underlying UDP channel has not been established and the connection times out after ~10 seconds. When the connection has been established correctly an `rtc connected` line should appear in the client-side logs (JS console). There isn't a single solution as it depends on your infrastructure/deployment specifics. However, if you're a system or network admin, you may need to open up the UDP port or configure the network accordingly. + +### I can't screen share using Mattermost desktop on macOS + +There's a known bug on macOS with some versions of Chrome (which is used by Mattermost desktop). If you've given screen sharing permissions to Mattermost desktop, and are still unable to screen share, do the following: + +1. Quit Mattermost. +2. Open Terminal. +3. In the terminal, run: `tccutil reset ScreenCapture Mattermost.Desktop` +4. Restart Mattermost and start a call. +5. Select **Screen share** and give it permissions again. +6. Restart Mattermost again. + +If the issue persists please post on the Mattermost Community Server in the [Developer: Calls](https://community.mattermost.com/core/channels/developers-channel-call) channel to troubleshoot further. + +## Debugging + +If you experience issues with calls, collecting information is helpful as you can share it with us for debugging purposes. + +As with any other issue, but more importantly with calls, it’s very useful to let us know the date and time that the problem occurred, with as much detail as possible so that information can be cross-checked with server logs. Also please include any reproduction steps if applicable. Other important information includes: + +- Browser/app version +- Operating system type and version + +### JS console logs + +#### Web app + + ++++ + + + + + + + + + + + + + + + + + + + + +
BrowserAction
ChromeCMD+OPTION+J (macOS) CTRL+SHIFT+J (Windows, Linux, ChromeOS)
FirefoxCMD+SHIFT+J (macOS)/CTRL+SHIFT+J (Windows, Linux, ChromeOS)
SafariEnable Developer Menu in Safari > Preferences > Advanced > Show Develop Menu in Menu Bar. Then Develop > Show Javascript Console. Right-click on the console and select Save to file to download the logs.
+ +#### Desktop app + +In the top menu bar of the app, select **View \> Developer Tools \> Developer Tools for Current Tab**. In the logs that are generated, right-click and select **Save as** to download the logs. + +#### Mobile app + +You can access and share debug logs from **Account screen \> Settings \> Report a problem**. + +### Call stats dump + +In cases where there are audio/video issues, difficulty in hearing other participants, and/or stuttering video and/or choppy audio, run the `/call stats` slash command in the channel where the call is currently active. This returns a JSON object via an ephemeral message. Additionally, run the `/call logs` command to review the client logs for the last call session. + +You can run this command in an active call or after leaving the call in question. However, we will only save data for the last joined call so joining again will delete the previous call's feedback. + +### WebRTC internals (Chrome and Firefox only) + +This is an additional method for Chrome and Firefox users in cases where there are audio/video issues, difficulty in hearing other participants, and/or stuttering video and/or choppy audio. + +#### Chrome browser (recommended) + +Open `chrome://webrtc-internals/` in the browser that you're using for the active call. + +#### Firefox browser + +Open `about://webrtc` in the browser that you're using for the active call. + +### Share information + +Debug information is helpful to our community as there may be other community members having the same issue as you. We recommend that debug information be shared in either of the two options below: + +- Post in [Developers: Calls](https://community.mattermost.com/core/channels/developers-channel-call) channel: prefer this method when possible but keep in mind the channel is public. +- Post in [Team: Calls](https://community.mattermost.com/private-core/channels/calls-team) channel: use this channel if posting sensitive information. diff --git a/docs/main/end-user-guide/collaborate/manage-channel-bookmarks.mdx b/docs/main/end-user-guide/collaborate/manage-channel-bookmarks.mdx new file mode 100644 index 000000000000..076690b65ed0 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/manage-channel-bookmarks.mdx @@ -0,0 +1,143 @@ +--- +title: "Manage channel bookmarks" +--- + + +From Mattermost v10.1, you can bookmark up to 50 links or files to the top of channels for quick and easy access, unless your system admin has disabled your ability to do so. Bookmarks display directly under channel headers. Files added as channel bookmarks are also [searchable](/end-user-guide/collaborate/search-for-messages) in Mattermost. + +## Open a bookmark + +Opening a channel bookmark works the same way as selecting a file link or attachment in a message. Select or tap a bookmark to view the file or link. + +From Mattermost v10.11, bookmarks containing `mattermost://` links open directly in the desktop app using deep linking. This turns bookmarks into one-click shortcuts to channels, threads, or messages, letting you jump straight to key assets in Mattermost quickly and easily. + +## Add a bookmark + +
+ +Web/Desktop + +1. From Mattermost v10.5, select the channel name at the top of the center pane to access the drop-down menu, and select **Bookmarks Bar** to add a link or attach a file. In Mattermost versions prior to v10.5, select **Add a bookmark** in the bookmarks bar instead. + +> - Select **Add a link** to specify the link URL, specify bookmark text, and an optional bookmark icon. +> - Select **Attach a file** to select a file, specify bookmark text, and an optional bookmark icon. + +
+ +
+ +Mobile + +The bookmarks bar is hidden when a channel has no bookmarks. + +1. In a channel, select the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +2. Select **View info**. + +![Tap on View info to view additional information about the channel.](/images/mobile-select-view-info-for-a-channel.jpg) + +3. Tap on **Add a bookmark** to add the first bookmark. + +![Tap on Add a bookmark to add the first bookmark.](/images/mobile-add-first-channel-bookmark.jpg) + +For subsequent bookmarks, select the **Plus** The Plus icon provides access to channel and direct message functionality. icon in the bookmarks bar. + +![Tap on the Plus icon to add more bookmarks to the channel.](/images/mobile-add-subsequent-channel-bookmarks.jpg) + +4. You can either select **Add a link** to specify the link URL, specify bookmark text, and an optional bookmark icon. + +![Tap on Add a link to add a Bookmark link.](/images/mobile-attach-a-channel-bookmark-link.jpg) + +Or you can select **Add a file** to select a file, specify bookmark text, and an optional bookmark icon. + +![Tap on Add a file to add a file as Bookmark.](/images/mobile-attach-a-channel-bookmark-file.jpg) + +5. Tap on **Save**. + +
+ +## Manage bookmarks + +You can [edit](#edit-bookmarks) and [delete](#delete-bookmarks) bookmarks, as well as [copy bookmark links](#copy-bookmark-links). Additionally, web and desktop users can [reorder bookmarks](#reorder-bookmarks), and mobile users can [share bookmarks](#share-bookmarks). Changes to bookmarks are visible to all channel members. + +### Reorder bookmarks + +Using Mattermost in a web browser or the desktop app, drag bookmarks to reorder them in the bookmarks bar. Reordering channel bookmarks changes the display order for all channel members. + + + +You can't reorder channel bookmarks using the mobile app. + + + +### Edit bookmarks + +You can make changes to the bookmark link or file, the bookmark title, or the optional bookmark icon. Editing a bookmark changes the bookmark for all channel members. + +
+ +Web/Desktop + +Select the **More** Use the More icon to access additional message options. icon next to a bookmark and select **Edit**. + +
+ +
+ +Mobile + +Long-press on a bookmark and select **Edit**. + +![Tap and hold a bookmark name to explore more options.](/images/mobile-edit-a-channel-bookmark.gif) + +
+ +### Share bookmarks + +Using the mobile app, long-press on a bookmark and select **Share**. + +### Copy bookmark links + +You can copy bookmark links when your system admin has [enabled your ability to do so](/administration-guide/configure/site-configuration-settings#enable-public-file-links). + +
+ +Web/Desktop + +Select the **More** Use the More icon to access additional message options. icon next to a bookmark and select **Copy link**. + +
+ +
+ +Mobile + +Long-press on a bookmark and select **Copy link**. + +![Tap and hold a bookmark name to explore more options.](/images/mobile-copy-a-channel-bookmark-link.gif) + +
+ +### Delete bookmarks + +Deleting a channel bookmark deletes it for all channel members. + +
+ +Web/Mobile + +Select the **More** Use the More icon to access additional message options. icon next to a bookmark and select **Delete**. + +
+ +
+ +Mobile + +Long-press on a bookmark and select **Delete**. + +![Tap and hold a bookmark name to explore more options.](/images/mobile-delete-a-channel-bookmark.gif) + +
diff --git a/docs/main/end-user-guide/collaborate/manage-channel-members.mdx b/docs/main/end-user-guide/collaborate/manage-channel-members.mdx new file mode 100644 index 000000000000..3a96220eb1d8 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/manage-channel-members.mdx @@ -0,0 +1,164 @@ +--- +title: "Manage channel members" +--- + + +## Add members to a channel + +Any member of a channel can add other members to public or private channels, unless your system admin has restricted access to do so. + +When a channel has [attribute-based access controls](/administration-guide/manage/admin/attribute-based-access-control) enabled, you'll see details about which user attributes are permitted access to the channel. Only users who meet the requirements appear in search results when adding members to that channel. + +
+ +Web/Desktop + +To add members to a channel: + +1. Select the channel name at the top of the center pane to access the drop-down menu, then select **Add Members**. + + ![Use options available through the channel name to add a member to a channel.](/images/add-member-to-channel.png) + +2. Search for users, select users, then select **Add** to add users to the current channel. Mattermost notifies you when a user is already a member of the channel. + +
+ +
+ + Tip + +
+ + - From Mattermost v7.8, people you've messaged directly are listed first, followed by all users in alphabetical order. + - Alternatively, to add members to a channel, select the channel name, select the **View Info** Use the Channel Info icon to access additional channel management options. icon, select **Members** in the right pane, and then select **Add**. If the channel has access control restrictions, you'll see details about required attributes at the top of the right pane. + +
+ +
+ +
+ +Mobile + +To add members to a channel: + +1. Tap the channel name at the top of the screen. + + ![Click on the channel name to explore available options.](/images/mobile-channel-name-click.jpg) + +2. Tap **Add members**. + + ![Tap on Add members to add members to the channel.](/images/mobile-edit-channel.jpg) + +3. Select members to add to the channel. You can scroll through the alphabetical list of members, or search for members in the Search field. + + ![Select a user from the list and search one using the search field that you want to add to the channel.](/images/mobile-select-members-to-add-to-a-channel.jpg) + +4. Tap **Add Members**. + + ![Click on Add Members to add the member(s) to the current channel.](/images/mobile-add-selected-member-to-a-channel.jpg) + +
+ +### Mention users + +You can also [@mention users](/end-user-guide/collaborate/mention-people) to add them to a channel. If they're not a channel member, Mattermost prompts you to add them. + +![If a user mentioned in a channel is not a member already, then Mattermost prompts to add the user.](/images/mobile-add-user-to-a-channel-by-mentioning.jpg) + +### Add users from their profile + +Using a web browser or the desktop app, you can also add users to channels within their profile pop-over. + +1. Select a user's profile image. + +2. Tap on Account plus outline icon used to add user to a channel. icon. + + ![Use options on a user's profile pop-over to add a member to a channel.](/images/add-member-pop.jpg) + +3. Type to find a channel name, then select a channel and choose **Add**. + + ![Type the channel name and tap on Add to add the user to it.](/images/mobile-add-user-from-profile.jpg) + +## Leave a channel + +You can leave public or private channels any time. + +
+ +Web/Desktop + +Select the channel name at the top of the center pane to access the drop-down menu, then select **Leave Channel**. When you have permission to manage channel members, you can also leave a channel by going to **View Info \> Members \> Manage** and selecting your own name. + +
+ +
+ +Mobile + +1. In a channel, tap Use the More icon in the top left corner to access Mattermost desktop apps customization settings. in the top right corner. + + ![Tap on More options to access available options for the channel you want to leave.](/images/mobile-select-more-options-for-a-channel.jpg) + +2. Tap **Leave channel**. + + ![Tap on Leave channel to leave the current channel.](/images/mobile-select-view-info-for-a-channel.jpg) + +3. Tap on **Leave** to confirm you choice. + + ![Tap on Leave to confirm your choice.](/images/mobile-confirm-leave-a-channel.jpg) + +
+ +## Remove other members from a channel + +Any member of a channel can remove other members from a channel. + +
+ +Web/Desktop + +You have two ways to remove members from a channel: + +- Select the channel name at the top of the center pane to access the drop-down menu, then select **Manage Members**. Select the member's [user role](/end-user-guide/collaborate/learn-about-roles), then select **Remove from Channel**. +- Select the channel's **View Info** Use the Channel Info icon to access additional channel management options. icon, and select **Members** in the right pane. From there, select **Manage**, select a user's role, then select **Remove from Channel**. + +![Use options available through the channel name to remove a member from a channel.](/images/remove-member-from-channel.png) + +
+ +
+ +Mobile + +1. In a channel, tap Use the More icon in the top left corner to access Mattermost desktop apps customization settings. in the top right corner. + + ![Tap on More options to access available options for the channel you want to leave.](/images/mobile-select-more-options-for-a-channel.jpg) + +2. Tap **View Info**. + + ![Tap on View info to view additional information about the channel.](/images/mobile-select-view-info-for-a-channel.jpg) + +3. Tap **Members**. + + ![Tap on View info to view additional information about the channel.](/images/mobile-edit-channel.jpg) + +4. Tap **Manage** in the top right corner of the screen. + + ![Tap on Manage to access the user role of the members.](/images/mobile-view-members-of-a-channel.jpg) + +5. Tap a user role to change it, and tap **Remove from Channel**. + + ![Tap on Manage to access the user role of the members.](/images/mobile-manage-channel-members-list.jpg) + + ![Tap on Remove from channel to remove the selected user.](/images/mobile-remove-user-from-a-channel.jpg) + +6. Tap **Remove**. + + ![Tap on Remove to confirm your choice.](/images/mobile-confirm-remove-user-from-channel.jpg) + +7. Tap **Done**. + + ![Tap on Done to exit and return to the channel.](/images/mobile-exit-after-removing-user-from-a-channel.jpg) + +
diff --git a/docs/main/end-user-guide/collaborate/mark-channels-unread.mdx b/docs/main/end-user-guide/collaborate/mark-channels-unread.mdx new file mode 100644 index 000000000000..2c7c101af6e4 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/mark-channels-unread.mdx @@ -0,0 +1,14 @@ +--- +title: "Mark messages as unread" +--- + + +If you read messages in a channel, but don't have time to address them right away, you can mark that channel as unread. Hover over the channel name in the channel sidebar, select the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. option, then select **Mark as Unread**. + +![When you hover over channels in the channel sidebar, you can access more message options from the More icon.](/images/channel-more.png) + + + +Marking messages as unread displays those channels as bold in the channel sidebar. + + diff --git a/docs/main/end-user-guide/collaborate/mark-messages-unread.mdx b/docs/main/end-user-guide/collaborate/mark-messages-unread.mdx new file mode 100644 index 000000000000..e5c817d74cf2 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/mark-messages-unread.mdx @@ -0,0 +1,28 @@ +--- +title: "Mark messages as unread" +--- + + +If you read a message, but don't have time to address it right away, you can mark that message as unread. Marking a message as unread displays the channel as bold in the channel sidebar, and groups the message with all other unread messages. + +
+ +Web/Desktop + +Hover over the message, select the **More** Use the More icon to access additional message options. option, then select **Mark as Unread**. + +![When you hover over messages, you can access more message options from the More icon.](/images/message-more.png) + +![You can mark messages as unread to return to them later.](/images/mark-message-as-unread.png) + +
+ +
+ +Mobile + +Long press a message, and then tap **Mark as Unread**. + +![Tap and hold on a message to access the available options.](/images/mobile-mark-a-message-as-unread.gif) + +
diff --git a/docs/main/end-user-guide/collaborate/mention-people.mdx b/docs/main/end-user-guide/collaborate/mention-people.mdx new file mode 100644 index 000000000000..036e8d619ad7 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/mention-people.mdx @@ -0,0 +1,126 @@ +--- +title: "Mention people in messages" +--- + + +When you want to get the attention of specific Mattermost users, you can use @mentions. Mattermost supports the following types of @mentions: + +- [@username](#username) +- [@channel](#channel-and-all) +- [@all](#channel-and-all) +- [@here](#here) +- [@groupname](#groupname) +- [@customusergroupname](#customusergroupname) + + + +- If you forget to mention someone in a message, editing the existing message to add an @mention won't trigger new @mention notifications, desktop notifications, or notification sounds. +- Mattermost supports mentions for names that include accents (also known as diacritics). Names like Zoë, Jesús, Sørina, François, André, Jokūbas, Siân, KŠthe, or Fañch are returned in autocomplete results. + + + +## @username + +You can mention a teammate by using the *@* symbol plus their username to send them a mention notification. + +Type *@* or the full-width "@" (U+FF20) to bring up a list of team members who can be mentioned. To filter the list, type the first few letters of any username, first name, last name, or nickname. + + + +Mattermost v11.3 added support for full-width @, improving the experience for Japanese IME and other international keyboard users. Existing @ mentions are unaffected. See the :doc:v11.3 release notes \ for details. + + + + + +Using Mattermost in a web browser or the desktop app, you can also press the and arrow keys to scroll through entries in the list, and press ENTER on Windows or Linux, or on Mac, to select the person to mention. When selected, the username replaces the full name or nickname. + + + +The following example sends a special mention notification to Alice, whose username is **alice**. The notification alerts her of the channel and message where she was mentioned. If Alice is away from Mattermost and has email notifications turned on, she'll receive an email alert of her mention along with the message text. + +``` text +@alice how did your interview go with the new candidate? +``` + +If the person you mentioned doesn't belong to the channel or the team, a system message is posted to let you know, and you're given the option to add the person to the channel. You are the only one who can see this message. + +## @channel and @all + +You can mention an entire channel by typing `@channel` or `@all`. All members of the channel receive a mention notification that behaves the same way as if the members had been mentioned personally. If used in Town Square, it notifies all members of your team. + +You can ignore channel-wide mentions in specific channels in the **Channel Menu \> Notification Preferences \> Ignore mentions for @channel, @here and @all**. + +``` text +@channel great work on interviews this week. I think we found some excellent potential candidates! +``` + +If a channel has five or more members, you may be prompted to confirm that you want notifications sent to everyone in the channel. + +## @here + +You can mention everyone who is online in a channel by typing `@here`. This sends a desktop notification and push notification to members of the channel who are online. It's counted as a mention in the sidebar. Members who are offline don't receive a notification. When they return to Mattermost they won't see a mention counted in the channel sidebar. Members who are away receive a desktop notification only if they have notifications set to **For all activity**, and they won't see a mention counted in the sidebar. + +``` text +@here can someone complete a quick review of this? +``` + +If a channel has five or more members, you may be prompted to confirm that you want notifications sent to everyone in the channel. + +You can ignore channel-wide mentions in specific channels by enabling the **Channel Menu \> Notification Preferences \> Ignore mentions for @channel, @here, and @all** option. + +## @groupname + + + +This feature enables system admins to configure custom mentions for [LDAP synced groups](/administration-guide/onboard/ad-ldap-groups-synchronization) via the Group Configuration page. This functionality is also supported on the mobile app (from v1.34) if the AD/LDAP groups feature is enabled. The mobile app supports auto-suggesting groups, highlights group member mentions, and also provides a warning dialog when a mention will notify more than five users. + +Once enabled for a specific group, users can mention and notify the entire group in a channel (similar to `@channel` or `@all`). Members of the group in that channel will receive a notification. If members of the group mentioned aren't members of the channel, the user who posted the mention is prompted to invite them. + +Group mention identifiers (slugs) use the LDAP group name by default. To customize/rename the slug: + +1. Open **System Console \> User Management \> Groups**. +2. Select **Edit** next to the group you want to edit. +3. In **Group Profile \> Group Mention** enter the new slug. +4. Select **Save**. + +As with `@username` mentions, use *@* to bring up a list of groups that can be mentioned. To filter the list, type the first few letters of any group. Press the and arrow keys to scroll through entries in the list, and then press Enter on Windows or Linux, or pressing on Mac to select the group you want to mention. + +``` text +@dev-managers great work hitting all of our code coverage goals this quarter! +``` + +## @customusergroupname + +You can add groups of users to a channel or team by [creating a custom group](/end-user-guide/collaborate/organize-using-custom-user-groups) and @mentioning that custom group in a channel. + +- Mattermost prompts to you to add any users who aren't already members of that channel to the channel. +- From Mattermost v9.1, you're given the option to add any users who aren't already members of that team to the team, if you have the permissions to do so. + +## Words that trigger mentions + +You can customize words that trigger mention notifications in **Settings \> Notifications \> Words That Trigger Mentions**. By default, you receive mention notifications for your username and for `@channel`, `@all` and `@here`. You can choose to have your first name be a word that triggers mentions. + +You can add a list of customized words to get mention notifications for by typing them into the input box, separated by commas. This is useful if you want to be notified of all posts on certain topics, such as "interviewing" or "marketing". + +## See all recent mentions + +Select **@** to the right of the **Search** box to query for your most recent @mentions and words that trigger mentions (excluding LDAP group mentions). + +![See your most recent @mentions](/images/recent-mentions.png) + +Your recent mentions are shown for all of your teams. + +Select **Jump** next to a search result in the right-hand sidebar to jump the center pane to the channel and location of the message with the mention. + +## Confirmation dialog warnings + +When your system admin has configured Mattermost to require confirmations for @mentions, you must confirm any mention that will trigger notifications for more than five users before sending the notification. + +This confirmation dialog only appears when your system admin has configured this setting in the System Console. See our [configuration settings](/administration-guide/configure/site-configuration-settings#show-channel-all-or-here-confirmation-dialog) product documentation for details. This configuration setting is supported on the Mattermost Mobile App (from v1.34) if the [AD/LDAP groups](/administration-guide/onboard/ad-ldap-groups-synchronization) feature is enabled. + +## Mention highlights + +Valid mentions will have highlighted font text with some exceptions, for example if mentions are disabled at the channel level. The highlighted text becomes a hyperlink when a username is displayed. When the username is selected, the profile popover is displayed. + +When mentions trigger a notification, the user being notified will see highlighted font text and highlighted font background. This functions as an identifier of which mentions in the post triggered a notification for the user. diff --git a/docs/main/end-user-guide/collaborate/message-priority.mdx b/docs/main/end-user-guide/collaborate/message-priority.mdx new file mode 100644 index 000000000000..3b903ec8cc3a --- /dev/null +++ b/docs/main/end-user-guide/collaborate/message-priority.mdx @@ -0,0 +1,58 @@ +--- +title: "Set message priority" +--- + + +From Mattermost v7.7 and mobile v2.4, you can add a message priority label to root messages to make important messages requiring timely action or response more visible and less likely to be overlooked. + +Ensure important and urgent messages stand out clearly by adding priority labels to root messages. + +To set the priority of a new root message: + +1. Select the **Message Priority** Mark a message as important or urgent using the Priority Message icon. icon in the message formatting toolbar. Select from Standard, Important, or Urgent. +2. Select the priority for the message. Messages have a standard priority by default. +3. Select **Apply** + +When you send a priority message, the priority label displays next to your name in the channel, as well as the **Threads** view when others reply to the thread. + +## Send persistent notifications + +From Mattermost v8.0, messages marked as urgent with a priority label and containing an @mention can trigger persistent notifications that repeat until the recipient acknowledges, reacts, or replies. + +To enable persistent notifications for a message: + +1. Compose a root message with at least one @mention. +2. Select the **Message Priority** Mark a message as important or urgent using the Priority Message icon. icon in the message formatting toolbar. +3. Select **Urgent**. +4. Select **Send persistent notifications**. +5. Select **Apply**. + + + +- @channel, @all and @here mentions don't send persistent notifications. +- System admins can customize the maximum number of @mentions permitted, how frequently and how many persistent notifications are sent, as well as disable persistent notifications for all users, if preferred. By default, users are notified every 5 minutes for a total of 30 minutes. See the [configuration](/administration-guide/configure/site-configuration-settings#persistent-notifications) documentation for details. + + + +## Receive persistent notifications + +You must have desktop and/or mobile push notifications enabled to receive persistent notifications. How you're notified depends on your [notifications preferences](/end-user-guide/preferences/manage-your-notifications) for desktop and mobile push notifications. You won't be notified when your availability is set to **Do Not Disturb**, or if you're [Out of Office](/end-user-guide/preferences/set-your-status-availability#set-your-availability). Learn more about managing and customizing how you receive [Mattermost notifications](/end-user-guide/preferences/manage-your-notifications). + +Urgent messages show a red mention badge which remains visibible until you view the message. Selecting the **Acknowledge** icon (when present) won't impact the urgent red mention badge. + +![Example of the channel sidebar with both regular and urgent unread messages.](/images/urgent-message.png) + +To stop receiving persistent notifications, you can reply to the thread, select the **Acknowlege** icon (when present), or react to the thread with an emoji. Persistent notifications also stop if the original message is deleted, or if the maximum number of persistent notifications are sent. + +## Request acknowledgements + +You can additionally request that recipients actively acknowledge the message to track that messages have been seen and actioned. By default, marking a message as Urgent priority automatically requests an acknowledgement. + +When you request acknowlegement of a message, an **Acknowledge** Select the Acknowledge button to indicate that you've read it and taken necessary action. button is added below the sent message. You can mark message as acknowledged by selecting the button, and you can hover over the **Acknowledged** Select the Acknowledge button to indicate that you've read it and taken necessary action. icon to review who has acknowledged the message. + + + +- When you have push notifications enabled on mobile, you'll be notified every five minutes until you acknowledge or reply to the message. +- After acknowledging a message, you have up to five minutes to change your mind. Select the **Acknowledged** Select the Acknowledge button to indicate that you've read it and taken necessary action. button again to remove your name from the list of acknowledged users. + + diff --git a/docs/main/end-user-guide/collaborate/message-reminders.mdx b/docs/main/end-user-guide/collaborate/message-reminders.mdx new file mode 100644 index 000000000000..3358c42b9a2a --- /dev/null +++ b/docs/main/end-user-guide/collaborate/message-reminders.mdx @@ -0,0 +1,16 @@ +--- +title: "Set a reminder" +--- + + +From Mattermost v7.10, using Mattermost in a web browser or the desktop app, you can set 1 timed reminder on a post made in a channel, direct message, and group message. The ability to set up recurring reminders isn't supported. + +Hover over the message you want to remember, select the **More** Use the More icon to access additional message options. option, then select **Remind**. Select a time period or enter a custom date and time. You'll receive a direct message at the time you've chosen, with the body of the message you wanted to be reminded about. + +Once you've been reminded about a message, you won't receive another reminder unless you set one. + + + +From Mattermost v10.3, you can also schedule reminder messages to be sent in the future. See the [schedule messages](/end-user-guide/collaborate/schedule-messages) documentation for details. + + diff --git a/docs/main/end-user-guide/collaborate/navigate-between-channels.mdx b/docs/main/end-user-guide/collaborate/navigate-between-channels.mdx new file mode 100644 index 000000000000..6255f6a1fb81 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/navigate-between-channels.mdx @@ -0,0 +1,17 @@ +--- +title: "Navigate channels" +--- + + +## Navigate between channels + +Using Mattermost in a web browser or the desktop app, you can navigate between channels by selecting the **Find channel** option in the channel sidebar, or by pressing Ctrl K on Windows or Linux, or K on Mac. The Find channels screen also displays [member availability](/end-user-guide/preferences/set-your-status-availability) at a glance. + +> ![Navigate between channels and review member availability.](/images/switch-channels.png) + +## Return to recently viewed channels + +Using a web browser or the desktop app, use the **History** arrows at the top of the sidebar to move back and forth through your channel history. + +- Select the left arrow to go back one page. +- Select the right arrow to go forward one page. diff --git a/docs/main/end-user-guide/collaborate/organize-conversations.mdx b/docs/main/end-user-guide/collaborate/organize-conversations.mdx new file mode 100644 index 000000000000..6da4dd97550e --- /dev/null +++ b/docs/main/end-user-guide/collaborate/organize-conversations.mdx @@ -0,0 +1,112 @@ +--- +title: "Organize conversations using threaded discussions" +--- + + +Threads are a key part of the messaging experience in Mattermost. They're used to organize conversations and enable users to discuss topics without adding noise to channels or direct messages. + +Threaded discussions offers an enhanced experience for users communicating in threads and replying to messages that includes a unified threads inbox to read all conversations in one view. Threads improve the ability to process channel content, find, follow, and resume conversations more easily, and keep threaded conversations focused. + +![Organize conversations using threaded discussions.](/images/collapsed-reply-threads.gif) + + + +- From Mattermost v7.0, threaded discussions are enabled by default for all new Mattermost deployments. All Mattermost users can create new threads, unless the system admin has [disabled the ability to do so](/administration-guide/configure/site-configuration-settings#threaded-discussions). +- System admins can [configure default availability and user opt-in](/administration-guide/configure/site-configuration-settings#threaded-discussions) of threaded discussions. + + + +## Start or reply to threads + +[Replies to messages](/end-user-guide/collaborate/reply-to-messages) are collapsed under the first message of a thread. Open a thread by selecting the message or reply count. + +From Mattermost v11.2, when using Mattermost in a web browser, you can open threads in separate browser windows by selecting the **New Window** Open thread in a new browser window icon. icon in the thread header. This allows you to view and participate in multiple threads simultaneously without losing context. + +## Follow threads and messages + +You'll automatically follow every thread you participate or are mentioned in. You can manually follow particular messages and threads so that any reply activity triggers [notifications](/end-user-guide/preferences/manage-your-notifications). Follow or unfollow any thread, at any time. In channels, a dot next to thread participants means there are unread replies for the threads you're following. + +![Follow threads to stay updated on replies to messages.](/images/crt-following-thread.png) + +
+ +Web/Desktop + +Toggle the thread’s **Follow** option, or select **Follow thread** from the **More Actions** Use the More icon to access additional message options. icon. + +![Unfollow threads from the More Actions icon.](/images/crt-following-thread.jpg) + + + +\- Follow messages with no replies from the **More Actions** Use the More icon to access additional message options. icon to be notified if someone replies to the message later based on your notification preferences. - You can also use keyboard arrow keys to navigate threads in the **Threads** view. + + + +
+ +
+ +Mobile + +Long-press on a message to access message options, then tap **Follow Thread**. + +![Tap and hold on a message thread to select Follow Thread.](/images/mobile-follow-a-message-thread-with-follow-option.gif) + +Alternatively, you can also tap on the **Follow** indicator below a message thread to follow it. + +![Toggle the Follow indicator to start folowing a thread.](/images/mobile-follow-a-message-thread-by-tapping-follow.gif) + + + +Follow messages with no replies from the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon to be notified if someone replies to the message later based on your notification preferences. + +![Tap and hold on a message with no replies to select Follow Message.](/images/mobile-follow-a-message-with-no-replies.gif) + + + +
+ +## Unfollow threads + +If you’re no longer interested in a or message thread, unfollow it to stop receiving notifications. Viewing a thread without responding to it doesn’t automatically follow that thread. + +
+ +Web/Desktop + +Toggle the thread’s **Following** indicator, or select **Unfollow thread** from the **More Actions** Use the More icon to access additional message options. icon to unfollow it. + +![Unfollow threads from the More Actions icon.](/images/desktop-unfollow-message-thread.jpg) + +
+ +
+ +Mobile + +Long-press on a message to access message options, then tap **Unfollow Thread**. + +![Tap and hold on a message thread you're following to select Unfollow Thread.](/images/mobile-unfollow-a-message-thread-with-unfollow-option.gif) + +Alternatively, you can tap on the **Following** indicator below the message thread to unfollow it. + +![Toggle the Following indicator to stop following a thread.](/images/mobile-unfollow-a-message-thread-by-tapping-following.gif) + +
+ +## View all threads + +Select **Threads** at the top of the channel sidebar to see all your followed threads on the currently selected team. Threads with the most recent replies display at the top of the list. + +Select **Unreads** to filter your followed threads by only those with unread replies. + +![Select Threads in the channel sidebar to see all thread updates in your Threads View.](/images/crt-thread-view.jpg) + +## Tutorial video + +
+
+ +## Known issues + +Threaded discussions were released as generally available in Mattermost v7.0, including significant server performance improvements and more flexible configuration options for system admins to enable the feature by default. We highly recommended [upgrading Mattermost](/administration-guide/upgrade/upgrading-mattermost-server) to take advantage of configuration and performance enhancements. diff --git a/docs/main/end-user-guide/collaborate/organize-using-custom-user-groups.mdx b/docs/main/end-user-guide/collaborate/organize-using-custom-user-groups.mdx new file mode 100644 index 000000000000..09513fc74b0f --- /dev/null +++ b/docs/main/end-user-guide/collaborate/organize-using-custom-user-groups.mdx @@ -0,0 +1,85 @@ +--- +title: "Manage custom groups" +--- + + +Custom groups reduce noise and improve focus by notifying the right people in a channel at the right time, while maintaining transparency for all members in that channel. Custom user groups let you notify up to 256 users at a time rather than notifying users individually. + +For example, perhaps you want to @mention a cross-functional team about a bug fixes needed for an upcoming feature release, without notifying everyone else in the channel. Using a custom group notifies the cross-functional team immediately, while keeping important stakeholders in the loop on the status of the feature release. + +Or perhaps you want to add a group of users to a team and a channel. When you @mention a custom group in a channel, Mattermost prompts you to add anyone from that custom group who isn't already a channel and team member. See the [invite people to your workspace](/end-user-guide/collaborate/invite-people) documentation for details. + +Once a custom user group has been created, you can mention that group the same way you @mention another Mattermost member. See the [mention people in messages](/end-user-guide/collaborate/mention-people) documentation for details. + + + +- System admins need to enable this feature. See our [Mattermost Configuration Settings](/administration-guide/configure/site-configuration-settings#enable-custom-user-groups) documentation for details. +- From Mattermost v7.2, system admins can limit who can manage custom user groups through the Custom Group Manager system admin role. See the [delegated granular administration](/administration-guide/onboard/delegated-granular-administration) documentation for details. +- The ability to create custom user groups on mobile will be available in a future release. @mentions for custom user groups on mobile work the same as [LDAP-synced groups](/end-user-guide/collaborate/mention-people#groupname). + + + +## Create a custom group + +1. Using Mattermost in a web browser or the desktop app, select The Plus icon provides access to channel and direct message functionality. at the top of the channel sidebar, then select **Create New User Group**. +2. Specify a name and mention. The mention is the handle you use to @mention a notification to the group. Group names must be unique across the Mattermost [workspace](/end-user-guide/end-user-guide-index). If a name is in use as a channel name, display name, or another custom group's name, it won't be available. +3. Search for and select members to add to the custom user group, then select **Create Group**. + +## Review group members + +From Mattermost v7.8, using Mattermost in a web browser or the desktop app, select a group mention in a thread to display a list of group members. + +## Manage custom user groups + +You can review and filter the list of custom groups, add people to an existing group, edit the group name or mention, leave the group, or archive the group. + +To manage a custom user group in a web browser or the desktop app, select **User Groups** from the Products menu, then select the group you want to modify. + +![Access tools to manage user groups.](/images/access-user-groups.png) + +### Review available groups + +Review a list of all available custom user groups, search for specific groups by name. + + + +You can filter the list of groups to display only groups you're a member of, or only archived groups. + + + +### Change name or mention + +1. From the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon to the right of any custom group, select **View Group**. + +> ![Access tools to manage your custom user groups.](/images/manage-user-groups.png) + +2. From the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon, select **Edit Details**. + +> ![Edit details of a custom user group.](/images/edit-custom-group.png) + +3. Update the **Name** or **Mention**, then select **Save Details**. + +### Add people + +1. Select **Add People**. +2. Search for and select people to add to the group, then select **Add People**. + +### Remove people + +Hover over a member, then select the **Trash** icon to remove them from the group. + +### Join a group + +While viewing the members of a group, from the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon, select **Join Group**. + +### Leave a group + +From the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon, select **Leave Group**. + +### Archive group + +From the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon, select **Archive Group**. When you archive a custom user group, you won’t be able to mention the group’s handle or view its members. However, the group isn't deleted from the list, and all members remain in the group unless they're manually removed. + +### Unarchive group + +From Mattermost v9.1, you can restore an archived group. From the **More Actions** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon, filter the list of groups to show only archived groups. Select an archived group view details about the group, if preferreed, and then select **Restore Group**. diff --git a/docs/main/end-user-guide/collaborate/organize-using-teams.mdx b/docs/main/end-user-guide/collaborate/organize-using-teams.mdx new file mode 100644 index 000000000000..01e32093c100 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/organize-using-teams.mdx @@ -0,0 +1,99 @@ +--- +title: "Organize using teams" +--- + + +A team is a digital [workspace](/end-user-guide/end-user-guide-index) where you and your teammates can collaborate in Mattermost. Depending on how Mattermost is [set up](/administration-guide/configure/experimental-configuration-settings#primary-team) in your organization, you can belong to one team or multiple teams, and [access to the team](/end-user-guide/collaborate/team-settings#access-settings) can be open or restricted. + +Users with the **Create Teams** permission can [create new teams](#create-a-team) and [manage team settings](/end-user-guide/collaborate/team-settings) for existing teams. System admins can grant the **Create Team** permission to roles via the [System scheme](/administration-guide/onboard/advanced-permissions#system-scheme) or the [Team override scheme](/administration-guide/onboard/advanced-permissions#team-override-scheme). + +## Single team versus multiple teams + +Mattermost can be deployed both to a single team and to multiple teams. Currently, we recommend deploying to a single team for the following reasons: + +- Single team deployments promote communication across the organization. When you add multiple teams, groups can become isolated. +- We don't yet support search or channels across teams, which can impact the cross-team user experience. This includes general searches, saved posts, and recent mentions. +- Integrations (e.g., webhooks and slash commands) are only persistent across single team deployments. + +However, some Mattermost customers prefer multiple team deployments for the following reasons: + +- Teams are useful when there is a purpose for each of them. For example, one team is used for staff members and another team for external users. +- Performance is better when users are scattered across multiple teams instead of all in the same one. With multiple teams, there is less content to load per team or channel switch and database queries are faster. +- Creating a shared team for all users, and using advanced permissions to control who can create channels and add members to the shared team, improves cross-team collaboration when using multiple teams. Additionally, an annoucement banner can be used to provide system-wide announcements. + +## Team sidebar + +If you belong to more than one team, a team sidebar displays to the left of the channel sidebar. Drag teams to reorder them in the sidebar. You can also use keyboard shortcuts to navigate between teams. + +![Navigating between teams in Mattermost.](/images/teams.gif) + +## Create a team + +You can create a team using a web browser or the desktop app by selecting a team name, and then selecting **Create a Team**, unless your system admin has disabled your ability to do so. + +![Create a new team by selecting the team name.](/images/create-team.gif) + +### Team name and URL selection + +There are a few details and restrictions to consider when selecting a team name and team URL. + + + +If your system admin has enabled anonymous team and channel URLs (available in Mattermost Enterprise Advanced from v11.6.0), team creation becomes a single-step flow and you will not be prompted to choose a team URL. The URL is assigned automatically. + + + +#### Team name + +This is the display name of your team that appears in menus and headings. + +- Team names can contain any letters, numbers, or symbols. +- Team names are case sensitive. +- Team names must be 2 - 64 characters in length. + +#### Team URL + +If your system admin has not enabled anonymous URLs, you choose a team URL during team creation. The team URL is part of the web address that navigates to your team on the system domain, `https://domain.com/teamurl/`. + +- Teams may contain only lowercase letters, numbers, and dashes. +- Teams must start with a letter and cannot end in a dash. +- Teams must be 2 - 64 characters in length. +- Team names cannot start with the following restricted words: `admin`, `api`, `channel`, `claim`, `error`, `files`, `help`, `landing`, `login`, `mfa`, `oauth`, `plug`, `plugins`, `post`, `signup`, or `playbooks`. + +## Join a team + +You can join any open teams, or join any team you receive an invitation to join. + +If you haven't yet joined any teams in Mattermost, you're prompted to join available teams when you [log in to Mattermost](/end-user-guide/access/access-your-workspace). + +You can be a member of multiple teams at the same time. To join additional teams, select the current team name, choose **Join Another Team**, and select the name of the team you want to join. + +![Select a team name to join another team.](/images/join-team.png) + +## Leave a team + +Users can also choose to remove themselves from a team, from **Team menu \> Leave Team**. This will remove the user from the team, and from all public channels and private channels on the team. + +They will only be able to rejoin the team if it's open, or if they receive a new invitation. If they do rejoin, they will no longer be a part of their old channels. + +## Remove people from teams + +Team admins can remove users from a team via **Team menu \> Manage Members \> Remove From Team** in the dropdown menu beside a user entry. + +When a user is removed from a team, the team will no longer be visible or accessible in their team sidebar. If they currently have the team open, they are redirected to the first team that appears in their team sidebar. If they didn't belong to any other teams, the user is sent to the team selection page. + +Removing a user from the team does not deactivate the account. The user will still be able to log in to the site, and join other teams. They will also be able to rejoin the team they were removed from if they receive another invite, or if the team is set to ["Allow anyone with an account on this server to join this team"](/end-user-guide/collaborate/team-settings#users-on-this-server). If the user does rejoin the team, they will no longer belong to the channels they were previously a part of, and they will lose all Admin privileges if they had them previously. + +A system admin can also remove users from teams via **System Console \> Users**, and selecting the dropdown beside a user entry and selecting **Manage Teams**. The list of teams an individual user belongs to can be viewed on the user's profile page via **System Console \> Users** and selecting the member's name from the list provided in the **User Configuration** screen. + +## Archive a team + +A Mattermost system admin can archive teams they no longer need by going to **System Console \> Teams**, selecting a team, and selecting **Archive Team**. Archived teams can be unarchived if needed. + +When a team is archived, the team will no longer be visible or accessible in the team sidebar for any user. If users currently have the team open when it's being archived, users are redirected to the first time that appears in their team sidebar. If users didn't belong to any other teams, users are sent to the team selection page. + + + +Archiving a team doesn't remove the team data from the Mattermost database. Teams may still be accessible by using the Mattermost API. + + diff --git a/docs/main/end-user-guide/collaborate/react-with-emojis-gifs.mdx b/docs/main/end-user-guide/collaborate/react-with-emojis-gifs.mdx new file mode 100644 index 000000000000..040b629c9d39 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/react-with-emojis-gifs.mdx @@ -0,0 +1,100 @@ +--- +title: "React with emojis and GIFs" +--- + + +Emojis and GIFs are small, digital images, animated images, or icons you can use to communicate or express concepts such as emotions, humor, and physical gestures in your messages. + +From Mattermost v10.10, text emoticons (such as `:)` or `:D`) are automatically converted to emoji characters in your messages by default. You can [disable this auto-rendering](/end-user-guide/preferences/manage-your-display-options#render-emoticons-as-emojis) if you prefer to keep emoticons as text. + +## Quick emoji reactions + +You can react with up to 50 emojis per message. Recently used emojis are sorted based on how often you've used them. Don't see your most recently used emojis? Enable quick reactions by going to **Settings \> Display** and enabling **Quick reactions on messages**. + +
+ +Web/Desktop + +Hover over a message to select a recently used emoji. + +> ![React to messages quickly by selecting one of your most recently used emojis.](/images/recent-emojis.png) + +
+ +
+ +Mobile + +Long press on a message, and then select a recently used emoji. + +
+ +## Include emojis and GIFs in messages + + + +Can't find the perfect emoji? [Upload your own custom emoji](#upload-custom-emojis). + + + +
+ +Web/Desktop + +Select the **Smile** icon Use the Smile icon to add emojis to your message. inside the Mattermost message input box to open the emoji and GIF picker. + +Select an emoji from the **Emojis** tab, or switch to the **GIFs** tab to search for a GIF. + +You can also specify emojis based on their name. Type `:` followed by at least two characters of the word describing the emoji. This opens an emoji autocomplete. Descriptions include skin tone details for people-based emojis, where supported. + +![Emoji autocomplete](/images/emojiautocomplete.png) + +
+ +
+ +Mobile + +Select the Use the Smile icon to add emojis to your message. to add an emoji. Mattermost accesses the emojis and GIFs available on your mobile device. You can also specify emojis based on their name. Type at least two characters of the word describing the emoji. This opens an emoji autocomplete. + +![Tap and hold on a message to access the recent emojis or even choose other ones.](/images/mobile-include-emojis-for-a-message-reaction.gif) + +
+ +## Manage emojis + +Using Mattermost in a web browser or the desktop app, you can select recently used emojis, select a default skin tone for people-based emojis, as well as manage custom emojis. From Mattermost mobile v2.37.0, you can select custom emojis and apply custom skin tones on mobile devices. + +### Select default skin tone + +Select the **Skin tone** icon in the top right corner of the emoji picker to specify the skin tone you prefer to use for people-based emojis by default. You can select an alternate skin tone at any time. + +![Select a default skin tone preference for people-based emojis.](/images/emoji-skin-tone.png) + +## Upload custom emojis + +Using Mattermost in a web browser or the desktop app, you can upload new emojis that everyone in your Mattermost [workspace](/end-user-guide/end-user-guide-index) can access to react to messages, unless your system admin has [disabled your ability to do so](/administration-guide/configure/site-configuration-settings#enable-custom-emoji). + +1. From the emoji picker, select **Custom Emoji**. + +![Select Custom Emoji to upload custom emojis to Mattermost.](/images/add-custom-emoji1.png) + +2. Enter a name for your custom emoji. This is the name that shows up in the emoji autocomplete. +3. Choose **Select**, then select the image to use for the emoji. Small, square pictures work best when selecting an image to upload. The file can be any JPG, GIF, or PNG that's up to 512 KiB in size. +4. Select **Save**. Once saved, your emoji is added to the list of custom emoji. + +![Name and upload custom emojis to Mattermost.](/images/add_custom_emoji.png) + +4. To use your custom emoji in a message, select it from the emoji picker, or type `:` followed by your emoji name to bring it up in the emoji autocomplete. + +### Remove custom emojis + +Using Mattermost in a web browser or the desktop app, you can remove custom emojis that you uploaded to Mattermost. + +1. Open the emoji picker. +2. Select **Custom Emoji**. +3. If required, use the Search bar to find your custom emoji in the list. +4. Under **Actions** select **Delete**. +5. Choose **Delete** to confirm. + +![Remove custom emoji](/images/delete_custom_emoji.png) diff --git a/docs/main/end-user-guide/collaborate/rename-channels.mdx b/docs/main/end-user-guide/collaborate/rename-channels.mdx new file mode 100644 index 000000000000..1fa40a98c124 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/rename-channels.mdx @@ -0,0 +1,53 @@ +--- +title: "Rename channels" +--- + + +Anyone can rename the channels they belong to, unless the system admin has [restricted the permissions to do so using advanced permissions](/administration-guide/onboard/advanced-permissions). + +
+ +Web/Desktop + +Select the channel name at the top of the center pane to access the drop-down menu, then select **Channel Settings**. You'll be prompted to provide two pieces of information: + +- **Channel name:** The channel name that displays in the Mattermost user interface for all users. Enter a different channel name if needed or preferred. +- **Channel URL:** The web URL used to access the channel in a web browser. Select **Edit** to change the URL, and select **Done** to save your changes. If your system admin has enabled anonymous team and channel URLs (available in Mattermost Enterprise Advanced from v11.6.0), channel URLs are assigned automatically and do not reflect the channel name. + +If your system admin has enabled [channel category sorting](/administration-guide/configure/experimental-configuration-settings#enable-channel-category-sorting), you can assign the renamed channel to a new or existing channel category. + +For example, a channel could be named `UX Design` and have a URL of `https://community.mattermost.com/core/channels/ux-design` (or an anonymous URL if enabled by your system admin). + +
+ +
+ +Mobile + +1. Tap the channel you want to rename. + +> ![Select a channel that you want to rename.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +> ![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View info**. + +> ![Tap on View info to see the basic channel info.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Edit Channel**. + +> ![Click on Edit channel to rename the channel.](/images/mobile-edit-channel.jpg) + +5. You're prompted to provide three pieces of information: + +> - **Name:** This appears in the Mattermost user interface. +> - **Purpose:** (Optional) Used to describe the channel's function or goal. +> - **Header:** (Optional) Used to include information relevant to the channel, such as key contacts or document links. +> +> Tap on **Save** to save the new channel name. +> +> ![Type the new channel name and click on Save to rename the channel.](/images/mobile-rename-channel-name-and-save.jpg) + +
diff --git a/docs/main/end-user-guide/collaborate/reply-to-messages.mdx b/docs/main/end-user-guide/collaborate/reply-to-messages.mdx new file mode 100644 index 000000000000..508c1d5ca37d --- /dev/null +++ b/docs/main/end-user-guide/collaborate/reply-to-messages.mdx @@ -0,0 +1,46 @@ +--- +title: "Reply to messages" +--- + + +
+ +Web/Desktop + +Reply to messages by selecting the **Reply** Reply icon. icon next to the message text. + +![Reply to Mattermost messages](/images/reply-to-message.png) + +
+ +
+ +Mobile + +Long press on a message and select **Reply** or simply tap on it to reply. + +![Tap and hold on text to select reply.](/images/mobile-reply-to-a-message-using-reply.gif) + +![Tap on a Message to send a reply.](/images/mobile-reply-to-a-message-by-tapping-on-it.gif) + +
+ +Depending on how your system admin has configured Mattermost, you may be able to [edit](/end-user-guide/collaborate/send-messages#edit-messages), [restore](/end-user-guide/collaborate/send-messages#restore-a-previous-version-of-an-edited-message), and [delete](/end-user-guide/collaborate/send-messages#delete-messages) messages after you've sent them. + + + +It's easy to return to a message in progress with global message drafts. Find all of your draft messages in the **Drafts** view available at the top of the channel sidebar. See the [draft messages](/end-user-guide/collaborate/send-messages#draft-messages) documentation for details. + + + +## Organize discussions into threads + +When you reply to messages, those replies are [organized into a discussion thread](/end-user-guide/collaborate/organize-conversations). Threaded discussions are easy to follow and allow multiple parallel conversations to occur at the same time without confusion. + +Using Mattermost in a web browser or the desktop app, replies appear indented slightly in the center pane to indicate that they are child messages of a parent message. Selecting the reply link opens a sidebar in the right-hand sidebar in a web browser and the desktop app. To expand the right-hand sidebar to its full width, select the **Expand** icon with two arrows at the top of the sidebar. + +![Expand right-hand sidebar to its full width](/images/expand-sidebar.png) + +To shrink the right-hand sidebar to its original width, select the same **Collapse** icon. + +![Collapse the right-hand sidebar to its original width](/images/collapse-sidebar.png) diff --git a/docs/main/end-user-guide/collaborate/save-pin-messages.mdx b/docs/main/end-user-guide/collaborate/save-pin-messages.mdx new file mode 100644 index 000000000000..143da91a80e6 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/save-pin-messages.mdx @@ -0,0 +1,121 @@ +--- +title: "Save and pin messages" +--- + + +You have two ways to mark a post to make it easy to find later: + +- [Saving a message](#save-messages) saves it for only you. +- [Pinning a message](#pin-messages) marks it for an entire channel. + +## Save messages + +
+ +Web/Desktop + +Save messages for later follow up by selecting the **Save** Save icon. icon next to a message. + +![Save messages for later follow up using the Save option.](/images/save-message.png) + +To see all of your saved messages, select the **Bookmark** icon to the left of your profile picture. The right-hand sidebar opens to show the list of saved messages. + +Remove an item from your **Saved Posts** list by selecting the **Save** icon next to message to clear it. + +![Remove saved messages by toggling the Save option.](/images/remove-from-saved-posts.png) + +
+ +
+ +Mobile + +Long press a message, and then select **Save**. + +![Tap and hold on a message in the channel to explore available options to save it.](/images/mobile-save-a-message.gif) + +To see all of your saved messages, tap the **Save** Save icon. icon at the bottom of the app. + +![Tap on Save icon at the bottom of the app to access the Saved Messages list.](/images/mobile-view-saved-messages.gif) + +Remove an item from your **Saved Messages** list by long pressing a message and selecting **Unsave**. + +![Tap and hold on a message in the saved messages list to explore available options to unsave it.](/images/mobile-unsave-a-message-from-saved-messages.gif) + +Alternatively, you can also tap on the saved message in a channel and then tap the Saved icon. icon below it to unsave. + +![Tap and hold on a saved message in the channel to explore available options to unsave it.](/images/mobile-unsave-a-message-from-the-channel.gif) + +
+ +## Pin messages + +All members of a channel can pin important or useful messages to that channel. The list of pinned messages is visible to all channel members. There is no limit to the number of pinned posts in a channel. From Mattermost v10.2, the **Pinned** Pin icon used to indicate when there are pinned messages in a given channel. icon is hidden when no messages are pinned. + +
+ +Web/Desktop + +1. Hover over the message that you want to pin. The **More** Use the More icon to access additional message options. icon link appears. +2. Select the **More** option, then select **Pin to channel**. + +![You can pin messages to make them easy to return to later.](/images/pin-message-to-channel.png) + +Pinned messages are marked with the pinned icon. For example: + +![An example of a pinned message in a channel marked with a pin icon.](/images/pinned-example-channel.png) + +To see all pinned messages in a channel, select the **Pinned posts** icon in the channel header. + +![Open pinned messages in the right-hand sidebar.](/images/pinned-posts.png) + +The right-hand sidebar opens to show the list of pinned messages. For example: + +![Review the list of pinned messages.](/images/pinned-example-rhs.png) + +To unpin a message: + +1. Mouse over the message that you want to unpin. The **More** Use the More icon to access additional message options. icon link appears. +2. Select the **More** icon, then select **Unpin from channel** + +![You can unpin messages from a channel when they're no longer needed or become outdated.](/images/unpin-message-from-channel.png) + +
+ +
+ +Mobile + +Long press a message, and then select **Pin to Channel**. + +![Tap and hold on a message in the channel to explore available options to pin it.](/images/mobile-pin-a-message-to-the-channel.gif) + +To see all of your pinned messages in a channel: + +1. Tap the channel whose pinned messages you want to review. + +![Select a channel whose pinned messages you want to view.](/images/mobile-select-a-channel.jpg) + +2. Tap the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon located in the top right corner of the app. + +![Tap on More options to access available options for the channel.](/images/mobile-select-more-options-for-a-channel.jpg) + +3. Tap **View Info**. + +![Tap on View info to view additional information about the channel.](/images/mobile-select-view-info-for-a-channel.jpg) + +4. Tap **Pinned Messages**. + +![Tap on Pinned Messages to view the list of pinned messages.](/images/mobile-edit-channel.jpg) + +![View the specific pinned message you want to see from the list.](/images/mobile-view-the-pinned-message-in-the-pinned-messages-list.jpg) + +Remove an item from your **Pinned Messages** list by long pressing a message and selecting **Unpin from Channel**. + +![Tap and hold on a message in the pinned messages list to explore available options to unpin it.](/images/mobile-unpin-a-message-from-pinned-messages.gif) + +Alternatively, you can long press on a pinned message in the channel and then tap on **Unpin from Channel** to unpin it. + +![Tap and hold on a pinned message in the channel to explore available options to unpin it.](/images/mobile-unpin-a-message-from-the-channel.gif) + +
diff --git a/docs/main/end-user-guide/collaborate/schedule-messages.mdx b/docs/main/end-user-guide/collaborate/schedule-messages.mdx new file mode 100644 index 000000000000..02427a98a379 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/schedule-messages.mdx @@ -0,0 +1,66 @@ +--- +title: "Schedule messages" +--- + + +There are times when you want to send a message, but you don’t want it sent immediately. For example, it may be after working hours for the recipient. Scheduled messages can include a [priority](/end-user-guide/collaborate/message-priority), [request acknowledgements](/end-user-guide/collaborate/message-priority#request-acknowledgements), include [file attachments](/end-user-guide/collaborate/share-files-in-messages), and include anything that a non-scheduled message can contain, except [slash commands](/integrations-guide/run-slash-commands). + +
+ +Web/Desktop + +From Mattermost v10.3, you can schedule messages to send in the future. Compose a message, then select the right side of **Send** to schedule when the message will be sent. You can choose from a fixed time or set a custom time, and Mattermost displays both your local time and the recipient’s local time. + +![Compose a message and select the right side of the \*\*Send\*\* button to schedule when the message will be sent.](/images/schedule-a-message.png) + +
+ +
+ +Mobile + +From Mattermost mobile v2.28, you can schedule messages to send in the future. Compose a message, then long press on **Send** to schedule when the message will be sent. You can choose from a fixed time or set a custom time, and Mattermost displays both your local time and the recipient’s local time. + +
+ +## Manage scheduled messages + +Once you schedule a message to send in the future, that message is available within the [Drafts view](/end-user-guide/collaborate/send-messages#draft-messages), under the **Scheduled** tab. + +You can manage scheduled messages with the following actions: + +- **Delete scheduled post**: Confirm that you want to delete the message. +- **Edit scheduled post**: Make changes to the draft inline before its sent. +- **Copy text**: Copy the draft text. +- **Reschedule message**: Change when the message should be sent. +- **Send now**: Confirm that you want to send the message immediately. + +Once a message is scheduled, you can delete, edit, and reschedule it, copy the message text, or send it immediately. + + + +Once you schedule a message, file attachments are read-only and can't be changed. + + + +## Troubleshoot scheduled messages + +Scheduled messages may fail for the following reasons: + +- You're no longer a member of the channel. +- The channel is archived. +- The channel is read-only. +- The Mattermost server was down for more than 24 hours. Mattermost processes scheduled posts up to 24 hours old, so in cases where the server is down for short time, scheduled messages will be processed. Scheduled messages older than 24 hours may fail to send. + +If a scheduled message fails to send, you'll be alerted 2 ways: + +- A red badge displays a total scheduled post count in the left pane next to **Drafts**. Total count of scheduled messages. +- An alert banner dislays on the **Scheduled** tab + +If a scheduled draft message can't be sent, Mattermost provides context about why it can't be sent on the Scheduled tab under Drafts. + + + +You can't reschedule a failed message, but you can schedule a new replacement message. + + diff --git a/docs/main/end-user-guide/collaborate/search-for-messages.mdx b/docs/main/end-user-guide/collaborate/search-for-messages.mdx new file mode 100644 index 000000000000..078263da2792 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/search-for-messages.mdx @@ -0,0 +1,224 @@ +--- +title: "Search for messages" +--- + + +Use Mattermost search to find messages, replies, and the contents of files. You can also search by [hashtags](#hashtags), perform more advanced searches using [search modifiers](#search-modifiers), or adjust search results to show messages from the current team, a specific team, or all teams. + +## Search for message + +
+ +Web/Desktop + +1. Select the Search field, select **Messages**, enter your search criteria. + +> ![Use the Search field to search for messages.](/images/search-messages.png) +> +> ![Use the expanded Search field to search for messages.](/images/search-messages-expanded.png) + +2. By default, your search results include messages from all channels within your current team. From Mattermost v10.8, you can select **All Teams** to search all channels across all teams, select a specific team instead, or continue searching within the current team. + +> ![Select All Teams to search all channels across all teams.](/images/search-all-teams.png) +> +>
+> +>
+> +> Tip +> +>
+> +> From Mattermost v10.10, the `from:` search modifier is available for cross-team searches. When searching all teams, you must manually add the `from:` modifier as part of your search criteria to search by specific users across teams. +> +>
+ +3. When message results display in the Search Results pane, select **Jump** to view a full message in context. + +> ![From search results, you can go to the full message by selecting Jump.](/images/jump-to-message.png) + + + +From Mattermost v10.8, you can also adjust your search results to show messages from the current team, a specific team, or all teams. + + + +
+ +
+ +Mobile + +1. Tap the **Search** Search for messages and files in Mattermost. icon at the bottom of the app to search for messages or files attached to messages. + +> ![Tap on the Search icon to search for messages.](/images/mobile-search-for-messages.jpg) + +2. By default, your search results include messages from all channels within your current team. From mobile v2.28, tap **All Teams** to search all channels across all teams, or select a specific team instead. + +> ![Tap on the Team selector to select the team you want to search in.](/images/mobile-search-message-team-selection.jpg) + +3. Enter your search criteria. + +> ![Type your search criteria along with applicable hashtags.](/images/mobile-search-message-criteria-with-hashtags.jpg) + +4. Tap to apply [search modifiers](#search-modifiers) to your search. + +> ![Apply search modifiers to further refine your search.](/images/mobile-search-message-with-modifiers.jpg) +> +> ![Check the search results to find your required message or file from the list.](/images/mobile-search-message-results.jpg) + + + +When using Mattermost in a web browser or the desktop app, you can open your current search results in a separate popout window by selecting the **Open in new window** Open thread in a new browser window icon. icon in the search results header. + + + +
+ +## Search for files + +From the **Search** field, select **Files** to search for files attached to messages. From Mattermost v10.8 and mobile v2.28, you can specify whether you want to search all channels you're a member of in the current team, a specific team, or all channels across all teams. + +![Use the Search field to serach for files attached to messages.](/images/search-files.png) + +File contents that match on file name, or contain matching text content within supported document types, are returned in the Search Results pane. Each search result includes file name, extension, and size details, as well as details about when and where the file was originally shared. You can adjust search results to show messages from the current team, a specific team, or all teams. + +- For Mattermost Cloud [workspaces](/end-user-guide/end-user-guide-index), supported document file formats include PDF, PPTX, DOCX, ODT, HTML, and plain text documents. DOC and RTF file formats, as well as the contents of ZIP files, are not supported. +- For Mattermost self-hosted deployments, supported document file formats include PDF, PPTX, DOCX, ODT, HTML, and plain text documents. + + + +7zip (`.7z`) files are not supported for file content search and are skipped during search indexing for security reasons. Only standard ZIP files are supported when ZIP file search is enabled. + + + + + +System admins can extend file content search support for self-hosted deployments to include: + +- [files shared before upgrading to Mattermost Server v5.35](/administration-guide/manage/mmctl-command-line-tool#mmctl-extract). +- [DOC and RTF file formats](/administration-guide/configure/environment-configuration-settings#enable-document-search-by-content). +- [documents within ZIP files](/administration-guide/configure/environment-configuration-settings#enable-searching-content-of-documents-within-zip-files). + + + +### Filter results by file type + +Using Mattermost in a web browser or the desktop app, you can narrow search results further by selecting the **File Type Filter** option, then selecting specific file types, such as documents, spreadsheets, or images. + +![You can filter search results by file type.](/images/file-search-filter.png) + +### Access recently shared files + +You can access files recently shared in a channel: + +
+ +Web/Desktop + +Select the Use the Channel Files icon to search for files attached to messages in a given channel. icon to the right of the channel name to access files recently shared in that channel. + +![Use the Channel Files option to access recently shared files in the current channel.](/images/channel-files-icon.png) + +Alternatively, you can select the channel name, select the **View Info** Use the Channel Info icon to access additional channel management options. icon, then select **Files** in the right pane. + +
+ +
+ +Mobile + +Tap the channel name to view channel options, then tap **Files**. + +
+ +## Search modifiers + +You can apply search modifiers to any search to reduce the number of results returned. Select a search modifier to add it to the Search field. Supported modifiers are described below. Your search results include messages from all of your teams. + +### `from:` and `in:` + +- Use `from:` to find messages or files from specific users. + - For example, searching `from:john.smith` only returns content from your direct message history with John Smith. + - From Mattermost v10.10, you can use `from:` in cross-team searches to find messages from specific users across all teams you're a member of. +- Use `in:` to find messages or files posted in specific public channels, private channels, direct messages, or group messages. You can specify channels by display name or channel ID. + - For example, searching `Mattermost in:town-square` only returns results in the Town Square public channel that contains the term `Mattermost`, while searching `Mattermost in:john.doe` only returns results that contains the term `Mattermost` in your direct message history with John Smith. + +### `before:`, `after:`, and `on:` + +- Use `before:` to find messages or files posted before a specified date. + + - For example, searching `website before: 2018-09-01` returns messages or files containing the term `website` posted prior to September 1, 2018. + +- Use `after:` to find messages or files posted after a specified date. + + - For example, searching `website after: 2018-08-01` returns messages or files containing the term `website` posted after August 1, 2018. + +- Use both `before:` and `after:` together to search in a specified date range. + + - For example, searching `website before: 2018-09-01 after: 2018-08-01` returns all messages or files containing the term `website` posted between August 1, 2018 and September 1, 2018. + +- Use `on:` to find messages or files posted on a specific date. Use the date picker to select a date, or type it in YYYY-MM-DD format. + + - For example, searching `website on: 2018-09-01` returns messages or files containing the term `website` posted on September 1, 2018. + + ![Select the on modifier to specify messages or files for a specific a date.](/images/calendar2.png) + +### Exclusions + +Use the hyphen `-` symbol to exclude terms from your search results. For example, searching `test -release` only returns results that include the term `test` and exclude the term `release`. + +This exclusion modifier can be used in combination with other modifiers to further refine search results. For example, searching `test -release -in:release-discussion -from:eric` returns all results with the term `test`, excludes posts with the term `release`, excludes posts made in the `release-discussion` channel, and excludes messages sent in direct messages by `eric`. + +### Quotation marks + +Use quotation marks `" "` to return search results for exact terms. For example, searching `"Mattermost website"` returns messages containing the exact phrase `Mattermost website`, but doesn't return results containing `Mattermost` and `website` as separate terms. + +### Wildcards + +Use the asterisk `*` symbol at the end of the word to perform a wildcard search. The wildcard search returns all words that begin with the specified letters. The wildcard in search cannot be used at the beginning or in the middle of a word. For example, searching `rea*` returns messages or files containing words like `reach`, `reason`, `reality`, `real`, and other words starting with `rea`. However, searches like `*each` and `re*ch` are invalid wildcard searches. + +### Hashtags + +Hashtags are searchable labels for messages. Anyone can create a hashtag in a message by using the pound sign `#` followed by alphanumeric or other unicode characters. Hashtag examples include: `#bug`, `#marketing`, `#user_testing`, `#per.iod`, `#check-in`, `#마케팅`. + +Valid hashtags: + +- Don't start with a number. +- Are at least three characters long, excluding the `#`. +- Are made up of alphanumeric or other unicode characters. +- May contain dots, dashes, or underscores. + +To search for messages containing hashtags, select a hashtag in an existing post, or type the hashtag (including the pound `#` symbol) into the search bar. + + + +Hashtags don't link to channels. If you have a channel named “Marketing”, selecting a `#marketing` hashtag does not take you to the Marketing channel. To link to public channels, use the tilde `~` symbol followed by the channel name. For example `~marketing`. + + + +## Search public channels you haven't joined + + + +From Mattermost v11.6, when your system admin [enables searching public channels without membership](/administration-guide/configure/environment-configuration-settings#allow-searching-public-channels-without-membership), search results can include messages from public channels you haven't joined. Results are scoped to teams you belong to, so you'll only see messages from public channels in your teams. This setting doesn't affect private channels — you can only search private channels you're a member of. + +## Notes about performing Mattermost searches + +- Multiple-word searches return results that contain *all* of your search criteria. +- Search modifiers can help narrow down searches. See the [search modifiers](#search-modifiers) section for details. +- You can search Archived channels as long as you're a member of that channel. + - If you're unable to see messages or files in archived channels in your search results, ask your system admin if **Allow users to view archived channels** has been disabled via **System Console \> Site Configuration \> Users and Teams**. + - To remove archived channels from your search results, you can leave the Archived channels. +- Like many search engines, common words such as `the`, `which`, and `are` (known as "stop words"), as well as two-letter and one-letter search terms, are not shown in search results because they typically return too many results. See the [Technical notes about searching](#technical-notes-about-searching) section below for details. +- IP addresses (e.g. `10.100.200.101`) don't return results. + +## Technical notes about searching + +By default, Mattermost uses full text search support included in PostgreSQL. Select the **product menu** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. then select **About Mattermost** to see which database you’re using. + +- Stop words are filtered out of search results. See [PostgreSQL](https://www.postgresql.org/docs/10/textsearch-dictionaries.html#TEXTSEARCH-STOPWORDS) database documentation for a full list of applicable stop words. +- URLs don’t return results. +- Hashtags or recent mentions of usernames containing a dash don't return results. +- Terms containing a dash return incorrect results since dashes are ignored in the search engine. +- From Mattermost v7.1, search results respect the `default_text_search_config` value instead of being hardcoded to English. We recommend that Mattermost system admins review this value to ensure it's set correctly. diff --git a/docs/main/end-user-guide/collaborate/send-messages.mdx b/docs/main/end-user-guide/collaborate/send-messages.mdx new file mode 100644 index 000000000000..fe30337df95b --- /dev/null +++ b/docs/main/end-user-guide/collaborate/send-messages.mdx @@ -0,0 +1,236 @@ +--- +title: "Send messages" +--- + + +You can send messages in public and private channels as well as to other users in Mattermost. Depending on when you compose a message, you can send it immediately, [schedule it for later](/end-user-guide/collaborate/schedule-messages), or [set its priority](/end-user-guide/collaborate/message-priority). + +Mattermost may notify you when a recipient's availability is set to [Do Not Disturb](/end-user-guide/preferences/set-your-status-availability#set-your-availability), and the recipient's local time is outside of regular business hours (between 10PM and 6AM). This warning displays directly above the message text field. + + + +From Mattermost v11.5, you can access help resources for message formatting by selecting the **Help** link below the message text field. + + + +
+ +Web/Desktop + +Enter a message in the text field, then select **Send** Select the Send icon to post your message. to send the message. + + + +You can also use a keyboard to send messages: + +- Press Enter on Windows or Linux, or on Mac. +- You can configure Mattermost to require Shift Enter on Windows or Linux, or on Mac to send multi-line messages. Select the **gear** Use the Settings icon to customize your Mattermost user experience. icon to go to **Settings**, then select **Advanced \> Send messages on CTRL+ENTER**. + + + +
+ +
+ +Mobile + +1. Tap the text field at the bottom of the Mattermost app to type a message. + +![Type a message in the text box at the bottom of the mobile app.](/images/mobile-type-a-message-in-a-channel.jpg) + +2. Tap **Send** Select the Send icon to post your message. icon to send it in the channel. + +![Tap on the send icon to send the message in the channel.](/images/mobile-sending-a-message.gif) + +
+ +## Rewrite messages with AI + +You can use AI to enhance your messages before sending them. This feature helps you improve writing quality, fix spelling, adjust message length, or transform your text based on specific needs. + +From Mattermost v11.5, when you use AI Rewrite while composing a reply in a thread, the AI incorporates context from the thread to generate suggestions that better fit the ongoing conversation. + +On Web/Desktop or Mobile: + +> 1. Type your message in the message compose field. +> 2. Select the **Rewrite** AI Rewrite icon. option from the message actions. +> 3. Select a bot from the list of available AI agents. +> 4. Choose from available rewrite options: +> - **Improve writing**: Enhance clarity and professionalism +> - **Fix spelling**: Correct spelling and grammar errors +> - **Shorten**: Make your message more concise +> - **Elaborate**: Add more detail and context +> - **Simplify**: Use clearer, easier-to-understand language +> - **Summarize**: Condense your message to key points +> - **Custom prompt**: Specify your own transformation instructions +> 5. Review the AI-generated suggestion. Select **Regenerate** to try again or **Discard** to return to your original message. +> 6. Select **Send** Select the Send icon to post your message. + + + +Messages that have been rewritten using AI are automatically marked as AI-generated content for transparency. Your system admin must [configure AI agents](/administration-guide/configure/agents-admin-guide) for the rewrite feature to be available. + + + +## Send burn-on-read messages + + + +From Mattermost v11.3, burn-on-read messages stay concealed until recipients reveal them. After revealing, the message is deleted for that recipient when the timer expires. Burn-on-read messages can't be replied to or edited. You can send burn-on-read messages unless your system admin has [disabled the ability to do so](/administration-guide/configure/site-configuration-settings#enable-burn-on-read-messages) in your Mattermost instance. + +
+ +Web/Desktop + +1. Compose your message. +2. Select the **Burn-on-read** Burn on Read icon. icon in the message toolbar. +3. Select **Send** Select the Send icon to post your message. + +
+ +
+ +Mobile + +From Mattermost mobile v2.38.0, you can send burn-on-read messages from the mobile app. + +1. Compose your message. +2. Tap the **Burn-on-read** Burn on Read icon. icon in the message toolbar. +3. Tap **Send** Select the Send icon to post your message. + +
+ +Recipients see a concealed placeholder with **Reveal**. After revealing, a timer shows when the message will be deleted. + +As the message sender, hover over the **Burn-on-read** Burn on Read icon. icon above the sent message to see how many recipients have read the message. You can also delete the burn-on-read message for all recipients before the timer expires by selecting the **Burn-on-read** Burn on Read icon. icon above the sent message. + +## Draft messages + +From Mattermost v7.7, when composing new messages, it's easy to return to a message in progress later, unless your system admin has [disabled global drafts](/administration-guide/configure/site-configuration-settings#enable-server-syncing-of-message-drafts) in the System Console. + +By default, message drafts are synchronized on the Mattermost server and are accessible everywhere you access Mattermost, including a web browser or the desktop app. Limit drafts to your current Mattermost client only by going to **Settings \> Advanced \> Allow message drafts to sync with the server** to disable draft synchronization. + +
+ +Web/Desktop + +Draft messages are added to a **Drafts** view available at the top of the channel sidebar. + +Global drafts makes it easy for you to find all messages in progress. + +
+ +
+ +Mobile + +When composing a message, you can simply choose to complete it later. The partially composed message is kept in the text field and an **Edit** option Edit icon. displays next to the channel name. + +From Mattermost v10.5, you'll find local draft messages under **Drafts**. Drafts synchronized to the Mattermost server will be listed under **Drafts** in a future mobile app release. + +![You can sync a daft message by exiting the channel mid-way while composing the message.](/images/mobile-draft-a-message.gif) + +
+ +## Edit messages + +All users can edit their own sent messages, unless the system admin has [restricted the ability to do so](/administration-guide/onboard/advanced-permissions). + +
+ +Web/Desktop + +1. Using Mattermost in a web browser or the desktop app, select the **More** Use the More icon to access additional message options. icon next to a message that you've sent. + +> ![Select the More option to edit or delete a sent message.](/images/more-actions.png) + +2. Select **Edit** to edit your own messages. Editing a message won't trigger new [@mention notifications](/end-user-guide/collaborate/mention-people), or [desktop notifications](/end-user-guide/preferences/manage-your-notifications). + + + +From Mattermost v10.5, using a web browser or the Mattermost Desktop app, you can also change or remove message attachments when editing your sent messages. + + + +
+ +
+ +Mobile + +1. Long press on the message that you want to edit and tap on **Edit**. + +![Tap and hold on a message that you want to edit.](/images/mobile-edit-a-message.gif) + +2. Type the updated message and tap on **Save**. + +![Type the updated message and tap save to save the edited message.](/images/mobile-editing-a-message.jpg) + + + +From Mattermost v10.11 and mobile app v2.31.0, when editing messages on mobile, you can also view, delete, and save message attachments as you would when using Mattermost in a web browser or the desktop app. + + + +
+ +### Restore a previous version of an edited message + +From Mattermost v7.9, [Mattermost Enterprise or Professional](https://mattermost.com/pricing) customers can [edit or delete messages](#edit-or-delete-messages) after sending them if your system admin hasn't restricted the ability to do so using [advanced permissions](/administration-guide/onboard/advanced-permissions). + +Message recipients can't see your message edit history, and restoring a previous message version won't trigger new [@mention notifications](/end-user-guide/collaborate/mention-people). + + + +Restoring a previous version of the message is available in the Mattermost desktop app or a web browser. The ability to restore using the mobile app isn't supported. + + + +1. Select the word **Edited** next to your message. +2. In the right pane, review all previous versions of the message. +3. Select the **Restore** Use the Restore icon to restore a previous version of an edited message. icon next to the version you want to restore. +4. Select **Confirm**. + +![Select Edited next to an edited message, and then select the version you want to restore.](/images/restore-previous-edited-message.gif) + +## Delete messages + +
+ +Web/Desktop + +All users can delete their own sent messages, unless the system admin has [restricted the ability to do so](/administration-guide/onboard/advanced-permissions). + +1. Using Mattermost in a web browser or the desktop app, select the **More** Use the More icon to access additional message options. icon next to a message that you want to delete. +2. Select **Delete** to delete your own messages. Select **Delete** again to confirm. + +
+ +
+ +Mobile + +1. Long Press on the message you want to delete and tap on **Delete**. + +![Tap and hold on the message that you want to delete.](/images/mobile-delete-a-message.gif) + +2. Tap on **Delete** again to confirm your choice. + +![Confirm your choice to delete the message.](/images/mobile-confirm-delete-a-message.jpg) + +
+ +## Do more with your messages + + + +Using a RTL plugin, Mattermost can automatically detect and display messages written using right-to-left scripts, such as Arabic, Hebrew, or Persian. Your system admin must install the [RTL Plugin](https://github.com/QueraTeam/mattermost-rtl) to enable this functionality. + + + +Do more with your Mattermost messages using the following features: + +- [Format messages](/end-user-guide/collaborate/format-messages) +- [Mention people](/end-user-guide/collaborate/mention-people) +- [Share files](/end-user-guide/collaborate/share-files-in-messages) +- [Share links to channels and messages](/end-user-guide/collaborate/share-links) diff --git a/docs/main/end-user-guide/collaborate/share-files-in-messages.mdx b/docs/main/end-user-guide/collaborate/share-files-in-messages.mdx new file mode 100644 index 000000000000..f303951e1889 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/share-files-in-messages.mdx @@ -0,0 +1,99 @@ +--- +title: "Share files in messages" +--- + + +With file attachments, you can share additional information that helps your team to visually understand your ideas. Sharing videos, voice recordings, screenshots, and photos can make your messages more effective and clear. + +
+ +Web/Desktop + +You can share files with other Mattermost users or entire channels by: + +- Dragging and dropping files into channels. +- Selecting the **Attachment** Add a message attachment using the Upload files icon in the message formatting toolbar. icon in the message input box. +- Pasting from the clipboard. + +## Share public links + +Public links allow you to share message attachments with anyone outside your Mattermost [workspace](/end-user-guide/end-user-guide-index). To share an attachment, select the thumbnail of an attachment, then select **Get Public Link**. + + + +If **Get Public Link** is not visible in the file previewer, ask your system admin to enable the feature from the System Console under **Site Configuration \> Public Links**. + + + +## Download files + +You can download an attached file by selecting the **Download** Use the Download icon to download an attached file to your local system. icon next to the file thumbnail. + + + +From Mattermost desktop app v5.2, you can review download status, access downloads, and clear the list of downloads from a new **Downloads** Use the desktop app download icon to review download status, as well as access and clear the list of downloaded files. option located in the top-right corner of the desktop app window. + + + +## Access files + +Access all files shared in a channel by selecting the **Channel files** Use the Channel Files icon to search for files attached to messages in a given channel. icon in the channel header. + +
+ +
+ +Mobile + +You can share files with other Mattermost users or entire channels by tapping the **Attachment** Add a message attachment using the Upload files icon in the message formatting toolbar. icon under the message input box when composing a message. + +From Mattermost v10.7 and mobile v2.27, you can play and download audio files directly from the message thread. + +![Tap on attachment icon to attach a file and send it in the channel.](/images/mobile-attach-a-file-to-send-in-a-channel.gif) + +## Access files on mobile + +1. Tap the channel name at the top of the screen. + +![Click on the channel name to explore available options.](/images/mobile-channel-name-click.jpg) + +2. Tap **Files**. + +![Tap on Files to explore the available file attachments in the channel.](/images/mobile-edit-channel.jpg) + +3. Tap a file to download it, open it, or copy a public link to the file. + +![Tap on a file to download and open it.](/images/mobile-tap-a-file-name-to-download.jpg) + +Or you can also click on Use the More icon to access additional message options. to download the file or open it in the channel. + +![You can also use more options to download ot view the file in the channel.](/images/mobile-more-options-to-download-or-view-a-file.jpg) + +
+ +## Attachment limits and sizes + +Up to 10 files can be attached per post. The default maximum file size is 100 MB, but this can be changed by the system admin. See our [Configuration Settings](/administration-guide/configure/environment-configuration-settings#maximum-file-size) product documentation for details. + +Image files can be a maximum size of 7680 pixels x 4320 pixels, with a maximum image resolution of 33 MP (mega pixels) or 8K resolution, and a maximum raw image file size of approximately 253 MB. System admins can customize the maximum image resolution size within the `config.json` file. See our [Configuration Settings](/administration-guide/configure/experimental-configuration-settings#maximum-image-resolution) product documentation for details. + +## Preview file attachments + +Mattermost has a built-in file previewer that you can use to: + +- Download files +- Share public links +- View media + +Select the thumbnail of an attached file to open it in the file previewer. + +### View media + +The following media formats are supported on most browsers: + +- Images: BMP, GIF, JPG, JPEG, PNG, SVG, WEBP +- Video: browser supported video formats, including but not limited to MP4 and MOV +- Audio: MP3, M4A +- Files: PDF, TXT + +Other document previews (such as Word, Excel, or PPT) are not yet supported. diff --git a/docs/main/end-user-guide/collaborate/share-links.mdx b/docs/main/end-user-guide/collaborate/share-links.mdx new file mode 100644 index 000000000000..857eb995231c --- /dev/null +++ b/docs/main/end-user-guide/collaborate/share-links.mdx @@ -0,0 +1,75 @@ +--- +title: "Share links to channels and messages" +--- + + +You can share links to Mattermost [channels](#share-channel-links) and [messages](#share-message-links) with other Mattermost users. + +## Share channel links + +Sharing channel links makes it easy for others to find and join channels. To share a link to a channel, type `~` into the message text box, then select the channel you want to link to. If you're a member of multiple teams, only channels for the current team are listed. + + + +Alternatively, you can select the **View info** Use the Channel Info icon to access additional channel management options. icon in the top right corner of the screen to access additional channel management options, including a **Copy Link** option you can share with others. + + + +## Share message links + +
+ +Web/Desktop + +Sharing message links displays a preview of the message in the post. To share links to messages in Mattermost, select the **More** Use the More icon to access additional message options. icon next to a message, then select **Copy Link**. + +![When you hover over messages, you can access more message options from the More icon.](/images/message-more.png) + +![You can share links to messages with others using the More option.](/images/copy-link.png) + +Paste the link into a message to share the image link with others. Sharing links to messages generates a preview of the message. + +![Mattermost generates previews of links shared in Channels.](/images/permalink-previews.png) + + + +- You can also hover over an image and select the Use the Copy Link icon to copy the public URL link for an image in a message. icon in the top right corner. +- The timestamp next to the username of any message is also a permanent link to that conversation. + + + +
+ +
+ +Mobile + +Long press a message, and then tap **Copy Link** to copy the link to the clipboard. Long press to paste the link as a message or reply. From mobile v2.23, sharing links to messages generates a preview of the message. + +![Tap and hold on a message to access the available options.](/images/mobile-copy-a-link-to-the-message.gif) + +
+ + + +- Message previews respect channel membership permissions, so they’re only visible to users who have access to the original message. If the link is to a message in a public channel, any member of the team can see the message preview. If the link is to a message in a private channel or direct message, only members in that channel can see the message preview. +- If you're unable to share links, contact your Mattermost system admin for assistance. An [SSL certificate (or a self-signed certificate)](/administration-guide/onboard/ssl-client-certificate) may be required for this functionality to work. + + + +## Deep links + +Deep links are a powerful feature in Mattermost that allow you to create direct links to specific teams, channels, messages, or threads. These links can be used to quickly navigate to important content within Mattermost, enhancing collaboration and efficiency. + +Deep links can also be used, in combination with bots, scripts, and integrations, to trigger specific actions within Mattermost. + +From Mattermost v10.11, [channel bookmarks](/end-user-guide/collaborate/manage-channel-bookmarks) containing `mattermost://` open directly in the desktop app using deep linking. This turns channel bookmarks into one-click shortcuts that enable you jump straight to key assets in Mattermost quickly and easily. + +### Format deep links + +Deep links must be formatted in Mattermost as follows: + +- Deep link to a team: `mattermost:///<team-name>` +- Deep link to a channel: `mattermost:///<team-name>/channels/<channel-name>` +- Deep link to a channel message or thread: `mattermost:///<team-name>/pl/<post-id>` +- Deep link to a direct message: `mattermost:///<team-name>/messages/@<user-name>` diff --git a/docs/main/end-user-guide/collaborate/team-keyboard-shortcuts.mdx b/docs/main/end-user-guide/collaborate/team-keyboard-shortcuts.mdx new file mode 100644 index 000000000000..59ace05c9f8d --- /dev/null +++ b/docs/main/end-user-guide/collaborate/team-keyboard-shortcuts.mdx @@ -0,0 +1,48 @@ +--- +title: "Team keyboard shortcuts" +draft: true +--- + + +Keyboard shortcuts help you make a more efficient use of your keyboard when navigating Mattermost teams in a web browser or the desktop app. + + + +See a list of available keyboard shortcuts any time by pressing Ctrl / on Windows or Linux, pressing / on Mac, or using the `/shortcuts` slash command. + + + +## Team navigation + +The following keyboard shortcuts are supported in all [supported browsers](/deployment-guide/software-hardware-requirements#software-requirements) and in the Mattermost Desktop App. + + +++ + + + + + + + + + + + +
+

On Windows & Linux | On Mac | Description |

+
+
+
===========================================+======================================+==============================================+
+
+

Ctrl Alt | | Navigate to the previous team. |

+
+
Ctrl Alt | | Navigate to the next team. |
Ctrl Alt 1-9 | 1-9 | Navigate to a specific team.
+ + + +Though Mattermost keyboard shortcuts support standard languages and keyboard layouts, they may not work if you use keymapping that overwrites default browser shortcuts. + + diff --git a/docs/main/end-user-guide/collaborate/team-settings.mdx b/docs/main/end-user-guide/collaborate/team-settings.mdx new file mode 100644 index 000000000000..097d5e0b6c10 --- /dev/null +++ b/docs/main/end-user-guide/collaborate/team-settings.mdx @@ -0,0 +1,86 @@ +--- +title: "Team settings" +--- + + +Team settings enable system and team administrators to adjust settings applied to a specific team. Using Mattermost in a web browser or the desktop app, select the team name to access **Team Settings**. + +![Access team settings from the team name.](/images/team-settings.png) + +## Info settings + +Info settings provide configuration options for how teams are displayed to users. + +### Team name + +Your **Team Name** is displayed on the login screen, and in the top of the channel sidebar for your team. + +Team names can contain any letters, numbers, or symbols, must be 2 - 64 characters in length, and are case-sensitive. + + + +Team names don't support [some unicode characters](https://www.w3.org/TR/unicode-xml/#Charlist). + + + +### Team description + +Your **Team Description** is displayed when viewing the list of teams available to join and in the tooltip when hovering over the team name in the team sidebar. + +You can enter a description up to 50 characters in length. + + + +Team descriptions don't support [some unicode characters](https://www.w3.org/TR/unicode-xml/#Charlist). + + + +### Team icon + +A **Team Icon** displays in the team sidebar. By default, the team icon contains the first two letters of the team name. + +To customize the team icon: + +1. Select **Team Settings**. +2. Select the Team Icon **Edit** option. + +![Manage the team icon from Team Settings.](/images/edit-team-icon.png) + +3. Select an icon image in BMP, JPG, or PNG format. We recommend using square images with a solid background color since transparency in PNG icons fills with a white background in the team sidebar. +4. Select **Save**. + + + +When a team icon is configured, select **Remove image** to reset the team icon to the default icon containing the first two letters of the team name. + + + +## Access settings + +Access settings enable the ability to control who can join the team. + +### Users with a specific email domain + +System and team administrators can limit who can join the team based on their email domain. Enable this option to specify approved email domains. Separate multiple email domains using spaces, commas, pressing Tab, or pressing Enter. + +When enabled, only users that have an email domain from the approved domain list is able to join the team. The setting's intent is solely to gate joining a team. Once joined, team members will be able to update their email to a non-approved domain without any restrictions. Additionally, team members who joined prior to approved domains being specified won't be removed from the team once approved email domains are configured and enforced. + + + +Mattermost deployments using [email authentication](/administration-guide/configure/authentication-configuration-settings#enable-sign-in-with-email) must also enable the [require email verification configuration setting](/administration-guide/configure/authentication-configuration-settings#require-email-verification) for domain restrictions to be effective. + + + +### Users on this server + +System and team administrators can include the team in a list of teams to join for new Mattermost users who aren't yet members of a team. Enable this option to allow any user with a Mattermost account on this instance to join this team from the **Teams you can join** page. + + + +When you enable this option, users looking for more teams to join will also see this team in the list when they select the The Plus icon provides access to channel and direct message functionality. icon in the team sidebar. + + + +### Invite code + +The **Invite Code** is used as part of the URL in team invitation links. Select **Regenerate** to create a new invitation link and invalidate any previous link. diff --git a/docs/main/end-user-guide/collaborate/view-system-information.mdx b/docs/main/end-user-guide/collaborate/view-system-information.mdx new file mode 100644 index 000000000000..0c611c3549dc --- /dev/null +++ b/docs/main/end-user-guide/collaborate/view-system-information.mdx @@ -0,0 +1,35 @@ +--- +title: "View system information" +--- + + +You can view technical details about your Mattermost server, including version information and system metrics. This information is useful when working with Mattermost support or troubleshooting issues. + +
+ +Web/Desktop + +1. Select your profile picture in the top-right corner of Mattermost. +2. Select **About Mattermost** from the dropdown menu. + +
+ +
+ +Mobile + +1. Tap your profile picture. +2. Tap **About** to view system information. + +
+ +## About dialog information + +The About dialog displays key information about your Mattermost instance, including: + +- **Mattermost Version**: The current version of the Mattermost server. Click to copy the version number. +- **Desktop App Version**: The current version of the Mattermost Desktop App (when using Desktop App). Click to copy the version number. +- **Database Schema Version**: The version of the database schema in use +- **License**: Information about your Mattermost license (if applicable) +- **Build Information**: Details about the server build +- **Load Metric**: Monthly active users relative to licensed users ([learn more](/administration-guide/manage/admin/generating-support-packet#load-metric)) diff --git a/docs/main/end-user-guide/end-user-guide-index.mdx b/docs/main/end-user-guide/end-user-guide-index.mdx new file mode 100644 index 000000000000..01f80812f1a4 --- /dev/null +++ b/docs/main/end-user-guide/end-user-guide-index.mdx @@ -0,0 +1,22 @@ +--- +title: "End User Guide" +--- +If you're using Mattermost to connect and collaborate, build repeatable, automated processes, and making Mattermost match your work preferences, this Mattermost end user product documentation is for you. + +In this documentation, you'll learn about using Mattermost. Your Mattermost system admin has deployed Mattermost for your organization. A live Mattermost instance is ready for you to log into using your user credentials. Your Mattermost workspace is where you'll send and receive messages, see activity notifications, create, run, and participate in playbook runs, and where you'll customize look and feel through workspace preferences. + +- [Access Your Workspace](/end-user-guide/access/access-your-workspace) - Learn how to access Mattermost using web, desktop, or mobile apps, and authenticate with your credentials. +- [Messaging Collaboration](/end-user-guide/messaging-collaboration) - Learn how to use Mattermost to connect and collaborate with your teammates. +- [Workflow Automation](/end-user-guide/workflow-automation) - Learn how to use Mattermost Playbooks to build repeatable processes, move faster, and make fewer mistakes with checklist-based automations. +- [Audio and Screensharing](/end-user-guide/collaborate/audio-and-screensharing) - Learn about Mattermost's self-hosted audio calls plugin with screen sharing and the many video conferencing integrations Mattermost supports. +- [Project and Task Management](/end-user-guide/project-task-management) - Learn how to use Mattermost Boards to coordinate operational work with Kanban-style planning. +- [AI Agents](/end-user-guide/agents) - Learn how to use AI agents to help you make decisions, find information, and automate repetative tasks. +- [Customize Your Preferences](/end-user-guide/preferences) - Learn how to make Mattermost match the way you prefer to work. + +![An example of the Mattermost screen that includes teams, the channel sidebar, an active conversation in the center pane, reply threads in the right-hand pane.](/images/Channels_Hero.png) + + + +From Mattermost v9.1, when using Mattermost in a browser or the desktop app, you can resize both the channel sidebar and right-hand sidebar panes! + + diff --git a/docs/main/end-user-guide/messaging-collaboration.mdx b/docs/main/end-user-guide/messaging-collaboration.mdx new file mode 100644 index 000000000000..7aaf88351721 --- /dev/null +++ b/docs/main/end-user-guide/messaging-collaboration.mdx @@ -0,0 +1,21 @@ +--- +title: "Messaging Collaboration" +--- + + +Mattermost provides 1:1 and group messaging that features integrated voice/video conferencing, file, image, and link sharing, rich markdown formatting, and a fully searchable message history. With Mattermost, you can keep all of your team's communications in one place and remove information and organizational silos. + +This Mattermost end user documentation is designed for anyone who wants guidance on using Mattermost to collaborate. + +## Getting Started + +- [Organize using teams](/end-user-guide/collaborate/organize-using-teams) - Learn about team-based organization in Mattermost. +- [Organize using custom user groups](/end-user-guide/collaborate/organize-using-custom-user-groups) - Learn about creating and managing custom user groups in Mattermost. +- [Invite people to your workspace](/end-user-guide/collaborate/invite-people) - Learn how to add new users to Mattermost and add users to existing teams and channels. +- [Learn about Mattermost user roles](/end-user-guide/collaborate/learn-about-roles) - Learn about the 6 user roles in Mattermost and what they can do. +- [View system information](/end-user-guide/collaborate/view-system-information) - View technical details about your Mattermost server, including version information and system metrics. +- [Collaborate within channels](/end-user-guide/collaborate/collaborate-within-channels) - Learn how to get started collaborating within Mattermost channels. +- [Communicate with messages and threads](/end-user-guide/collaborate/communicate-with-messages) Learn how to get started collaborating within Mattermost channels. +- [Collaborate within Microsoft Teams](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams) - Learn how to get started collaborating within Microsoft Teams. +- [Keyboard shortcuts](/end-user-guide/collaborate/keyboard-shortcuts) - Make a more efficient use of your keyboard with keyboard shortcuts. +- [Extend Mattermost with integrations](/end-user-guide/collaborate/extend-mattermost-with-integrations) - Find open source integrations to common tools in the Mattermost Marketplace. diff --git a/docs/main/end-user-guide/preferences.mdx b/docs/main/end-user-guide/preferences.mdx new file mode 100644 index 000000000000..6620bee194e8 --- /dev/null +++ b/docs/main/end-user-guide/preferences.mdx @@ -0,0 +1,27 @@ +--- +title: "Customize your preferences" +--- + + +You can customize many aspects of your Mattermost experience based on your preferences, including notifications for Mattermost activity, how unread channels are organized, the number of direct messages displayed, your Mattermost look and feel, and more! + + + +Download [this guide to customizing Mattermost for technical teams](https://mattermost.com/customizing-mattermost-for-technical-teams-guide/) to learn how to get more from the platform. + + + +## Learn more + +- [Manage your notifications](/end-user-guide/preferences/manage-your-notifications) - Learn how Mattermost notifications work by default and how to customize notifications based on how you prefer to work. +- [Customize your Mattermost theme](/end-user-guide/preferences/customize-your-theme) - Learn how to change the look and feel of Mattermost based on your preferences. +- [Customize your channel sidebar](/end-user-guide/preferences/customize-your-channel-sidebar) - Organize conversations in the sidebar to keep your workspace efficient. +- [Manage your profile](/end-user-guide/preferences/manage-your-profile) - Configure your Mattermost profile. +- [Manage your security preferences](/end-user-guide/preferences/manage-your-security-preferences) - Configure your Mattermost security preferences. +- [Set your status and availability](/end-user-guide/preferences/set-your-status-availability) - Let your team know whether you’re available. +- [Customize your display options](/end-user-guide/preferences/manage-your-display-options) - Customize your Mattermost display to suit your preferences. +- [Manage your sidebar options](/end-user-guide/preferences/manage-your-sidebar-options) - Customize your Mattermost channel sidebar to suit your preferences. +- [Manage advanced options](/end-user-guide/preferences/manage-advanced-options) - Customize advanced Mattermost user options to suit your preferences. +- [Manage your plugin preferences](/end-user-guide/preferences/manage-your-plugin-preferences) - Customize Mattermost plugin preferences for Microsoft Teams and Calls. +- [Customize your desktop app experience](/end-user-guide/preferences/customize-desktop-app-experience) - Learn about additional preferences available only in the desktop app. +- [Connect to multiple Mattermost workspaces](/end-user-guide/preferences/connect-multiple-workspaces) - Learn how to connect to multiple Mattermost workspaces using the Mattermost desktop or mobile app. diff --git a/docs/main/end-user-guide/preferences/connect-multiple-workspaces.mdx b/docs/main/end-user-guide/preferences/connect-multiple-workspaces.mdx new file mode 100644 index 000000000000..09dd4243b961 --- /dev/null +++ b/docs/main/end-user-guide/preferences/connect-multiple-workspaces.mdx @@ -0,0 +1,166 @@ +--- +title: "Connect to multiple Mattermost workspaces" +--- + + +Using the Mattermost desktop or mobile app, you can connect to multiple Mattermost servers from a single interface, and manage system permissions. + +## Add a server + +
+ +Web/Desktop + +The **Server** list is located in the top left corner of the window and displays all servers available. Drag to reorder the servers in the list. You can also navigate the server options using [keyboard shortcuts](/end-user-guide/collaborate/keyboard-shortcuts). + + + +If you're using the desktop app prior to release v5.0, individual servers display as separate tabs at the top of the window instead of the top left corner of the window as a list, and servers are managed by going to **… \> File \> Settings** on Windows and **Mattermost \> Preferences** on Mac. + + + +1. Select **Add a server**. + +> ![Connect the desktop app to a Mattermost Server using options located in the top left corner of the Mattermost screen.](/images/desktop-server-add.png) + +2. Enter the server URL. Server URLs must begin with either `http://` or `https://`. + +>
+> +>
+> +> Tip +> +>
+> +> Can't find your Mattermost server URL? Ask your company’s IT department or your Mattermost system admin for your organization’s **Mattermost Site URL**. It’ll look something like `https://example.com/company/mattermost`, `mattermost.yourcompanydomain.com`, or `chat.yourcompanydomain.com`. These URLs could also end in `.net`. +> +>
+ +3. Enter the server's Display Name. +4. \[Desktop only\] If your server requires an authentication secret, you'll be prompted to enter it when you connect. Enter the secret provided by your administrator and select **OK**. +5. Select **Add**. + +
+ +
+ +Mobile + +Tap the **Servers** Access server connection options using the Servers icon. icon located in the top left corner of the window to access all available servers and to add new servers. + +1. Tap **Add a server**. +2. Enter the server URL. Server URLs must begin with either `http://` or `https://`. + + + +Can't find your Mattermost server URL? Ask your company’s IT department or your Mattermost system admin for your organization’s **Mattermost Site URL**. It’ll look something like `https://example.com/company/mattermost`, `mattermost.yourcompanydomain.com`, or `chat.yourcompanydomain.com`. These URLs could also end in `.net`. + + + +3. Enter the server's Display Name. +4. Optionally toggle the **Advanced Options** section to enter an **Authentication secret**. This is an additional security measure that some organizations use. Your system admin can provide you with the secret if required. + +> Mobile app server setup screen showing the optional authentication secret field. + +5. Tap **Done**. + +
+ +## Edit a server + +
+ +Web/Desktop + +1. Hover over a server and select the **Edit** icon. + + > ![Edit an existing Mattermost server connection using options located in the top right corner of the Mattermost screen.](/images/desktop-edit-server.png) + +2. Modify the server's display name or URL, then select **Save**. + +> \[Desktop only\] To update an authentication secret, connect to the server. If the secret has changed, you'll be prompted to enter the new one provided by your system admin. + +
+ +
+ +Mobile + +1. Swipe left on an existing server entry to reveal additional options. Tap **Edit**. + +> In the Mattermost mobile app, swipe left on an existing server connection entry to edit the connection. + +2. Modify the server's display name or authentication secret, and then tap **Save**. + +> Mobile app edit server screen showing display name fields. +> +> To view or update the authentication secret, expand the **Advanced Options** section. If a secret is currently configured, it will be pre-filled in the field. + +
+ +## Remove a server + +Removing a server from your desktop app doesn't delete its data. You can add the server back any time. + +
+ +Web/Desktop + +1. Hover over a server and select **Remove**. + + > ![Remove a Mattermost server connection using options located in the top right corner of the Mattermost screen.](/images/desktop-remove-server.png) + +2. Select **Remove** when prompted to confirm. + +
+ +
+ +Mobile + +Tap the **Servers** Access server connection options using the Servers icon. icon located in the top left corner of the window to access all available servers and to add new servers. + +Swipe left on an existing server entry to reveal additional options. Tap **Remove**. + +In the Mattermost mobile app, swipe left on an existing server connection entry to delete the connection. + +
+ +## Switch between workspaces + +Select a workspace from the **Servers** list in the top left of the desktop app. See [keyboard shortcuts](/end-user-guide/collaborate/keyboard-shortcuts) for more navigation options. + +## Manage system permissions + +From Mattermost desktop v5.9, you can manage system permissions when creating or managing existing Mattermost server connections, including: microphone access, camera access, notifications, and location. + +Granting a system permission sets it to **Accept**, and revoking it sets it to **Always Deny**. + +![A screenshot of the system permissions that Mattermost users can manage when creating new server connections or editing existing connections.](/images/desktop-system-permissions.png) + + + +- You can't manage system permissions when using the Mattermost mobile app. +- You'll be prompted to accept or deny notifications after adding a new server connection, and any time you open the desktop app if you haven't explicitly accepted or denied system permissions. +- You may also need to enable notifications for Mattermost within your operating system preferences. + + + +## Open multiple workspace contexts + +From desktop v6.0, you can keep multiple workspaces open at the same time and work across them without constant switching to improve situational awareness and operational efficiency. This capability is especially useful for organizations that operate in distributed or multi-domain environments, as it enhances cross-system interoperability and command-level situational awareness. + +Select the **New tab** The Plus icon provides access to channel and direct message functionality. icon at the top of the desktop app to open a new tab for the current workspace. You can drag and drop to reorder the tabs in the main desktop window. + +Open internal Mattermost links in a new tab or window by right-clicking on the link and selecting **Open in new tab** or **Open in new window**. + +- Convert tabs to new windows by right-clicking the tab label and selecting **Move to new window**. +- Convert pop-out windows back to tabs in the main window by right-clicking on the window title and selecting **Move to main window**. +- Close pop-out windows by right-clicking on the window title and selecting **Close window**. + + + +You can manage windows and tabs from the Desktop app's **File** menu, and review all open tabs from the **Windows** menu. + + diff --git a/docs/main/end-user-guide/preferences/customize-desktop-app-experience.mdx b/docs/main/end-user-guide/preferences/customize-desktop-app-experience.mdx new file mode 100644 index 000000000000..6b6d6743224f --- /dev/null +++ b/docs/main/end-user-guide/preferences/customize-desktop-app-experience.mdx @@ -0,0 +1,95 @@ +--- +title: "Customize your Desktop App experience" +--- + + +You can customize your desktop app further with additional settings. Select the tab below that matches your operating system to learn more about what's available. + +
+ +macOS + +With the Mattermost desktop app in focus, select **Mattermost \> Settings...** + +![Access Desktop App customization settings by selecting Mattermost from the menu bar, then selecting Preferences.](/images/mac-desktop-app-settings.png) + +## General + +- **Download Location**: Specify where on your machine you want files to be downloaded from the desktop app. +- **Show icon in the notification area**: The Mattermost icon displays in the notification area. You can hide this icon if preferred. Restart the desktop app to apply changes to this setting. +- **Synchronize Desktop App theme with server**: The desktop app theme automatically matches the theme set on your primary Mattermost server. Disable this setting to manage desktop app themes independently. +- **Open app in full screen**: Configure the desktop app to open in fullscreen. Disable this setting to open the app in a windowed view. +- **Maximum number of open views**: From Desktop v6.0, set the maximum number of open tabs and windows per workspace. When a limit is set, Mattermost prompts you to close tabs or windows when the limit is exceeded. Leave this field blank for no maximum limit. + +## Notifications + +- **Show red badge on Dock icon to indicate unread messages**: A red badge on the Dock icon displays a count of unread messages and mentions. You can configure the desktop app to display a count of mentions only, if preferred. +- **Bounce the Dock icon**: When a new message is received on any of your active teams and servers, the Dock icon bounces once or bounces until you open the desktop app. You can configure the Mattermost Desktop App Dock icon to bounce more, less, or not at all. + +## Language + +- **App Language**: Specify your preferred language for the desktop app. +- **Check spelling**: Misspelled words detected in your messages are highlighted based on your app language preference. You can disable spell check if preferred. +- **Spell Checker Languages**: Specify additional spell check languages if needed. Restart the desktop app to change this setting. When multiple languages are configured: + - All selected languages show as spelled correctly when a word matches at least one selected language + - All selected languages show as spelled incorrectly when a word matches none of the selected languages. +- **Use an alternative dictionary URL**: Specify an alternate dictionary for spell check as a site URL. + +## Servers + +- **Add and manage server connections**: Learn more about [connecting your desktop app to multiple Mattermost workspaces](/end-user-guide/preferences/connect-multiple-workspaces). + +## Advanced + +- **Logging level**: Adjust logging levels to isolate and troubleshoot issues. Increasing the log level increases disk space usage and can impact performance. +- **Send anonymous usage data to your configured servers**: Send desktop app usage and performance data to your configured Mattermost servers set up to accept it. +- **Send error reports to help improve the app**: From Mattermost Desktop v6.1.0, error reports and crash information are automatically sent to Sentry (a third-party error tracking service) to help identify and fix issues. This setting is enabled by default. Error reports include crash information, app version, and platform details (OS, architecture, memory stats), but no personally identifiable information (PII) is included. You can disable error reporting if preferred. Restart the desktop app to apply changes to this setting. +- **Use GPU hardware acceleration**: GPU hardware acceleration renders the desktop app interface more efficiently. If you encounter decreased stability, disable GPU hardware acceleration. Restart the desktop app to apply changes to this setting. + +
+ +
+ +Windows/Linux + +With the Mattermost desktop app in focus, select the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon in the top left of the menu bar and select **File \> Settings...** + +![Access Desktop App customization settings by selecting More in the top left corner, then selecting File \> Settings.](/images/desktop-app-settings.jpg) + +## General + +- **Download Location**: Specify where on your machine you want files to be downloaded from the desktop app. +- **Start app on login**: The desktop app starts up automatically when you log in to your machine. You can disable this if preferred. +- **Launch app minimized**: Configure the desktop app to launch minimized in the system tray. +- **Icon color**: Display a light, dark, or system default-driven Mattermost icon. +- **Leave app running in notification area when application window is closed**: When closing the desktop app, you’re prompted to confirm whether you want to permanently close the app. Disable this confirmation by selecting **Don’t ask again**. Silence these notifications by selecting **Don’t show again**. Restart the desktop app to apply changes to this setting. +- **Open app in full screen**: Configure the desktop app to open in fullscreen. Disable this setting to open the app in a windowed view. +- **Synchronize Desktop App theme with server**: The desktop app theme automatically matches the theme set on your primary Mattermost server. Disable this setting to manage desktop app themes independently. +- **Maximum number of open views**: From Desktop v6.0, set the maximum number of open tabs and windows per workspace. When a limit is set, Mattermost prompts you to close tabs or windows when the limit is exceeded. Leave this field blank for no maximum limit. + +## Notifications + +- **Show red badge on taskbar icon to indicate unread messages**: +- **Flash taskbar icon when a new message is received**: Your desktop app taskbar icon flashes when a new message is received on any of your active teams and servers. You can disable the flashing taskbar icon if preferred. + +## Language + +- **App Language**: Specify your preferred language for the desktop app. +- **Check spelling**: Misspelled words detected in your messages are highlighted based on your app language preference. You can disable spell check if preferred. +- **Spell Checker Languages**: Specify additional spell check languages if needed. Restart the desktop app to apply changes to this setting. When multiple languages are configured: + - All selected languages show as spelled correctly when a word matches at least one selected language + - All selected languages show as spelled incorrectly when a word matches none of the selected languages. +- **Use an alternative dictionary URL**: Specify an alternate dictionary for spell check as a site URL. + +## Servers + +- **Add and manage server connections**: Learn more about [connecting your desktop app to multiple Mattermost workspaces](/end-user-guide/preferences/connect-multiple-workspaces). + +## Advanced + +- **Logging level**: Adjust logging levels to isolate and troubleshoot issues. Increasing the log level increases disk space usage and can impact performance. +- **Send anonymous usage data to your configured servers**: Send desktop app usage and performance data to your configured Mattermost servers set up to accept it. +- **Send error reports to help improve the app**: From Mattermost Desktop v6.1.0, error reports and crash information are automatically sent to Sentry (a third-party error tracking service) to help identify and fix issues. This setting is enabled by default. Error reports include crash information, app version, and platform details (OS, architecture, memory stats), but no personally identifiable information (PII) is included. You can disable error reporting if preferred. Restart the desktop app to apply changes to this setting. +- **Use GPU hardware acceleration**: GPU hardware acceleration renders the desktop app interface more efficiently. If you encounter decreased stability, disable GPU hardware acceleration. Restart the desktop app to apply changes to this setting. + +
diff --git a/docs/main/end-user-guide/preferences/customize-your-channel-sidebar.mdx b/docs/main/end-user-guide/preferences/customize-your-channel-sidebar.mdx new file mode 100644 index 000000000000..9d6959bd08d9 --- /dev/null +++ b/docs/main/end-user-guide/preferences/customize-your-channel-sidebar.mdx @@ -0,0 +1,178 @@ +--- +title: "Customize your channel sidebar" +--- + + +Conversations in Mattermost are crucial to company productivity and success. Keeping conversations organized in the sidebar creates an efficient workplace. Using a web browser or the desktop app, you can customize your own channel sidebar based on how you prefer to use Mattermost. Customizations you make are only visible to you, are visible when using the mobile app, and won't affect what your teammates see in their sidebars. + +Here's how your sidebar is set up by default: + +- All public and private channels you've joined are listed in the **Channels** category, sorted alphabetically. +- All your direct messages and group messages are listed in the **Direct Messages** category, sorted by recent activity. + +## What can you customize? + +Using Mattermost in a web browser or the desktop app, you can customize your sidebar in the following ways: + +- [Create custom categories](#create-custom-categories) +- [Group and order channels into your categories](#organize-channels-in-categories) +- [Mute and unmute entire categories](#mute-and-unmute-categories) +- [Mark entire categories as read](#mark-channel-categories-as-read) +- [Sort channels in each category](#sort-channels-in-categories) manually, alphabetically, or by recent activity +- [Filter your sidebar to view unread channels only](#group-unread-channels-separately), or choose to group unread messages into an **Unreads** category +- [Manage your direct messages](#manage-direct-messages) by sorting them alphabetically or by recent activity, and by setting how many to display in your sidebar +- [Make channel categories work for you](#make-categories-work-for-you) by prefixing category names with emojis, by collapsing and expanding categories, by reordering categories, and by adding direct message conversations to categories. + +![Organize your channel sidebar with channel categories.](/images/channel_sidebar_updates.gif) + +## Create custom categories + +Create custom categories to group channels together for quicker and easier navigation. For example, you can create a category called "Design" or "Marketing". + +To create categories, select the **+** symbol at the top of the sidebar. Or, select the **More options** Use the More icon to access additional message options. icon in the sidebar on any category header, then select **Create New Category**. + + + +If your system admin has enabled [channel category sorting](/administration-guide/configure/experimental-configuration-settings#enable-channel-category-sorting), you can assign channels to new or existing channel categories when [creating channels](/end-user-guide/collaborate/create-channels) and [renaming channels](/end-user-guide/collaborate/rename-channels). + + + +Next, type a category name, select **Create**, then drag any channels or direct messages into this new category. You can also multi-select channels and direct messages to drag them together as a group by pressing Ctrl or Shift and selecting on Windows or Linux, or or and selecting on Mac. See the section [drag and drop selections](#drag-and-drop-selections) below for details. + +Your custom categories can't be shared with other Mattermost users. + +## Rename categories + +1. Select the **Category options** icon in the sidebar, then select **Rename Category**. +2. Type a new category name, then select **Rename**. + +## Delete categories + +1. Select the **Category options** icon in the sidebar, then select **Delete Category**. +2. Select **Delete** to confirm or select **X** to cancel. + +All channels and direct message conversations in the deleted category move back to their default **Channels** and **Direct Messages** categories. Deleting a category never removes you from channels you have joined. + +## Organize channels in categories + +Once you've created categories, you can move channels around to organize your sidebar by dragging and dropping, or by moving. + +### Drag and drop selections + +To select multiple channels: + +- Select sequential channels and/or direct messages by pressing Shift while selecting on Windows or Linux, or while selecting on Mac. +- Select non-sequential channels and/or direct messages by pressing Ctrl while selecting on Windows or Linux, or while selecting on Mac +- Press ESC to clear channel or direct message selections. + +Using the Mattermost web or desktop app, drag selected channels and/or direct messages between or within categories. + + + +Multi-selected channels and direct messages move together as a group in the order they originally appeared. + + + +![Move a group of selected channels by dragging them to a new location in the channel sidebar.](/images/multi-select-drag.gif) + +### Move selections + +In addition to selecting and dragging, you can specify a category destination for selected channels and/or direct messages. To do this, select the **Channel options** icon in the sidebar and then select **Move to**. + +![Move a group of selected channels to a specified category destination.](/images/multi-select-move.gif) + +You can also specify a category destination for the current channel or conversation using the **Move to** option directly from the channel header. Channels that have been moved to a category will display a checkmark next to the category name. + +![Move channels or conversations directly from the channel header.](/images/channel-heading-categories.png) + +## Mute and unmute categories + +When you mute or unmute a category, all channels within that category are also muted or unmuted. You can selectively unmute specific channels within a muted category. + +Select the **Category options** icon in the sidebar, then select **Mute Category**. + +Once a category is muted: + +- Email, desktop, and push notifications are disabled for all channels in the category. +- A mute icon displays next to each channel name in the category. +- The category and all of its channels appear at reduced opacity in the left-hand sidebar. Channels in the category aren't marked as unread unless you’re mentioned directly. + +To unmute the category, select the **Category options** icon in the sidebar, then select **Unmute Category**. + +![Mute or unmute a category to mute or unmute all channels within that category. You can also selectively unmute specific channels within a muted category.](/images/mute-categories.gif) + +## Mark channel categories as read + +When you mark a channel category as read, all channels within that category are marked as read. You can selectively mark specific channels as unread where preferred. + +Select the **Category options** icon in the sidebar, then select **Mark category as read**. + +## Sort channels in categories + +Select the **Category options** icon in the sidebar, then select **Sort** and choose from **Alphabetically**, **Recent Activity**, or **Manually**. + +![Sort channels within a category alphabetically, by recent activity, or manually.](/images/sort-categories.gif) + +## Group unread channels separately + +By default, Mattermost provides a one-click **Unreads** filter to only show channels with unread activity. Alternatively, you may choose to automatically group unread channels in their own category at the top of your sidebar. + +Go to **Settings \> Sidebar**, set **Group unread channels separately** to **On**, then select **Save**. + +- When this setting is enabled, all unread messages appear only in the **Unreads** category, sorted with mentions first. +- When this setting is disabled, all unread messages appear within their respective categories and channels. You can use the **Unread filter** to focus on only unread channels in the sidebar. + +When enabled, unread channels with mentions will sort to the top of the category. + +![The Unreads filter only shows channels with unread activity. You can also group unread channels into their own category at the top of the channel sidebar.](/images/unreads.gif) + + + +If you prefer to see only unread channels in their respective categories, we recommend collapsing your custom categories and disabling **Group unread channels separately** under **Settings \> Sidebar**. + + + +## Manage direct messages + +To sort your direct messages, select the **Channel options** icon in the sidebar, then select **Sort** and choose from **Alphabetically** or **Recent Activity**. + +### How many direct messages to display? + +Control how many direct message conversations display in the **Direct Messages** category to keep your conversations manageable. You can choose to show all messages or a fixed number of messages. + +To configure the number of direct messages to display, go to **Settings \> Sidebar**, then set **Number of direct messages to show**. Or select the **Channel options** icon in the sidebar, then select **Show**. + +Choose to show **10**, **15**, **20**, or **40** messages. Once you exceed the number of direct messages configured, older messages are hidden from the **Direct Messages** category. You can always increase the number of conversations displayed to see older direct messages. + +![alt: Control the number of direct message conversations to display under the Direct Messages category by showing all messages or a fixed number of messages.](/images/dm-display.gif) + + + +Direct message conversations that you add to custom categories don't count against the maximum number of conversations shown in the **Direct Messages** category. + + + +## Make categories work for you + +### Prefix channel category names with emojis + +Channel category names can include emojis. Specify the emoji by its name in the format `:smile:`. We recommend prefixing channel category names with emojis for the following reasons: + +- Emojis can make it easier for users to quickly identify and manage channels and channel categories, particularly in large workspaces with many channels. +- Sharing the same emoji across channels and categories related to a specific category or function helps maintain organization and consistency across the workspace. +- Making channel categories more visually distinct with emojis helps users find what they need more quickly and easily at a glance, reducing the time spent searching for the right place to take action. +- New users can quickly understand the purpose of various channels and channel categories based on their emoji prefixes without needing extensive explanations. +- As users grasp channel structure through emojis, the time and effort needed to train new members on navigating the workspace is reduced. +- A well-organized and visually appealing workspace can encourage users to participate more actively, which can lead to more effective communication and collaboration. + +### Categories are collapsible + +When you collapse a channel category, only unread channels display to reduce unnecessary scrolling. When you expand a channel category, all channels in the category display, including channels with unread messages. + +### Reorder categories + +Drag to reorder entire categories to prioritize important conversations. + +### Categories can contain direct message conversations + +Select and drag direct messages into any category. You can also multi-select direct messages to drag them together as a group. diff --git a/docs/main/end-user-guide/preferences/customize-your-theme.mdx b/docs/main/end-user-guide/preferences/customize-your-theme.mdx new file mode 100644 index 000000000000..ea821594e45a --- /dev/null +++ b/docs/main/end-user-guide/preferences/customize-your-theme.mdx @@ -0,0 +1,264 @@ +--- +title: "Customize your Mattermost theme" +--- + + +The colors of the Mattermost user interface are customizable. You can choose from [five standard themes](#standard-themes) designed by Mattermost, or design your own custom theme. Your theme changes apply to all teams you're a member of, and are visible across all Mattermost clients. Mattermost Enterprise customers can configure a different theme for every team they're a member of. + +
+ +Web/desktop + +Select the **Settings** Use the Settings icon to customize your Mattermost user experience. icon, then go to **Display \> Theme**. Select **Theme Colors** to choose from five standard themes designed by the Mattermost team. + +You can customize a standard theme further to truly make it your own. After selecting a standard theme, select **Custom Theme** and modify your color choices based on your preferences. See the [custom themes](#custom-themes) documentation to learn what's configurable, and see the [custom theme examples](#custom-theme-examples) documentation for inspiration. + +
+ +
+ +Mobile + +Tap **Theme** to select one of 5 standard Mattermost themes. + + + +You can define a custom theme using Mattermost in a web browser or the desktop app. + + + +
+ +## Custom themes + +Select **Custom Theme**, then expand the [Sidebar Styles](/end-user-guide/preferences/customize-your-theme#sidebar-styles), [Center Channel Styles](/end-user-guide/preferences/customize-your-theme#center-channel-styles), and [Link and Button Styles](/end-user-guide/preferences/customize-your-theme#link-and-button-styles) options to customize individual interface colors, such as backgrounds, links, text, and borders. + +Your custom theme changes are applied in Mattermost as you make them. Select **Save** to confirm your theme changes. Discard your changes by exiting the **Display Settings** window and selecting **Yes, Discard**. + +### Custom theme examples + +Customize your theme colors and share them with others by copying and pasting theme values into the input box. Below are some example themes with their corresponding theme values. + +#### Mattermost + +![Mattermost Theme](/images/Mattermost.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#145dbf","sidebarText":"#ffffff","sidebarUnreadText":"#ffffff","sidebarTextHoverBg":"#4578bf","sidebarTextActiveBorder":"#579eff","sidebarTextActiveColor":"#ffffff","sidebarHeaderBg":"#1153ab","sidebarTeamBarBg":"#0b428c","sidebarHeaderTextColor":"#ffffff","onlineIndicator":"#06d6a0","awayIndicator":"#ffbc42","dndIndicator":"#f74343","mentionBg":"#ffffff","mentionBj":"#ffffff","mentionColor":"#145dbf","centerChannelBg":"#ffffff","centerChannelColor":"#3d3c40","newMessageSeparator":"#ff8800","linkColor":"#2389d7","buttonBg":"#166de0","buttonColor":"#ffffff","errorTextColor":"#fd5960","mentionHighlightBg":"#ffe577","mentionHighlightLink":"#166de0","codeTheme":"github"} +``` + +#### Organization + +![Organization Theme](/images/Organization.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#2071a7","sidebarText":"#ffffff","sidebarUnreadText":"#ffffff","sidebarTextHoverBg":"#136197","sidebarTextActiveBorder":"#7ab0d6","sidebarTextActiveColor":"#ffffff","sidebarHeaderBg":"#2f81b7","sidebarTeamBarBg":"#256996","sidebarHeaderTextColor":"#ffffff","onlineIndicator":"#7dbe00","awayIndicator":"#dcbd4e","dndIndicator":"#ff6a6a","mentionBg":"#fbfbfb","mentionColor":"#2071f7","centerChannelBg":"#f2f4f8","centerChannelColor":"#333333","newMessageSeparator":"#ff8800","linkColor":"#2f81b7","buttonBg":"#1dacfc","buttonColor":"#ffffff","errorTextColor":"#a94442","mentionHighlightBg":"#f3e197","mentionHighlightLink":"#2f81b7","codeTheme":"github"} +``` + +#### Mattermost Dark + +![Mattermost Dark Theme](/images/MattermostDark.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#1b2c3e","sidebarText":"#ffffff","sidebarUnreadText":"#ffffff","sidebarTextHoverBg":"#4a5664","sidebarTextActiveBorder":"#66b9a7","sidebarTextActiveColor":"#ffffff","sidebarHeaderBg":"#1b2c3e","sidebarTeamBarBg":"#152231","sidebarHeaderTextColor":"#ffffff","onlineIndicator":"#65dcc8","awayIndicator":"#c1b966","dndIndicator":"#e81023","mentionBg":"#b74a4a","mentionColor":"#ffffff","centerChannelBg":"#2f3e4e","centerChannelColor":"#dddddd","newMessageSeparator":"#5de5da","linkColor":"#a4ffeb","buttonBg":"#4cbba4","buttonColor":"#ffffff","errorTextColor":"#ff6461","mentionHighlightBg":"#984063","mentionHighlightLink":"#a4ffeb","codeTheme":"solarized-dark"} +``` + +#### Windows Dark + +![Windows Dark Theme](/images/WindowsDark.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#171717","sidebarText":"#ffffff","sidebarUnreadText":"#ffffff","sidebarTextHoverBg":"#302e30","sidebarTextActiveBorder":"#196caf","sidebarTextActiveColor":"#ffffff","sidebarHeaderBg":"#1f1f1f","sidebarTeamBarBg":"#181818","sidebarHeaderTextColor":"#ffffff","onlineIndicator":"#399fff","awayIndicator":"#c1b966","dndIndicator":"#e81023","mentionBg":"#0177e7","mentionColor":"#ffffff","centerChannelBg":"#1f1f1f","centerChannelColor":"#dddddd","newMessageSeparator":"#cc992d","linkColor":"#0d93ff","buttonBg":"#0177e7","buttonColor":"#ffffff","errorTextColor":"#ff6461","mentionHighlightBg":"#784098","mentionHighlightLink":"#a4ffeb","codeTheme":"monokai"} +``` + +#### GitHub Theme + +![GitHub Theme](/images/GitHub.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"awayIndicator":"#D4B579","buttonBg":"#66CCCC","buttonColor":"#FFFFFF","centerChannelBg":"#FFFFFF","centerChannelColor":"#444444","codeTheme":"github","linkColor":"#3DADAD","mentionBg":"#66CCCC","mentionColor":"#FFFFFF","mentionHighlightBg":"#3DADAD","mentionHighlightLink":"#FFFFFF","newMessageSeparator":"#F2777A","onlineIndicator":"#52ADAD","sidebarBg":"#F2F0EC","sidebarHeaderBg":"#E8E6DF","sidebarHeaderTextColor":"#424242","sidebarText":"#2E2E2E","sidebarTextActiveBorder":"#66CCCC","sidebarTextActiveColor":"#594545","sidebarTextHoverBg":"#E0E0E0","sidebarUnreadText":"#515151"} +``` + +#### Monokai Theme + +![Monokai Theme](/images/Monokai.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"awayIndicator":"#B8B884","buttonBg":"#90AD58","buttonColor":"#FFFFFF","centerChannelBg":"#FFFFFF","centerChannelColor":"#444444","codeTheme":"monokai","linkColor":"#90AD58","mentionBg":"#7E9949","mentionColor":"#FFFFFF","mentionHighlightBg":"#54850C","mentionHighlightLink":"#FFFFFF","newMessageSeparator":"#90AD58","onlineIndicator":"#99CB3F","sidebarBg":"#262626","sidebarHeaderBg":"#363636","sidebarHeaderTextColor":"#FFFFFF","sidebarText":"#FFFFFF","sidebarTextActiveBorder":"#7E9949","sidebarTextActiveColor":"#FFFFFF","sidebarTextHoverBg":"#525252","sidebarUnreadText":"#CCCCCC"} +``` + +#### Solarized Dark Theme + +![Solarized Dark Theme](/images/SolarizedDark.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"awayIndicator":"#E0B333","buttonBg":"#859900","buttonColor":"#fdf6e3","centerChannelBg":"#073642","centerChannelColor":"#93a1a1","codeTheme":"solarized-dark","linkColor":"#268bd2","mentionBg":"#dc322f","mentionColor":"#ffffff","mentionHighlightBg":"#d33682","mentionHighlightLink":"#268bd2","newMessageSeparator":"#cb4b16","onlineIndicator":"#2AA198","sidebarBg":"#073642","sidebarHeaderBg":"#002B36","sidebarHeaderTextColor":"#FDF6E3","sidebarText":"#FDF6E3","sidebarTextActiveBorder":"#d33682","sidebarTextActiveColor":"#FDF6E3","sidebarTextHoverBg":"#CB4B16","sidebarUnreadText":"#FDF6E3","errorTextColor":"#dc322f"} +``` + +#### Gruvbox Dark Theme + +![Gruvbox Dark Theme](/images/GruvboxDark.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"awayIndicator":"#fabd2f","buttonBg":"#689d6a","buttonColor":"#ebdbb2","centerChannelBg":"#3c3836","centerChannelColor":"#ebdbb2","codeTheme":"monokai","errorTextColor":"#fb4934","linkColor":"#83a598","mentionBg":"#b16286","mentionColor":"#fbf1c7","mentionHighlightBg":"#d65d0e","mentionHighlightLink":"#fbf1c7","newMessageSeparator":"#d65d0e","onlineIndicator":"#b8bb26","sidebarBg":"#282828","sidebarHeaderBg":"#1d2021","sidebarHeaderTextColor":"#ebdbb2","sidebarText":"#ebdbb2","sidebarTextActiveBorder":"#d65d0e","sidebarTextActiveColor":"#fbf1c7","sidebarTextHoverBg":"#d65d0e","sidebarUnreadText":"#fe8019"} +``` + +#### One Dark Theme + +![One Dark Theme](/images/OneDark.png) + +[Visit the one-dark-mattermost GitHub repository online:](https://github.com/georgewitteman/one-dark-mattermost) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#21252b","sidebarText":"#abb2bf","sidebarUnreadText":"#abb2bf","sidebarTextHoverBg":"#3a3f4b","sidebarTextActiveBorder":"#4d78cc","sidebarTextActiveColor":"#d7dae0","sidebarHeaderBg":"#282c34","sidebarHeaderTextColor":"#abb2bf","onlineIndicator":"#98c379","awayIndicator":"#d19a66","dndIndicator":"#be5046","mentionBg":"#98c379","mentionColor":"#ffffff","centerChannelBg":"#282c34","centerChannelColor":"#abb2bf","newMessageSeparator":"#c67add","linkColor":"#61afef","buttonBg":"#4d78cc","buttonColor":"#ffffff","errorTextColor":"#f44747","mentionHighlightBg":"#525a69","mentionHighlightLink":"#61afef","codeTheme":"monokai","mentionBg":"#98c379"} +``` + +#### Discord Dark Theme (New) + +![Discord New Dark Theme](/images/DiscordNewDarkTheme.png) + +[Visit the mattermost-discord-dark GitHub repository online:](https://github.com/melroy89/mattermost-discord-dark) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg": "#121214", "sidebarText": "#ffffff", "sidebarUnreadText": "#ffffff", "sidebarTextHoverBg": "#1d1d1e", "sidebarTextActiveBorder": "#ffffff", "sidebarTextActiveColor": "#ffffff", "sidebarHeaderBg": "#121214", "sidebarHeaderTextColor": "#ffffff", "sidebarTeamBarBg": "#121214", "onlineIndicator": "#43a25a", "awayIndicator": "#ca9654", "dndIndicator": "#d83a42", "mentionBg": "#6e84d2", "mentionBj": "#6e84d2", "mentionColor": "#ffffff", "centerChannelBg": "#1a1a1e", "centerChannelColor": "#efeff0", "newMessageSeparator": "#ff4d4d", "linkColor": "#2095e8", "buttonBg": "#5865f2", "buttonColor": "#ffffff", "errorTextColor": "#ff6461", "mentionHighlightBg": "#a4850f", "mentionHighlightLink": "#a4850f", "codeTheme": "monokai"} +``` + +#### Discord Dark Theme (Old) + +![Discord Dark Theme (old)](/images/DiscordDarkTheme.png) + +[Visit the mattermost-discord-dark-old GitHub repository online:](https://github.com/melroy89/mattermost-discord-dark) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#2f3136","sidebarText":"#ffffff","sidebarUnreadText":"#ffffff","sidebarTextHoverBg":"#33363c","sidebarTextActiveBorder":"#66cfa0","sidebarTextActiveColor":"#ffffff","sidebarHeaderBg":"#27292c","sidebarHeaderTextColor":"#ffffff","onlineIndicator":"#43b581","awayIndicator":"#faa61a","dndIndicator":"#f04747","mentionBg":"#6e84d2","mentionBg":"#6e84d2","mentionColor":"#ffffff","centerChannelBg":"#36393f","centerChannelColor":"#dddddd","newMessageSeparator":"#6e84d2","linkColor":"#2095e8","buttonBg":"#43b581","buttonColor":"#ffffff","errorTextColor":"#ff6461","mentionHighlightBg":"#3d414f","mentionHighlightLink":"#6e84d2","codeTheme":"monokai"} +``` + +#### Night Owl Dark Theme + +![Night Owl Dark Theme](/images/NightOwlDark.png) + +Want this theme? Copy and paste the following code into Mattermost: + +``` json +{"sidebarBg":"#011627","sidebarText":"#d6deeb","sidebarUnreadText":"#d6deeb","sidebarTextHoverBg":"#1d3b53","sidebarTextActiveBorder":"#ff2c83","sidebarTextActiveColor":"#82aaff","sidebarHeaderBg":"#1d3b53","sidebarHeaderTextColor":"#d6deeb","onlineIndicator":"#addb67","awayIndicator":"#ffbc42","dndIndicator":"#f74343","mentionBg":"#d6deeb","mentionBg":"#d6deeb","mentionColor":"#145dbf","centerChannelBg":"#011627","centerChannelColor":"#d6deeb","newMessageSeparator":"#ff8800","linkColor":"#2389d7","buttonBg":"#166de0","buttonColor":"#011627","errorTextColor":"#fd5960","mentionHighlightBg":"#0b2942","mentionHighlightLink":"#82aaff","codeTheme":"solarized-dark"} +``` + +#### Dark Theme (desktop app only) + +On Windows and macOS, the system display preference that you set on your computer (e.g., Light Mode or Dark Mode) is also applied to the Mattermost desktop app. On Linux, manage this manually via the **View** menu. + +![The system preference you set for Light Mode or Dark Mode on your computer is automatically applied to the Mattermost Desktop App.](/images/dark-theme-via-os.gif) + +### Export your custom theme + +Export a theme from Mattermost by copying the theme values from the Custom Theme menu. + +### Import a custom theme + +Import a theme into Mattermost by pasting the theme values into the Custom Theme menu. Copy existing theme values, then paste the theme values into the **Copy and paste to share theme colors** field. Select **Save** to confirm your theme changes. + +### Sidebar styles + +You can customize every aspect of your Mattermost theme, as described below: + +Sidebar BG +Background color of the Channels pane, and Account and Team settings navigation sidebars. + +Sidebar Text +Text color of read channels in the Channels pane, and tabs in the Account and Team settings navigation sidebar. + +Sidebar Header BG +Background color of the header above the Channels pane and all dialog window headers. + +Team Sidebar BG +Background color of the Global Header. + +Sidebar Header Text +Text color of the header above the Channels pane and all dialog window headers. + +Sidebar Unread Text +Text color of unread channels in the Channels pane. + +Sidebar Text Hover BG +Background color behind channel names and settings tabs as you hover over them. + +Sidebar Text Active Border +Color of the rectangular marker on the left side of the Channels pane or Settings sidebar indicating the active channel or tab. + +Sidebar Text Active Color +Text color of the active channel or tab in the Channels pane or Settings sidebar. + +Online Indicator +Color of the online indicator appearing next to team members names in the direct messages list. + +Away Indicator +Color of the away indicator appearing next to team members names in the direct messages list when they have had no browser activity for 5 minutes. + +Do Not Disturb Indicator +Color of the do not disturb indicator appearing next to team members names in the direct messages list. + +Mention Jewel BG +Background color of the jewel indicating unread mentions that appears to the right of the channel name. This is also the background color of the “Unread Posts Below/Above” indicator appearing at the top or bottom of the Channels pane on shorter browser windows. + +Mention Jewel Text +Text color on the mention jewel indicating the number of unread mentions. This is also the text color on the “Unread Posts Below/Above” indicator. + +### Center channel styles + +You can customize every aspect of your Mattermost theme, as described below: + +Center Channel BG +Color of the center pane, right-hand sidebar and all dialog window backgrounds. + +Center Channel Text +Color of all the text - with the exception of mentions, links, hashtags and code blocks - in the center pane, right-hand sidebar, and dialogs. + +New Message Separator +The new message separator appears below the last read message when you navigate to a channel with unread messages. + +Error Text Color +Color of all error text. + +Mention Highlight BG +Highlight color behind your words that trigger mentions in the center pane and right-hand sidebar. + +Mention Highlight Link +Text color of your words that trigger mentions in the center pane and right-hand sidebar. + +Code Theme +Background and syntax colors for all code blocks. + +### Link and button styles + +You can customize every aspect of your Mattermost theme, as described below: + +Link Color +Text color of all links, hashtags, teammate mentions, and low priority UI buttons. + +Button BG +Color of the rectangular background behind all high priority UI buttons. + +Button Text +Text color appearing on the rectangular background for all high priority UI buttons. diff --git a/docs/main/end-user-guide/preferences/manage-advanced-options.mdx b/docs/main/end-user-guide/preferences/manage-advanced-options.mdx new file mode 100644 index 000000000000..a27556091466 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-advanced-options.mdx @@ -0,0 +1,218 @@ +--- +title: "Manage advanced options" +--- + + +Using Mattermost in a web browser or the desktop app, you can customize advanced Mattermost options based on your preferences. Select the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then select **Advanced**. + +## Send messages on CTRL/⌘+ENTER + +By default, you send messages in Mattermost by composing a message in the message text box at the bottom of the Mattermost screen and selecting the **Send** Select the Send icon to post your message. icon or by pressing Enter on Windows or Linux, or on Mac. + +And you enter new text lines by pressing Shift Enter on Windows or Linux, or on Mac before sending the message. + +You can chance this message send behavior. + +
+ +Web/Desktop + +If you find you're accidentally sending messages too soon, you can configure Mattermost to require an extra keystroke to send all messages, or for code blocks. + +Select **Send Messages on CTRL/⌘ + ENTER \> Edit** to configure how messages are sent in Mattermost. + +You can configure Mattermost to send messages by pressing Ctrl Enter on Windows or Linux, or on Mac for all messages or only for code blocks that start with ``\`\`\`. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Enable post formatting + +By default, Mattermost formats your messages with Markdown to show links, emojis, text styles, and line breaks. You can control whether your messages show the formatting or show text only. + +
+ +Web/Desktop + +Select **Enable Post Formatting** to show your messages as raw text only that includes Markdown syntax. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Enable join/leave messages + +By default, Mattermost shows you system messages when users join or leave channels you're a member of. You can hide these messages if preferred. + +
+ +Web/Desktop + +Select **Enable Join/Leave Messages** to hide the system messages when users join or leave channels you're a member of. When users are added to or removed from a channel, a system message displays even when you've disabled this feature. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Deactivate account + +You can deactivate your account if you access Mattermost using an email address and password, and when your system admin has [enabled your ability to do so](/administration-guide/configure/experimental-configuration-settings#enable-account-deactivation). Deactivating your account removes your ability to access Mattermost, and disables all email and mobile notifications. + + + +- If you deactive your account, you must contact your system admin to have it reactivated. +- If you access Mattermost using another authentication method, such as AD/LDAP or SAML, or use accounts that don't have this setting available, contact your system admin to deactivate your account in the System Console. + + + +
+ +Web/Desktop + +Select **Deactivate Account** to deactivate your Mattermost user account. + +
+ +
+ +Mobile + +This option isn't applicable to the mobile app. + +
+ +## Delete account + +From Mattermost v10.11, you can permanently delete your account if you access Mattermost using an email address and password, and when your system admin has [enabled your ability to do so](/administration-guide/configure/user-management-configuration-settings#delete-users). Deleting your account permanently removes your user account and profile information from Mattermost. This action cannot be undone. + + + +- **Account deletion is permanent and cannot be undone.** Once deleted, your account and profile data cannot be recovered. +- Your message history and file uploads will remain in channels but will show as "Deleted User" instead of your name. +- If you access Mattermost using another authentication method, such as AD/LDAP or SAML, this option may not be available. Contact your system admin for account deletion. +- Consider [deactivating your account](/end-user-guide/preferences/manage-advanced-options#deactivate-account) instead if you might want to reactivate it in the future. + + + +
+ +Web/Desktop + +Select **Delete Account** to permanently delete your Mattermost user account. You'll be asked to confirm this action before proceeding. + +
+ +
+ +Mobile + +This option isn't applicable to the mobile app. + +
+ +## Performance debugging + +You can disable key Mattermost features temporarily to help isolate issues while debugging Mattermost, if your system admin [enables your ability to do so](/administration-guide/configure/environment-configuration-settings#enable-client-debugging). We don't recommend leaving these settings enabled for an extended period of time as they can negatively impact your user experience. + +
+ +Web/Desktop + +Select **Performance Debugging** to disable one or more of the following Mattermost features: + +- Client-side plugins +- telemetry events sent from the client +- "User is typing..." messages + +You may need to refresh Mattermost to see these settings take effect. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Scroll position when viewing unread channels + +You can choose where to start viewing unread messages in all channels you're a member of. + +
+ +Web/Desktop + +Select **Scroll position when viewing an unread channel** to choose your scroll position starting point as where you left off or at the newest message. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Allow message drafts to sync with the server + +By default, [message drafts](/end-user-guide/collaborate/send-messages#draft-messages) are synchronized on the Mattermost server and accessible everywhere you access Mattermost using a web browser or the desktop app. You can disable server-synchronized drafts and limit drafts to your current Mattermost client, if preferred. + +
+ +Web/Desktop + +Select **Allow message drafts to sync with the server** to disable server-synchronized drafts. + +
+ +
+ +Mobile + +This option isn't applicable to the mobile app. + +
+ +## Delete local files + +You can delete local Mattermost files from your mobile device using the mobile app. + +
+ +Web/Desktop + +This option isn't applicable to the web or desktop app instance of Mattermost. + +
+ +
+ +Mobile + +Access **Settings** by tapping on your profile picture. Then, tap **Advanced Settings** and **Delete local files**. + +Only data specific to the current Mattermost server is removed from your device. You'll need to repeat this process for each [Mattermost workspace you're connected to](/end-user-guide/preferences/connect-multiple-workspaces) on the mobile app. + +
diff --git a/docs/main/end-user-guide/preferences/manage-your-channel-specific-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-channel-specific-notifications.mdx new file mode 100644 index 000000000000..49d0d2f84b45 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-channel-specific-notifications.mdx @@ -0,0 +1,70 @@ +--- +title: "Manage your channel-specific notifications" +--- + + +By default, your web and desktop notification preferences apply to all channels you’re a member of. You can customize your per-channel notification preferences for any channel you're a member of for the following actions: + +- [Mute channels](#mute-channels) +- [Ignore channel-wide @mentions](#ignore-channel-wide-@mentions) +- [Message notification sounds](#message-notification-sounds) +- [Auto-follow all new threads](#auto-follow-all-new-channel-threads) + +
+ +Web/Desktop + +You have 2 ways to manage notification preferences per channel: + +1. Select the channel name, then select **Notification Preferences** from the drop-down list. + +![Select the channel name dropdown to access channel-specific notification preferences.](/images/channel-notification-settings.gif) + +2. Alternatively, select the channel's **View Info** Use the Channel Info icon to access additional channel management options. icon, and then select **Notification Preferences** in the right pane. + +
+ +
+ +Mobile + +Tap the channel name, and then tap **Mobile Notifications**. + +
+ +## Mute channels + +All channels are unmuted by default, including direct and group messages, as well as private and public channels. + +You can choose to mute or unmute a channel at any time as follows: + +- Select **Mute Conversation** or **Unmute Conversation** for direct and group messages. +- Select **Mute Channel** or **Unmute Channel** for private and public channels. + +Once a channel is muted: + +- All notifications for that channel are disabled, including email, desktop, incoming call ring tones, and push notifications. +- The muted channel displays a mute icon next to the channel name. +- The channel is greyed out in the channel sidebar, and doesn't appear bold to indicate unread messages unless you’re [@mentioned](/end-user-guide/collaborate/mention-people) in that channel directly. + +## Ignore channel-wide @mentions + +By default, you're notified every time someone uses channel-wide [@mentions](/end-user-guide/collaborate/mention-people) including [@channel and @all](/end-user-guide/collaborate/mention-people#channel-and-all), as well as [@here](/end-user-guide/collaborate/mention-people#here). + +When you choose to ignore channel-wide @mentions in channels, the channel name is bolded in the channel sidebar for new unreads unless it's muted. + +## Message notification sounds + +From Mattermost v10.1, when you configure Mattermost to notify you about all new messages, or mentions, direct messages, and keywords only, on a per-channel basis, you can also specify an audible message notification sound to play for those notifications. + +## Follow all new channel threads + +By default, you don’t automatically follow new conversation threads in any channel unless you start a thread or reply to a thread, follow a thread, or are @mentioned in a thread. + +When using Mattermost on your mobile device, you can configure Mattermost to automatically follow every thread in a channel. + +1. In a channel, tap the **More** icon Use the More icon to access additional message options. to the right of the channel name. +2. Tap **View info**. +3. Tap **Follow all threads**. + +Tap **Threads** in the channel list to access all threads you're following, and to unfollow threads you no longer want to follow. diff --git a/docs/main/end-user-guide/preferences/manage-your-desktop-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-desktop-notifications.mdx new file mode 100644 index 000000000000..195a73a4f441 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-desktop-notifications.mdx @@ -0,0 +1,71 @@ +--- +title: "Manage your desktop notifications" +--- + + +## Enable notifications + +From Mattermost v9.9 and desktop app v5.5, Mattermost prompts you to enable notifications in the desktop app the first time you connect to a Mattermost server. + +![An example of a Mattermost desktop app notification prompt.](/images/desktop-notification-prompt.png) + +- When you select **Allow**, you won't be asked again. You'll start receiving notifications in the desktop app for all Mattermost activity with [badges](#badge-based-notifications), [banner alerts](#banner-alerts) and [sounds](#notification-sounds). See the section below on [customizing your notifications](#customize-your-notifications) based on how you prefer to be notified about Mattermost activity in the desktop app. +- If you dismiss this prompt, you won't receive Mattermost notifications in the desktop app, and you'll be prompted again the next time you open Mattermost in the desktop app, or go to **Settings \> Notifications \> Desktop and mobile notifications**. +- If you select **Deny** or **Deny Permanently**, you won't be asked again. You won't receive Mattermost notifications in the desktop app. You can change this preference by [editing the server connection](/end-user-guide/preferences/connect-multiple-workspaces#edit-a-server) to [manage your notification permissions](/end-user-guide/preferences/connect-multiple-workspaces#manage-system-permissions). + + + +You may also need to enable notifications in Windows, macOS, or Linux for Mattermost by changing your System Preferences. + + + +## Badge-based notifications + +Mattermost desktop app icons display the following types of badges: + +- A numbered badge for unread [direct](/end-user-guide/collaborate/channel-types#direct-message-channels) [group](/end-user-guide/collaborate/channel-types#group-message-channels) messages, [@mentions](/end-user-guide/preferences/manage-your-mentions-keywords-notifications), and [keywords](/end-user-guide/preferences/manage-your-mentions-keywords-notifications) you're actively watching. A numbered badge means you have at least 1 unread message, @mention, or one of your keywords has triggered a notification. +- A dot badge for unread activity. A dot on the badge means you have unread activity in at least one channel you're a member of. + +## Banner alerts + +Banner alerts in the desktop app are popup windows that display for a limited time in the top right corner of your screen that summarizes the new activity. + +## Notification sounds + +By default, desktop app notifications include audible sounds. + +## Customize your notifications + +By default, you are notified when you're @mentioned, when you receive a direct or group message, or for matches to keywords you're following. + +Want to receive notifications about replies to threads you’re following? Select **Notify me about replies to threads I’m following**. + +Want notifications for all new messages? Select **Desktop and mobile notifications \> All new messages** + +Desktop app users can also [customize their desktop app experience](/end-user-guide/preferences/customize-desktop-app-experience) further based on their platform operating system. + +### Change or disable sounds + +You can change or disable notification sounds by going to **Desktop notification sounds \> Message notification sound**. + +### Incoming Call notifications + +Want to hear a sound when a Mattermost call starts? If your Mattermost admin [enables this Beta feature](/administration-guide/configure/plugins-configuration-settings#enable-call-ringing), you can choose the sound that plays when a call is started within a direct or group message by going to **Desktop notification sounds \> Incoming call sound**. + +### Disable all desktop notifications + +Select **Desktop and mobile notifications \> Nothing** to disable all desktop and [web notifications](/end-user-guide/preferences/manage-your-web-notifications). + +Clear the **Use different settings for my mobile devices** to additionally disable all Mattermost mobile notifications everywhere you use Mattermost. + +Additionally, macOS users can disable notifications for all unread activity in the desktop app by [customizing your desktop app experience](/end-user-guide/preferences/customize-desktop-app-experience) to disable the **Show red badge on Dock icon to indicate unread messages** option. + +## Frequently asked questions + +### What does a Mattermost icon with an exclamation point mean? + +![A Mattermost logo with an exclamation point means you're logged out of at least 1 Mattermost server you connect to using the desktop app.](/images/server-logout-indicator.png) + +A Mattermost icon with an exclamation point means that you're logged out of at least 1 Mattermost server you connect to using the desktop app. Log back in to any servers as needed. See the [Connect to multiple workspaces](/end-user-guide/preferences/connect-multiple-workspaces) documentation for details. + +If the icon continues to display, refresh the **Playbooks** and/or **Boards** tabs located at the top of the desktop app window. diff --git a/docs/main/end-user-guide/preferences/manage-your-display-options.mdx b/docs/main/end-user-guide/preferences/manage-your-display-options.mdx new file mode 100644 index 000000000000..d1442b540914 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-display-options.mdx @@ -0,0 +1,364 @@ +--- +title: "Manage your display options" +--- + + +You can customize Mattermost display options based on your preferences. + +- Using Mattermost in a web browser or the desktop app, select the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then go to **Display**. +- On the Mattermost mobile app, tap your profile picture, and then tap **Settings \> Display**. + +## Theme + +
+ +Web/Desktop + +Select **Theme** to apply a different look and feel to Mattermost. + +Select **Theme Colors** to select one of 5 standard themes designed by the Mattermost team. Or, select **Custom Theme** to customize a standard theme even further. + +See the [customize your theme](/end-user-guide/preferences/customize-your-theme) documentation for more information. + +
+ +
+ +Mobile + +Tap **Theme** to select one of 5 standard Mattermost themes. + + + +You can define a custom theme using Mattermost in a web browser or the desktop app. See the [customize your theme](/end-user-guide/preferences/customize-your-theme) documentation for more information. + + + +
+ +## Threaded discussions + +Threaded discussions offers an enhanced experience for users communicating in threads and replying to messages. Threaded discussions are generally available in Mattermost Cloud and from self-hosted Mattermost v7.0, and are enabled by default for all new Mattermost deployments. + +Depending on how your system admin has [configured threaded discussions](/administration-guide/configure/site-configuration-settings#threaded-discussions) for your [workspace](/end-user-guide/end-user-guide-index), it may already be enabled for you, or you may be able to enable this feature for your account. See our [organize conversations using threaded discussions](/end-user-guide/collaborate/organize-conversations) documentation to learn more about working with threaded discussions. + +
+ +Web/Desktop + +Select **Threaded discussions \> Edit** to manage this option. + +
+ +
+ +Mobile + +Tap **Threaded discussions** to manage this option. + +
+ +## Clock display + +You can customize how time is displayed in Mattermost. + +
+ +Web/Desktop + +Select **Clock Display \> Edit** to display time in Mattermost using a 12-hour or 24-hour convention. + +
+ +
+ +Mobile + +Tap **Clock Display** to display time in Mattermost using a 12-hour or 24-hour convention. + +
+ +## Teammate name display + +You can customize how names are displayed in Mattermost unless your system admin has [disabled your ability to do so](/administration-guide/configure/site-configuration-settings#lock-teammate-name-display-for-all-users). + +
+ +Web/Desktop + +Select **Teammate Name Display \> Edit** to control how names are displayed in Mattermost. Options include: username, nickname (if it exists), or first and last name. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Show online availability on profile images + +You can show or hide [availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability) on profile pictures in Mattermost. + +
+ +Web/Desktop + +Select **Show online availability on profile images \> Edit** to show or hide availability in Mattermost. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Share last active time + +By default, Mattermost shows when you were last online in your profile and in direct message channel headers, unless your system admin has [disabled this option](/administration-guide/configure/site-configuration-settings#enable-last-active-time). + +
+ +Web/Desktop + +Select **Share last active time \> Edit** to show or hide when you were last online in Mattermost. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Timezone + +You can customize the timezone used for timestamps in Mattermost and in email notifications. + +
+ +Web/Desktop + +Select **Timezone \> Edit** to select your timezone. + +From Mattermost v10.10, you can also select **Automatic** to set your timezone automatically based on your computer's timezone settings. This option is enabled by default. + +
+ +
+ +Mobile + +Tap **Timezone** to set your timezone automatically based on your mobile device preference. + +
+ +## Website link previews + +You can control whether website link previews in Mattermost show a preview of the website content directly below the message. + + + +Your system admin must [enable this feature](/administration-guide/configure/site-configuration-settings#enable-message-link-previews). It's disabled by default. Once enabled, only the first web link in a message creates a preview of the website. + + + +
+ +Web/Desktop + +Select **Website Link Previews \> Edit** to show or hide website previews in messages. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Default appearance of image previews + +When messages in Mattermost include images, you can control whether an image preview displays directly below the message for image attachments, image link previews, and [in-line images](/end-user-guide/collaborate/format-messages#in-line-images) over 100px in height. + +
+ +Web/Desktop + +Select **Default Appearance of Image Previews \> Edit** to expand or collapse all image links and image attachments. + + + +This setting can also be controlled using the [slash commands](/integrations-guide/run-slash-commands) `/expand` and `/collapse`. + + + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Message display + +You can control how messages in a channel are displayed. + +
+ +Web/Desktop + +Select **Message Display \> Edit** to display standard or compact messages. + + + +**Compact** mode fits more messages on the screen by decreasing the spacing around posts, collapsing link previews, and hiding thumbnails so that only file names are shown. Some formatting types, such as block quotes and headings, are also reduced in size. + +When you select **Compact**, usernames are colorized by default, and username colors are consistent for all users. Disable the **Colorize usernames** option to display all usernames in a single color instead. + + + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Click to open threads + +By default, Mattermost opens reply threads in the right pane when you select any part of a message. You can change this default behavior. + +
+ +Web/Desktop + +Select **Click to open threads \> Edit** to disable the default behavior of opening reply threads in the right pane automatically. You'll need to select the replies count to open a reply thread. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Channel display + +You can control the width of the center channel area in Matermost. + +
+ +Web/Desktop + +Select **Channel Display \> Edit** to specify the center channel as fixed width and centered, or full width. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Quick reactions on messages + +By default, you can hover over messages to react using recently-used emojis. You can hide your recently-used emojis instead if preferred. + +
+ +Web/Desktop + +Select **Quick reactions on messages \> Edit** to hide your recently-used emojis. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. + +
+ +## Render emoticons as emojis + +From Mattermost v10.10, you can choose whether to automatically convert text emoticons to emoji characters in your messages. This feature is enabled by default, so that text-based emoticons like `:)` or `:D` are displayed as their corresponding emoji images. Disable this auto-rendering if you prefer to keep emoticons as text. + +
+ +Web/Desktop + +Select **Render emoticons as emojis \> Edit** to disable automatic conversion of emoticons to emojis in your messages. + +
+ +
+ +Mobile + +This option isn't available in the mobile app. + +
+ +## Language + +You can control what language Mattermost displays in. Options include: + +- Deutsch - German +- English (U.S.) +- English Australian +- Español - Spanish +- Français - French +- Italiano - Italian +- Magyar - Hungarian +- Nederlands - Dutch +- Polski - Polish +- Português (Brasil) - Portuguese +- Română - Romanian +- Svenska - Swedish +- Tiếng Việt - Vietnamese +- Türkçe - Turkish +- български - Bulgarian +- Pусский - Russian +- Yкраїнська - Ukrainian +- فارسی - Persian +- 한국어 - Korean +- 中文 (简体) - Simplified Chinese +- 中文 (繁體) - Traditional Chinese +- 日本語 - Japanese + +
+ +Web/Desktop + +Select **Language \> Edit** to set the display language in Mattermost. + +
+ +
+ +Mobile + +This option isn't something you can set using the mobile app. However, when you change the display language using a web browser or the desktop app, that language selection is also applied to the mobile app. + +
diff --git a/docs/main/end-user-guide/preferences/manage-your-mentions-keywords-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-mentions-keywords-notifications.mdx new file mode 100644 index 000000000000..9dbd64801d47 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-mentions-keywords-notifications.mdx @@ -0,0 +1,32 @@ +--- +title: "Manage your @mention and keyword notifications" +--- + + +You're [notified](/end-user-guide/preferences/manage-your-notifications) in a [web browser](/end-user-guide/preferences/manage-your-web-notifications), the [desktop app](/end-user-guide/preferences/manage-your-desktop-notifications), and on your [mobile device](/end-user-guide/preferences/manage-your-mobile-notifications), when you're @mentioned by your username or first name, @mentioned as part of a user group, and for matches to keywords you're following. + +You're also notified when someone uses channel-wide [@mentions](/end-user-guide/collaborate/mention-people) including [@channel and @all](/end-user-guide/collaborate/mention-people#channel-and-all), as well as [@here](/end-user-guide/collaborate/mention-people#here). + +For all other messages, channels appear bolded to indicate unread activity. + +## Customize notification keywords + +Using a web browser or the desktop app, you can customize keywords to trigger notifications. Keywords aren't case-sensitive. + +For example, you can receive notifications for all messages and threads related to a specific topic, project name, or customer. + +![A walkthrough of setting keywords that trigger mentions in Mattermost.](/images/keywords-trigger-mentions.gif) + + + +Separate multiple keywords using commas or by pressing Tab, and use Backspace to manage keywords. + + + +## Passively track keywords (no notification) + +From Mattermost v9.3, Mattermost Enterprise and Professional customers interested calling attention to specific topics of interest across channels can do so without sending notifications to a Mattermost client. + +Using a web browser or the desktop app, you can passively track key terms by specifying single or multiple words to be highlighted in all channels you're a member of. Keywords and phrases are automatically highlighted using a color based on your [Mattermost theme](/end-user-guide/preferences/customize-your-theme). + +![A walkthrough of setting keywords that are highlighted in Mattermost.](/images/keywords-highlighted.gif) diff --git a/docs/main/end-user-guide/preferences/manage-your-mobile-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-mobile-notifications.mdx new file mode 100644 index 000000000000..a2d4c959ba5c --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-mobile-notifications.mdx @@ -0,0 +1,95 @@ +--- +title: "Manage your mobile notifications" +--- + + +## Enable notifications + +From Mattermost mobile v2.34, the Mattermost **Settings \> Notifications** screen alerts you when notifications are disabled by your device. Follow the link in the notification to enable device-level notifications. + +From Mattermost v9.9, Mattermost prompts you to enable notifications in the mobile app the first time you open the app. + +Once Mattermost notifications are enabled at the device level and in the mobile app, you'll start receiving notifications for all Mattermost activity with [badges](#badge-based-notifications), and [push notifications](#push-notifications). See the section below on [customizing your notifications](#customize-your-notifications) based on how you prefer to be notified about Mattermost activity on your mobile device. + + + +You may also need to enable notifications in iOS or Android for Mattermost by changing your device preferences. + + + +## Badge-based notifications + +Mattermost mobile app icons display numbered badges for unread [direct](/end-user-guide/collaborate/channel-types#direct-message-channels) and [group](/end-user-guide/collaborate/channel-types#group-message-channels) messages, and [@mentions](/end-user-guide/preferences/manage-your-mentions-keywords-notifications), [keywords](/end-user-guide/preferences/manage-your-mentions-keywords-notifications) you're actively watching. + +A numbered badge means you have at least 1 unread message, @mention, or one of your keywords has triggered a notification. + + + +- The Mattermost mobile app doesn't display dot badges indicating other unread activity by design. The activity you're directly involved in is prioritized over other activity. +- Android users may see Mattermost notifications in the Android Notification Shade while the Mattermost icon shows no badge. This is because the Android notification system may also display badges unread activity. + + + +## Push notifications + +You'll see mobile push notification messages on your device as follows: + +- **iOS**: On the Lock Screen, Notification Center, and as Banners/Alerts based on your iOS settings. +- **Android**: On the Lock Screen, Notification Shade, and as Banners/Heads-Up Notifications based on your Android settings. + +## Customize your notifications + +You can manage your mobile notifications in both the desktop app and the mobile app. + +
+ +Desktop app + +In the desktop app, manage your mobile notification preferences by selecting the **Settings** Use the Settings icon to customize your Mattermost user experience. icon located in the top right corner of the screen, and select **Notifications \> Desktop and mobile notifications**. + +By default, you receive mobile notifications for @mentions, direct messages, and group messages when your Mattermost availability is [Online, Away, or Offline](/end-user-guide/preferences/set-your-status-availability#set-your-availability). You won't receive Mattermost notifications on your device if you're actively using Mattermost in a web browser. + +- Want to receive fewer mobile notifications? Under **Trigger mobile notifications when I am**, select **Away or Offline** or **Offline**. +- Want different desktop and mobile notifications? Select **Use different settings for my mobile devices**, and then select **All new messages**, or **Mentions, direct messages and group messages**. + +
+ +
+ +Mobile app + +In the mobile app, tap your profile picture, then tap **Settings \> Notifications**. + +- Tap **Mentions** to disable notifications based on keywords that trigger mentions, including first name, username, channel-wide @mentions, and keywords you've specified. +- Tap **Push Notifications** to choose what to be notified about. + +You can also [manage email notifications](/end-user-guide/preferences/manage-your-notifications#email-notifications) and [send automatic replies to direct messages](/end-user-guide/preferences/manage-your-thread-reply-notifications#send-automatic-replies-to-direct-messages) directly from your device. + +
+ +### Incoming Call notifications + +Want to hear a sound on your mobile device when a Mattermost call starts? If your Mattermost admin [enables this Beta feature](/administration-guide/configure/plugins-configuration-settings#enable-call-ringing), select **Call Notifications** to choose the sound that plays when a call is started within a direct or group message you're participating in. + + + +- From Mattermost mobile app v2.19, incoming call sounds also include device vibration, as well as vibration-only when your device is in silent mode. +- If you prefer a separate call sound on mobile, your mobile change applies only to your mobile device. + + + +### Disable all mobile notifications + +To disable all Mattermost mobile notifications, tap **Push Notifications \> Nothing**. + +## Frequently asked questions + +### Are mobile notification counts the same as other Mattermost clients? + +No. You're only notified of unread threads with @mentions on your mobile device. You're not notified of general unread activity on mobile. + +### What does a Mattermost icon with an exclamation point mean? + +![A Mattermost logo with an exclamation point means you're logged out of at least 1 Mattermost server you connect to using the mobile app.](/images/server-logout-indicator.png) + +A Mattermost icon with an exclamation point means that you're logged out of at least 1 Mattermost server you connect to using the mobile app. Log back in to any servers as needed. See the [Connect to multiple workspaces](/end-user-guide/preferences/connect-multiple-workspaces) documentation for details. diff --git a/docs/main/end-user-guide/preferences/manage-your-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-notifications.mdx new file mode 100644 index 000000000000..bae21f21d63e --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-notifications.mdx @@ -0,0 +1,87 @@ +--- +title: "Manage your notifications" +draft: true +--- + + +Mattermost notifies you of new activity you're directly involved in. How you're notified depends on what Mattermost client you're using, the type of Mattermost activity you're being notified about, and how you prefer to be notified. + + + +**Missing notifications?** + +- Your mobile device may have Mattermost notifications disabled. See the [manage your mobile notifications](/end-user-guide/preferences/manage-your-mobile-notifications#enable-notifications) for details. +- You may need to grant permissions in the Mattermost [desktop app](/end-user-guide/preferences/manage-your-desktop-notifications#enable-notifications) or [web browser](/end-user-guide/preferences/manage-your-web-notifications#enable-notifications) to show notifications. +- Visit our [troubleshoot notifications](/end-user-guide/preferences/troubleshoot-notifications) documentation for guidance on ensuring you receive Mattermost notifications. + + + +## You're in control + +You are in control of how, when, and where you're notified of activity that matters to you based on how you prefer to work and collaborate. To access notification preferences: + +- In a web browser or the desktop app, select the **Settings** Use the Settings icon to customize your Mattermost user experience. icon located in the top right corner of the screen to manage your notification preferences. +- On mobile, tap your profile picture, then tap **Settings \> Notifications**. + +See the [Default notifications](#default-notifications) table below for details on customizing your notification experience based on your preferred Mattermost client. + + + +From Mattermost v9.8, your desktop and mobile notification preferences have been combined together under **Notifications**. If you're using an older Mattermost release and older Mattermost clients, you'll find separate preferences for desktop and mobile. + + + +## Default notifications + +Mattermost notifies you of new activity, including unread activity, [direct](/end-user-guide/collaborate/channel-types#direct-message-channels) and [group](/end-user-guide/collaborate/channel-types#group-message-channels) messages, and [@mentions](/end-user-guide/preferences/manage-your-mentions-keywords-notifications), [keywords](/end-user-guide/preferences/manage-your-mentions-keywords-notifications) you're actively watching, [thread replies](/end-user-guide/preferences/manage-your-thread-reply-notifications), and unread activity in [specific channels](/end-user-guide/preferences/manage-your-channel-specific-notifications). + +The table below lists the types of notifications you can expect to see and hear in Mattermost. Select your preferred Mattermost clients to learn more about notifications for that client. + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Notification Type

=======================

Icon badge (dot)

A dot on the badge means you have unread activity in at least one channel you're a member of.

What it Means

===================================================

You have unread activity in at least 1 channel you're a member of

Which Mattermost Clients? |

==================================================================================+

Web, Desktop |

Icon badge (number)

A numbered badge means you have at least 1 unread message, @mention, or one of your keywords has triggered a notification.

You have at least 1 unread message with an @mention, or a match to a keyword you're watchingWeb & Desktop & Mobile
Banner alert popupsWeb & Desktop
Push notifications
Mobile
Alert soundsYou have at least 1 unread message with an @mention, a match to a keyword you're watching, or replies to a thread you're followingWeb, Desktop, & Mobile
+ +### Email notifications + +When your admin [enables email notifications](/administration-guide/configure/site-configuration-settings#enable-email-notifications), Mattermost notifications are sent to you via email for [@mentions](/end-user-guide/collaborate/mention-people) and [direct messages](/end-user-guide/collaborate/channel-types#direct-message-channels) as soon as you're away from Mattermost for 5 minutes. + +You can also opt in to be notified by email about thread replies you're following. + +Additionally, if your admin [enables email batching](/administration-guide/configure/site-configuration-settings#enable-email-batching), email-based notifications are batched, and you can customize how frequenly you receive batched notifications by going to **Settings \> Notifications \> Email notifications**. The default frequency is 15 minutes. Choosing every 15 minutes or every hour will reduce the number of emails you receive. + +Disable email notifications by going to **Settings \> Notifications \> Email notifications** and changing **On** to **Off**. + +## Missing notifications? + +Visit the Mattermost [notifications Knowledge Base article](https://support.mattermost.com/hc/en-us/articles/19161390661780-Troubleshooting-Mattermost-Notifications) for additional troubleshooting tips and tricks. diff --git a/docs/main/end-user-guide/preferences/manage-your-plugin-preferences.mdx b/docs/main/end-user-guide/preferences/manage-your-plugin-preferences.mdx new file mode 100644 index 000000000000..292796e5a45a --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-plugin-preferences.mdx @@ -0,0 +1,28 @@ +--- +title: "Manage your plugin preferences" +--- +Using Mattermost in a web browser or the desktop app, you can customize Mattermost plugin preferences for Microsoft Teams and Calls by selecting **Settings** Use the Settings icon to customize your Mattermost user experience. next to your profile picture. + +## Microsoft Teams plugin preferences + + + +Select **MS Teams** to connect your Mattermost and Microsoft Teams accounts, and manage notification preferences for Microsoft Teams chats and group chats. See the [connect your account](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams#connect-your-mattermost-account-to-your-microsoft-teams-account). + + + +Download our [Mattermost for Microsoft Teams datasheet](https://mattermost.com/mattermost-for-microsoft-teams-datasheet/) to learn how Mattermost helps your organization get more from your Microsoft tools. + + + +## Calls plugin preferences + + + +Select **Calls** to specify the audio devices, including micrphone and speaker, used for Mattermost calls. + + + +Download our [Mattermost Calls datasheet](https://mattermost.com/mattermost-calls-datasheet/) to learn how Calls make it easy for teams to adapt their communication to a wider variety of situations. + + diff --git a/docs/main/end-user-guide/preferences/manage-your-profile.mdx b/docs/main/end-user-guide/preferences/manage-your-profile.mdx new file mode 100644 index 000000000000..fcf515f210d6 --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-profile.mdx @@ -0,0 +1,51 @@ +--- +title: "Manage your Mattermost profile" +draft: true +--- + + +Select your profile picture and select **Profile** to manage the details of your Mattermost profile, including your name, username, nickname, email, and profile picture. + +Your Mattermost system admin may [define custom user profile fields](/administration-guide/manage/admin/user-attributes) that you can personalize. Additionally, some of your profile information may be pulled from another source, which means you won't be able to modify it in Mattermost. Contact your Mattermost system admin for assistance. + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Profile setting

=====================

Full, first, and last name

Description

================================================================================================================

Your name appears in the direct messages member list and team management modal. By default, you'll receive mention notifications when someone types your first name in a message.

Username

Usernames are unique identifiers appearing next to all posts. Usernames must begin with a letter, and contain between 3 to 22 lowercase characters made up of numbers, letters, and the symbols ., -, and _.

Pick something easy for teammates to recognize and recall. By default, you'll receive mention notifications when someone types your username. Changing your username won't change your existing @mentions in sent messages.

Nickname(Optional) Nicknames appear in the direct messages member list and team management modal. | Your nickname can be up to 64 characters long. | | You won't be notified when someone types your nickname unless you add your nickname to the list | of Keywords that Trigger Notifications as a notification preference |. | From Mattermost v10.8, nicknames display in | threaded discussions when available. |
Position(Optional) Position can be used to describe your role or job title. Your position appears in the profile popup that displays when you select a user's name in the center channel or right-hand sidebar.
EmailEmail is used for signing in, notifications, and password reset.
Profile picture

Profile pictures appear next to all posts, and you can select your profile picture to access your profile settings. To change your profile picture:

Using the web or the desktop app

  1. Select Edit next to the Profile Picture option.
  2. Choose Select, pick the profile image you want to use, and select Save.

Using the mobile app

  1. Tap your current profile picture.
  2. Take a photo using your device, or select an image to use.

For best results, choose an image that's at least 128 x 128 pixels in size. Supported image formats include: BMP, JPG, JPEG, and PNG. GIF isn't supported.

diff --git a/docs/main/end-user-guide/preferences/manage-your-security-preferences.mdx b/docs/main/end-user-guide/preferences/manage-your-security-preferences.mdx new file mode 100644 index 000000000000..d2748b7190ab --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-security-preferences.mdx @@ -0,0 +1,43 @@ +--- +title: "Manage your security preferences" +draft: true +--- + + +Select your profile picture, select **Profile**, and then select **Security** to configure your password, view access history, and to view or logout of active sessions. + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Security setting

======================

Password

Description

============================================================================================================

You may change your password if you've logged in by email using Mattermost in a web browser or using the desktop app.

  • If you sign in to Mattermost using a single sign-on service, you must update your password through your SSO service account.
  • Password Security Enhancement: From v11.0, Mattermost uses PBKDF2 password hashing for improved security. When you log in after your server upgrades to v11.0+, your password will be automatically migrated to the more secure format. If your server is later downgraded to a version prior to v11.0, you may be unable to log in and will need to contact your system administrator for a password reset.
Multi-factor authentication (MFA)If your system admin has enabled multi-factor authentication | (MFA), you can require a passcode in addition to your password to log-in to your Mattermost account. | | You'll need to download a MFA passcode generation app, such as Google Authenticator or a similar app, | and then set-up MFA in your Mattermost account. | | Download a passcode generation app | | - Download Google Authenticator for an Apple device from | iTunes | - Download Google Authenticator for an Android device from | Google Play | | Enable MFA in Mattermost | | 1. Open Mattermost in a web browser or the desktop app. | 2. In Mattermost, from your profile picture, select Profile > Security. | 3. Under Multi-factor Authentication, select Edit. | | .. image:: ../../images/multi-factor-authentication.png | :alt: Enable multi-factor authentication through your Mattermost user profile. | | 4. Select Add MFA to Account. | | .. image:: ../../images/add-mfa-to-account.png | :alt: Add multi-factor authentication to your Mattermost user profile. | | 5. Scan the QR code or enter the Secret provided by Mattermost into the authenticator app. | 6. In Mattermost, enter the MFA Code generated by the authenticator app. | 7. Select Save. |
Sign-in methodThis option allows you to switch your login method between using email/username and password and | single sign-on credentials. | | You can configure this setting using Mattermost in a web browser or using the desktop app. | | .. note:: | | While you can choose to log in with either set of credentials, you can only enable one login method | at a time. For example, if AD/LDAP single sign-on is enabled, you can select | Switch to using AD/LDAP, and enter your AD/LDAP credentials to switch login over to AD/LDAP. | You'll need to enter the password for your email account to verify your existing credentials. | Following the change, you'll receive an email to confirm the action. |
View access history

Using Mattermost in a browser or using the desktop app, you can access a chronological list of the last 20 login and logout attempts, channel creations and deletions, account settings changes, or channel setting modifications made with your account.

The details of the Session ID, which is a unique identifier for each Mattermost browser session, and IP Address of the action is recorded for audit log purposes.

View and log out of active sessions

Sessions are created when you log in with your credentials a new browser on a device. Sessions let you use Mattermost for up to 30 days without having to log in again.

Using Mattermost in a browser or using the desktop app:

  • Select Logout during an active session if you want to revoke automatic login privileges for a specific browser or device.
  • Select More Info to view browser and system details.
diff --git a/docs/main/end-user-guide/preferences/manage-your-sidebar-options.mdx b/docs/main/end-user-guide/preferences/manage-your-sidebar-options.mdx new file mode 100644 index 000000000000..05fe602e22eb --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-sidebar-options.mdx @@ -0,0 +1,30 @@ +--- +title: "Manage your sidebar options" +--- + + +Using Mattermost in a web browser or the desktop app, you can customize your Mattermost sidebar based on your preferences. Select the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then select **Sidebar**. + +Your channel sidebar includes [enhanced sidebar features](/end-user-guide/preferences/customize-your-channel-sidebar), including custom, collapsible channel categories, drag and drop, unread filtering, channel sorting options, and more. + + + +- The following sidebar settings apply to your current sidebar only. +- You must manage sidebar settings individually for every team you're a member of. +- You can manage these settings in a web browser or the desktop app. You can't manage these channel sidebar settings using the Mattermost mobile app. + + + +## Group unread channels separately + +You can control whether unread channels are grouped together separately in the channel sidebar, unless your system admin has [disabled your ability to do so](/administration-guide/configure/experimental-configuration-settings#group-unread-channels). + +Select **Sidebar Settings \> Group unread channels separately \> Edit** to group unread channels at the top of the channel sidebar in an **Unreads** category. + +## Number of direct messages to show + +You can set the default number of direct messages to show in the channel sidebar. + +Select **Sidebar Settings \> Number of direct messages to show \> Edit** to define a default number of direct messages. + +You can update the number of direct messages displayed in the channel sidebar at any time, regardless of the default you set. See the [manage direct messages](/end-user-guide/preferences/customize-your-channel-sidebar#manage-direct-messages) documentation for details. diff --git a/docs/main/end-user-guide/preferences/manage-your-thread-reply-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-thread-reply-notifications.mdx new file mode 100644 index 000000000000..238bd7ac169a --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-thread-reply-notifications.mdx @@ -0,0 +1,43 @@ +--- +title: "Manage your thread reply notifications" +--- + + +You're [notified](/end-user-guide/preferences/manage-your-notifications) in a [web browser](/end-user-guide/preferences/manage-your-web-notifications), the [desktop app](/end-user-guide/preferences/manage-your-desktop-notifications), and on your [mobile device](/end-user-guide/preferences/manage-your-mobile-notifications), for threads you're following when you're @mentioned or the messages contain a keyword you're tracking. + + + +- Mattermost auto-follows you on all direct and group messages, any thread you start, as well as any thread where you've been [@mentioned](/end-user-guide/collaborate/mention-people) directly. +- You can choose to [follow or unfollow any thread](/end-user-guide/collaborate/organize-conversations#follow-threads-and-messages) at any time. + + + +You won't receive notifications for threads you're not following, or thread replies when they don't @mention you directly. However, blue message indicators show you unread thread replies you're not following in a given public or private channel. + +For all other messages, a channel appears bolded to indicate unread messages. + +## Customize your notifications + +### Follow all threads in channels automatically + +You can follow all threads in a channel automatically by going to **Channel Settings \> Notification Preferences \> Follow all threads in this channel and enable the Automatically follow threads in this channel**. + +### Get notified when threaded discussions are disabled + +If your organization doesn't use threaded discussions, or you have [opted out of threaded discussions](/end-user-guide/preferences/manage-your-display-options#threaded-discussions), you can configure Mattermost to notify you when someone replies to a thread you started, or have participated in. Go to **Settings \> Notifications \> Reply notifications** to choose one of 3 options: + +- Receive notifications for messages in reply threads that you either start or participate in. +- Receive notifications on messages, but only in threads that you start. +- Don't receive notifications on messages in reply threads unless you're directly @mentioned. + +### Send automatic replies to direct messages + +Want to automatically reply to direct messages when you're out of office? When your system admin [enables the ability for you to do so](/administration-guide/configure/experimental-configuration-settings#enable-automatic-replies), you can configure Mattermost to send custom replies to direct messages by going to **Settings \> Notifications \> Automatic Direct Message Replies**, selecting **Enable**, and composing your automatic reply message. + +## Frequently asked questions + +### Are thread notification counts the same across all Mattermost clients? + +No. Mobile app notifications only indicate unread threads with @mentions, and not general unread activity. + +Using Mattermost in a web browser or the desktop app, the **Threads** list bolds unread threads that don't contain @mentions. diff --git a/docs/main/end-user-guide/preferences/manage-your-web-notifications.mdx b/docs/main/end-user-guide/preferences/manage-your-web-notifications.mdx new file mode 100644 index 000000000000..af06a8a1371d --- /dev/null +++ b/docs/main/end-user-guide/preferences/manage-your-web-notifications.mdx @@ -0,0 +1,62 @@ +--- +title: "Manage your web notifications" +--- + + +## Enable notifications + +From Mattermost v9.10, Mattermost prompts you to grant permission to your web browser to show notifications. + +![From Mattermost v9.10, you're prompted to enable notifications.](/images/enable-notifications.png) + +- When you select **Enable notifications**, you won't be asked again. You'll start receiving notifications in your web browser for all Mattermost activity with [badges](#badge-based-notifications) and [sounds](#notification-sounds). See the section below on [customizing your notifications](#customize-your-notifications) based on how you prefer to be notified about Mattermost activity in a web browser. +- If you dismiss this prompt, you won't receive Mattermost notifications in the web browser, and you'll be prompted again the next time you open Mattermost in a web browser, or go to **Settings \> Notifications \> Desktop and mobile notifications**. +- If you select **Deny** or **Deny Permanently**, you won't be asked again. You won't receive Mattermost notifications in the web browser. You can change this preference by granting notification permissions for Mattermost in the web browser. + +## Badge-based notifications + +In a web browser, Mattermost icons display the following types of badges: + +- Numbered badges for unread [direct](/end-user-guide/collaborate/channel-types#direct-message-channels) [group](/end-user-guide/collaborate/channel-types#group-message-channels) messages, [@mentions](/end-user-guide/preferences/manage-your-mentions-keywords-notifications), and [keywords](/end-user-guide/preferences/manage-your-mentions-keywords-notifications) you're actively watching. + +A red dot badge means you have unread @mentions, keywords, direct messages, and group messages. ![An example of a Chrome web browser mention badge indicator.](/images/chrome-mention-badge.png) + +A black dot badge means you have unread activity in channels you're a member of. ![An example of a Chrome web browser activity badge indicator.](/images/chrome-activity-badge.png) + +## Notification sounds + +By default, web-based notifications include audible sounds. + +## Customize your notifications + + + +Mattermost notification settings labeled as Desktop also configure your web-based notifications when using Mattermost in a web browser. + + + +### Reduce web notifications + +To reduce the number of notifications you receive, select **Desktop and mobile notifications \> Mentions, direct messages, and group messages**, and save your changes. You can set this preference across all channels or for specific channels. + +With limited notifications enabled, you can also choose to receive notifications about replies to threads you're following by selecting **Notify me about replies to threads I'm following**. + +### Change or disable sounds + +You can change or disable notification sounds by going to **Desktop notification sounds \> Message notification sound**. + +### Incoming Call notifications + +Want to hear a sound when a Mattermost call starts? If your Mattermost admin [enables this Beta feature](/administration-guide/configure/plugins-configuration-settings#enable-call-ringing), you can choose the sound that plays when a call is started within a direct or group message by going to **Desktop notification sounds \> Incoming call sound**. + +### Disable all web notifications + +Select **Desktop and mobile notifications \> Nothing** to disable all web and desktop notifications. + +Clear the **Use different settings for my mobile devices** to additionally disable all Mattermost mobile notifications everywhere you use Mattermost. + +## Frequently asked questions + +### Why am I prompted repeatedly enable notifications I don't want? + +Mattermost will continue to prompt you to grant permission to the browser to show notifications until you respond to the prompt. If you want to disable all Mattermost notifications, select **Enable notifications** when prompted, and then [disable all Mattermost web notifications](#disable-all-web-notifications). diff --git a/docs/main/end-user-guide/preferences/set-your-status-availability.mdx b/docs/main/end-user-guide/preferences/set-your-status-availability.mdx new file mode 100644 index 000000000000..f2aefef9808c --- /dev/null +++ b/docs/main/end-user-guide/preferences/set-your-status-availability.mdx @@ -0,0 +1,61 @@ +--- +title: "Set your status and availability" +draft: true +--- + + +Let your team know whether you're available by setting a [custom status](/end-user-guide/preferences/set-your-status-availability#set-a-custom-status) and your [availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability) in Mattermost. + +## Set a custom status + +Set a custom status to display a descriptive status message and optional emoji next to your name in Mattermost. Other members can see your status anywhere they can see your name, such as the channel sidebar and in conversations. To set a custom status in Mattermost: + +
Web/Desktop1. Select your profile picture, then select **Set a custom status**.2. Choose from a list of suggested statuses, or enter a new emoji and status. The Speech bubble emoji 💬 is used by default if you don't specify an emoji. A custom status can be a maximum of 100 characters in length.3. Specify when to clear your custom status.4. Select **Set Status**.
+ +
Mobile1. Select your profile picture, then selecting **Set a status**.2. Choose from a list of suggested statuses, reuse a recent status, or tap to enter a status and select an emoji. The Speech bubble emoji 💬 is used by default if you don't specify an emoji. A custom status can be a maximum of 100 characters in length.3. Specify when to clear your custom status.4. Tap **Done**.
+ + + +- Custom statuses are enabled by default in Mattermost. System admins can disable this feature by going to **System Console \> Site Configuration \> Users and Teams \> Enable Custom Statuses**. Disabling this feature also removes the `Update your status` prompts in Mattermost. + + + +### Clear a custom status + +To clear a custom status, select your profile picture, then select **Clear Status**, or select the **Clear** option next to your current status. + +![Clear your custom status.](/images/clear-custom-status.png) + +## Set your availability + +To set your availability, select your profile picture, then specify your availability as **Online**, **Away**, **Do Not Disturb**, or **Offline**. + + +++ + + + + + + + + + + + + + + +

Availability | Description |

==================+======================================================================================================================================+
online | Online: |
                                                                                                                                     |
- Set automatically for you when you're active on Mattermost using a browser, the desktop app, or the mobile app. |
- When using the desktop app, any mouse or keyboard activity keeps your availability set to Online. |
- By default, notifications are sent to the browser, the desktop app, and the mobile app. |
away | Away: |
                                                                                                                                     |
- Set automatically for you when you've been inactive for more than 5 minutes. System admins can change this |
  value using an experimental configuation setting called |
  `user status away timeout <mm-ref:administration-guide%2Fconfigure%2Fexperimental-configuration-settings%3Auser%20status%20away%20timeout>`\_\_. |
                                                                                                                                     |
- You're inactive in Mattermost when you're not: typing in or navigating between channels, switching to |
  another browser tab, or when you've minimized or moved the browser window to the background. |
                                                                                                                                     |
- You can manually set yourself as Away any time. |
- By default, notifications are sent to your Mattermost mobile app. |
dnd | Do Not Disturb: |
                                                                                                                                     |
- Set your availability as Do Not Disturb any time you don't want notifications for a period of time. |
offline | Offline:
                                                                                                                                     |
- Set automatically for you when you exit the Mattermost desktop app or close the browser window, sleep or |
  lock your computer, or on mobile when you change apps, close the Mattermost mobile app, or lock your |
  mobile device screen. |
- You can manually set yourself as Offline any time. |
- By default, notifications are sent to your Mattermost mobile app. |
+ +Other members can see your availability anywhere they can see your name, such as the channel sidebar, within conversations, and within direct messages. + +### Set your availability as Do Not Disturb + +Set your availability to **Do Not Disturb** to disable all desktop, email, and push notifications when you are unavailable or need to concentrate. + +You can specify how long to disable notifications by selecting a preset expiration, by setting a custom expiration, or by setting your status as **Don't clear**. Your availability automatically reverts to its previous setting once the expiration is reached (this may take up to five minutes). + +![Example of setting your Mattermost availability as Do Not Disturb.](/images/set-your-availability-dnd.png) diff --git a/docs/main/end-user-guide/preferences/troubleshoot-notifications.mdx b/docs/main/end-user-guide/preferences/troubleshoot-notifications.mdx new file mode 100644 index 000000000000..576953404c31 --- /dev/null +++ b/docs/main/end-user-guide/preferences/troubleshoot-notifications.mdx @@ -0,0 +1,255 @@ +--- +title: "Troubleshoot notifications" +--- + + +The Mattermost notifications you receive depend on your [Mattermost preferences](#check-your-mattermost-preferences), the [Mattermost client](#check-your-mattermost-client-settings) you're using, and the [operating system (OS)](#check-your-operating-system-settings) you're running Mattermost on. + +## Send yourself a test notification + +From Mattermost v10.3, you can send yourself a test notification by selecting **Settings** Use the Settings icon to customize your Mattermost user experience., and going to the **Notifications** options. + +Under **Troubleshooting notifications** select the **Send a test notification** option. If notifications are working, you'll receive a system-bot direct message in Mattermost confirming that notifications are working. + +If you don't receive a system-bot direct message, see the following sections for troubleshooting steps you can follow to ensure you're receiving the notifications you want. + +## Check your Mattermost preferences + +Start by ensuring that your Mattermost preferences have notifications enabled. + +
+ +Desktop + +1. Select **Settings** Use the Settings icon to customize your Mattermost user experience. in the top right corner of Mattermost. +2. Select **Desktop and mobile notifications**. + +If **Send notifications for** is set to **Nothing**, then Mattermost notifications are currently disabled. Select either the **All new messages** or **Mentions, direct messages, and group messages** option instead, and save your changes. + +![Select the Gear icon to enable Mattermost notifications.](/images/desktop-notification-check.gif) + +
+ +
+ +Web + +1. Select **Settings** Use the Settings icon to customize your Mattermost user experience. in the top right corner of Mattermost. +2. Select **Desktop and mobile notifications**. + +If **Send notifications for** is set to **Nothing**, then Mattermost notifications are currently disabled. Select either the **All new messages** or **Mentions, direct messages, and group messages** option instead. + +
+ +
+ +Mobile + +1. Tap on your profile picture in the bottom right corner of Mattermost. +2. Tap **Settings** Use the Settings icon to customize your Mattermost user experience.. +3. Tap **Notifications**. +4. Tap **Push Notifications**. +5. Ensure that **All new messages** or **Mentions, direct messages, and group messages** option is selected. +6. Under **Trigger push notifications when…**, select **Online, away or offline** to always receive notifications. + +
+ +We recommend checking your Mattermost client settings next. + +## Check your Mattermost client settings + +
+ +Desktop + +Ensure notifications are enabled in your Mattermost server connection. + +1. Select the Mattermost Server option in the top left of the desktop app, then edit the server details. +2. Under **Permissions**, enable **Notifications** and save your changes. + +![Select the server option to enable Mattermost notifications.](/images/desktop-server-notification-check.gif) + +
+ +
+ +Web + +If you prefer to use Mattermost in a web browser, you must grant notification permissions for Mattermost in the web browser. If you don't, the web browser can block you from receiving Mattermost notifications. + +Select the **Chrome**, **Edge**, **Firefox**, or **Safari** tab below based on your preferred web browser: + +
+ +Chrome + +Grant notification permissions for Mattermost in your Chrome web browser. + +1. From the Chrome menu, select **Settings**. +2. Select **Privacy and Security** in the left pane. +3. Expand **Site settings**. +4. Under **Permissions**, expand **Notifications**. +5. Enable the **Sites can ask to send notifications** option, and add your Mattermost workspace URL to the **Allowed to send notifications** list. + +
+ +
+ +Edge + +Grant notification permissions for Mattermost in your Edge web browser. + +1. From the Edge menu, select the **Settings and more (...)** option. +2. Select **Cookies and Site Permissions** in the left pane. +3. Under **All Permissions**, **select Notifications**. +4. Add your Mattermost workspace URL to the **Allow** section. + +
+ +
+ +Firefox + +Grant notification permissions for Mattermost in your Firefox web browser. + +1. From the Firefox menu, select **Settings**. +2. Select **Privacy and Security** in the left pane. +3. Under **Permissions**, select the **Settings** option for **Notifications**. +4. Enable notifications for your Mattermost workspace URL in the **Permissions** list. + +
+ +
+ +Safari + +Grant notification permissions for Mattermost in your Safari web browser. + +1. From the Safari menu, select **Preferences**. +2. Select **Websites** and select **Notifications** in the left pane. +3. Enable notifications for your Mattermost site. + +
+ +
+ +
+ +Mobile + +Ensure that your mobile device isn't blocking device settings. Visit the **Android** or **iOS** tab below based on your mobile device type. + + + +From Mattermost mobile v2.34, if your device has notifications disabled, a banner displays in the Mattermost mobile **Settings \> Notifications** screen with a quick link to help you restore device-level notifications. + + + +
+ +Android + +Ensure that your Android device isn't blocking Mattermost notifications by granting notification permission for Mattermost in device settings. + +1. Open the Android **Settings app**, and tap **Application Manager**. +2. Locate **Google Play Services** and enable notifications for it. +3. Locate **Mattermost** and enable notifications for it. + +Also ensure that your Android device isn't set to **Do Not Disturb** mode which is designed to block notifications. See the [Android help](https://support.google.com/android/answer/9069335#zippy=%2Cturn-interruptions-back-on) documentation to learn more. + +
+ +
+ +iOS + +Ensure that your iOS device isn't blocking Mattermost notifications by granting notification permission for Mattermost in device settings. + +1. Open the iOS **Settings app** and tap **Notifications**. +2. In the list of apps, tap **Mattermost**. +3. Enable the **Allow notifications** toggle and set **Notification Delivery** to **Immediate Delivery**. + +Also ensure that your iOS device isn't set to **Do Not Disturb** mode or a **Focus mode** designed to block notifications. See the [iOS support](https://support.apple.com/en-ca/105112) documentation to learn more. + +
+ +
+ +We recommend checking your operating system settings next. + +## Check your Operating System settings + +The operating system you're running Mattermost on can also block Mattermost notifications. Select the **Linux**, **macOS**, or **Windows** tab based on your operating system: + +
+ +Windows + +If you're using Mattermost on a Windows machine, you must enable notifications from Mattermost and turn off both Do Not Disturb mode and Focus Assist. If you don't, Windows can block you from receiving Mattermost notifications. + +1. Open **Windows Settings** and go to **System \> Notifications & actions**. +2. Ensure that **Get notifications from apps and other senders**, is enabled. +3. Find Mattermost in the list and enable notifications. + +Also ensure that Windows’ **Do Not Disturb** mode and **Focus Assist** is turned off. See the Windows support docmentation on [Do Not Disturb mode](https://support.microsoft.com/en-us/windows/turn-off-notifications-in-windows-during-certain-times-81ed1b25-809b-741d-549c-7696474d15d3) and [Focus Assist](https://support.microsoft.com/en-us/windows/make-it-easier-to-focus-on-tasks-0d259fd9-e9d0-702c-c027-007f0e78eaf2) to learn more. + +
+ +
+ +Linux + +If you're using Mattermost on a Linux machine, you must enable pop-up notifications from Mattermost and turn off Do Not Disturb mode. If you don't, Linux can block you from receiving Mattermost notifications. + +1. Open **Settings**, then go to **Notifications**. +2. Enable the **Show Pop-up Notifications** option. +3. Enable the **Show Notification Center** to review and manage your Mattermost notifications. + +Also ensure that **Do Not Disturb** mode is turned off. + +
+ +
+ +macOS + +If you're using Mattermost on a macOS machine, you must enable application notifications for Mattermost and turn off focus mode. If you don't, macOS can block you from receiving Mattermost notifications. + +1. Open **System Settings** and go to **Notifications**. +2. Under **Application Notifications**, ensure notifications are enabled. + +Also ensure that macOS’ **Focus mode** is turned off. See the Apple Support [Focus mode](https://support.apple.com/en-ca/guide/mac-help/mchl999b7c1a/mac) documentation to learn more. + +
+ +## Frequently Asked Questions + +### What determines if a desktop notification should be triggered? + +Desktop notifications are triggered under to following conditions. Click to expand the flow chart. + +A flow diagram shows how Mattermost Desktop App notifications are triggered when a message is posted. + +### What determines if an email notification should be triggered? + +Email notifications are triggered under to following conditions. Click to expand the flow chart. + +A flow diagram shows how Mattermost email notifications are triggered when a message is posted. + +### What determines if a mobile push notification should be triggered? + +Mobile push notifications are triggered under to following conditions. Click to expand the flow chart. + +A flow diagram shows how Mattermost mobile push notifications are triggered when a message is posted. + +### Are mobile push notifications free? + +Yes, push notifications are free if you compile your own [push-proxy service](https://github.com/mattermost/mattermost-push-proxy). Push notifications are also free if you use the hosted Test Push Notification Service (TPNS) provided by Mattermost, Inc. + +TPNS, hosted at [https://push-test.mattermost.com](https://push-test.mattermost.com), offers transport-level encryption, but not production-level service level agreements (SLAs). + +If you need production-level SLAs for push notifications, you can either compile your own push-proxy service, with your own key, or you can use a paid option and become a Mattermost Professional subscriber [agreeing to our Conditions of Use](https://mattermost.com/terms-of-use/), which enables you to use a production-level Hosted Push Notification Service (HPNS) at `https://push.mattermost.com`. + +Learn more about [our push notification service](/administration-guide/configure/environment-configuration-settings#enable-push-notifications). + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/end-user-guide/project-management/boards-settings.mdx b/docs/main/end-user-guide/project-management/boards-settings.mdx new file mode 100644 index 000000000000..64b45a1463ce --- /dev/null +++ b/docs/main/end-user-guide/project-management/boards-settings.mdx @@ -0,0 +1,16 @@ +--- +title: "Settings" +--- + + +## Set language + +In a board, set your preferred language by selecting the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then go to **Set language** to apply your language settings. Language settings in Boards are independent from language settings in Channels. + +## Random emoji icons + +To enable or disable random emoji icons for your board and cards, select the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then toggle **Random icons on or off**. + +## Product tour + +If you skipped the product tour or want a refresher on Boards, you can restart the product tour by going to the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture and selecting **Product tour**. This will add a new **Welcome to Boards** template to your sidebar and kick-off the guided onboarding tour. diff --git a/docs/main/end-user-guide/project-management/calculations.mdx b/docs/main/end-user-guide/project-management/calculations.mdx new file mode 100644 index 000000000000..335f887d1fe0 --- /dev/null +++ b/docs/main/end-user-guide/project-management/calculations.mdx @@ -0,0 +1,48 @@ +--- +title: "Work with calculations" +--- + + +When you view a board in table or board view, you can use calculations to answer basic metric questions without needing to create complex reports. Hover over the bottom of a column to display the **Calculate** feature, then select the arrow to open the menu options. + +You can use calculations to quickly see: + +- How many story points are planned for a release. +- How many tasks have been assigned or not assigned. +- How long has the oldest bug been sitting in the backlog. +- The count of cards where particular properties are empty (useful to make sure important info isn’t missing). +- The sum of estimated developer days for features (to make sure your team isn’t overloaded). +- The range of estimated dates (to make sure your milestones all line up). + +## Calculation options + +Calculation options include the following: + +- **Count**: Counts the total number of rows in table view or total number of cards in a column in Board view. Applies to any property type. +- **Count Empty**: Applies to any property type. + - Table View: Counts the total number of empty rows per column selected. + - Board View: Counts the total number of empty values per property specified within the same column. +- **Count Not Empty**: Applies to any property type. + - Table View: Counts the total number of rows with non-empty cells per column selected. + - Board View: Counts the total number of non-empty values per property specified within the same column. +- **Percent Empty**: Applies to any property type. + - Table View: Percentage of empty rows per column selected. + - Board View: Percentage of empty values per property specified within the same column. +- **Percent Not Empty**: Applies to any property type. + - Table View: Percentage of rows with non-empty cells per column selected. + - Board View: Percentage of non-empty values per property specified within the same column. +- **Count Value**: Applies to any property type. + - Table View: Counts the total number of values within the column (helpful for multi-select properties). + - Board View: Counts the total number of values per property specified within the same column. +- **Count Unique Values**: Applies to any property type. + - Table View: Counts the total number of rows with unique values within the column, omitting any duplicates from the count. + - Board View: Counts the total number of unique values per property specified within the same column, omitting any duplicates from the count. +- **Sum**: The sum of any specified number property within the same column. +- **Average**: The average of any specified number property within the same column. +- **Median**: The median of any specified number property within the same column. +- **Min**: The lowest number of any specified number property within the same column. +- **Max**: The highest number of any specified number property within the same column. +- **Range**: Displays the lowest and highest number. Requires a number property. +- **Earliest Date**: Displays the oldest date. Requires any custom date property or the included "Created time" or "Last updated time". +- **Latest Date**: Displays the most recent date. Requires any custom date property or the included "Created time" or "Last updated time". +- **Date Range**: The difference between the most recent date and oldest date within the same column. In Table View, it's labeled simply as "Range" for any date property/column. Requires any custom date property or the included "Created time" or "Last updated time". diff --git a/docs/main/end-user-guide/project-management/groups-filter-sort.mdx b/docs/main/end-user-guide/project-management/groups-filter-sort.mdx new file mode 100644 index 000000000000..7826e4e9eec7 --- /dev/null +++ b/docs/main/end-user-guide/project-management/groups-filter-sort.mdx @@ -0,0 +1,84 @@ +--- +title: "Work with groups, filter, and sort" +--- + + +Your board can be grouped, filtered, and sorted into different views using a range of properties. This gives you a powerful way to track work from various perspectives. When used in conjunction with [saved views](/end-user-guide/project-management/work-with-views#work-with-saved-views), you can create multiple views with different groupings and filters for quick access without having to reapply the groupings and filters every time. + +For example, easily find tasks assigned to you or a team member using the person or multi-person filters, and keep track of upcoming tasks with date filters. + +## Group cards + +You can group cards on your board if they utilize the **Select** or **Person** property. Card grouping is only available in board and table views and you must have at least one **Select** or **Person** property on your board for grouping to work. + +### Apply a group + +To apply a group, select the **Group by** option at the top of the board, then select any available **Select** or **Person** property to group your cards by. + +- In the [boards view](/end-user-guide/project-management/work-with-views#board-view), cards are automatically grouped into columns by the values from the specified property. +- In the table view \, grouped cards will appear in individual sections based on the values from the specified property. Select the arrow to the left of the group name to expand or collapse cards in the group. + +### Hide and unhide groups + +- To hide a group, select the options menu **(...)** to the right of any group name, then select **Hide**. Additionally, in table view only, you can hide empty groups by selecting the **Group by** option at the top of the board, then selecting **Hide empty groups**. +- To unhide a group, go to the hidden column section towards the right of a board view, select the group you want to unhide, then select **Show**. On table view, select the **Group by** option at the top of the board, then select **Show hidden groups**. + +### Ungroup cards + +To ungroup cards on table view, select the **Group by** option at the top of the board, then select **Ungroup** from the top of the menu. This will return your table to its default state. Cards can be ungrouped in table view only. Ungrouping is not possible on board view since groups are used to determine what to display. + +## Filters + +You can filter cards on your board if they utilize any of the following property types: + +- Select +- Text +- Email +- Phone +- URL +- Date +- Person +- Multi-person +- Created time +- Created by +- Last updated time +- Last updated by + +To use filters, you must have the above property types already added to your board. Go to **Filter \> Add filter**, and select the property you wish to filter by. You can use the modifiers to get even more granular results. + +### Add filters + +To add a filter, select the **Filter** option at the top of the board, then select **+ Add filter**. To change the property to filter by, select the name of the first property, then select another property (if available) from the menu. + +**Specify the filtering criteria** + +- **Includes**: Display cards with any of the specified values. +- **Doesn’t include**: Display all cards without any of the specified values. +- **Is empty**: Display cards with no values assigned to a property. +- **Is not empty**: Display cards with any value assigned to a property. + +To add another filtering layer, repeat the steps above with another property to refine your filtering results. Adding another layer will display cards that only match the criteria from the first layer and the second layer. + +### Delete filters + +To delete a filter, select the **Filter** option at the top of the board, then select **Delete** to the right of each filtering layer. Delete all filtering layers to completely remove filters from the board. + +## Sorting cards + +Cards can be sorted by the card name or by any property available on the card. + + + +Sorting is only available in boards, table, and gallery views. + + + +### Apply sorting + +To apply a sort, select the **Sort** option at the top of the board, then select an option from the menu. The cards will be sorted in ascending order by default based on the selected option and the **Sort** menu will display an upward pointing arrow next to the selected option. + +To change the sort order to descending order, select the same option again from the **Sort** menu. The cards will now be sorted in descending order and the menu will display a downward pointing arrow next to the selected option. + +### Clear sorting + +To clear a sort, select the **Sort** option at the top of the board, then select the **Manual** option from the top of the menu. diff --git a/docs/main/end-user-guide/project-management/migrate-to-boards.mdx b/docs/main/end-user-guide/project-management/migrate-to-boards.mdx new file mode 100644 index 000000000000..76b37af41a5f --- /dev/null +++ b/docs/main/end-user-guide/project-management/migrate-to-boards.mdx @@ -0,0 +1,179 @@ +--- +title: "Import, export, and migrate" +--- + + +## Import and export a board archive + +If you’d like to back up your board or re-use it on another team or channel workspace, you can export it as an archive file, and then import the archive file in the team or channel workspace of your choosing. Exported and imported board archives include all card content such as properties, comments, descriptions, and image attachments. + +To do this, select the options menu Use the More icon to access additional message options. to the left of the **New** button at the top of the board. Then select **Export board archive**. Download the archive file. Navigate to the team or channel workspace where you’d like to add the exported board. Select the Gear icon next to your profile picture, then choose **Import archive**. The board you exported will be added to this team or channel workspace. + +The **Import archive** option will import the board to your current team. Use [board permissions](/end-user-guide/project-management/share-and-collaborate#board-permissions) to control access to your imported board. The previous `.focalboard` format will be deprecated in a future release, but will support importing until then. Currently, the import dialog looks for `.boardarchive`. Use **Select all files** to select `.focalboard` files to import. + +## Export to CSV + +To export a board into a CSV file, select the options menu Use the More icon to access additional message options. to the left of the **New** button at the top of the board. Then select **Export to CSV**. + +## Import and export from other applications + +You can import data from other tools to use with Boards. + +## Import from Asana + +This node app converts an Asana JSON archive into a `.boardarchive` file. + +1. Log into your Asana account. +2. Select the drop-down menu next to the Asana board's name. Then select **Export/Print \> JSON**. This will create an archive file which you'll use in Boards. +3. Save the file locally, e.g. to `asana.json`. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to `focalboard`: + +``` sh +git clone https://github.com/mattermost/focalboard focalboard +``` + +5. Navigate to `focalboard/webapp`. +6. Run `npm install`. +7. Change directory to `focalboard/import/asana`. +8. Run `npm install`. +9. From within the same folder, run `npx ts-node importAsana.ts -i -o archive.boardarchive`. This generates the following data: + +``` sh +asana macbook$ npx ts-node importAsana.ts -i ~/Downloads/asana.json -o archive.boardarchive +Board: 1:1 Meeting Agenda Test +Card: [READ ME] Instructions for using this project +Card: [EXAMPLE TASK] Feedback on design team presentation +Card: [EXAMPLE TASK] Finalize monthly staffing plan +Card: [EXAMPLE TASK] Review Q2 launch video outline +Card: [EXAMPLE TASK] Mentor a peer + +Found 5 card(s). +Exported to archive.boardarchive +``` + +10. In Boards, open the board you want to use for the export. +11. Select **Settings \> Import archive** and select `archive.boardarchive`. +12. Select **Upload**. +13. Return to your board and confirm that your Asana data is now displaying. + +If you don't see your Asana data, an the error should be displayed. You can also check log files for errors. + +### Import scope + +Currently, the script imports all cards from a single board, including their section (column) membership, names, and notes. + +## Import from Notion + +This node app converts a Notion CSV and markdown export into a `.boardarchive` file. + +1. From a Notion Board, open the **...** menu at the top right corner of the board. +2. Select Export and pick Markdown & CSV as the export format. +3. Save the generated file locally, and unzip the folder. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to `focalboard`: + +``` sh +git clone https://github.com/mattermost/focalboard focalboard +``` + +5. Navigate to `focalboard/webapp`. +6. Run `npm install`. +7. Change directory to `focalboard/import/notion`. +8. Run `npm install`. +9. From within the same folder, run `npx ts-node importNotion.ts -i <path to the notion-export folder> -o archive.boardarchive`. +10. In Boards, open the board you want to use for the export. +11. Select **Settings \> Import archive** and select `archive.boardarchive`. +12. Select **Upload**. +13. Return to your board and confirm that your Notion data is now displaying. + +### Import scope + +Currently, the script imports all cards from a single board, including their properties and markdown content. + +The Notion export format does not preserve property types, so the script currently imports all card properties as a Select type. You can change the type after importing into Focalboard. + +## Import from Jira + +This node app converts a Jira `.XML` export into a `.boardarchive` file. + +1. Open Jira advanced search, and search for all the items to export. +2. Select **Export \> Export XML**. +3. Save the generated file locally, e.g. to `jira_export.xml`. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to `focalboard`: + +``` sh +git clone https://github.com/mattermost/focalboard focalboard +``` + +5. Navigate to `focalboard/webapp`. +6. Run `npm install`. +7. Change directory to `focalboard/import/jira`. +8. Run `npm install`. +9. From within the same folder, run `npx ts-node importJira.ts -i -o archive.boardarchive`. +10. In Boards, open the board you want to use for the export. +11. Select **Settings \> Import archive** and select `archive.boardarchive`. +12. Select **Upload**. +13. Return to your board and confirm that your Jira data is now displaying. + +### Import scope and known limitations + +Currently, the script imports each item as a card into a single board. Note that Jira `.XML` export is limited to 1000 issues at a time. + +Users are imported as Select properties, with the name of the user. + +The following aren't currently imported: + +- Custom properties +- Comments +- Embedded files + +## Import from Trello + +This node app converts a Trello `.json` archive into a `.boardarchive` file. + +1. From the Trello Board Menu, select **...Show Menu**. +2. Select **More \> Print and Export \> Export to JSON**. +3. Save the generated file locally, e.g. to `trello.json`. +4. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to `focalboard`: + +``` sh +git clone https://github.com/mattermost/focalboard focalboard +``` + +5. Navigate to `focalboard/webapp`. +6. Run `npm install`. +7. Change directory to `focalboard/import/trello`. +8. Run `npm install`. +9. From within the same folder, run `npx ts-node importTrello.ts -i -o archive.boardarchive`. +10. In Boards, open the board you want to use for the export. +11. Select **Settings \> Import archive** and select `archive.boardarchive`. +12. Select **Upload**. +13. Return to your board and confirm that your Trello data is now displaying. + +### Import scope + +Currently, the script imports all cards from a single board, including their list (column) membership, names, and descriptions. + +## Import from Todoist + +This node app converts a Todoist `.json` archive into a `.boardarchive` file. + +1. Visit the open source Todoist data export service at [https://darekkay.com/todoist-export/](https://darekkay.com/todoist-export/). +2. From the **Options** menu, select **Export As \> JSON (all data)**. +3. Uncheck the **Archived** option if checked. +4. Select **Authorize and Backup**. This will take you to your Todoist account. Follow the instructions on screen. +5. Note the name and location of the downloaded `.json` file. +6. Open a terminal window on your local machine and clone the focalboard repository to a local directory, e.g. to `focalboard`: + +``` sh +git clone https://github.com/mattermost/focalboard focalboard +``` + +7. Navigate to `focalboard/webapp`. +8. Run `npm install`. +9. Change directory to `focalboard/import/todoist`. +10. Run `npm install`. +11. From within the same folder, run `npx ts-node importTodoist.ts -i -o archive.boardarchive`. +12. In Boards, open the board you want to use for the export. +13. Select **Settings \> Import archive** and select `archive.boardarchive`. +14. Select **Upload**. +15. Return to your board and confirm that your Todoist data is now displaying. diff --git a/docs/main/end-user-guide/project-management/navigate-boards.mdx b/docs/main/end-user-guide/project-management/navigate-boards.mdx new file mode 100644 index 000000000000..27e2224aac05 --- /dev/null +++ b/docs/main/end-user-guide/project-management/navigate-boards.mdx @@ -0,0 +1,78 @@ +--- +title: "Navigate boards" +--- + + +## Access boards + +To access Mattermost Boards, select the **Product** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. menu in the top left corner of Mattermost, and then select **Boards** to view all the boards for your team. + +To access boards linked to a channel, select the **Toggle Linked Boards** icon to the far right. + +## Link a board to a channel + +Boards can be linked to channels and accessed from the channel Apps Bar. Select the **Boards** icon from the Apps Bar in a channel to open a right-hand sidebar (RHS) where channel members can search for and link boards to the channel. To link a board to the channel, select **Add** button to open the link boards dialog and search for a board to link. Channel members can only search and link boards within the team where they are also board admins. + + + +A channel can be linked to multiple boards, but each individual board can only be linked to one channel at a time. Linking the same board to another channel will automatically remove the link from the previous channel. + + + +Open the Boards Apps Bar icon, and select **Create a Board** to create a new board linked to the current channel. Once a board is linked to a channel, it's listed in the right-hand side of the Boards Apps Bar. Linking a board to a channel automatically grants all channel members access to the board, with the exception of guest accounts. Select a linked board to navigate directly to the board. + + + +All the boards previously associated with the workspace will automatically appear on the right-hand side panel post-migration as you upgrade to newer Boards versions. + + + +## Unlink a board from a channel + +If you're a board admin and want to unlink a board from a channel you're in, open the Boards Apps Bar, select the options Use the More icon to access additional message options. menu and select **Unlink**. Alternatively, you can open the **Share** dialog on the board, open the **Role** drop-down menu next to the channel's name and select **Unlink**. + +## Sidebar categories + +You can organize your boards in the left-hand sidebar using custom categories. By default, all boards will appear under the **Boards** category. To manage your categories, open the Use the More icon to access additional message options. menu next to the category to create, delete, or rename a category. With the exception to the default **Boards** category, all other categories can be renamed or deleted. + +After creating categories, you can move your boards to those categories by opening the more Use the More icon to access additional message options. menu next to the board and selecting **Move To…** to select the category where you want the board to be moved. + +If you delete a category with boards in it, then those boards will return to the default **Boards** category. + +Categories are organized per-user, so you can arrange your boards under categories that make sense to you without impacting boards or categories for other users. If a board is moved to a custom category, then the board will appear under that category for you only. Other users who are members of the board will continue to see the board in their own categories. + + + +If you belonged to a workspace prior to v7.2, you’ll see that the workspaces have been migrated to custom categories in the sidebar. All boards from a workspace are listed under a category of the same name. Boards from direct messages and group messages appear under the default **Boards** category. + +Categories are per-user, and can be renamed or deleted by each user after migration. New users won’t have default categories, and boards they join will appear under the default **Boards** category. + +Boards that you create after the migration won’t be linked to a workspace and will always appear under the default **Boards** category unless you move or hide the boards. + + + +## Drag and drop + +You can move both sidebar categories and boards and change the order of both to suit your preference. You can: + +- Set the position of a board within a category. +- Drag a board out of one category and drop it into another category. + +To do this, select and hold the cursor over the category or board name. Then move the category or board around as needed. Boards moved into a category are sorted to the top of the category by default unless you specifically position the board before releasing the cursor. + +## Manage boards on the sidebar + +In addition to moving boards to other categories, from the Use the More icon to access additional message options. menu next to each board name you can perform the following actions: + +- **Delete board**: If you're an admin of the board, you will see an option to delete the board. Deleting the board permanently removes the board from the sidebar of all board members. +- **Duplicate board**: Creates a copy of the board and all the cards on the board. The duplicated board will appear under the same category as the original board. Board members and comments from the original board aren't migrated to the new board. +- **New template from board**: Creates a custom board template of the board and all the cards on the board. +- **Hide board**: Hides the board from your sidebar only. The board will still remain visible on the sidebar for other board members. You can add the board back to your sidebar using the search box (CMD+K/CTRL+K). + +## Find a board + +From the top of the boards left hand sidebar, select the **Find Boards** field (CMD+K/CTRL+K) to open the board switcher, and start typing the name of the board you’re looking for. + +## Team sidebar + +If you’re a member of multiple teams, the team sidebar will appear on the left hand side of Boards. To switch teams, select any of the team icons from the team sidebar. diff --git a/docs/main/end-user-guide/project-management/share-and-collaborate.mdx b/docs/main/end-user-guide/project-management/share-and-collaborate.mdx new file mode 100644 index 000000000000..6d64234adecb --- /dev/null +++ b/docs/main/end-user-guide/project-management/share-and-collaborate.mdx @@ -0,0 +1,158 @@ +--- +title: "Share and collaborate" +draft: true +--- + + +## Board permissions + +Boards belong to teams and any member of that team can be granted access to a board. + +If your boards workspace looks different, you may be on an earlier version of boards. In earlier versions, boards are tied to channel workspaces and board membership is determined by channel membership. In this case, roles and permissions won't be applicable to you. + +## Roles + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Board permissions

Modify permissions

Admin | Editor | Commenter | Viewer |

=============+=============+================+==============+

checkmark | | | |

Share a public boardcheckmark | | | |
Delete boardcheckmark | | | |
Rename boardcheckmark | checkmark | | |
Add, edit, and delete viewscheckmark | checkmark | | |
Add, edit, and delete cardscheckmark | checkmark | | |
Comment, delete my commentscheckmark | checkmark | checkmark | |
Delete any commentcheckmark | | | |
Viewcheckmark | checkmark | checkmark | checkmark
+ +The level of access to a board is determined by a user’s assigned board role. Individual board membership always gets precedence, followed by highest (most permissive) group role. + +- **Admin**: Can modify the board, its contents, and its permissions. By default, board creators are also admins of the board. +- **Editor**: Can modify the board and its contents. +- **Commenter**: Can add comments to cards. +- **Viewer**: Can view the board and its contents but can't comment or edit the board. + +### System admin access + +System admins can access any board across the server provided they have the board's URL without having to request permission or be manually added. When a system admin joins a board, their default role is admin. System admins will have an **Admin** label assigned to their name on the participants list. + +### Team admin access + +Team admins can access any board within their team provided they have the board's URL without having to request permission or be manually added. When a system admin joins a board, their default role is admin. Team admins will have a **Team admin** label assigned to their name on the participants list. + +### Manage team access + +Board admins can manage team access to their board by selecting **Share** in the top-right corner of the board. On the dropdown next to **Everyone at… Team** option, select a minimum board role for everyone on the team. You can also easily assign the new roles to the entire team and/or to individual team members. + +Minimum default board roles reduce permission ambiguity and prevent security loopholes. The minimum default role means that board admins can't assign individual board members a role lower than the team role. If the team role is set to **Editor** then the board admin will only be able to assign the **Editor** or **Admin** role to individual team members. Lower roles will not be available for selection unless the admin changes the minimum board role. + +Depending on the role selected, everyone on the team will have access to the board with a minimum of the permissions from the role selected. Users can get elevated permissions based on their individual board membership. The default team access for a newly created board is **None**, which means nobody on the team has access to the board. + +### Manage individual board membership + +Only board admins can manage user permissions on a board, including adding, changing, and removing members. + +To add individual users from the team as explicit members of the board, open the **Share** dialog on the board, search for individual team members, then assign a role to set their permissions for the board. The role for individual board members overrides any role specified for team access. + +- To change a board member’s role, open the **Share** dialog, select the role dropdown next to the user’s name, then select another role from the list. +- To remove a member from a board, open the **Share** dialog, select the role dropdown next to the user’s name, then select **Remove member**. + +Board admins can also add individual members using the autocomplete list from @mentions and the person properties. To add an individual from the autocomplete list, type their username in an @mention or in the **Person** or **Multi-person** properties, then assign a role to the user from the confirmation dialog, and select **Add to board**. + +On boards with team access, board members with **Editor** or **Commenter** roles can also add individuals to the board from the autocomplete list. Board members added in this manner will be assigned the default minimum board role. + +### Channel role groups + +Board admins can add a channel to a board to grant all its members Editor access. To do this, select **Share** in the top-right corner of the board, search for the channel name, and add it to the board as a user. The default role is Editor. Doing so also [links the board back to the channel](/end-user-guide/project-management/navigate-boards#link-a-board-to-a-channel), where the board will appear on the channel RHS. + +To unlink the channel from the board, open the **Share** dialog, select the role dropdown next to the channel’s name, then select **Unlink**. + + + +A board can only be linked to one channel at a time. Linking another channel to the same board will automatically remove the link from the previous channel. + + + +## Guest accounts + +From Mattermost Boards v7.4, [guest accounts](/administration-guide/onboard/guest-accounts#guest-accounts) are supported in Boards. Guests can: + +- Access boards where they're added as an explicit member of the board. [Team access](#manage-team-access) and [channel role groups](#channel-role-groups) don't apply to guest accounts. +- Access existing boards, but not create new boards. Guests don't have access to the template picker and can't duplicate an existing board. +- Search for boards where they're currently an explicit member. +- Be assigned the Viewer, Commenter, or Editor roles, but not the board Admin. +- Only @mention current members on the board. + +If you're not able to access this functionality, you may be on an earlier version of Boards. + +## Share a board + +Boards can be shared internally with your team or published externally with limited accessibility. + +### Share a board internally + +To share a board with team members internally, select **Share** in the top-right corner of the board, then select **Copy link** from the **Share** tab below. Paste the copied link in a channel or direct message to share the board with other team members. Only team members who have permissions to the board will be able to open the board from the shared link. + +### Share a board publicly + +Sharing boards publicly is disabled by default. This means that the **Publish** tab is not available from the **Share** dialog. To enable public board sharing: + +1. Go to **Product menu \> System Console \> Products \> Boards**. +2. Set **Enable Publicly-Shared Boards** to **true**. +3. Select **Save**. + +Once enabled, board admins can share a read-only link online with anyone: + +1. Select **Share** in the top-right corner of the board. +2. Toggle to the **Publish** tab. +3. Switch to the **Publish to the web** option. +4. Select **Copy link**. + +Paste the link anywhere you want to share the board. Anyone with the link will be able to view the board, but they won’t be able to edit the board. + +Select the **Regenerate Token** icon in the URL box if you want to invalidate all the previously shared links. Confirm the action to regenerate the token. + +## Share cards on Channels + +Cards can be linked and shared with team members directly on Mattermost Channels. When you share a link to a card within Channels, the card details are automatically displayed in a preview. This preview highlights what the card is about at a glance without having to navigate to it. + +To share a card, you'll need to copy the card link first: + +- Open a card and select the options menu **(...)** at the top right of the card, then select **Copy link**. +- Alternatively, you can open the board view and hover your mouse over any card to access the options menu **(...)** for the card and select **Copy link** from there. + +After you've copied the link, paste it into any channel or direct message to share the card. A preview of the card will display within the channel with a link back to the card on Boards. diff --git a/docs/main/end-user-guide/project-management/work-with-boards.mdx b/docs/main/end-user-guide/project-management/work-with-boards.mdx new file mode 100644 index 000000000000..b051871f1807 --- /dev/null +++ b/docs/main/end-user-guide/project-management/work-with-boards.mdx @@ -0,0 +1,97 @@ +--- +title: "Work with boards" +--- + + +Start by selecting the type of board you want to use. A board contains cards, which typically track tasks or topics, and views, which define how to display the cards, or a subset of them. Views can display cards in a board, table, calendar, or gallery layout, optionally filtered and grouped by a property (e.g., priority, status, etc). + +## Add new boards + +To add a new board, select the plus icon The Plus icon provides access to channel and direct message functionality. at the top of the sidebar, then select **Create New Board** to open the template picker and select a template or blank board. + +### Board details + +To name or rename a board, select the title area to edit it. + +To display board description, hover above the board’s title and select **Show description** to activate the show/hide toggle. Once the description field is displayed, select **Add a description** right below the board title to add or edit the description. + +Boards and cards are created with random icons by default. To change or remove icons, select the icon then choose the appropriate action. + +All changes you make to boards and cards are saved immediately. + +## Choose a board template + +Templates provide you with a predefined structure so that you can get started quickly. Each template has a different function, but can be customized to suit your use case. When you create a new board from the template picker, select each template’s name to preview it and make sure it suits your requirements. Alternatively, you can create your own board templates. + +### Board templates + +Standard board templates include: + +- **Content Calendar**: Plan and organize your content creation and publication schedule. +- **Company Goals & OKRs**: Plan your company goals and objectives more efficiently. +- **Competitive Analysis**: Track and stay ahead of the competition. +- **Meeting Agenda**: Use this template for recurring meetings. Queue up items, organize discussions, and plan what to revisit later. +- **Personal Goals**: Categorize and plan your personal goals. +- **Personal Tasks**: Organize your life and track your personal tasks. +- **Project Tasks**: Stay on top of your project tasks, track progress, and set priorities. +- **Roadmap**: Plan your roadmap and manage your releases more efficiently. +- **Sprint Planner**: Plan your sprints and releases more efficiently. +- **Team Retrospective**: Identify what worked well and what can be improved for the future. +- **User Research Sessions**: Manage and keep track of all your user research sessions. +- **Welcome to Boards!**: Onboarding template with guided tour points to help you quickly ramp up on Boards. + +### Create a blank board + +If none of the available templates suit your requirements, you can create a blank board using the **Create empty board** option from the template picker. + +### Create a new template + +To create a new board template select the plus icon The Plus icon provides access to channel and direct message functionality. at the top of the sidebar to open the template picker, select **Create New Board** and then select **+ New template**. + +To turn an existing board into a template, hover over the board title in the sidebar. Select the options menu Use the More icon to access additional message options., then select **New template from board**. + +### Share a custom board template + +
+ +From Boards v7.2 or later + +Custom templates support permissions control, and are restricted to only the template creator by default. The template creator is an admin of the template. To make the template accessible to everyone on the team, select **Share** on the template editor, and then set the team role as **Viewer**. All members of the team will now be able to see and select the template from the template picker. + +The admin of the template can also grant specific team members elevated permissions to the template and/or limit access to selected team members by setting the team role as **None** and adding individual members to the template. Individual team members can be assigned the following roles on a template: + +- **Admin**: Can modify the template and its permissions, and delete the template. +- **Editor**: Can modify but not delete the template, nor change permissions. +- **Viewer**: Can view and select the template. + +
+ +
+ +Prior to Boards v7.2 + +Boards and templates are channel-specific so whichever channel you create your board or template in, is where you’ll find it. If you’d like to re-use a board as a template on another channel workspace, you can export it and then import the archive file in the channel of your choosing. + +To do this, select the options menu Use the More icon to access additional message options. in the toolbar at the top of the board. Then select **Export** board archive. Download the archive file. Navigate to the channel where you’d like to add the exported board. Select the gear icon Use the Settings icon to customize your Mattermost user experience. next to your profile picture, then choose **Import archive**. The board you created will be added to this channel. + +
+ +## Edit board templates + +Custom templates are fully editable, but standard templates cannot be edited or deleted. To open the template editor for a specific template, go to the template picker then hover over the custom template and select the pencil icon. Any changes made on the template editor will be automatically saved and visible to team members who have access to the template. + +
+ +From Boards v7.2 or later + +Only admins and editors of a custom template can edit the template. If you don't see the pencil icon when hovering over the template, then you don't have the appropriate permissions to edit the template. + +
+ +
+ +Prior to Boards v7.2 + +Any member of the channel workspace can edit a custom template in the channel. To limit access to the template, create or export the template to a private channel. + +
diff --git a/docs/main/end-user-guide/project-management/work-with-cards.mdx b/docs/main/end-user-guide/project-management/work-with-cards.mdx new file mode 100644 index 000000000000..16aea40a72b4 --- /dev/null +++ b/docs/main/end-user-guide/project-management/work-with-cards.mdx @@ -0,0 +1,159 @@ +--- +title: "Work with cards" +--- + + +A card consists of: + +- **A set of properties**: Properties are common to all cards in a board. Board views can group cards by “Select” type properties into different columns. +- **A list of comments**: Comments are useful for noting important changes or milestones. +- **A set of content**: The content of a card can consist of Markdown text, checkboxes, and images. Use this to record detailed specs or design decisions for an item for example. + +Drag cards from one column to another to change their group-by property. For example, if cards are grouped by “Status” on board view, drag a card to the **Completed** column to mark it as completed. When a board is unsorted, you can drag a card up and down within a column to custom sort your cards. + +For sorted boards, dragging a card to a column will auto-sort it using the specified sort settings. The ability to move cards between boards isn't supported. + +Our standard board templates provide some default card properties that can be customized or removed. In the Roadmap template, we include **Type** property, whereas in the Project Tasks template, we include an **Estimated Hours** property. These properties are not exclusive to any template and can be easily re-created in any of the templates provided. + +## Card descriptions + +Card descriptions can include text with Markdown formatting, checkboxes, and visual elements such as images or GIFs, and can be separated into blocks of content. To add a description, open a card, select **Add a description** below the **Comments** section, and start typing in your content. + +To add a new content block in the description section, hover over the section and select **Add content**. Then choose from any of the following options: + +- **Text**: Adds a new text block that can be formatted with Markdown. +- **Image**: Select and embed an image file into the content block. The following image formats are currently supported: GIF, JPEG, and PNG. +- **Divider**: Adds a divider content block below the previous block. +- **Checkbox**: Adds a checkbox content block. Press Enter/Return after typing in content for your checkbox to add another checkbox within the same block. Please note, Markdown formatting isn't supported within the **Checkbox** content block. + +To manage the description content blocks on a card, hover over any existing block and select the options menu Use the More icon to access additional message options. to move the block up or down, insert a new block above, or delete the current block. Alternatively, you can hover over any existing block, then select and hold the grid button to drag and drop it to a new position within the description section. + +## Card properties + +Cards can contain different data fields depending on the purpose of the board. Using card properties, you can customize these data fields to fit your needs and track the information most important to you. For example, in a **Roadmap** board, cards include a **Type** field where you can add categories such as **Bug**, **Epic**, etc. In a **Project Task** board, cards include the **Estimated Hours** field instead. + +## Add properties + +To create a new property field open a card and select **Add a property**. Then select the type of property from the drop-down menu. The property type specifies the type of data you plan to capture within that field. When you create new card properties, they're added to all new and all existing cards on the current board. + +Properties are automatically added to the board filter list at the top of the page, so ensure you customize all property names to make it easy to filter your board by specific properties later. + +### Work with property types + +Boards supports a wide range of fully customizable property types: + +- **Text** can be used to add short notes to a card. An advantage of the text property over card descriptions is that it can be [shown on the board](#toggle-properties-shown-on-a-board) without needing to open the card. +- **Numbers** are useful to capture metrics such as task sizing or effort estimates. Use in conjunction with calculations to get the most out of the number property type. +- **Email** and **Phone** can be used to record contact information. +- **URL** can be used to provide a link to a pull request or relevant website. Clicking on the box of a URL property will automatically open the link in a new tab on your browser. Hover over the box to surface options to copy or edit the URL. +- **Select** and **Multi-select** allows you to create a predefined list of options that can be color-coded and displayed as badges on the card to indicate things like status and priority. +- **Dates** are useful to set and track due dates or milestones. Use the date property to make a card appear on the [Calendar view](/end-user-guide/project-management/work-with-views#calendar-view). Set a single date or toggle on the **End date** to set a date range. +- **Person** and **Multi-person** provides a quick way to capture user assignments. +- **Checkbox** is a toggle property that can be used for assigning simple binary options on a card such as True/False or Yes/No. +- **Created time/Created by/Last updated time/Last updated by** are predefined system properties to help you audit changes on a card. The names of these properties are customizable, but the values are not. + +## Rename a property + +The default name for a new property is the name of the property type (e.g. **Date**, **URL**). To rename a property field, open up a card and select the property name to open an editable field. Enter the new name in the field provided. The change is saved immediately and applied across all cards on the current board. + +## Change a property type + +To change a property type, select the property then open the **Type** menu and choose a new property type. You’ll be asked to confirm the change from every card on the current board. Changing the type for an existing property will affect values across all cards on the board and may result in data loss. + +## Delete a property + +To delete properties you no longer need, select the property, then choose **Delete**. You’ll be asked to confirm that you want to remove that property from every card on the current board. Properties are displayed in the order they were created and cannot be re-ordered at this time. + +## Define a "Select" or "Multi-select" property + +The options on a **Select** and **Multi-select** property type appear as color-coded tags on a card. To add and configure the options on these types: + +1. Select a card to open the card view. +2. Add a new property, give it a name, and set its type to **Select** (or **Multi-Select**). +3. Select the field box for the property, and start typing the name of a new option. Press Enter to accept. Repeat this step to add additional options. + +- To assign a color to or delete an option, select the value and select the options menu **(...)** next to each option name. +- To select an option on the property, select the box and choose one of the values from the menu. +- To remove an option on the property, select the box and chooose the X next to the option name you want to remove. + +Alternatively, you can also add new options directly from a board: + +1. Open a board view. +2. Group by a **Select** property. +3. Scroll to the right of the board and select **+ Add a group**. + +This will add a new column, which corresponds to a new value option for the Select property. Options in a **Select** or **Multi-Select** property list are sorted in the order they were created and cannot be re-ordered or renamed at this time. + +## Toggle properties shown on a board + +Once you have card properties defined, you have full control over which properties are shown on the board as a preview without having to open the card. Select **Properties** at the top of the board, then enable all properties you want to see at a glance, and hide all properties you don’t want to see. + +## Attach files + +You can attach files to your cards that other board members can download. There are no limitations to the file types that you can upload. + +To upload a file to a card, select **Attach** in the top-right corner of the card. Then select the file you'd like to upload. When your file has been uploaded, you can find it in the **Attachments** section of the card. Select the **+** sign to add additional files to your card. + +To delete a file, hover over it and select the Use the More icon in the top left corner to access Mattermost desktop apps customization settings. menu. Then select **Delete**. To download the file, select the download icon. + +## Card badges + +Card badges are a quick way to view card details without opening up a card. To add them, select **Properties \> Comments and Description**. Icons related to the card description, comments, and checkboxes will be displayed on cards with the respective content. Open the card to view the details. + +- The description icon indicates that a card has a text description. +- The comment icon displays a number indicating how many comments have been added to a card. When a new comment is added, that number is updated. +- The checkbox icon displays the number of items checked off relative to the total number of checkboxes within the card. When an item is checked off, the icon is automatically updated. + +## Comment on a card + +Comments allow you to provide feedback and ask questions relevant to the specific work item on the card. + +To add a comment, select a card to open the card view, then click on **Add a comment…** to type in your comment, and press **Send** to save the comment to the card. All team members who are [following the card](#receive-updates) will receive a notification with a preview of your comment in Mattermost Channels. + +Only board members with the *Commenter* role or higher can comment on a card. Board members assigned the *Viewer* role can view, but not comment on, a card. + +## Mention people + +You can include a team member on a card by [mentioning them on a card](/end-user-guide/collaborate/mention-people) the same way you would in Channels. Mentions are supported in the [Comments](#comment-on-a-card) and [Description](#card-descriptions) sections within a card. The team member you mention will receive a direct message notification from the boards bot with a link to the card you mentioned them on. To mention multiple team members, separate each name with a comma. + +## Receive updates + +When you create a card, you automatically follow it. You can @mention someone on a card to add them as a follower. This can be a card you've created or someone else's card. Lastly, you can also follow cards manually using the **Follow** option on the top-right corner of a card. To unfollow a card, select **Following**. + +When updates are made to a card you're following, you'll receive a direct message from the boards bot with a summary of the change (e.g. Bob changed status from **In progress** to **Done**) and a link to the card for more detailed information. You won't get a notification of your own changes made to a card, even if you're following that card. + +## Search cards + +You can search through all the cards on a board to find what you’re looking for. Open the board you want to search, then select the **Search cards** field in the top-right of the board. + +## Card templates + +Card templates can help reduce repetitive manual input for similar types of work items. Each board can have any number of card templates. To create a new card template: + +1. Open the board where you want to add the card template. +2. Select the drop-down arrow next to **New**, then select **New template**. +3. Add a title to the card template. +4. Then assign values to any properties and add a description you wish to have pre-populated when a card is created from the template. +5. Close the card using the **X** in the top left corner. +6. Select the drop-down arrow next to **New**, then select the template you just created. + +Alternatively, you can turn any existing card into a template: + +1. Open the card you want to use as a template. +2. Select the options menu Use the More icon to access additional message options. in the top-right corner of the card. +3. Select **New template from card**. +4. Edit the card as needed, including a helpful name. +5. Close the card using the **X** in the top left corner. +6. Select the drop-down arrow next to **New**, then select the template you just created. + +To set a default card template for all new cards created on the board: + +1. Select the drop-down arrow next to **New**. +2. Open the options menu Use the More icon to access additional message options. next to the card template of your choosing. +3. Select **Set as default**. + + + +The card template is applicable only to the board in which it’s created and isn’t available in other boards in your team workspace. Comments on a template don't get populated on to new cards. Additionally, properties can't be hidden from a card template at this time. All cards on a board share the same properties, so adding or deleting a property on a template will also apply to all cards on a board. + + diff --git a/docs/main/end-user-guide/project-management/work-with-views.mdx b/docs/main/end-user-guide/project-management/work-with-views.mdx new file mode 100644 index 000000000000..8b0f03686720 --- /dev/null +++ b/docs/main/end-user-guide/project-management/work-with-views.mdx @@ -0,0 +1,28 @@ +--- +title: "Work with saved views" +--- + + +You can change board views to adjust how your cards are represented. To add a new view to a board, from the board header, select the menu next to the current view name. Scroll down and select **+ Add view**, then select the new visualization you’d like to use. + +## Board view + +This is a kanban view where cards are grouped into columns. Column groups only work with the **Select** or **Person** properties and display all cards that share the same value from the specified property. The column names are editable, and any changes to the column names are also applied to the value from the property. Cards can be dragged between columns, which will automatically update the property’s assigned value on the card. + +## Table view + +Displays cards in a table format with rows and columns. Use this view to get an overview of all your project tasks. Easily view and compare the state of all properties across all cards without needing to open individual cards. Each column corresponds to a card property. You can edit cells directly or you can select **Open** to open the card view for that row. + +## Gallery view + +Displays cards in a gallery format, so you can manage and organize cards with image attachments. Gallery view displays a preview of the first image attached on the card. For cards with no image attachments, a preview of the first description block will be displayed instead. + +## Calendar view + +To use this view, cards need to have the **Date** property added. + +If cards don’t have a custom **Date** property, they’ll be sorted and displayed by the card creation date (default). These cards can’t be moved around the board until a custom **Date** property is added. If your cards do have a **Date** property and you’re not able to move them around, you may be displaying them by **Created Time** or **Last Updated Time**. + +- To add a new card, select the **+** option in the top-left corner of the relevant date. +- To create a date range event, select a start date and then drag to the end date to create a card for that date range event. +- To add a date range to an existing card, hover over the side of the card to display the arrow and drag to the left or right to create a date range. diff --git a/docs/main/end-user-guide/project-task-management.mdx b/docs/main/end-user-guide/project-task-management.mdx new file mode 100644 index 000000000000..5800517304ad --- /dev/null +++ b/docs/main/end-user-guide/project-task-management.mdx @@ -0,0 +1,41 @@ +--- +title: "Project and Task Management" +--- + + +Mattermost Boards provides tight integration between project management and Mattermost to align, define, organize, track, and manage work across teams. + +With Boards you can: + +- **Manage projects and organize tasks:** A familiar kanban board structure integrated with channel-based communication. +- **Manage and collaborate on various projects:** Software releases, product launches, meetings, personal to-do’s, events, etc. +- **Stay on schedule:** Clearly-defined tasks, owners, checklists, deadlines, and calendars. +- **Increase transparency and keep everybody in the loop:** Everything your team needs in one place, including documents, images, and links that are visible to every stakeholder. + +## Install Boards + +Your system admin may need to install and enable Mattermost Boards before you can use it. See the [install Mattermost Boards](/administration-guide/configure/install-boards) documentation to learn how to install and configure the Boards plugin for your Mattermost instance. + +## What's a board? + +A board is a collection of cards to help you manage your projects, organize tasks, and collaborate with your team all in one place. + +Boards can be displayed and filtered in different views such as kanban, table, calendar, and gallery views to help you visualize work items in the format that makes most sense to you. Learn about [working with boards](/end-user-guide/project-management/work-with-boards). + +## What's a card? + +Cards are used on a board to track individual work items. Cards are customizable and can have a number of properties added to them, which are then used as a way to tag, sort, and filter the cards. + +When working with cards, you can manage properties, add descriptions, attach images, assign them to team members, mention team members, add comments, and so on. Learn more about [working with cards](/end-user-guide/project-management/work-with-cards). + +Learn more about working with boards by visiting the following documentation pages: + +- [Work with boards](/end-user-guide/project-management/work-with-boards) - Work with boards. +- [Work with cards](/end-user-guide/project-management/work-with-cards) - Work with cards. +- [Work with views](/end-user-guide/project-management/work-with-views) - Work with views. +- [Work with groups, filter, and sort](/end-user-guide/project-management/groups-filter-sort) - Work with groups, filter, and sort. +- [Work with calculations](/end-user-guide/project-management/calculations) - Work with calculations. +- [Share and collaborate](/end-user-guide/project-management/share-and-collaborate) - Share and collaborate +- [Import, export, and migrate](/end-user-guide/project-management/migrate-to-boards) - Migrate your data from other tools into Mattermost Boards. +- [Navigate boards](/end-user-guide/project-management/navigate-boards) - Navigate boards. +- [Boards settings](/end-user-guide/project-management/boards-settings) - Adjust language and emoji settings, and restart the product tour. diff --git a/docs/main/end-user-guide/workflow-automation.mdx b/docs/main/end-user-guide/workflow-automation.mdx new file mode 100644 index 000000000000..a8bba40b809a --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation.mdx @@ -0,0 +1,66 @@ +--- +title: "Workflow Automation" +--- + + +Mattermost Playbooks provides structure, monitoring and automation for repeatable, team-based processes integrated with the Mattermost platform. Playbooks are [configurable checklists](/end-user-guide/workflow-automation/work-with-tasks) for teams to achieve [specific and predictable outcomes](/end-user-guide/workflow-automation/metrics-and-goals), such as incident response, software release management, and logistical operations. + +From Mattermost v11.1, Entry, Enterprise, and Enterprise Advanced customers can enable adaptive, conditional workflows responding in real time to changing mission or operational context. Admins can define attributes such as severity, category, or linked ticket ID, and use those attributes to hide or show tasks depending on the values of these attributes which can be seen and modified during a playbook run. Learn more about [playbook attributes](/end-user-guide/workflow-automation/work-with-playbooks#playbook-attributes) and [conditional playbook tasks](/end-user-guide/workflow-automation/work-with-tasks#conditional-tasks). + +While Playbooks primarily focus on coordinating people and tasks, they also have integration points. You can trigger a playbook run via an incoming webhook, allowing an external tool to trigger a playbook run. Within a playbook, you can define steps that execute webhooks or call external APIs. Additionally, playbooks can work in conjunction with plugins, keeping the entire workflow visible in Mattermost, and reducing the need to switch between apps during critical processes. + +Playbooks monitor channels for keywords or user actions to trigger a structured process, which brings up a set of individual or shared tasks, each associated with manual or automated actions. As playbooks are executed, some may have requirements for [broadcasting status updates to stakeholders](/end-user-guide/workflow-automation/notifications-and-updates) at regular intervals, to populate workflow dashboards by conducting [retrospectives](/end-user-guide/workflow-automation/metrics-and-goals#configure-retrospectives-before-a-run) after the core process is complete, or other customer requirements as exit criteria for a [playbook “run”](/end-user-guide/workflow-automation/work-with-runs). + +[Advanced permissions](/end-user-guide/workflow-automation/share-and-collaborate) are also available to delegate and manage playbook controls in larger organizations. + +![An example of the collaborative playbooks screen that includes active run details in the right-hand pane.](/images/Playbooks_Hero.png) + +## Configuration + +Playbooks comes pre-packaged, installed, and enabled with Mattermost server. + +## Access + +
+ +Web and Desktop + +Access playbooks using a web browser or the desktop app by selecting the product menu located in the top-left corner of the Mattermost interface and then selecting **Playbooks**. + +
+ +
+ +Mobile + +From Mattermost v11.0 and mobile app v2.34.0, mobile users can: + +- **Post status updates directly from mobile**: When you open a playbook run on mobile, a new status update button allows you to post progress updates and share status with your team while on the move or in the field. +- **Create and manage playbook runs** for operational command at the edge. + +From Mattermost v11 and mobile app v2.32.0, mobile users can access playbooks from the mobile app to [interact with playbook tasks](/end-user-guide/workflow-automation/work-with-tasks#interact-with-playbook-tasks) and [update tasks](/end-user-guide/workflow-automation/work-with-tasks#update-tasks). + +From Mattermost v10.11 and mobile app v2.31.0, mobile users can access playbooks from the mobile app in read-only mode. [Playbooks slash commands](/end-user-guide/workflow-automation/interact-with-playbooks#slash-commands) are supported in the mobile app, but actions like starting runs or updating checklists aren't available through the mobile interface. + +
+ +## Usage + +Use collaborative playbooks to orchestrate prescribed workflows and define, streamline, and document complex, recurring operations, and help your organization stay in command with integrated communication, collaboration, and status dashboards managing your workflow life cycles. + +### Try it yourself! + +Walk through our [Incident Response playbook demonstration](https://mattermost.com/demo/playbooks-incident-response/) to see what you can do with playbooks. + +## Learn more + +This end user documentation is for anyone who wants guidance on building repeatable processes in Mattermost. + +- [Overview](/end-user-guide/workflow-automation/learn-about-playbooks) - Learn what collaborative playbooks are and how they're used. +- [Work with collaborative playbooks](/end-user-guide/workflow-automation/work-with-playbooks) - Customize a playbook for successful runs. +- [Work with runs](/end-user-guide/workflow-automation/work-with-runs) - Edit triggers and actions in an active run. +- [Work with tasks](/end-user-guide/workflow-automation/work-with-tasks) - Work with tasks and the task inbox. +- [Work with notifications and updates](/end-user-guide/workflow-automation/notifications-and-updates) - Keep track of all your active runs and tasks. +- [Work with metrics and goals](/end-user-guide/workflow-automation/metrics-and-goals) - Unlock insights about the performance of collaborative workflows across organizations with workflow dashboards. +- [Share and collaborate](/end-user-guide/workflow-automation/share-and-collaborate) - Reuse and share collaborative playbooks with your organization. +- [Interact with collaborative playbooks](/end-user-guide/workflow-automation/interact-with-playbooks) - Interact with collaborative playbooks using slash commands and the REST API. diff --git a/docs/main/end-user-guide/workflow-automation/interact-with-playbooks.mdx b/docs/main/end-user-guide/workflow-automation/interact-with-playbooks.mdx new file mode 100644 index 000000000000..edb945073d2d --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/interact-with-playbooks.mdx @@ -0,0 +1,33 @@ +--- +title: "Interact with playbooks" +--- + + +## Slash commands + +Slash commands are available for collaborative playbooks. The `/playbook` slash command allows interaction with incidents via the post textbox on desktop, browser, and mobile. To run a playbook use the `/playbook run` slash command from any channel. + +Available slash commands include: + +- `/playbook run` - Run a playbook. +- `/playbook finish` - Finish the playbook run in this channel. +- `/playbook update` - Provide a status update. +- `/playbook check [checklist #] [item #]` - Check/uncheck the checklist item. +- `/playbook checkadd [checklist #] [item text]` - Add a checklist item. +- `/playbook checkremove [checklist #] [item #]` - Remove a checklist item. +- `/playbook owner [@username]` - Show or change the current owner. +- `/playbook info` - Show a summary of the current playbook run. +- `/playbook timeline` - Show the timeline for the current playbook run. +- `/playbook todo` - Get a list of your assigned tasks. +- `/playbook settings digest [on/off]` - Turn daily digest on/off. +- `/playbook settings weekly-digest [on/off]` - Turn weekly digest on/off. + +## Playbooks on the go + +Learn how to [access and work with playbooks on the go](https://docs.mattermost.com/end-user-guide/workflow-automation.html#itab--Mobile--0_1-Mobile) with the Mattermost mobile app. + +## API documentation + +To interact with the data model programmatically, consult the [REST API specification](https://github.com/mattermost/mattermost-plugin-incident-collaboration/blob/master/server/api/api.yaml). + +Playbooks help streamline and manage complex processes while decreasing the risk of forgotten steps or tasks. They also support tool integration, status updates in a dedicated channel, and can be edited on the fly. When a playbook run is finished, you can review the entire run to assess any areas of improvement for the next run. diff --git a/docs/main/end-user-guide/workflow-automation/learn-about-playbooks.mdx b/docs/main/end-user-guide/workflow-automation/learn-about-playbooks.mdx new file mode 100644 index 000000000000..6f864d44ff93 --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/learn-about-playbooks.mdx @@ -0,0 +1,59 @@ +--- +title: "Learn about collaborative playbooks" +--- + + +A collaborative playbook is a repeatable process that is measured and refined over time. For example, the steps you follow when dealing with an outage, a software release, or welcoming a new member of your team can all be made into a playbook. + +Using collaborative playbooks, teams can orchestrate prescribed workflows and define, streamline, and document complex, recurring operations. + +Each playbook represents a recurring outcome or specific goal that your teams collaborate on to achieve, such as service outage recovery or customer onboarding. Collaborative playbooks are made up of: + +- [Checklists](/end-user-guide/workflow-automation/work-with-playbooks#make-checklists): The list of tasks to be completed for the run. Can be edited during a run. From Playbooks v2.6.0, checklists can also be created and managed directly within public and private channels. +- [Templates](/end-user-guide/workflow-automation/work-with-playbooks#templates): Used for frequently-used actions such as updates and reminders. You can create your own templates or use default ones. +- [Automation actions](/end-user-guide/workflow-automation/work-with-tasks#task-actions): Used for inviting members, creating webhooks, editing welcome messages, and more. +- [Permissions](/end-user-guide/workflow-automation/share-and-collaborate): Manage permissions at the channel and at the playbook level. + +Teams run a playbook every time they want to orchestrate people, tools, and data to achieve that outcome as quickly as possible while providing visibility to stakeholders. + +- For participants, playbooks prescribe processes and actions such as task checklists, status updates, and retrospective reports. +- For your integrated tools, playbooks configure the triggers that execute automated actions. +- For stakeholders, playbooks provide a single pane of glass for visibility into each run as well as aggregate insights over time. + +## What's a run? + +A run is the execution of the steps in a playbook. When a playbook is run, the process begins in a channel. Members of a playbook can view the run's progress in the run details page or they can participate in the run channel. + +To find all playbook runs, open **Product menu \> Playbooks**, and then select any playbook name. Next, select **Runs** from the navigation bar, then choose a run to view its overview. Select **Go to channel** to open the run’s channel. + +When the process is completed, the run is ended. A retrospective can be run and the channel can be archived. + +## Keywords + +It's important to make it easy to start a run. One way to do this is by setting up keywords. These keywords prompt a user to start the run when they're used. In the incident response playbook, the keywords are specific to critical incidents, for example `sev-1` and `#incident`. It's unlikely that someone would use those terms in general conversation and, even if they do, they can elect not to start the playbook run when prompted. + +## Welcome message + +Create a welcome message so that when members join your run, it's easy for them to see where they're needed and where to find the relevant information. This is especially important during a time-sensitive incident to eliminate confusion and help members ramp up quickly. + +## Tasks and checklists + +Tasks and checklists are the foundation of a template and a workflow. In an incident, it's critical to get stakeholders together as soon as possible, so one of the first tasks is to add the on-call engineer to the channel, followed by starting a bridge call. When you're setting up these tasks, you can add slash commands, @mentions, and integrations with tools such as Zoom to make the initiation as seamless as possible. + +## Status updates + +Regular updates are important communication tools, especially in the middle of an incident like an outage. Channels can get very busy and overwhelming, and if you have more than one incident at a time, it's often too noisy for stakeholders to keep track of everything. + +Use the **Broadcast update to other channels** option to cut through the noise and share critical information with both channel members and other users in a dedicated channel. + +Additionally, set a timer that issues a reminder for updates to be shared. + +## Retrospective + +When an incident is over, create a retrospective that captures the impact of the event. You can also add metrics, such as how long it took to resolve the incident, which you can apply to other, similar incidents to see where you can improve and refine your workflows. + + + +Looking to optimize team productivity? Learn how to automate repeatable workflows with [this on-demand webinar](https://mattermost.com/webinar/4-strategies-to-improve-technical-teams-productivity/), then download our [Mattermost Playbooks datasheet](https://mattermost.com/mattermost-playbooks-datasheet/). + + diff --git a/docs/main/end-user-guide/workflow-automation/metrics-and-goals.mdx b/docs/main/end-user-guide/workflow-automation/metrics-and-goals.mdx new file mode 100644 index 000000000000..efa8eab7b639 --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/metrics-and-goals.mdx @@ -0,0 +1,52 @@ +--- +title: "Metrics and goals" +--- + + +Workflow dashboards unlock insights about the performance of workflows across organizations. They compare the output metrics from different runs of collaborative playbooks, against targets and historical performance. Each time a collaborative playbook is run, you can update the workflow dashboard for the team and stakeholders to review, where dashboard components are customized per playbook. + +Examples of metrics-based workflow dashboards that can be set up to monitor and inform performance include: time to detect, time to resolve in incident response workflows, work plan completion percentage for monthly software releases management workflows, and launch success rate for logistical workflows involving launch operations. + +## Configure retrospectives before a run + +Access the **Playbooks** tab in Mattermost. Locate the playbook you want to modify, select the **...** icon under **Actions** and then select **Edit**. In the next screen, select **Retrospective**. Move the toggle to **Enable Retrospective**. + +You can set a reminder to fill out the retrospective after a run is finished. The configured template is pre-populated in the run's retrospective. + +Use the run timeline to help write an accurate retrospective. Events such as owner changes, status updates, and task assignments appear automatically. Selected posts may also be added to the timeline by using the post context menu. + +![Create and publish retrospective reports.](/images/Retro.gif) + +## Metrics + +Use metrics to identify key areas where you want to extract valuable insights by measuring performance and improvement. Metrics are enabled when you enable retrospectives. Calibrate the type of metric you want to measure, and once a run is finished you can view the output in the retrospective. You can have multiple metrics configured per playbook and you can edit them at any time. Metrics can be configured based on numeric, time, or value input. + +These metrics can be anything that's of interest to you and your team. For example, for a software release playbook you might want to have a metric tracking how many bugs were detected during a run. The output of the metrics you've added is provided in the retrospective. Over time, you can use metrics across retrospectives to examine anomalies and refine goals. + +Another example is a support incident playbook. The time to resolution metric can be applied and used to identify areas that need more refinement, such as tasks that might work better if they're split up so goals are reached faster. + +When you delete configured metrics from a playbook, the data isn't deleted, but you no longer see those metrics in the dashboard. In addition, the corresponding metric field is removed from the retrospective form and from published retrospectives. + +### Metrics dashboard + +For each run, you can enter a value per metric under the retrospective section. This value can be based on whatever you are measuring, such as number of bugs found per run. + +You can edit this value as many times as you'd like - for example to ensure you have the correct parameters for your metric - until you've published the retrospective at which point both the metrics and report are no longer editable. The final value only shows up in the playbook dashboard once the retrospective has been published. + +The playbook dashboard reports on each metric for all runs by showing: + +- Average value for all runs +- The last 10-run average value and difference with prev 10-run average +- The value range for all runs +- The target value +- The actual values chart for last 10-runs + +The lower half of the page shows a list of finished runs with metrics values. You can filter or sort a list by metrics values. + +![View and assess metrics for your playbook.](/images/playbook-metrics.png) + +### Export channel data + + + +See the [export channel data](/administration-guide/comply/export-mattermost-channel-data) documentation for details on working with channel export functionality. diff --git a/docs/main/end-user-guide/workflow-automation/notifications-and-updates.mdx b/docs/main/end-user-guide/workflow-automation/notifications-and-updates.mdx new file mode 100644 index 000000000000..a869077961b9 --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/notifications-and-updates.mdx @@ -0,0 +1,88 @@ +--- +title: "Notifications and updates" +--- + + +There are multiple ways to receive collaborative playbook updates and notifications. + +## Status updates + +Status updates ensure that stakeholders remain informed about the playbook run's progress. + +You can post a status update from the run channel and you can also configure the playbook to send a reminder to post a status update. + +
+ +Web and Desktop + +1. To post a status update, access the **Playbooks** tab in Mattermost. Select the run you want to post the update for. In the run details page, select **Post update**. + - If this is the first status update and the playbook has a defined template, that template will be pre-populated here. + - If this is a subsequent status update, the message from the last status update will be pre-populated here. +2. Optionally set a reminder to prompt for the next status update. + - If this is the first status update and the playbook has a defined default reminder timer, that timer will be pre-selected here. + - If this is a subsequent status update, the last reminder timer will be pre-populated here. +3. Select **Post update** to post your status update. + +
+ +
+ +Mobile + +From Mattermost v11.1 and mobile v2.34.0, mobile users can post status updates directly from the Mattermost mobile app: + +1. Open a playbook run from your mobile app. +2. Select the status update button that appears when viewing the run details. +3. In the status update modal: + - If this is your first status update and the playbook has a status update template, the template content will be pre-populated. + - For subsequent updates, your most recent status update content will be pre-populated. + - The modal header shows how many people and channels will receive your status update. +4. Select your reminder timing from the predefined options available in the mobile app. +5. Select **Post update** to share your status update. + + + +- The status update button is only available to participants in the playbook run and is disabled when the run is finished. +- Mobile time selector options are limited to predefined choices, unlike the web interface which allows custom date entry. + + + +
+ +When the playbook has a defined broadcast channel, status updates are copied to the broadcast channel as a message from the Playbooks bot. Status updates broadcast to another channel won’t be updated or removed if the original post is edited or deleted. + +The most recent status post alsos displays in the right-hand sidebar of the run channel and in the timeline. To correct or remove a status post, edit or delete the post as needed. + +## Request an update + +To request a status update, access the **Playbooks** tab in Mattermost. Select the run you want an update for. In the run details page, select the Use the More icon in the top left corner to access Mattermost desktop apps customization settings. menu next to **Post update** and select **Request update**. + + + +Requesting updates is only available in the web browser and desktop app. This functionality is not available on mobile. + + + +## Follow runs and playbooks + +Follow specific playbooks to receive updates on important events such as when a run is started and finished, as well as status and retrospective updates every time that playbook is run. This is a good option if you're interested in all instances of a specific workflow, such as an outage resolution playbook. + +You can also choose to follow a specific run without actively participating. You’ll receive updates for that run only and can take action if needed. This is useful when you’re only interested in a single instance of a procedure—for example, following onboarding for one specific customer rather than every onboarding run. + + + +Following playbooks and runs is only available in the web browser and desktop app. This functionality is not available on mobile. + + + +## Daily digest + +To help you keep track of your runs, tasks, and statuses, a daily digest is sent via direct message in Mattermost. + +Running playbooks in multiple channels can be overwhelming. The daily digest is sent once a day, in the morning. It lists the actionable items for each run, as well as any outstanding tasks or status updates required. Select the run name to move to that channel. + +The digest is on by default. To turn it off, use the slash command `/playbook settings digest off`. + +## Playbook to do + +As you complete tasks and finish runs, you can update the details in the digest using the slash command `/playbook todo`. This slash command can be run in any channel, direct message, or group message. Once run, it delivers an updated digest which includes a list of active runs you belong to. diff --git a/docs/main/end-user-guide/workflow-automation/share-and-collaborate.mdx b/docs/main/end-user-guide/workflow-automation/share-and-collaborate.mdx new file mode 100644 index 000000000000..0a923e48fed3 --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/share-and-collaborate.mdx @@ -0,0 +1,137 @@ +--- +title: "Share and collaborate" +--- + + +There are different ways for teams to access and interact with collaborative playbooks. This is managed in the System Console using permissions. Permissions can be granted in a variety of ways, to allow for different combinations of access and visibility. + +Permissions are provided using: + +- **System Scheme:** Applies permissions universally across all teams, channels, and playbooks. +- **Team Override Schemes:** Allow admins to customize permissions for each team. + +For more information about System and Team Override Schemes, refer to the [Advanced Permissions](/administration-guide/onboard/advanced-permissions) documentation. + + + +Some permissions functionality is only available to Mattermost Enterprise customers. For more information, visit [https://mattermost.com/pricing](https://mattermost.com/pricing). + + + +In the context of collaborative playbooks, members are assigned a role and based on the selected permissions, this determines how they interact with playbooks. A member can be a member of one playbook, and an admin of another. This allows for granular permissions across teams and departments. For example, setting playbook visibility so only certain teams can view it, or setting permissions to allow an organization to view a playbook but only designated team members can make edits. + +Permissions are applied only to playbooks. There are no permissions that are specific to runs. + + + +From Playbooks v2.6.0, channel checklists use [channel-based permissions](/administration-guide/manage/team-channel-members) rather than playbook-specific permissions. This means that users with appropriate channel permissions can create, manage, and interact with checklists directly within channels without requiring separate playbook access permissions. + + + +## Playbook roles + +- **Member**: In the context of collaborative playbooks, members are users of Mattermost who are added to a playbook. +- **Playbook Admin**: Playbook Admins are also members, and may have elevated permissions to change playbook and run visibility as well as functional settings. They do not have access to the System Console and their privileges are managed by the system admin. Members need to be promoted to the role from within playbooks. The Playbook Admin role is applied per playbook. + + + +Before you make system or team changes to permissions, ensure that you don't lose access to your existing playbooks. Navigate to the playbook you're a member of. Select the **Manage Access** icon and change your role from **Member** to **Admin**. + + + +## Playbooks permissions + +Default playbooks settings are completely open which enable all members to participate in runs, edit playbooks, view runs and playbooks, remove other members from runs, edit actions, and make other changes. Permissions provide better control over confidential runs and playbooks, as well as member management. Note that even with the default settings, private playbooks restrict these actions to members of the playbook. + +### Create read-only playbooks + +In the following example, only playbook admins can edit playbooks. Other users can view public playbooks and private playbooks of which they are a member, but can't edit any playbook or change playbook memberships. + +1. Go to **System Console \> User Management \> Permissions**. +2. In the **All Members** section, uncheck **Manage Public Playbooks** and uncheck **Manage Private Playbooks**. +3. Scroll down to the **Playbook Admin** section and confirm that **Manage Public Playbooks** and **Manage Private Playbooks** are checked. +4. Select **Save**. + +## Restrict who can create playbooks + +You can also set permissions for read-only playbooks that do allow members to create new public or private playbooks. + +1. Go to **System Console \> User Management \> Permissions**. +2. In the **All Members** section, uncheck **Manage Public Playbooks** and uncheck **Manage Private Playbooks**. +3. Then, check **Create Public Playbook** and **Create Private Playbook**. +4. Select **Save**. + +### I want to restrict who can convert playbooks from public to private + +You can control whether Members can convert playbooks from public to private. + +1. Go to **System Console \> User Management \> Permissions**. +2. In the **All Members** section, check **Convert Playbooks**. +3. Select **Save**. + +Alternatively, to restrict this action so only Playbook Admins can convert playbooks from public to private, uncheck the setting above and: + +1. Go to **System Console \> User Management \> Permissions**. +2. Scroll down to **Playbook Admin**. +3. Check **Convert Playbooks**. +4. Select **Save**. + +### I want to control who starts a run + +By default, all Members can start a run using a playbook. You can restrict this so that only Playbook Admins can start a run. Note that with this configuration, Members are not able to start runs or edit playbooks. + +1. Go to **System Console \> User Management \> Permissions**. +2. In the **All Members** section, uncheck **Manage Runs**. This also unchecks **Create Runs**. +3. Scroll down to **Playbook Admin** and ensure that **Manage Runs** is checked. +4. Select **Save**. + +If you want to continue to allow Members to edit playbooks, an alternative to this configuration is to make the playbook private. + +## Duplicate a playbook + +Playbooks are repeatable workflows and sometimes it’s easier to copy and improve rather than start from scratch. + +You can do this by duplicating a playbook in the Playbooks screen. Select the **...** under **Actions** and then select **Duplicate**. The copied playbook will have **Copy of** appended to its original name which you can edit. + +To import a playbook, go to the Playbooks screen, and select **Import**. Choose the team you’re importing to, then select the JSON file. You can also export any playbook to JSON to easily share with other Mattermost servers. + +## Archive a playbook + + + +To archive a playbook, you must be a member of the playbook or playbook admin and have applicable **Manage Playbook Configurations** permission granted by a system administrator. + + + +To archive a playbook: + +1. Go to the **Product** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. icon and select **Playbooks**. +2. Select **View all...** under the **Playbooks** section in the left menu. +3. Select the **...** in the **Actions** column for the playbook you would like to archive. +4. Select the **Archive** menu option then the **Archive** button to confirm you would like to archive the playbook. + +![Archive a playbook](/images/archive-a-playbook.gif) + +## Restore an archived playbook + + + +To restore an archived playbook, you must have applicable **Manage Playbook Configurations** permission granted by a system administrator. + + + +To restore an archived playbook: + +1. Go to the **Product** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. icon and select **Playbooks**. +2. Select **View all...** under the **Playbooks** section in the left menu. +3. Verify the **With archived** checkbox next to the playbook search bar is selected. +4. Select the **...** in the **Actions** column for the playbook you would like to restore. +5. Select the **Restore** menu option then the **Restore** button to confirm you would like to restore the playbook. + +![Restore an archived playbook](/images/restore-an-archived-playbook.gif) + +## Export channel data + + + +See the [export channel data](/administration-guide/comply/export-mattermost-channel-data) documentation for details on working with channel export functionality. diff --git a/docs/main/end-user-guide/workflow-automation/work-with-playbooks.mdx b/docs/main/end-user-guide/workflow-automation/work-with-playbooks.mdx new file mode 100644 index 000000000000..1a0d39c105ae --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/work-with-playbooks.mdx @@ -0,0 +1,205 @@ +--- +title: "Work with collaborative playbooks" +--- + + +A collaborative playbook is a checklist of the tasks that make up your processes. Collaborative playbooks allow you to take codified knowledge and processes and make them accessible and editable by your organization and team. When you're setting up your playbook, you'll be able to break tasks down, and assign actions to them - such as using a slash command to start a Zoom call. You can also decide whether to use the same channel every time your playbook is run, or a new one. + +There are other parts of a playbook, such as automation settings, and metrics. Playbook configuration applies both to the execution of the playbook as well as to its management and improvement. + +But the very first thing you’ll want to set up is a checklist. + +Each time you use the process you’ve documented, such as onboarding a new customer, the playbook is used to start a run - a discrete single use of the process - and that run is captured in a channel (either a dedicated one or a new one every time you run the playbook). + +Setting up a playbook includes configuring how the playbook manages the creation of its channel as well as how stakeholders are notified. + +To open a playbook and view its statistics, select the playbook name. To begin a run using a specific playbook, select **Run** beside that playbook’s name. + +## Templates + +Creating a playbook from scratch can be daunting, even if you have the process mapped out. One way to get started quickly is to use one of the pre-configured templates available. These templates are populated with content and settings to provide guidance and are customizable. + +Playbook templates are basic workflows that you can use to get started quickly. As you learn more about your workflows, you can customize them into specific playbooks. + +### Choose a template + +The first step is to choose the right template for your use case. There are pre-configured templates for specific scenarios. The checklists, actions, status updates, and retrospective settings for these templates may already be filled in and, where appropriate, enabled. You can always edit and adjust these settings - they're there to guide you - removing them doesn't negatively affect the playbook run. + + + +Take a look at the **Learn how to use playbooks** template. This template breaks down the components of a playbook and you can also start a test run to see how everything fits together. If you're taking this option, you can stop reading here and enjoy the test run. You can also choose a blank template and start from scratch - this is a good option if your use case is unique. + + + +In the incident response template, the template contains items that are relevant to incident resolution. These are general items to help you get started. + +## Edit a playbook + +You can change a playbook’s configuration at any time, but changes will only be applied to future incidents. Ongoing or ended incidents previously started from that playbook remain unchanged. + +1. Go to **Product menu \> Playbooks**. +2. Find the playbook you want to edit. + - Only public playbooks and private playbooks that you're a member of are listed. System admins have unrestricted access to all playbooks on the team. +3. Select the name of the playbook. + - To edit the playbook directly select the actions menu next to the playbook name, then select **Edit**. + - To access the playbook dashboard, select the hyperlinked playbook name. +4. Select the **Outline** tab. +5. Edit the text portions of the playbook inline. Use the left-hand menu to navigate to other parts of the playbook that you may want to edit. + +## Make checklists + +Checklists in a playbook or run are restricted to playbook participants and owners. + +To create a checklist in a playbook, go to the **Tasks** section. Start from templated tasks or create your own. Select **Add a task** or **Add a section** to build out checklists in the playbook. Drag and drop to reorder tasks and sections as needed. Task descriptions support a limited form of Markdown, including text styling and hyperlinks. + +Playbook tasks consist of text rendered in Markdown (when present). You can't run commands directly from a task in a playbook, but you can trigger [built-in slash commands](/integrations-guide/built-in-slash-commands) and [custom slash commands](https://developers.mattermost.com/integrate/slash-commands/custom/), or outgoing webhooks, to run as part of the task action by starting the task with `/`. + +### Channel checklists + +From Playbooks v2.6.0, you can additionally create and manage channel-based checklists directly within [public](/end-user-guide/collaborate/channel-types#public-channels) and [private](/end-user-guide/collaborate/channel-types#private-channels) channels without requiring a playbook template or a run. Channel checklists use existing Mattermost channel permissions to control access, so any channel member who can manage channel names, headers, and purpose can create, edit, and manage channel checklists. + +To create a new channel checklist or modify an existing checklist, select the **Checklists** option in the top left corner of the Mattermost interface. + + + +- Channel checklists aren't available in [direct messages](/end-user-guide/collaborate/channel-types#direct-message-channels) or [group messages](/end-user-guide/collaborate/channel-types#group-message-channels). +- To create a channel checklist, you must be a channel [Member](/end-user-guide/collaborate/learn-about-roles#member) (not a [Guest](/end-user-guide/collaborate/learn-about-roles#guest)). To edit a channel checklist, any channel member who can post to the channel can do so, including guests. +- Channel checklists in [archived](/end-user-guide/collaborate/channel-types#archived-channels) channels can't be modified. Archived channels must be [unarchived](/end-user-guide/collaborate/archive-unarchive-channels#unarchive-a-channel) to access and edit their channel checklists. +- A single channel can contain both playbook runs and channel checklists. +- When using Mattermost in a web browser or the Desktop app, you can convert a channel checklist into a playbook by selecting the checklist name and then selecting **Save as a Playbook**. + + + +## Multiple runs in a channel + +From Mattermost v7.7, you can choose to start each run in a new channel or re-use an already existing channel. + +Here are some scenarios why you might want to start each run in the same channel: + +- Short, frequently-used processes benefit from being in the same channel - it keeps the process streamlined. +- Teams with multiple independent workflows, such as release teams, benefit from having them in one place. +- Cutting down on the number of new channels created makes it easier to find run channels again. +- The run name isn't linked to the channel's name so you can tell multiple workflows apart. + +When you're configuring your playbook: + +- You can link it to an existing channel so that each run starts in that channel. +- You can choose that each time the playbook is run, it creates a new channel. + +To access this setting, open the **Playbooks** tab. Select the playbook you want to edit, then select the **Outline** tab. Select **Actions** in the left-hand menu and make your selection under the **When a run starts** heading. + +When you start a run, your selection is the default but can be changed for each run. Additionally, it's also possible to move a started run to another channel, so you're not locked into whichever option you select. + +## Status updates + +There may be multiple active runs on any given day. + +Configuring an update cadence is an easy way to centralize status updates, decrease noise, and remember where everything is. You can do this when you're setting up your playbook. Navigate to the **Usage** section and set the parameters based on expected update cycles and where the updates should be published. + +## Keywords + +You can use keywords to trigger a playbook. Keywords are set in the **Channel Actions** menu and are applicable to a specific channel. When you use the Keywords action any channel member who has access to the playbook and who uses one of the listed keywords will be prompted to run the associated playbook. + +If you find your keywords result in too many false positives, consider refining your list and also consider that URLs used by run members may also contain monitored keywords. + +## Actions + +You can customize actions associated with your playbook to ensure a smooth start when starting a run. Select the **Actions** tab to view the automation options available. + +Options include: + +- Create a channel when a run is started +- Invite members to the run +- Send outgoing webhooks +- Automatically add the run channel to a sidebar category + +Actions such as channel creation and adding the channel to a sidebar category are set per-playbook and applied to each run that uses that playbook. + +If you’re a system admin or channel admin of the run channel you can also edit these settings in the run channel, via the channel menu, in **Channel Actions**. Editing the settings in the run channel will only affect that channel and the changes aren’t applied to the playbook. Only channel admins can edit the **Channel Actions** items (such as the welcome message) but members who have access to the playbook can edit the welcome message and run behavior settings. Editing these won’t change the welcome message of a run that’s in progress - it only applies going forward. If you want to change the behavior of all future runs associated with the playbook, edit the playbook directly in the **Actions** menu. + +## Playbook attributes + + + +From Mattermost v11.1, using Mattermost in a web browser or the desktop app, you can define custom attributes for your playbooks to create adaptive workflows that respond to changing mission or operational context. From Mattermost mobile v2.37.0, you can view and edit playbook run attributes on mobile devices, including text fields, select, and multi-select types. Attributes such as severity, category, or linked ticket ID can be configured to trigger context-aware tasks and enable intelligent adaptation to situational conditions. + + + +This feature requires Mattermost Playbook v2.5.0 or later. + + + +Attributes enable you to: + +- Define contextual information that varies between runs (e.g., incident severity, priority level, customer type). +- Trigger different tasks or workflows based on attribute values. +- Create conditional logic in your playbooks for more sophisticated automation. +- Maintain consistent data collection across runs. + +Playbook attributes are visible to all run participants and can be referenced in status updates. + + + +When viewing and editing playbook run attributes on mobile devices, color formatting and URL links in attributes are not supported and display as plain text. + + + +### Configure attributes + +To configure attributes: + +1. Go to the **Product** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. icon and select **Playbooks**. + +2. Select the playbook you want to define attributes for. + +3. Select the **Attributes** tab. + +4. Select **Add your first attribute**. + + ![An example of the Playbooks Attributes tab with no attributes defined.](/images/playbook-attributes-create-first.png) + +5. Enter an attribute name and specify its type as **Text**, **URL**, **Select**, or **Multi-Select**. + +6. For **Select** and **Multi-Select** types, define the available values. + +7. Select **Add attribute** to add additional attributes and values. + + ![An example of the Playbooks Attributes tab with one attribute and multiple values defined.](/images/playbook-attributes-create-second.png) + + + +- Control how attribute-based conditions appear in a playbook outline by dragging and dropping them into your preferred order. +- Use the **Actions** menu to rename, duplicate, or delete attributes. + +![An example of the Playbooks Attributes tab with the Actions menu open.](/images/playbook-attribute-actions.png) + + + +## Conditional playbooks + + + +From Mattermost v11.1, using Mattermost in a web browser or the desktop app, you can create conditional playbooks with more sophisticated workflows that respond intelligently to changing circumstances. From Mattermost mobile v2.37.0, you can also view and edit playbook run attributes on mobile devices. By leveraging playbook attributes, you can define conditions that determine which tasks and checklists are included in a playbook run based on real-time data. + +Conditional playbooks enable you to: + +- Add tasks that only apply when specific conditions are met. +- Define tasks and checklists that change based on attribute values. +- Create adaptive workflows that change based on real-time data. + +See the [conditional tasks](/end-user-guide/workflow-automation/work-with-tasks#conditional-tasks) documentation for details on configuring conditional tasks within playbooks. + +## Run metrics + +The **Usage** tab in the workflow dashboard provides run metrics for that playbook. These metrics are available to all viewers. It's not possible to edit or add to these metrics. + +## Webhooks + +- For information about the webhook payload for `run start`, see the [PlaybookRunWebhookPayload](https://github.com/mattermost/mattermost-plugin-playbooks/blob/b4c8058d8660efe35050bc7eb080e3819c7ab09c/server/app/playbook_run_service.go#L176-L185) struct. An example of the JSON payload for a run start [is available](https://gist.github.com/icelander/b68f2bf2b4ffefec93400cb050211cf1). +- For information about the webhook payload for `status update`, see the [PlaybookRunWebhookPayload](https://github.com/mattermost/mattermost-plugin-playbooks/blob/b4c8058d8660efe35050bc7eb080e3819c7ab09c/server/app/playbook_run_service.go#L176-L185) struct. An example JSON payload for a status update [is available](https://gist.github.com/icelander/2f9938ad68d1e0aa656f97969895d080). + + + +Watch this [on-demand webinar on securing your mission-critical work](https://mattermost.com/webinar/cybersecurity-incident-response/) to learn about the key features and functionality to look for in your incident response tooling. + + diff --git a/docs/main/end-user-guide/workflow-automation/work-with-runs.mdx b/docs/main/end-user-guide/workflow-automation/work-with-runs.mdx new file mode 100644 index 000000000000..0170fd42d1c8 --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/work-with-runs.mdx @@ -0,0 +1,47 @@ +--- +title: "Work with runs" +--- + + +A run is the execution of a collaborative playbook. You can start each run in a new channel or you can elect to use the same channel for multiple runs. + +To access runs, select the product menu in the top-left corner of Mattermost, then select **Playbooks**. In the runs list, you can select a run to view more details, such as the overview and retrospective. This is an easy way to assess all the active runs to which you have access. + +## Follow and participate + +You don't have to be in a run's channel to follow the run. You can: + +- **Follow**: If you're following a playbook, you won't necessarily be added to each of the playbook's runs but you will be added as a follower. To join a run channel, select **Participate** in the header of that run. +- **Participate**: If you're participating in a run it's likely because you're in a team or group of people who've been added to it. In this case, you'll be able to follow the run in the run channel and also view the details in the list of runs in the **Playbooks** tab. + +## View run details + +When you’re in a channel with an active run, select the **Toggle Run Details** icon in the channel header to open the right-hand pane to view the run details. Information such as run name and description can be edited in-line, and the checklists can be collapsed and filtered based on their status. + +Some run actions can be edited while the run is in progress. This increases visibility into the run's progress and can improve accountability. + +## Playbook runs on mobile + +From Mattermost server v11.0 and mobile app v2.34.0, mobile users can create and manage playbook runs for operational command at the edge. + +## Runs and channel behavior + +When you configure your playbook, you can decide whether each run of that playbook starts in a new channel or uses the same channel. You can run multiple playbooks in the same channel, simultaneously. Each playbook in use is listed in the RHS of the run channel. + +If you decide to run a playbook in a new channel, you can do this when you start the run. In the channel RHS, select **Start run**. Then select how you'd like it to be executed. + + + +- When deciding whether to reuse a channel for multiple runs, or create new channels for each playbook run, multiple runs in a single channel can help avoid too many channels being created, which can lead to channel overload. +- Playbook run channels aren't automatically archived when runs are marked as complete; however, you can [archive channels](/end-user-guide/collaborate/archive-unarchive-channels#archive-a-channel) you no longer need, and system admins can [allow user access to archived channels](/administration-guide/configure/site-configuration-settings#allow-users-to-view-archived-channels) if needed. See the [multiple runs in a channel](/end-user-guide/workflow-automation/work-with-playbooks#multiple-runs-in-a-channel) documentation for additional considerations. +- In contrast, using a dedicated channel for each playbook run can be helpful particularly in cases where strict [compliance](/administration-guide/comply/compliance-export) and [channel data export](/administration-guide/comply/export-mattermost-channel-data) is required. + + + +## Send outgoing webhooks + +1. In your run, select **Toggle Run Details** to open the right-hand sidebar. +2. Select **Run details**. +3. In the **Run details** page, scroll down to **Actions**. +4. Add your webhook URLs in the field provided. You can turn off this option using the toggle. +5. Select **Save**. diff --git a/docs/main/end-user-guide/workflow-automation/work-with-tasks.mdx b/docs/main/end-user-guide/workflow-automation/work-with-tasks.mdx new file mode 100644 index 000000000000..e447922e4a0f --- /dev/null +++ b/docs/main/end-user-guide/workflow-automation/work-with-tasks.mdx @@ -0,0 +1,102 @@ +--- +title: "Work with tasks" +--- + + +## Tasks and due dates + +In some workflows, there are time constraints on tasks and others may have more flexible timeframes. Associating tasks with deliverable dates provides visibility into workloads and helps everyone stay accountable during the run. + +To assign a due date to a task, select the **Toggle Run Details** icon to open the **Run Details** screen. Hover over the task you’d like to edit and select the calendar icon to assign a due date. Due dates can be used to sort tasks in the run overview. + +When a due date is assigned to a task, and the task is overdue or due today, a reminder is added to the playbook's daily digest along with tasks that don't have an assigned due date. As tasks are completed, they're removed from the daily digest reminders. You can refresh the list of assigned tasks at any time using the `/playbook todo` slash command. + +Due dates can be entered in text (e.g., "two minutes ago") or numerically (e.g., "15 March 2023"). + +## Task actions + +You can automatically complete tasks in a playbook run using keyword triggers. When the keywords you've entered are mentioned in the run, the task is marked as completed. + +For this feature, you should use a string of text rather than individual words. The search is an `ANY` search, meaning that if you used the individual words "target" and "completed", either of those words will trigger the action to be marked as complete. If you're using phrases that have formatting, make sure you use the Markdown formatting in the text field. + +When you edit a task, you'll see the following: + +- The text to search for in the messages +- Ability to limit this for posts from a specific user (or bot) +- Option to mark the task as done (or not). + +![Configure tasks to be automatically marked as complete.](/images/task-actions.png) + +## Conditional tasks + + + +From Mattermost v11.1, using Mattermost in a web browser or the desktop app, tasks can be conditionally included in playbooks based on attribute values or runtime conditions. This enables adaptive workflows where tasks are only presented when they're relevant to the current context. For example: + +- **Security incidents**: Include additional forensic tasks for incidents classified as security-related. +- **Customer tier workflows**: Show different approval processes based on customer subscription level. +- **Geographic operations**: Include region-specific compliance tasks based on the location property. +- **Skill-based assignments**: Automatically assign tasks to team members based on areas of expertise. + +### Configure conditional logic + +To set up conditional behavior in a playbook: + +1. Go to **Product** Navigate between Channels, collaborative playbooks, and boards using the product menu icon. icon and select **Playbooks**. + +2. Select the playbook or run you want to add conditions to. + +3. Select the **Outline** tab. + +4. Under **Tasks**, identify a task you want to make conditional. + +5. From the **More** Use the More icon in the top left corner to access Mattermost desktop apps customization settings. icon next to the task, select **Add condition**. + + ![An example of a playbook condition being added.](/images/playbook-conditions-add.png) + +6. Select an attribute, condition, and value to define when the task should be included. Then select **Done editing**. + + ![An example of a playbook condition with values defined.](/images/playbook-conditions-values.png) + +Conditional tasks are evaluated and automatically added to or removed from the checklist based on defined conditions. This reduces cognitive load by showing only relevant tasks and ensures that critical steps aren't overlooked in different scenarios. + + + +You can add up to 2 conditions per task to create an either/or condition. + + + +## Task inbox + +In addition to the daily digest, you also have access to a task inbox. The task inbox provides you with a cross-run overview of the tasks you're accountable for, sorted by due date. + +You can: + +- Access each task directly, without having to visit the individual runs. +- Mark tasks as complete or skip them. +- Change the task assignee from yourself to another team member. The task will then be removed from your inbox. +- You can change the due date of tasks to manage priorities and urgency. + +To view your task inbox, access the **Playbooks** tab in Mattermost. In the header, next to your profile image, select the tasks list icon. A list of every task assigned to you from every run that's in progress is displayed. + +## Mobile playbooks task management + +From Mattermost v11.0 and mobile v2.32.0, mobile users can perform the following task management operations on playbook runs: + +### Interact with playbook tasks + +- **Task interaction**: Tap on any task to open a detailed bottom sheet view with task options and information. +- **Check/Uncheck tasks**: Complete or reopen tasks directly from the Mattermost mobile app. +- **Skip/Unskip tasks**: Mark tasks as skipped or return them to active status as workflow requirements change. + +### Update tasks + +- **Update assignee**: Change who is responsible for completing a task directly from the mobile app. +- **Modify due dates**: Adjust task deadlines to accommodate changing priorities and schedules. +- **Edit task commands**: Update slash commands or instructions associated with tasks. +- **Change run ownership**: Transfer run ownership between team members. +- **Rename tasks**: Update a task's name to reflect evolving scope or priorities. (From Mattermost mobile v2.38.0) +- **Add or edit task descriptions**: Add context to a task or update an existing description. (From Mattermost mobile v2.38.0) +- **Delete a task**: This action cannot be undone. (From Mattermost mobile v2.37.0) + +These mobile capabilities provide full task management functionality for teams working with playbooks while on mobile devices, complementing your existing desktop and web browser experiences. diff --git a/docs/main/for/administrator.mdx b/docs/main/for/administrator.mdx new file mode 100644 index 000000000000..68e036bf95d2 --- /dev/null +++ b/docs/main/for/administrator.mdx @@ -0,0 +1,39 @@ +--- +title: "For Administrators" +description: "Start here if you configure and operate Mattermost for your organization." +slug: /for/administrator +hide_table_of_contents: true +--- + +Persona landing + +# For Administrators + +You're the workspace or system admin who owns the day-to-day operation of one or more Mattermost workspaces. This page is a curated entry point — every link goes to the canonical guide. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/air-gapped-operator.mdx b/docs/main/for/air-gapped-operator.mdx new file mode 100644 index 000000000000..6af4902b4484 --- /dev/null +++ b/docs/main/for/air-gapped-operator.mdx @@ -0,0 +1,43 @@ +--- +title: "For Air-Gapped Operators" +description: "Start here if you deploy and operate Mattermost in network-isolated enclaves." +slug: /for/air-gapped-operator +hide_table_of_contents: true +--- + +Persona landing + +# For Air-Gapped Operators + +You deploy and operate Mattermost in network-isolated enclaves — air-gapped classified networks, sovereign-cloud enclaves, DoD IL4/IL5 environments, or tactical edges with DDIL connectivity. This page is a curated entry point — every link goes to the canonical guide. + +:::important No internet egress +Every page linked from here works without internet access. Stage artifacts on an operator workstation, transfer across your approved boundary, and operate offline. +::: + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/compliance-officer.mdx b/docs/main/for/compliance-officer.mdx new file mode 100644 index 000000000000..173234bef96d --- /dev/null +++ b/docs/main/for/compliance-officer.mdx @@ -0,0 +1,39 @@ +--- +title: "For Compliance Officers" +description: "Start here if you collect audit evidence, respond to audits, and map regulatory mandates to Mattermost configuration." +slug: /for/compliance-officer +hide_table_of_contents: true +--- + +Persona landing + +# For Compliance Officers and Auditors + +You collect audit evidence, respond to audits, and map regulatory mandates to Mattermost configuration. You need step-by-step runbooks for exports + eDiscovery + Legal Hold, plus regulatory framework mappings. This page is a curated entry point — every link goes to the canonical guide. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/developer.mdx b/docs/main/for/developer.mdx new file mode 100644 index 000000000000..57446ce00ae4 --- /dev/null +++ b/docs/main/for/developer.mdx @@ -0,0 +1,39 @@ +--- +title: "For Developers and Integrators" +description: "Start here if you build plugins, use the REST API, or integrate Mattermost with other systems." +slug: /for/developer +hide_table_of_contents: true +--- + +Persona landing + +# For Developers and Integrators + +You build plugins, hit the REST API, or integrate Mattermost with other systems. This page is a curated entry point — the bulk of the canonical content lives in the Developers tab and the API reference. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/end-user.mdx b/docs/main/for/end-user.mdx new file mode 100644 index 000000000000..d6cb916369aa --- /dev/null +++ b/docs/main/for/end-user.mdx @@ -0,0 +1,39 @@ +--- +title: "For End Users" +description: "Start here if you use Mattermost day to day." +slug: /for/end-user +hide_table_of_contents: true +--- + +Persona landing + +# For End Users + +You use Mattermost day-to-day to message, collaborate, and get work done. This page is a curated entry point — every link goes to the canonical guide. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/security-architect.mdx b/docs/main/for/security-architect.mdx new file mode 100644 index 000000000000..5b3b02fed70d --- /dev/null +++ b/docs/main/for/security-architect.mdx @@ -0,0 +1,39 @@ +--- +title: "For Security Architects" +description: "Start here if you evaluate Mattermost for regulated, classified, or DISC environments." +slug: /for/security-architect +hide_table_of_contents: true +--- + +Persona landing + +# For Security Architects and Accreditors + +You evaluate Mattermost for use in regulated, classified, or DISC (Defense, Intelligence, Security, Critical Infrastructure) environments. You write SSPs, POA&Ms, and authorization memos. You need citable specifics: CMVP certificates, NIST control mappings, attestation status, audit log schemas. This page is a curated entry point — every link goes to the canonical guide. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/for/sre.mdx b/docs/main/for/sre.mdx new file mode 100644 index 000000000000..57c44e9455c5 --- /dev/null +++ b/docs/main/for/sre.mdx @@ -0,0 +1,39 @@ +--- +title: "For SREs and Platform Operators" +description: "Start here if you own deploy, scale, observability, and disaster recovery for Mattermost." +slug: /for/sre +hide_table_of_contents: true +--- + +Persona landing + +# For SREs and Platform Operators + +You own Mattermost's deployment, scaling, and operations. This page is a curated entry point — every link goes to the canonical guide. + +## Start here + + + +## Common tasks + + + +## Other personas + + diff --git a/docs/main/get-help/community-chat.mdx b/docs/main/get-help/community-chat.mdx new file mode 100644 index 000000000000..b359f21d1a59 --- /dev/null +++ b/docs/main/get-help/community-chat.mdx @@ -0,0 +1,41 @@ +--- +title: "Join our community" +--- +Connect with thousands of contributors, customers, partners, and users to build, share, and learn together at [community.mattermost.com](https://community.mattermost.com). This server is our virtual office and is open to everyone. Please review our [Code of Conduct](https://handbook.mattermost.com/contributors/contributors/guidelines/contribution-guidelines) before participating. + +## General channels + +- [Contributors](https://community.mattermost.com/core/channels/tickets) +- [Community Team](https://community.mattermost.com/core/channels/community-team) +- [Developers](https://community.mattermost.com/core/channels/developers) +- [New Channel Notifications](https://community.mattermost.com/core/channels/new-channel-notifications) +- [Off-Topic](https://community.mattermost.com/core/channels/off-topic-pub) +- [Reception](https://community.mattermost.com/core/channels/town-square) + +## Technical support channels + +To familiarize yourself with our community support process, start by reading the [Get Help](/get-help/get-help-index) documentation page. + +- [Ask Anything](https://community.mattermost.com/core/channels/ask-anything) +- [Bugs](https://community.mattermost.com/core/channels/bugs) +- [Peer-to-peer Help](https://community.mattermost.com/core/channels/peer-to-peer-help) + +We also recommend using the [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) for technical support. + +## Contributor community channels + +To familiarize yourself with our community contribution process, start by exploring the [Contribute to Mattermost](https://mattermost.com/contribute/) documentation. + +- [AI Exchange](https://community.mattermost.com/core/channels/ai-exchange) +- [Developers: Meeting](https://community.mattermost.com/core/channels/developers-meeting) +- [DWG: Documentation Working Group](https://community.mattermost.com/core/channels/dwg-documentation-working-group) +- [Feature Proposals](https://community.mattermost.com/core/channels/feature-ideas) +- [i18n - Localization](https://community.mattermost.com/core/channels/localization) +- [Open Source Fridays (OSF)](https://community.mattermost.com/core/channels/open-source-fridays) +- [Public Speakers](https://community.mattermost.com/core/channels/public-speakers) +- [QA: Contributors](https://community.mattermost.com/core/channels/qa-contributors) +- [Thank you!](https://community.mattermost.com/core/channels/thank-you) + +There are many channels that specialize in different areas of the Mattermost platform. To find and join them, search “**Developers:**” in the [LHS](https://handbook.mattermost.com/company/about-mattermost/list-of-terms#lhs) “🔍 Find channel” search bar on the community server. + +We hold a public developer community meeting every Wednesday at 8:30 AM Palo Alto time. ☎️ The meeting is held via an audio call in [Developers: Meeting](https://community.mattermost.com/core/channels/developers-meeting) and everyone is welcome. This weekly meeting is a great opportunity to ask questions about the project and get involved. diff --git a/docs/main/get-help/community-for-mattermost.mdx b/docs/main/get-help/community-for-mattermost.mdx new file mode 100644 index 000000000000..23c393728b73 --- /dev/null +++ b/docs/main/get-help/community-for-mattermost.mdx @@ -0,0 +1,72 @@ +--- +title: "Community for Mattermost" +--- + + +Join the [Mattermost Community server](https://community.mattermost.com/) directly from your Microsoft 365, Microsoft Outlook, or Microsoft Teams instance! + +Use the Mattermost for Microsoft Teams integration to stay connected with thousands of users, contributors, and Mattermost staff directly from the tools you use every day. Join thousands of Mattermost users, contributors, and staff members in a vibrant community where you can ask questions, get support, share ideas, and contribute to shaping the future of Mattermost. + +![Community for Mattermost is available in the Microsoft App Store.](/images/mattermost-for-microsoft_365.png) + +This app is designed to work with Microsoft 365, Outlook, and Teams. A free Mattermost account is required to access the Mattermost Community server. + +## Setup + +### Admin setup + +A Microsoft Teams administrator must make the Community for Mattermost app available to all users. + +1. Go to the Microsoft Teams Admin Center. +2. Select **Teams Apps \> Manage Apps**. +3. Search for **Community for Mattermost** and select it. +4. Under the **Users and Groups** tab, enable the app for all users. + +### End user setup + +Once enabled for all, any Microsoft 365 user can complete the steps below to access the Community for Mattermost app within their Microsoft environment: + +1. Sign in to your Microsoft Teams account from a [web browser](https://teams.microsoft.com/v2/?clientexperience=t2) or the desktop application. +2. Select the **\[+\] Apps** button in the Teams sidebar. +3. Search for **Mattermost for Microsoft 365** and then select **Add** to install the application. +4. (Optional) Pin the Mattermost app to your Teams sidebar by right-clicking on it and selecting **Pin**. +5. Once the Mattermost app is installed, you'll be connected to the public Mattermost Community instance. + +## Getting started + +Once you've installed the app, here are some ways to get started: + +- **Ask questions**: Use the [~ask-anything](https://community.mattermost.com/core/channels/ask-anything) channel in Mattermost to ask technical questions or get support from the community. +- **Stay informed**: Follow the [~release-announcements](https://community.mattermost.com/core/channels/release-announcements) channel to keep up with the latest news about upcoming releases and updates from the Mattermost team. +- **Contribute**: If you're interested in contributing to Mattermost, join the [~developers](https://community.mattermost.com/core/channels/developers) channel to connect with other contributors. +- **Share feedback**: Your Mattermost ideas and feedback are valuable! Share your thoughts in the [~user-feedback](https://community.mattermost.com/core/channels/user-feedback) channel. + +## Key features + +- **Direct Access**: Access the Community for Mattermost app directly from a tab without switching applications or opening a browser. +- **Seamless Integration**: Experience the full functionality of Community for Mattermost within a familiar interface. +- **Real-time Collaboration**: Engage with the Mattermost community in real-time discussions on product features, technical questions, and best practices. +- **Product Support**: Get help from both Mattermost staff and experienced community members. +- **Contribute to Development**: Participate in discussions that shape the future direction of Mattermost products. +- **Knowledge Sharing**: Learn implementation strategies and best practices from a diverse community of users. +- **Stay Updated**: Keep up with the latest Mattermost announcements, updates, and roadmap information. + +## Benefits + +- Seamlessly communicate with the Mattermost community using application tabs. +- Evaluate a showcase deployment of Mattermost capabilities in consideration of self-hosting the platform within your Azure or on-prem environments. +- Share input with Mattermost staff and developers on future improvements to the platform. + +## FAQ + +### Where can I get support for the Mattermost for Microsoft 365 app? + +You can browse existing open issues or submit a new issue for support [in GitHub](https://github.com/mattermost/mattermost-teams-tab/issues). + +### Do I need a Mattermost account to use this application? + +Yes, you'll need to create a free Mattermost account on the Mattermost Community server when you first access it through the app. + +### Can I use this app to connect to my organization's Mattermost server? + +No, this app is specifically designed to connect to the public Mattermost Community instance. If you're interested in connecting to your own Mattermost instance, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/). diff --git a/docs/main/get-help/contribute-to-documentation.mdx b/docs/main/get-help/contribute-to-documentation.mdx new file mode 100644 index 000000000000..3b747a095ed3 --- /dev/null +++ b/docs/main/get-help/contribute-to-documentation.mdx @@ -0,0 +1,69 @@ +--- +title: "Contribute to this documentation" +--- +Mattermost has a diverse community that extends well beyond code contributions. If you're interested in contributing to Mattermost, why not help improve the documentation? Be sure to join the documentation community in [DWG: Documentation Working Group](https://community.mattermost.com/core/channels/dwg-documentation-working-group) so we can support and celebrate you! + +## How to get started + +The fastest way to get started with a documentation contribution is to find something you want to change in the documentation. This might be a typo or broken link, or something more extensive like revising or expanding content. Once you've found a page you want to update, select the edit option Contribute to Mattermost documentation by selecting the Edit option located in the top right corner of any documentation page. located in the top right corner of that page. + +## First-time contributor? + +Start by exploring the [Contribute to Mattermost](https://mattermost.com/contribute/) documentation, specifically the ["You want to help with content"](https://developers.mattermost.com/contribute/why-contribute/#you-want-to-help-with-content) section. + +In a GitHub pull request, you can make changes as if you were editing code. If you're new to contributing to documentation using pull requests in GitHub, the following [video](https://www.youtube.com/watch?v=V8ROl9wiHr8) will help you get started: + +
+ +
+ +## Where to find more information + +Explore the README links below for details on building and previewing documentation locally for our different documentation repositories: + +- [Mattermost Product Documentation README](https://github.com/mattermost/docs#readme) +- [Mattermost Developer Documentation README](https://github.com/mattermost/mattermost-developer-documentation/blob/master/README.md) +- [Mattermost API Reference README](https://github.com/mattermost/mattermost/blob/master/api/README.md) +- [Mattermost Handbook README](https://github.com/mattermost/mattermost-handbook/blob/0.2.1/README.md) + +Thank you for your support! 💙 If you have any questions, reach out to us in [DWG: Documentation Working Group](https://community.mattermost.com/core/channels/dwg-documentation-working-group). + +## Frequently asked questions + +### How can I contribute to Mattermost? + +You can get involved and contribute to Mattermost in the following ways: + +- Join the [Developers](https://community.mattermost.com/core/channels/developers) channel on the Mattermost Community server to get troubleshooting help or provide help to others +- [Contribute code](https://developers.mattermost.com/contribute/why-contribute/#youre-looking-to-practice-your-skills-or-give-back-to-the-community) +- [Find "Help Wanted" projects](https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+org%3Amattermost+label%3A%22Help+Wanted%22++label%3A%22Up+For+Grabs%22&type=issues) +- [File bugs](https://developers.mattermost.com/contribute/why-contribute/#youve-found-a-bug) +- [Test new features](https://developers.mattermost.com/contribute/why-contribute/#you-want-to-help-test-new-features) +- [Share feature ideas](https://developers.mattermost.com/contribute/why-contribute/#you-have-a-feature-idea) +- [Contribute to content](https://developers.mattermost.com/contribute/why-contribute/#you-want-to-help-with-content) +- [Help translate Mattermost into other languages](https://developers.mattermost.com/contribute/why-contribute/#you-want-to-help-with-product-translation) +- [Make Mattermost more accessible](https://developers.mattermost.com/contribute/why-contribute/#you-want-to-make-something-more-inclusive-or-accessible) + +### Can contributors add themselves to the Mattermost company page on LinkedIn? + +Yes! If you have contributed to the Mattermost project we think you should be recognized for it professionally beyond GitHub. + +To add yourself to the [Mattermost page on LinkedIn](https://www.linkedin.com/company/mattermost/), do the following: + +1. Log in to [LinkedIn](https://www.linkedin.com/) or create an account. +2. Go to **Me \> View profile**. +3. Under **Experience**, select the **plus** symbol and specify the following: + +> - **Title**: +> - Enter **Developer** if you contributed code to the open source project or created a plugin, integration, or other enhancement. +> - Enter **Contributor** if you've contributed without writing code (e.g., filed bug report, answered troubleshooting questions, proposed a feature, etc.). +> - Enter **Translator** if you've [helped translate](https://translate.mattermost.com) Mattermost products. +> - Enter **QA Tester** if you tested Mattermost features or workflows. +> - Enter **Documentation** if you contributed to Mattermost product, repository, or developer documentation. +> - **Company**: Find **Mattermost** (you’ll see the Mattermost logo). +> - **Location**: Enter where you live. +> - **From**: Date of first contribution or perhaps month you cloned github.com/mattermost. +> - Select **I currently work here**. +> - **Update my industry**: Leave unchecked. +> - **Update my headline**: Leave unchecked. +> - **Description**: Leave blank or write a sentence about what you have contributed. diff --git a/docs/main/get-help/get-help-index.mdx b/docs/main/get-help/get-help-index.mdx new file mode 100644 index 000000000000..0150f3fc7af4 --- /dev/null +++ b/docs/main/get-help/get-help-index.mdx @@ -0,0 +1,55 @@ +--- +title: "Training and Support" +--- +Get the help you need with Mattermost via robust documentation, extensive community support, and professional support services. If you're struggling with something on your Mattermost journey, take a look at the following learning resources: + +## Training + +[Mattermost Academy](https://academy.mattermost.com/) - Get the most out of your Mattermost experience by enrolling in free online customer onboarding, end user, and administration courses for self-hosted deployments. + +## Documentation + +- [Mattermost product documentation](https://docs.mattermost.com/) - Read information for end users and administrators about deploying, managing, and using Mattermost. +- [Mattermost developer documentation](https://developers.mattermost.com/) - Read information for developer community members about integrating, extending, customizing, and contributing to Mattermost. +- [Mattermost API reference](https://api.mattermost.com/) - Read information for developer community members about the Mattermost API used by Mattermost clients and third-party applications. + +We welcome [community contributions to this documentation](/get-help/contribute-to-documentation). + +## Help Center + +Visit the [Mattermost Help Center](https://support.mattermost.com/hc/en-us) to access frequently asked questions and common troubleshooting tips. + +## Commercial Customer Support + +### Enterprise + +[Mattermost Enterprise](/product-overview/editions-and-offerings) support is available 24 x 7 at all times on all days through email and the [Mattermost online ticketing system](https://support.mattermost.com/hc/en-us/requests/new) with a 4 hour response time service-level target. For more information, please see [Mattermost Support Terms](https://mattermost.com/support-terms/). + +#### Premier + +Available as an additional purchase for Mattermost Enterprise customers, Mattermost Premier Support offers additional license entitlements for non-production environments, direct access to senior support team members, screen-sharing and audio calling for Priority 1 and Priority 2 tickets, and access to a private channel with Mattermost technical staff. For more information, please see [Mattermost Support Terms](https://mattermost.com/support-terms/). + +### Professional + +[Mattermost Professional](/product-overview/editions-and-offerings) support includes business hours support from 8am to 8pm United States Pacific Time (UTC-8 except for U.S. daylight savings time, with next business day response time via email and the Mattermost online ticketing system. For more information, please see [Mattermost Support Terms](https://mattermost.com/support-terms/). + +## Non-Commercial Support + +Community support for [Mattermost Free](/product-overview/editions-and-offerings) is available on the [peer-to-peer discussion forums](https://forum.mattermost.com/). + +Organizations using Mattermost Free to evaluate a future purchase of [Mattermost Enterprise](/product-overview/editions-and-offerings) can talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) to apply for early access to commercial support as part of the evaluation process. + +### Community server + +- [Mattermost Community server](https://community.mattermost.com) - Connect with thousands of contributors, customers, and users to build, share, and learn together. This server is our virtual office and is open to everyone. Learn more about the many [channels you can join](/get-help/community-chat) on the community server. + +Please review our [Code of Conduct](https://handbook.mattermost.com/contributors/contributors/guidelines/contribution-guidelines) before participating. + +### Mattermost user forums + +- [Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) - Join our community forum for peer-based technical support. Please review our [Code of Conduct](https://handbook.mattermost.com/contributors/contributors/guidelines/contribution-guidelines) before participating. + +## Feedback + +- [Report a bug](https://developers.mattermost.com/contribute/why-contribute/#youve-found-a-bug) - Report bugs or other issues you encounter when using Mattermost to our development team. +- [Propose a feature](https://portal.productboard.com/mattermost/33-what-matters-to-you) - Vote for feature proposals or submit your own. diff --git a/docs/main/index.mdx b/docs/main/index.mdx new file mode 100644 index 000000000000..002951521f41 --- /dev/null +++ b/docs/main/index.mdx @@ -0,0 +1,171 @@ +--- +slug: / +title: Mattermost Documentation +description: Mission-critical collaboration for defense, intelligence, security, and critical infrastructure. +sidebar_position: 1 +sidebar_label: Welcome +hide_table_of_contents: true +--- + +The secure, self-hosted collaboration platform for defense, intelligence, security, and critical infrastructure organizations. Documentation for operators, administrators, end users, developers, and the compliance team. + +## Find your starting point + + + +Or jump to one of the specialized personas: +[SREs / Platform Operators](/for/sre) · +[Compliance Officers](/for/compliance-officer) · +[Air-Gapped Operators](/for/air-gapped-operator) + +## The Intelligent Mission Environment (IME) + +Mattermost is an Intelligent Mission Environment (IME), purpose-built for mission-critical operations. It delivers a unified platform for secure, extensible, AI-powered collaboration and automation, deployable across the most demanding environments—from classified networks to the tactical edge. Organizations use Mattermost to maintain full control over communications, workflows, and infrastructure while accelerating decision-making. + +IME integrates secure messaging, workflow automation, task management, agentic AI, and real-time communication within a sovereign, cyber-resilient architecture. It supports extensibility through open APIs and integrations, and runs flexibly across on-premises, cloud, and air-gapped systems—enabling operational focus, adaptability, and resilience from edge nodes to centralized data centers. + + + +It is designed to meet the evolving needs of national security, defense, intelligence, cybersecurity, and critical infrastructure sectors for mission-critical workflows, including: + +- **Cyber Defense**: Secure, out-of-band communications and automation for Security Operation Center (SOC)/Computer Emergency Response Team (CERT) workflows. +- **DevSecOps**: Sovereign Continuous Integration Continuous delivery (CI/CD), Information technology service management (ITSM), and digital system management at scale. +- **Mission Operations**: Collaboration across command, control, manufacturing, energy, and joint operations. + +See the [Use Case Guide](/use-case-guide/use-cases-index) to learn how operational teams use Mattermost to accelerate mission-critical work across a wide variety of disciplines. + +## Secure collaborative workflow + +Built on an extensible open-core architecture, Mattermost offers an array of collaborative tools across [managed Windows, Mac, or Linux desktop applications](/deployment-guide/desktop/desktop-app-deployment), secure web browsers with or without internet access, bring your own device (BYOD) or [mobile device management (MDM)-managed mobile](/security-guide/mobile-security), and [embedded Microsoft 365](/integrations-guide/mattermost-mission-collaboration-for-m365) user experiences. + +### Messaging collaboration + +[Mattermost Channels](/end-user-guide/messaging-collaboration) enables secure, real-time and asynchronous communication across web, desktop, and mobile—powering mission-critical collaboration and Chat Operations (ChatOps) workflows across connected, hybrid, and air-gapped environments. Channels feature the following capabilities: + +- [Public](/end-user-guide/collaborate/channel-types#public-channels) and [private](/end-user-guide/collaborate/channel-types#private-channels) channels, [direct messages](/end-user-guide/collaborate/channel-types#direct-message-channels), and [threaded conversations](/end-user-guide/collaborate/organize-conversations) for structured operational coordination. +- [Role-based access controls](/end-user-guide/collaborate/learn-about-roles) and [audit logs](/administration-guide/manage/logging#audit-logging) to support need-to-know enforcement. +- Configurable [notifications](/end-user-guide/preferences/manage-your-notifications) (e.g., [alerts](/end-user-guide/preferences/manage-your-notifications#default-notifications), [keyword triggers](/end-user-guide/preferences/manage-your-mentions-keywords-notifications), [muting](/end-user-guide/preferences/manage-your-channel-specific-notifications)) to surface high-priority activity. +- Integrated ChatOps capabilities via [slash commands](/integrations-guide/run-slash-commands), [bots](https://developers.mattermost.com/integrate/reference/bot-accounts/), and [webhooks](/integrations-guide/webhook-integrations) for real-time automation and system alerts. +- [Pinning](/end-user-guide/collaborate/save-pin-messages#pin-messages), [bookmarking](/end-user-guide/collaborate/manage-channel-bookmarks), and [advanced search](/end-user-guide/collaborate/search-for-messages) to maintain continuity and context in high-volume environments. +- Cross-platform support on web, desktop, and mobile clients for flexible field to command and control access. + +![An image showing Mattermost messaging collaboration, highlighting the ability to create public and private channels, direct messages, and threaded conversations for secure, real-time communication across web, desktop, and mobile.](/images/messaging-new-hero.png) + +See the [Client availability](/end-user-guide/access/client-availability) documentation to learn which features are available on different Mattermost clients. + +### Workflow automation + +[Mattermost Playbooks](/end-user-guide/workflow-automation) standardizes and automates mission workflows such as incident response, shift changeovers, and operational checklists—reducing human error and improving procedural consistency. Playbooks feature: + +- Structured [checklists](/end-user-guide/workflow-automation/work-with-playbooks#make-checklists) with assigned [tasks and due dates](/end-user-guide/workflow-automation/work-with-tasks#tasks-and-due-dates) to operationalize standard and incident or emergency operating procedures. +- Automated [status updates and real-time notifications](/end-user-guide/workflow-automation/notifications-and-updates) in linked channels to keep stakeholders informed of workflow progress or blockers. +- Embedded [actions , assignments, and guidance](/end-user-guide/workflow-automation/work-with-playbooks#actions) for repeatable execution to ensure operational consistency. +- Timeline, [retrospectives](/end-user-guide/workflow-automation/learn-about-playbooks#retrospective), and [metric tracking](/end-user-guide/workflow-automation/metrics-and-goals#metrics) for after-action reviews and accountability. +- Integration [triggers](/end-user-guide/workflow-automation/work-with-runs#send-outgoing-webhooks) (e.g., alerts from monitoring tools) to launch workflows automatically and decrease time to execution. + +![An image showing Mattermost playbooks, highlighting the ability to create structured checklists with tasks and due dates, automate status updates, and track metrics for operational workflows.](/images/playbooks.png) + +### Audio and screenshare + +[Mattermost Calls](/end-user-guide/collaborate/audio-and-screensharing) enables real-time communication and troubleshooting through sovereign audio calling and screen sharing—supporting secure knowledge transfer and fast response in time-sensitive scenarios. Key capabilities include: + +- Enables [1:1 and group audio calls](/end-user-guide/collaborate/make-calls#join-a-call) directly within channels and direct messages, maintaining contextual awareness and access control based on channel membership. +- Supports secure [screen sharing](/end-user-guide/collaborate/make-calls#share-your-screen) for visual coordination and analysis. +- Operates in [sovereign, air-gapped, or sensitive network](/administration-guide/configure/calls-deployment-guide) environments. +- Offers optional [AI-based transcription](/end-user-guide/collaborate/make-calls#transcribe-recorded-calls) and [summarization](/end-user-guide/agents#analyze-threads-and-channels) for meeting capture and follow ups. +- Works across web, desktop, and mobile for flexible, secure access. + +![An image showing a Mattermost call window, highlighting the ability to make secure audio calls and share screens within channels or direct messages, with options for live text captions, transcription, and summarization.](/images/call-window.png) + +### Project and task management + +[Mattermost Boards](/end-user-guide/project-task-management) enables you to coordinate operational work with Kanban-style planning that integrates directly into messaging workflows—enabling transparency, prioritization, and accountability across teams with the following capabilities: + +- Provides visual task [boards](/end-user-guide/project-management/work-with-boards) with drag-and-drop [cards](/end-user-guide/project-management/work-with-cards) and customizable workflows, supporting contextual awareness and [role-based task visibility](/end-user-guide/project-management/share-and-collaborate#board-permissions). +- Delivers real-time updates and synchronization with [linked Mattermost channels](/end-user-guide/project-management/navigate-boards#link-a-board-to-a-channel). +- Supports [card-level assignments, checklists, labels, and due dates](/end-user-guide/project-management/work-with-cards#card-properties) for operational clarity. +- Enables [filtering](/end-user-guide/project-management/groups-filter-sort#filters) and [sorting](/end-user-guide/project-management/groups-filter-sort#sorting-cards) to manage backlogs, priorities, and forward planning. +- Maintains [project visibility](/end-user-guide/project-management/navigate-boards#sidebar-categories) without requiring users to switch away from primary communication channels. + +![An image showing a Kanban board in Mattermost, highlighting the ability to manage tasks and projects visually with drag-and-drop functionality, customizable workflows, and real-time updates.](/images/boards-kanban.png) + +### AI Agents and open APIs + +[Mattermost Agents](/end-user-guide/agents) accelerate decisions and streamline repetitive tasks with AI-driven assistance, fully controllable within sovereign infrastructure—offering intelligent support for both users and workflows: + +- Provides configurable AI assistants that [summarize threads](/end-user-guide/agents#summarize-discussion-threads), [extract action items and answer questions](/end-user-guide/agents#chat-with-agents) with contextual insight and operational awareness. +- Supports [direct interactions with AI agents](/end-user-guide/agents#chat-with-agents) in dedicated threads or channels. +- Enables [semantic search](/end-user-guide/agents#search-with-ai) using natural language to surface relevant content across Mattermost data. +- Supports Retrieval-Augmented Generation (RAG), [custom instructions](/administration-guide/configure/agents-admin-guide#custom-instructions), and responsible [AI guardrails](/administration-guide/configure/agents-admin-guide#permission-configuration) for secure automation. +- Integrates with [local models](/agents/docs/providers) (e.g., Ollama, vLLM) and cloud LLMs via OpenAI-compatible APIs for flexible deployment. + +![An image showing an AI agent summarizing a meeting in Mattermost, highlighting the agent's ability to extract key points and action items from the conversation.](/images/agents-meeting-summary.png) + +## Integrations and AI platform + +The Intelligent Mission Environment (IME) is built for secure, extensible integration with mission-critical systems and AI workflows. Designed to operate in sovereign, regulated, and disconnected environments, IME supports modular automation, multi-agent orchestration, and the secure deployment of both local and cloud-based AI models—enabling faster decision-making while maintaining full control over data, infrastructure, and model behavior. + +### Layered extensibility + +Built to integrate securely with complex enterprise and mission-critical environments, this model enables teams to tailor workflows, automate operations, and connect to external systems using open standards and modular components—supporting rapid deployment of automation while maintaining flexibility and compliance across both air-gapped and connected environments. + +Key capabilities include: + +- Secure video integrations: Embed secure video platforms such as [Pexip](https://mattermost.com/marketplace/pexip-video-connect/), [Webex](https://mattermost.com/marketplace/webex-cloud/), and Jitsi for sovereign mission collaboration. +- Pre-packaged and custom integrations: Quickly connect with systems like [GitHub](/integrations-guide/github), [GitLab](/integrations-guide/gitlab), [Jira](/integrations-guide/jira), [ServiceNow](/integrations-guide/servicenow), [Jenkins](https://mattermost.com/marketplace/jenkins-plugin-2/), and [PagerDuty](https://mattermost.com/marketplace/pagerduty/). +- [Webhooks](/integrations-guide/webhook-integrations) and [slash commands](/integrations-guide/run-slash-commands): Enable real-time, event-driven automation and user-triggered actions directly from chat. +- Plugin architecture: Extend the Mattermost core with [custom UI components, server-side logic, and third-party services](https://developers.mattermost.com/integrate/customization/). + +Learn more in our [Integrations Guide](/integrations-guide/integrations-guide-index). + +![An image showing the GitHub integration in Mattermost, highlighting the ability to receive notifications and manage pull requests directly within channels.](/images/github-integration.png) + +### Multi-Agent, Multi-LLM integration + +A secure, extensible foundation for integrating multiple large language models (LLMs) and autonomous agents within a sovereign control plane enables organizations to operationalize AI within sovereign infrastructure—fusing data across systems, accelerating decisions, and maintaining full control over AI model access and performance. Organizations can leverage the following capabilities to operationalize AI: + +- [Sovereign AI](/agents/docs/sovereign_ai) model support: Integrate with [OpenAI, Anthropic, Meta Llama, and other LLMs](/agents/docs/providers) via secure APIs. +- [Custom instructions](/administration-guide/configure/agents-admin-guide#custom-instructions) and Retrieval-Augmented Generation (RAG): Adapt agent behavior to domain-specific tasks using internal data and policies. +- [Semantic search](/end-user-guide/agents#search-with-ai) and natural language interaction: Provide operational teams with intuitive ways to retrieve and act on information. +- [Responsible AI control plane](/agents/docs/sovereign_ai#security-and-compliance-features): Define model access policies, enforce guardrails, and monitor agent activity with feedback loops. +- Multi-agent orchestration: Use the [Mission Control Plane (MCP)](/administration-guide/configure/agents-admin-guide#model-context-protocol-mcp) integration and agent-to-agent protocols to coordinate actions across multiple autonomous agents. + +## Sovereign & cyber-resilient deployment flexibility + +The Intelligent Mission Environment (IME) is engineered for resilient, mission-critical operations—whether at the tactical edge, inside sovereign data centers, or across regulated cloud environments. Built on Kubernetes and designed for high availability, IME ensures continuity, scalability, and full operational control across diverse infrastructure profiles. + +### Tactical edge + +IME runs on lightweight, ruggedized, or mobile infrastructure, optimized for disconnected, denied, intermittent, and limited (DDIL) conditions. + +- Supports [single-node Linux binaries](/deployment-guide/server/deploy-linux) and [containerized deployments in local Kubernetes environments](/deployment-guide/server/deploy-containers) for rapid, lightweight setup. +- Enables flexible deployment on compact, portable compute platforms—ideal for ships, forward operating bases, mobile command units, or disconnected kits. +- Operates fully [air-gapped](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) without reliance on internet, Domain Name System (DNS), or external authentication systems. +- Delivers secure communications, screen sharing, and workflow automation in isolated or DDIL conditions. + +### Private Cloud & sovereign datacenter + +For high-security environments requiring full infrastructure control, IME supports scalable, highly available deployment within sovereign datacenters. + +- [Kubernetes-native architecture](/deployment-guide/server/deploy-kubernetes) enables containerized services, self-healing workloads, and zero-downtime updates. +- [High availability](/administration-guide/scale/high-availability-cluster-based-deployment) through clustering across application, database, and proxy layers. +- [Horizontal scalability](/administration-guide/scale/scaling-for-enterprise) to tens of thousands of users per instance. +- Complies with Security Technical Implementation Guide (STIG), Federal Information Processing Standard 140-3 (FIPS 140-3), and Federal Risk and Authorization Management Program (FedRAMP)-aligned security standards. + +### Hyperscaler & sovereign Cloud support + +IME is deployable across [major cloud providers](/deployment-guide/server/deploy-kubernetes) with support for hybrid and sovereign architectures: + +- Microsoft Azure – Supports virtual machines (VM) and Kubernetes deployments across Global, Government, and Local Regions. +- Amazon Web Services (AWS) – Deployable on AWS Global, GovCloud (US), and Outposts. +- Google Cloud – Supports Google Cloud Platform and Distributed Cloud (Edge and Hosted). +- Oracle Cloud Infrastructure – Available in the Oracle Marketplace for VM and Kubernetes deployments, including Oracle Sovereign Cloud. + +## Get started + +Mattermost provides mission-critical teams with a sovereign, extensible, and AI-integrated collaboration platform designed for secure operations across the most challenging environments. [Talk to an Expert](https://mattermost.com/contact-sales/) to explore how to architect your Intelligent Mission Environment. \ No newline at end of file diff --git a/docs/main/integrations-guide/built-in-slash-commands.mdx b/docs/main/integrations-guide/built-in-slash-commands.mdx new file mode 100644 index 000000000000..281383c3ce36 --- /dev/null +++ b/docs/main/integrations-guide/built-in-slash-commands.mdx @@ -0,0 +1,60 @@ +--- +title: "Built-In Slash Commands" +--- + + +The following built-in slash comamnds are available in your Mattermost [workspace](/end-user-guide/end-user-guide-index). + + + +Looking for more slash commands? See the [custom slash commands](https://developers.mattermost.com/integrate/slash-commands/custom/) developer documentation for details on creating custom commands. + + + +## Invite people + +- Invite one person using `/invite user1` or `/invite @user1`. +- Invite a custom user group using `/invite @usergroup`. +- Invite multiple people using `/invite @user1 @user2`. +- Invite one person to a specific channel using `/invite @user1 ~channel1`, or `/invite @user1 channel1`. +- Invite multiple people to multiple channels using `/invite @user1 @user2 ~channel1 ~channel2`. +- Invite people by email using `/invite_people {name@domain.com, ...}`. + +## Join, leave, or mute channels + +- Join a specific channel using `/join {channel-name}` or `/open {channel-name}`. +- Leave a channel using `/leave`. +- Mute a channel using `/mute` or `/mute {channel-name}` to turn off desktop, email, and push notifications for the current or specified channel. +- Remove someone from a channel using `/kick {@username}` or `/remove {@username}`. + +## Start or join a call + +- Start a call in a channe or thread using `/call start` +- Join a call in a channel or thread using `/call join` + +## Manage conversations + +- Send a direct message to someone using `/msg {@username} {message}`, or send a group message to multiple people using `/groupmsg {@username1, @username2, @username3,...} {message}`. +- Display text as a code block using `/code {text}`. +- Automatically collapse image previews using `/collapse`, and automatially expand them using `/expand`. +- Echo text back to yourself using `/echo {message} {delay in seconds}` or `/me {message}`. +- Respond with a shrug using `/shrug {message}`. +- Search message text using `search {text}`. + +## Set your availability and status + +- Set [your availability](/end-user-guide/preferences/set-your-status-availability#set-your-availability) using `/away`, `/offline`, `/online`, or `/dnd` +- Set [a custom status](/end-user-guide/preferences/set-your-status-availability#set-a-custom-status) using `/status {emoji_name} {descriptive status_message}`, such as `/status sick Feeling unwell and taking time off to recover`. Clear your current status using `/status clear`. + +## Manage channels + +- Edit the channel header using `/header {text}` or the channel purpose using `/purpose {text}`. +- Rename a channel using `/rename {text}`. + +## More useful slash commands + +- Open the Mattermost product documentation using `/help`. +- Open the in-product Marketplace using `/marketplace`. +- Display a list of keyboard shortcuts using `/shortcuts`. +- Open the **Settings** screen using `/settings`. +- Log out of Mattermost using `/logout`. diff --git a/docs/main/integrations-guide/faq.mdx b/docs/main/integrations-guide/faq.mdx new file mode 100644 index 000000000000..1bb6d78440b3 --- /dev/null +++ b/docs/main/integrations-guide/faq.mdx @@ -0,0 +1,72 @@ +--- +title: "Frequently Asked Questions" +--- +## What is meant by no-code, low-code, and pro-code? + +### No-code + +Integration or automation can be achieved without writing any code. All configuration is done via user-friendly interfaces or by installing pre-made components. This is ideal for non-technical users or admins. + +For example, installing a plugin from the marketplace or using a drag-and-drop automation tool would be considered no-code. The heavy lifting is pre-built and you just need to configure it. + +### Low-code + +Minimal coding or scripting is needed to implement the integration. Low-code solutions might require writing a few lines of script or simple configuration in code-like logic, but not building a full software application. + +In Mattermost’s context, something like setting up a webhook with a small custom script, or tweaking an automation template would be considered low-code. It typically assumes some technical knowledge, but far less than full-scale development. Utilizing templates or online AI tooling can likely meet the need for most low-code integration requirements. + +### Pro-code + +These kinds of integrations require a professional software developer to write code and sometimes build underlying infrastructure. These integrations offer maximum flexibility at the cost of technical complexity, for example building a custom Mattermost plugin or writing a complex bot program using the Mattermost API in a custom application. + +Pro-code integrations are essentially software projects – you’ll use developer tools, work with source code, and follow software development practices to build and maintain them. + +## What does Slack-compatible mean? + +Slack compatible means that Mattermost accepts integrations that have a payload in the same format as Slack's legacy "Message Attachment" payload. If you have a Slack integration, you should be able to set it up in Mattermost without changing the format of the message being sent over. + +## What if I have a webhook from somewhere other than Slack? + +If you have an integration that outputs a payload in a different format, you need an intermediary service to act as a translation layer to change it to the format Mattermost uses. These intermediary services could be no-code or low-code integrations with n8n, Zapier, or Make, but they could also be pro-code integrations leveraging something like AWS Lambda or other hosted services. + +There’s currently no general standard for webhook communication between services, so translating your webhooks is necessary otherwise Mattermost won't understand the data you're sending. + +## What are attachments? + +When "attachments" are mentioned in Mattermost integrations documentation, it refers to Slack's message attachments functionality. These "attachments" can be optionally added as an array in the data sent by an integration, and are used to customize the formatting of the message. + +Mattermost doesn't currently support the ability to attach files to a post made via webhook. You can use the API to attach files to a message if needed. + +## Where can I find existing integrations? + +Visit the [Mattermost Marketplace](https://mattermost.com/marketplace) to access open source integrations to common tools like Jira, Jenkins, and GitLab, along with interactive bot applications, and other communication tools that are freely available for use and customization. + +Alternatively, within Mattermost, when logged in as an Administrator, you can click on the "Marketplace" option in the main menu and easily install plugins or apps from there. + +## Where should I install my integrations? + +For self-hosted deployments in small setups, you might host integrations on the same server on which Mattermost is installed. For larger deployments, you can set up a separate server for integrations, or add them to the server on which the external application is hosted. + +For example, if you're self-hosting a Jira server you could deploy a Jira integration on the Jira server itself. When self-hosting restrictions are less strict, AWS, Heroku, and other public cloud options could also be used. + +## Where can I get more information about integrations? + +Join our [Developers channel](https://community.mattermost.com/core/channels/developers) on the Mattermost Community server for technical discussions, and visit our [Integrations channel](https://community.mattermost.com/core/channels/integrations) for all integrations and plugins discussions. + +## Can I use webhooks to be notified when new integrations are available on the Mattermost Marketplace? + +Yes! A [bash script](https://gist.github.com/mickmister/543a49584146af18ba5e5f82dd86ea93) is available that checks for new integrations in the Mattermost Marketplace, and triggers a post through a Mattermost [incoming webhook](https://developers.mattermost.com/integrate/webhooks/incoming/) request. The script downloads the latest listing, compares it with a locally stored version of the listing, and, if a new plugin is identified, a notification is pushed to a Mattermost channel. + +## Can I use Mattermost to add messaging functionality to my proprietary SaaS service? + +Mattermost is an open source, self-hosted alternative to proprietary SaaS services that lock in the data of users and customers. + +While you're welcome to use the Mattermost source code under its open source license, Mattermost, Inc. does not offer support or technical advice for proprietary SaaS projects that result in customers potentially being paywalled from their data should they stop paying SaaS fees. + +To learn more about why we strongly believe that users and customers should always have access to their data, please read [why we created Mattermost](https://mattermost.com/about-us/). + +## Can I customize the source code? + +Yes. As an open source project, we support your ability to modify the source code for the server or web app to make changes and customizations to meet your specific needs. + +Learn about [forking our open source repositories](https://developers.mattermost.com/integrate/other-integrations/customization/) and [customizing the Mattermost source code](https://developers.mattermost.com/integrate/customization/customization/) for your specific operational needs. diff --git a/docs/main/integrations-guide/github.mdx b/docs/main/integrations-guide/github.mdx new file mode 100644 index 000000000000..a1fa97fa366e --- /dev/null +++ b/docs/main/integrations-guide/github.mdx @@ -0,0 +1,185 @@ +--- +title: "Connect GitHub to Mattermost" +--- + + +Minimize distractions and reduce context switching between your GitHub code repositories and your communication platform by integrating GitHub with Mattermost. Help your teams stay focused and productive with real-time updates on commits, pull requests, issues, and more directly from Mattermost channels. + +![An example of the GitHub integration for Mattermost.](/images/github_mattermost.png) + +## Deploy + +A Mattermost system admin must perform the following steps to deploy the GitHub integration. + +### Install the integration + +1. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +2. Search for or scroll to GitHub, and select **Install**. + +### Set up the integration + +You can configure the GitHub integration using either the built-in setup wizard (recommended) or by following the manual configuration steps. + +
+ +Setup wizard (recommended) + +The recommended way to configure the GitHub integration is using the built-in setup wizard. The wizard guides you through each step of the configuration process, including creating the OAuth app and webhook in GitHub. + +1. In any Mattermost channel, run the `/github setup` slash command. +2. Follow the interactive prompts to complete the setup. + +The wizard walks you through: + +- Creating and configuring an OAuth app in GitHub +- Setting up the webhook connection between GitHub and Mattermost +- Announcing the integration to your team + +You can also run individual setup steps at any time using the following subcommands: + +- `/github setup oauth`: Configure the OAuth2 application in GitHub. +- `/github setup webhook`: Create a webhook from GitHub to Mattermost. +- `/github setup announce`: Announce the integration availability to designated channels. + +
+ +
+ +Manual configuration + +If you prefer to configure the integration manually instead of using the setup wizard, follow the steps below. + +**Register an OAuth app in GitHub** + +1. Go to [https://github.com/settings/applications/new](https://github.com/settings/applications/new) to register an OAuth app with GitHub. +2. Set the following values: + +> - **Application name**: `Mattermost GitHub Plugin - ` +> - **Homepage URL**: `https://github.com/mattermost/mattermost-plugin-github` +> - **Authorization callback URL**: `https://YOUR-MATTERMOST-URL.COM/plugins/github/oauth/complete`, replacing `https://YOUR-MATTERMOST-URL.COM` with your Mattermost URL. This value must match the Mattermost server URL you use to log in. + +3. Save your changes. +4. Select **Generate a new client secret**, and enter your GitHub password to continue. +5. Copy the **Client ID** and **Client Secret** in the resulting screen. +6. In Mattermost, go to **System Console \> Plugins \> GitHub**, and regenerate both a **Webhook Secret** and **At Rest Encryption Key** by selecting **Regenerate** next to each field. You'll need a copy of the **Webhook Secret** value to create a webhook in GitHub. + + + +We recommend making a copy of your webhook secret and encryption key, as it will only be visible to you once. + + + +**Create a webhook in GitHub** + +Create a webhook in GitHub for each GitHub organization you want to set up. + +1. In GitHub, go to the **Settings** page where you want to send notifications from, then select **Webhooks** in the sidebar. +2. Select **Add Webhook**. +3. Set the following values: + +> - **Payload URL**: `https://YOUR-MATTERMOST-URL.COM/plugins/github/webhook`. Replace `https://YOUR-MATTERMOST-URL.COM` with your Mattermost URL. +> - **Content Type**: `application/json` +> - **Secret**: The **Webhook Secret** value you copied earlier. + +4. Under **Which events would you like to trigger this webhook?**, select **Let me select individual events**. +5. Select the following events: + +> - Branch or Tag creation +> - Branch or Tag deletion +> - Discussions +> - Discussion comments +> - Issue comments +> - Issues +> - Pull requests +> - Pull request review +> - Pull request review comments +> - Pushes +> - Releases +> - Stars +> - Workflows + +6. Select **Add Webhook** to save your changes. + +**Configure the integration in Mattermost** + +1. Confirm whether your Mattermost deployment has a `github` user account. If it exists, that account posts GitHub messages in channels by default, and the messages won't include a BOT tag. You can change this account behavior to include a BOT tag by using one of the following methods: + +> - Convert the user account to a bot using [mmctl user convert](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-convert). +> - Change the existing `github` username to something else. A new bot account called `github` is created the Mattermost server is restarted when the [enable bot account creation](/administration-guide/configure/integrations-configuration-settings#enable-bot-account-creation) configuration setting is enabled. + +2. In Mattermost, go to **System Console \> Plugins \> GitHub** and configure the following settings, then select **Save**: + +> - Enter the **GitHub OAuth Client ID** and **GitHub OAuth Client Secret** obtained during registration. +> - (Optional) **GitHub Organization**: Lock the integration to GitHub organizations by specifying a comma seperated list of your GitHub organizations. +> - (GitHub Enterprise Only): Set **Enterprise Base URL** and **Enterprise Upload URL** values to your GitHub Enterprise URLs, e.g. `https://github.example.com`. These values are often the same. +> - (Mattermost desktop app only) **Display Notification Counters in Left Sidebar**: Display or hide GitHub notification counters in the Mattermost sidebar. +> - (Optional) **Enable Private Repositories**: Enable the ability to work with private repositories. Affected users are notified once private repositories are enabled, and must reconnect their GitHub accounts to gain access to private repositories. +> - (Optional) **Connect to private Repositories by default**: Connect to private GitHub repositories by default, when private repositories are enabled. +> - (Optional) **Enable Code Previews**: Expand permalinks to GitHub files with previews. You can can enable public repositories, public and private repositories, or disable this option. +> - (Optional) **Enable Webhook Event Logging**: Log webhook events when log level set to DEBUG by enabling the option. +> - (Optional) **Show Author in commit notification**: Show commit author instead of committer in GitHub push event notifications. + +
+ +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-github/releases) for the latest release, available releases, and compatibiilty considerations. + +## Enable + +Once you setup the integration, notify your teams that they can [connect their GitHub accounts to Mattermost](#connect-a-github-account-to-mattermost). + +## Use + +Users who want to use GitHub interconnectivity must connect their GitHub account to Mattermost. + +Once connected, you'll receive direct messages from the GitHub bot in Mattermost when someone mentions you, requests a review, comments on, modifies one of your pull requests/issues (includes adding labels or reopening the issue), or assigns you to an issue on GitHub. + +### Connect a GitHub account to Mattermost + +1. In Mattermost, run the `/github connect` slash command in any Mattermost channel to link your Mattermost account with your GitHub account. +2. Once connected, run the `/github help` slash command to see what you can do. + +### Get started + +Here are some common slash commands you can get started with: + +Run the `/github subscriptions add` slash command to subscribe a Mattermost channel to receive notifications for new pull requests, issues, branch creation, and more in a GitHub repository. + +For example, to post notifications for issues, issue comments, and pull requests matching the label **Help Wanted** from the `mattermost/mattermost-server` GitHub repository, use: `/github subscriptions add mattermost/mattermost-server --features issues,pulls,issue_comments,label:"Help Wanted"`. The following flags are supported: + +- `--features`: A comma-delimited list of one or more of: issues, pulls, pulls_merged, pulls_created, pushes, creates, deletes, issue_creations, issue_comments, pull_reviews, releases, workflow_success, workflow_failure, discussions, discussion_comments, label:"labelname". Defaults to `pulls,issues,creates,deletes`. +- `--exclude-org-member`: The events triggered by organization members that won't be delivered. It will be locked to the organization configured and only works for users whose membership is public. Organization members and collaborators are not the same. +- `--include-only-org-members`: events triggered only by organization members will be delivered. It will be locked to the organization provided in the plugin configuration and it will only work for users whose membership is public. Note that organization members and collaborators are not the same. +- `--render-style`: Notifications are delivered in the specified style (for example, the body of a pull request will not be displayed). Supported values are `collapsed`, `skip-body`, or `default` (which is the same as omitting the flag). +- `--exclude`: A comma-separated list of the repositories to exclude from getting the subscription notifications like `mattermost/mattermost-server`. Only supported for subscriptions to an organization. + +Run the `/github todo` slash command to get a message with items to do in GitHub, including a list of unread messages and pull requests awaiting your review. + +Run the `/github settings` slash command to update your settings for notifications and daily reminders. + +Run the `/github mute` slash command to manage muted GitHub users. You won't receive notifications for comments in your pull requests and issues from muted users. + +Run the `/github default-repo` slash command to set a default repository for the current channel. This repository will be auto-filled in the Create GitHub Issue modal for convenience. + +## Frequently asked questions + +### How do I connect a repository instead of an organization? + +Set up your GitHub webhook from the repository instead of the organization. Notifications and subscriptions will then be sent only for repositories you create webhooks for. The reminder and `/github todo` searches the whole organization, but only show items assigned to you. + +### How do I send notifications when a certain label is applied? + +If you want to send notifications to a Mattermost channel when **Severity/Critical** label is applied to any issue in the `mattermost/mattermost-plugin-github` repository, run the following slash command to subscribe to these notifications: `/github subscriptions add mattermost/mattermost-plugin-github issues,label:"Severity/Critical"` + +### How does the integration save user data for each connected GitHub user? + +GitHub user tokens are AES-encrypted with an **At Rest Encryption Key** generated in Mattermost. Once encrypted, the tokens are saved in the `PluginKeyValueStore` table in your Mattermost database. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost GitHub plugin repository](https://github.com/mattermost/mattermost-plugin-github). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. diff --git a/docs/main/integrations-guide/gitlab.mdx b/docs/main/integrations-guide/gitlab.mdx new file mode 100644 index 000000000000..67bf59e51d1d --- /dev/null +++ b/docs/main/integrations-guide/gitlab.mdx @@ -0,0 +1,212 @@ +--- +title: "Connect GitLab to Mattermost" +--- + + +Minimize distractions and reduce context switching between your GitLab code repositories and your communication platform by integrating GitLab with Mattermost. You control which events trigger notifications beyond default events, including merges, issue comments, merge request comments, pipelines, pull reviews, and many more. Help your teams stay focused and productive with daily task summaries, real-time updates and notifications on new and closed merge requests, new and closed issues, and tag creation events, directly from Mattermost channel subscriptions. + +Mattermost supports both Software-as-a-Service (SaaS) and on-premises versions of GitLab. + +![An example of the GitLab integration for Mattermost.](/images/gitlab_mattermost.png) + +## Deploy + +A Mattermost system admin must perform the following steps to deploy the GitLab integration. + +### Install the integration + +1. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +2. Search for or scroll to GitLab, and select **Install**. + +### Set up the integration + +You can configure the GitLab integration using either the built-in setup wizard (recommended) or by following the manual configuration steps. + +
+ +Setup wizard (recommended) + +The recommended way to configure the GitLab integration is using the built-in setup wizard. The wizard guides you through each step of the configuration process, including creating the OAuth app in GitLab. + +1. In any Mattermost channel, run the `/gitlab setup` slash command. +2. Follow the interactive prompts to complete the setup. + +The wizard walks you through: + +- Creating and configuring an OAuth app in GitLab +- Configuring the plugin settings in Mattermost +- Announcing the integration to your team + +You can also run individual setup steps at any time using the following subcommands: + +- `/gitlab setup oauth`: Configure the OAuth2 application in GitLab. +- `/gitlab setup announce`: Announce the integration availability to designated channels. + +
+ +
+ +Manual configuration + +If you prefer to configure the integration manually instead of using the setup wizard, follow the steps below. + +**Register an OAuth app in GitLab** + +1. Go to `https://gitlab.com/-/profile/applications` or `https://gitlab.YOURDOMAIN.com/-/profile/applications`, replacing `YOURDOMAIN.COM` with your GitLab URL, to register an OAuth app with GitLab. +2. Set the following values: + +> - **Name**: `Mattermost GitLab Plugin - ` +> - **Redirect URI**: `https://YOUR-MATTERMOST-URL.COM/plugins/com.github.manland.mattermost-plugin-gitlab/oauth/complete`, replacing `YOUR-MATTERMOST-URL.COM` with your Mattermost URL. This value must match the Mattermost server URL you use to log in. + +3. Select `api` and `read_user` in **Scopes**. +4. Save your changes. Copy the **Application ID** and **Secret** fields in the resulting screen. + +**Configure the integration in Mattermost** + +1. In Mattermost, go to **System Console \> Plugins \> GitLab** and configure the following settings, then select **Save**: + +> - Enter the **GitLab URL**, **GitLab OAuth Client ID**, and **GitLab OAuth Client Secret** you obtained when registering the OAuth app in GitLab. +> +> - Generate a **Webhook Secret** and **At Rest Encryption Key** by selecting **Generate**. +> +> - (Optional) **GitLab Group**: Lock the integration to a single GitLab group. +> +> - (Optional) **Enable Private Repositories**: Enable the ability to work with private repositories. Affected users are notified once private repositories are enabled, and must reconnect their GitLab accounts to gain access to private repositories. +> +> - (Optional) **Enable Child Pipeline Notifications**: When enabled, allows notifications for child pipeline events in addition to parent pipeline events. When disabled, only parent pipeline notifications are sent. This setting helps reduce notification noise in environments with complex CI/CD pipeline structures that use child pipelines extensively. +> +> - (Optional) **Enable Code Previews**: Control automatic expansion of GitLab file permalinks with code previews. Options include: +> +> - **Enable for public projects** (Default): Shows previews only for public GitLab repositories. +> +> - **Enable for public and private projects**: Shows previews for both public and private repositories. +> +>
+> +>
+> +> Warning +> +>
+> +> This setting has the potential to leak confidential code into public channels in cases where users with access to private GitLab repositories post permalinks in public Mattermost channels. The plugin automatically generates previews using the poster's GitLab permissions, allowing other channel members without access to view the confidential code. +> +>
+> +> - **Disable**: Completely disables code preview functionality. +> +> **Supported Permalink Types:** +> +> - Single line permalinks: Shows target line plus 3 lines of context +> - File permalinks: Shows file information (no code preview) +> - Line range permalinks: Shows file information (no code preview) +> +> **Preview Limits:** +> +> - Maximum 10 lines displayed per preview (single line permalinks may show fewer preview lines due to context limits) + +
+ +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-gitlab/releases) for the latest release, available releases, and compatibility considerations. + +## Enable + +Once you setup the integration, notify your teams that they can [connect their GitLab accounts to Mattermost](#connect-a-gitlab-account-to-mattermost). + +## Use + +Users who want to use GitLab interconnectivity must connect their GitLab account to Mattermost. + +Once connected, you'll receive direct messages from the GitLab bot in Mattermost when someone mentions you, requests a review, comments on, or modifies one of your merge requests/issues, or assigns you to an issue on GitLab. + +### Connect a GitLab account to Mattermost + +Run the `/gitlab connect` slash command in any Mattermost channel to link your Mattermost account with your GitLab account. + +Disconnect a GitLab account by running the `/gitlab disconnect` slash command. Run the `/gitlab me` slash command to review which account is connected to GitLab. + +Once connected, run the `/gitlab help` slash command to see what you can do. + +### Get started + +Run the `/gitlab todo` slash command to get a list of to-do's, assigned issues, assigned merge requests and merge requests awaiting your review. Alternatively, use the options located in the left sidebar. + +Run the `/gitlab webhook` slash command to have GitLab send events to Mattermost. For example: `/gitlab webhook add group[/project]` + +### Channel subscriptions + +Run the `/gitlab subscriptions list` to review all of your subscriptions. + +Run the `/gitlab subscriptions add group[/project] [features]` slash command to subscribe a Mattermost channel and receive posts for new merge requests, issues, or other features, from a GitLab project. To unsubscribe and stop receiving posts, run the `/gitlab subscriptions delete group[/project]` slash command. + +The following features are supported for channel subscriptions: + +- `merges` - Get notified when merge requests are merged +- `issues` - Get notified when issues are created +- `pushes` - Get notified when commits are pushed to a branch +- `issue_comments` - Get notified when comments are made on issues +- `merge_request_comments` - Get notified when comments are made on merge requests +- `tag` - Get notified when tags are created +- `pipeline` - Get notified about pipeline events (includes child pipeline events if enabled in plugin configuration) +- `wiki` - Get notified about wiki page events +- `releases` - Get notified when releases are created +- `deployments` - Get notified about deployment events + +For example, to subscribe to release and deployment events: `/gitlab subscriptions add group[/project] releases,deployments` + +For each project you want to receive notifications for or subscribe to, create a webhook in a channel where you want to watch events sent from GitLab by running the `/gitlab webhook` slash command. For example: `/gitlab webhook add group[/project]` + + + +For GitLab versions prior to 1.2: + +1. In GitLab, go to the project you want to subscribe to, and select **Settings \> Integrations** in the sidebar. +2. Set the following values: + +> - **URL**: `https://YOUR-MATTERMOST-URL.COM/plugins/com.github.manland.mattermost-plugin-gitlab/webhook`, replacing `https://YOUR-MATTERMOST-URL.COM` with your Mattermost URL. Ensure that you add `/plugins/com.github.manland.mattermost-plugin-gitlab/webhook` to the URL, or the webhook won't work. +> - **Secret Token**: Copy the webhook secret you generated earlier. +> - Select all the events in **Triggers**. +> - Add the webhook. + + + +### Create issues and manage comments + +You can create GitLab issues and manage issue comments directly from Mattermost using slash commands and interactive modals. + +#### Create a GitLab issue + +Run the `/gitlab issue create` slash command to open an interactive modal where you can create a new GitLab issue. The modal allows you to perform the following actions: + +- Set the issue title and description +- Assign labels +- Set the assignee +- Choose the milestone +- Select the target project + +#### Attach comments to existing issues + +Run the `/gitlab issue comment [issue-number]` slash command to attach a comment to an existing GitLab issue. This opens an interactive modal where you can compose and submit your comment directly from Mattermost. + +### Update settings + +Run the `/gitlab settings [setting] [value]` slash command to update your preferences for the integration: + +- Turn personal notifications on or off. +- Turn reminders on or off when you connect initially each day. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost GitLab plugin repository](https://github.com/mattermost/mattermost-plugin-gitlab). + +For questions, feedback, and assistance, join our public [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. + + + +Watch [this on-demand webinar on release management with Mattermost and GitLab](https://mattermost.com/webinar/release-management-with-gitlab/) to learn how to streamline and standardize your release processes, while reducing the amount of effort required to ship your latest releases. + + diff --git a/docs/main/integrations-guide/incoming-webhooks.mdx b/docs/main/integrations-guide/incoming-webhooks.mdx new file mode 100644 index 000000000000..0e7360ef0187 --- /dev/null +++ b/docs/main/integrations-guide/incoming-webhooks.mdx @@ -0,0 +1,231 @@ +--- +title: "Incoming Webhooks" +--- + + +**Technical complexity:** [No-code](#no-code) + +Send or receive real-time data from external tools. Webhooks require minimal coding and are easy to set up with virtually any tool or platform because they use lightweight HTTP POST requests with JSON payloads. + +Using incoming webhooks in Mattermost requires only basic setup. You generate a webhook URL using the Mattermost interface, then point another service to send data to that address. No coding is required if your external service triggering the events is able to send data via webhooks or HTTP POST requests, which most modern applications and platforms support. Setting this up usually involves pasting the Mattermost webhook URL into the service’s settings and selecting what type of events you want it to send. + +## Example Use Cases + +Here are some example use cases for incoming webhooks in Mattermost: + +**Monitoring alerts** + +Send real-time alerts from monitoring systems (such as Prometheus or Datadog) into a dedicated Mattermost channel so your team is immediately notified about system issues or downtime. + +**Build and deployment notifications** + +Post automated updates from CI/CD pipelines (such as Jenkins or GitLab CI) to a channel, keeping developers informed of build status, test results, and deployment progress. + +**Customer support updates** + +Forward new support ticket notifications from systems like Zendesk or ServiceNow into a support channel, ensuring the team can respond quickly to incoming requests. + +## Create + +1. In Mattermost, go to **Product Menu \> Integrations**. If you don't have the **Integrations** option, incoming webhooks may not be enabled on your Mattermost server or may be disabled for non-admins. A System Admin can enable them from **System Console \> Integrations \> Integration Management**. + +> ![Mattermost menu options showing the ability to work with integrations.](/images/product-menu-integrations.png) + +2. From the Integrations page, select **Incoming Webhooks**. + +> ![Dialog box showing the option to add an incoming webhook.](/images/manage-webhooks.png) + +3. Select **Add Incoming Webhook**. + +> ![Dialog box showing the option to add an incoming webhook.](/images/select-add-incoming-webhook.png) + +4. Enter a name and description for the webhook, and then select the channel. You can optionally limit bot posts to a specific channel by selecting **Lock to this channel**, or you can allow the webhook to post to any public channel or private channel the incoming webhook creator is a member of. Note that administrators can enforce channel locking for all incoming webhooks through **System Console \> Integrations \> Integration Management**. Select **Save**. + +> ![Dialog box showing the incoming webhook details.](/images/create-incoming-webhook-details.png) + +5\. Select **Done** to confirm. Mattermost generates a unique webhook URL, which will look something like this: `https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx`. Treat this URL as a secret. Anyone who has it will be able to post messages to your Mattermost instance. + +> ![Dialog box showing the incoming webhook URL.](/images/incoming-webhook-created.png) + +## Use + +To post a message, your application needs to send an HTTP POST request to the webhook URL with a JSON payload in the request body. + +``` bash +curl -i -X POST -H 'Content-Type: application/json' -d '{"text": "Hello, this is some text\nThis is more text. :tada:"}' https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx +``` + +A successful request will receive an HTTP 200 response with ok in the response body. + +For compatibility with Slack incoming webhooks, if no `Content-Type` header is set, the request body must be prefixed with `payload=`. + +### Post Examples + +Here are some examples of simple messages posted using incoming webhooks: + +Example of a GitHub notification posted to Mattermost using an incoming webhook. + +Example of a Jira notification posted to Mattermost using an incoming webhook. + +Example of a Mattermost notification posted to Mattermost using an incoming webhook. + +Example of a Fastlane notification posted to Mattermost using an incoming webhook. + +Example of a Weblate notification posted to Mattermost using an incoming webhook. + +## Parameters + +The JSON payload can contain the following parameters: + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequiredDescription
textYes (if attachments is not set)Markdown-formatted message. Use @<username>, @channel, and @here for notifications.
channelNoOverrides the default channel. Use the channel's name (e.g., town-square), not the display name. Use @<username> to send a Direct Message. The webhook can post to any public channel, and any private channel the creator is a member of.
usernameNoOverrides the default username. The Enable integrations to override usernames setting must be enabled.
icon_urlNoOverrides the default profile picture URL. The Enable integrations to override profile picture icons setting must be enabled.
icon_emojiNoOverrides the icon_url with an emoji. Use the emoji name (e.g., :tada:). The Enable integrations to override profile picture icons setting must be enabled.
attachmentsYes (if text is not set)An array of message attachment objects for richer formatting.
typeNoSets the post type, mainly for use by plugins. If set, must begin with custom_.
propsNoA JSON object for storing metadata. The card property can be used to display extra Markdown-formatted text in the post's info panel (RHS). This is available in Mattermost v5.14 and later, and is not yet supported on mobile.
priorityNoSets the priority of the message. See message priorities.
+ +### Example with Parameters + +``` json +{ + "channel": "town-square", + "username": "test-automation", + "icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "text": "#### Test results for July 27th, 2017\n@channel please review failed tests.\n\n| Component | Tests Run | Tests Failed |\n|:-----------|:-----------:|:-----------------------------------------------|\n| Server | 948 | :white_check_mark: 0 |\n| Web Client | 123 | :warning: 2 [(see details)](https://linktologs) |\n| iOS Client | 78 | :warning: 3 [(see details)](https://linktologs) |" +} +``` + +This renders as: + +Example of a webhook post with a custom username, icon, and formatted text. + +### Example with Card Prop + +Using the `card` property inside `props` will display an info icon on the post. Clicking the icon opens the right-hand sidebar to display the content. + +``` json +{ + "channel": "town-square", + "username": "Winning-bot", + "text": "#### We won a new deal!", + "props": { + "card": "Salesforce Opportunity Information:\n\n [Opportunity Name](https://salesforce.com/OPPORTUNITY_ID)\n\n-Salesperson: **Bob McKnight** \n\n Amount: **$300,020.00**" + } +} +``` + +![Example of a post with a card property displaying more information in the sidebar.](/images/card-prop-example.png) + +## Slack Compatibility + +Mattermost provides compatibility with Slack's webhook format to make migration easier. + +### Translating Slack's Data Format + +Mattermost automatically translates JSON payloads from Slack format: + +- `[https://mattermost.com/](https://mattermost.com/)` is rendered as a link. +- `` is rendered as linked text. +- `<userid>` triggers a user mention. +- ``, ``, or `` trigger channel-wide mentions. + +You can also send a direct message by overriding the channel name with `@username`, e.g., `"channel": "@jim"`. + +### Using Mattermost Webhooks in GitLab + +You can use GitLab's built-in Slack integration to send notifications to Mattermost: + +1. In GitLab, go to **Settings \> Services** and select **Slack**. +2. Paste the Mattermost incoming webhook URL. +3. Optionally, set a **Username**. Leave the **Channel** field blank. +4. Select **Save** and test the integration. + +### Known Slack Compatibility Issues + +- Referencing channels using `<#CHANNEL_ID>` is not supported. +- `` and `` are not supported. +- `*bold*` formatting is not supported; use `**bold**` instead. +- Webhooks cannot send a direct message to the user who created the webhook. + +## Troubleshooting + +To debug incoming webhooks, a System Admin can enable **Webhook Debugging** and set the **Console Log Level** to **DEBUG** in **System Console \> Logging**. + +Common error messages include: + +- **Couldn't find the channel**: The channel specified in the `channel` parameter does not exist. +- **Couldn't find the user**: The user specified does not exist. +- **Unable to parse incoming data**: The JSON payload is malformed. + +If your integration posts the JSON payload as plain text instead of a rendered message, ensure the request includes the `Content-Type: application/json` header. + +## Do More with Incoming Webhooks + +Transform basic message posts into rich, interactive notifications by including buttons, menus, and other interactive elements in your webhook messages, making them more engaging and useful for your team. + +- [Message Attachments](https://developers.mattermost.com/integrate/reference/message-attachments/): Present rich, structured summaries such as status, priority, fields, links, or images for faster triage and comprehension. (Slack‑compatible schema.) +- [Interactive Messages](https://developers.mattermost.com/integrate/plugins/interactive-messages): Make notifications actionable with buttons or menus such as Acknowledge, Assign, or Escalate that enable an immediate user response without switching tools or context. +- [Interactive Dialogs](https://developers.mattermost.com/integrate/plugins/interactive-dialogs/): Guide users to successful outcomes when interactions need structured input or confirmation (for example, “Acknowledge with note” or “Assign to user”). Improve data quality with required fields, minimum/maximum input lengths, server‑driven user/channel pickers, validated defaults, inline field errors, placeholders, and help text that help users enter the right data the first time. +- [Message Priority](https://developers.mattermost.com/integrate/reference/message-priority/): Set `priority` to elevate critical posts and optionally request acknowledgements or persistent notifications. + + + +- Need a dedicated identity, permissions scoping, or need to post outside of webhook/command flows? Use a [bot account](https://developers.mattermost.com/integrate/reference/bot-accounts/) if you need a more permanent solution than using overrides for simple branding. +- If your system later needs to call Mattermost APIs (e.g., post follow-ups, open dialogs), authenticate with a bot user [personal access token](https://developers.mattermost.com/integrate/reference/personal-access-token/). We recommend avoiding human/System Admin personal access tokens for automations and rotating and storing tokens securely. + + diff --git a/docs/main/integrations-guide/integrations-guide-index.mdx b/docs/main/integrations-guide/integrations-guide-index.mdx new file mode 100644 index 000000000000..044b84e0065d --- /dev/null +++ b/docs/main/integrations-guide/integrations-guide-index.mdx @@ -0,0 +1,146 @@ +--- +title: "Integrations Guide" +--- +Mattermost provides a variety of methods to integrate with your favorite tools, automate critical workflows, and extend the capabilities of the platform. This guide provides a high-level overview of integration options and the level of technical skills required [(no-code, low-code, or pro-code)](/integrations-guide/faq#what-is-meant-by-no-code-low-code-and-pro-code), and links to detailed documentation for each. + +## Choose Your Path + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Skill LevelBest OptionsExamples
No-code
    +
  • Connect Jira, GitHub, Zoom
  • +
  • Command line interactions
  • +
  • Automate with n8n, Zapier
  • +
  • Run incident playbooks
  • +
Low-code
    +
  • Send monitoring alerts
  • +
  • Trigger actions with keywords
  • +
Pro-code
    +
  • Build custom apps
  • +
  • Extend Mattermost core
  • +
+ +## Integration Options + +### Plugins + +Learn more about [Mattermost plugins](/integrations-guide/plugins). + +#### Pre-Built Plugins + +**Technical complexity:** [No-code](#no-code) + +Mattermost provides a set of [pre-built plugins](/integrations-guide/popular-integrations) that require no coding to install, configure, and use. These plugins are installed and managed entirely through the System Console, where you can enable, configure, and customize settings without any development work. + +Pre-built plugins available for no-code integration + +#### Custom-Built Plugins + +**Technical complexity:** [Pro-code](#pro-code) + +[Building custom plugins](/integrations-guide/plugins#custom-built-plugins) are the most comprehensive way to add new features and customization to self-hosted Mattermost deployments. Custom plugins are ideal for customers wanting to change the behavior of the Mattermost server, desktop, and web apps without forking the core codebase to suit their organization’s needs. + +Building a custom plugin is a **software development** task, using `Go` for the server-side functionality and optionally `TypeScript/React` for UI components. + +### Webhooks + +Learn more about [Mattermost webhooks](/integrations-guide/webhook-integrations). + +#### Incoming Webhooks + +**Technical complexity:** [No-code](#no-code) + +[Incoming webhooks](/integrations-guide/incoming-webhooks) allow external applications to post messages into Mattermost channels and direct messages. They are a simple way to receive notifications and data from other services in real-time and require only basic setup. + +Additionally, Mattermost webhook payloads are [fully compatible](/integrations-guide/incoming-webhooks#slack-compatibility) with Slack’s webhook format to make migration easier. + +#### Outgoing Webhooks + +**Technical complexity:** [Low-code](#low-code) + +[Outgoing webhooks](/integrations-guide/outgoing-webhooks) allow Mattermost to send messages and trigger actions in external applications when specific keywords are typed in channels. They are a straightforward way to connect Mattermost conversations to other services and automate responses. Outgoing webhooks require no coding to configure in Mattermost. Some light coding is required to parse the request from the external service and format a JSON response payload. + +### Slash Commands + +Learn more about [Mattermost slash commands](/integrations-guide/slash-commands). + +#### Built-In Slash Commands + +**Technical complexity:** [No-code](#no-code) + +Out-of-the-box [built-in slash commands](/integrations-guide/built-in-slash-commands) enable command line interaction with users, channels, and conversations. + +#### Custom Slash Commands + +**Technical complexity:** [Low-code](#low-code) + +You can create [custom slash commands](/integrations-guide/slash-commands#custom-slash-commands) that run preconfigured commands that can return a response, such as plain text, rich message content, interactive buttons or forms, directly into a channel. + +Mattermost's slash command format is Slack compatible, so you can easily migrate your commands from Slack. + +### RESTful API + +**Technical complexity:** [Pro-code](#pro-code) + +With [Mattermost's RESTful API](/integrations-guide/restful-api), you have full developer control for automation, bots, and integrations. + +## Build and Automate Workflows + +**Technical complexity:** [No-code](#no-code) + +In addition to direct tool integrations, Mattermost can be part of larger automated workflows across your integrated services. Automate multi-step processes across Mattermost and other systems, often with no coding required. + +### No-code Automation Platforms + +Platforms like n8n, Zapier, and Make provide powerful visual editors that support thousands of connected tools, with triggers and actions that integrate Mattermost to external services, enabling teams to build complex workflows without writing code. Admins migrating from tools like Slack Workflow Builder can recreate familiar automations in Mattermost using these platforms. + +Learn more about additional [no-code automation options](/integrations-guide/no-code-automation) available in Mattermost. + +### Mattermost Playbooks + +[Mattermost Playbooks](/end-user-guide/workflow-automation) lets you define and execute repeatable processes without any coding. Playbooks are often used for incident response, onboarding checklists, or any workflow that involves multiple steps, owners, and notifications. Playbooks have integration points you can use to trigger actions, and they can work in conjunction with plugins, making them a powerful no-code automation tool for orchestrating both human and system actions. + +Learn more about using [Playbooks](/end-user-guide/workflow-automation). + +## Frequently Asked Questions + +Have questions about coding levels, Slack compatibility, or setup options? Visit the [Integrations FAQ](/integrations-guide/faq). diff --git a/docs/main/integrations-guide/jira.mdx b/docs/main/integrations-guide/jira.mdx new file mode 100644 index 000000000000..bf98a7fbbc9a --- /dev/null +++ b/docs/main/integrations-guide/jira.mdx @@ -0,0 +1,275 @@ +--- +title: "Connect Jira to Mattermost" +--- + + +Minimize distractions, reduce context switching between your project management tool and your communication platform by integrating Jira with Mattermost. You control which events trigger notifications including issue creation, field-specific issue updates, reopened, resolved, or deleted issues, as well as new, updated, or deleted issue comments. Create Jira issues directly from Mattermost conversations, attach messages to Jira issues, transition and assign Jira issues, and follow up on action items in real-time, directly from Mattermost channel subscriptions. + +Mattermost supports versions 7 and 8 of Jira Core and Jira Software products, for Server, Data Center, and Cloud platforms. From v3.0 of this integration, a commercial Mattermost license is required for multiple Jira instances with Mattermost configured using Administrator Slash Commands. + +Jira Service Management (formerly known as Jira Service Desk) isn't supported. + +## Deploy + +Setup starts in Mattermost, moves to Jira, and finishes in Mattermost. + + + +- Jira Core and Jira Software products, for Server, Data Center, and Cloud platforms are supported, and tested with versions 7 and 8. +- Jira Service Management (formerly known as Jira Service Desk) isn't supported. +- From v3.0 of this integration, support for multiple Jira instances is supported with Mattermost Enterprise and Professional plans, configured using Administrator Slash Commands. + + + +### Mattermost configuration + +A Mattermost system admin must perform the following steps in Mattermost. + +1. Install the Jira integration from the in-product App Marketplace: + +> 1. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +> 2. Search for or scroll to Jira, and select **Install**. +> 3. Once installed, select **Configure**. You're taken to the System Console. +> 4. On the Jira configuration page, enable and configure Jira interoperability as follows, and then select **Save**: +> +> > - Generate a **Webhook Secret** by selecting **Regenerate**. +> > +> >
+> > +> >
+> > +> > Note +> > +> >
+> > +> > We recommend making a copy of your webhook secret, as it will only be visible to you once. +> > +> >
+> > +> > - **Allow users to attach and create Jira issues in Mattermost**: Enable or disable the user's ability to attach and create Jira issues in Mattermost. When enabled, you must also [install this Jira integration in your Jira instance](#install-integration-as-Jira-app). +> > - **Mattermost Roles Allowed to Edit Jira Subscriptions**: Specify the Mattermost roles that can edit Jira subscriptions to control which Mattermost users can subscribe channels to Jira tickets. +> > - **Jira Groups Allowed to Edit Jira Subscriptions**: (Applies to older Jira v2.4 or earlier deployments only) Specify the Jira groups allowed to edit Jira subscriptions as a comma-separated list of user group names. Leave blank to allow any Jira user the ability to create subscriptions. The user editing a subscription only needs to be a member of one of the listed groups. +> > - **Default Subscription Security Level to Empty**: Enable or disable default subscription security level. When enabled, subscriptions only include issues that have a security level assigned when a security level has been included as a filter. +> > - **Additional Help Text to be shown with Jira Help**: Define any additional help text to display when users run the `/jira help` slash command. +> > - **Hide issue descriptions and comments**: Show or hide issue descriptions and comments from subscription and webhook messages. +> > - **Enable slash command**: Enable or disable slash command autocompletion to guide users through available `/jira` slash commands. +> > - **Display Subscription name in notifications**: Show or hide subscription name in notification messages posted to a channel. +> > - **Admin API Token**: Set an [API token](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) to get notified for comments and issue creation events, even when the user triggering the event isn't connected to Jira, and set up Autolink. API tokens must be created using an admin Jira account; otherwise, notifications won't be delivered for projects the user can't access, and Autolink won't work. +> > - **Admin Email**: Set Admin email to get notified for comment and issue created events even if the user triggering the event is not connected to Jira and setup Autolink for Jira plugin. + +2. Run `/jira setup` to start the wizard to configure the plugin. If you wish to set up the plugin manually, then please follow the steps below. + +### Install Jira integration in your Jira instance + +To enable your users to create and manage Jira issues across Mattermost channels, you must install this Jira integration, as an application, in your Jira instance. + +- For Jira Server or Data Center instances, run the `/jira instance install server ` slash command in a Mattermost channel as a Mattermost system admin, then follow the steps posted to the channel, replacing `YOUR-JIRA-URL` with your Jira URL. This value must match the Jira server URL you use to log in. Run the `/jira instance uninstall server ` slash command to uninstall your Jira Server or Data Center instance from your Mattermost instance. +- For Jira Cloud, run the `/jira instance install cloud-oauth ` slash command in a Mattermost channel as a Mattermost system admin, then follow the wizard to complete the setup. Run the `/jira instance uninstall cloud-oauth ` slash command to uninstall your Jira Cloud instance from your Mattermost. + +### Configure webhooks in Jira + +A Mattermost system admin and a Jira system admin must perform the following steps to configure a single webhook for all possible event triggers, called a firehose, that you would like to be pushed into Mattermost. Mattermost receives a stream of events from the Jira server via a configured webhook, and routes the events to specific channels. A [channel subscription](#manage-channel-subscriptions-in-mattermost) processes the firehose of data, and routes the events to channels based on your subscriptions. + +1. In Mattermost, run the `/jira webhook ` slash command in a Mattermost channel to get the appropriate webhook URL, replacing `YOUR-JIRA-URL` with your Jira URL. +2. In Jira, go to **Jira Settings \> System \> WebHooks**. (For older versions of Jira, select the gear icon in bottom left corner, then go to **Advanced \> WebHooks**.) +3. Select **Create a WebHook**. +4. Enter a **Name** for the webhook and add the Jira webhook URL you retrieved above in Mattermost as the URL. +5. Specify the issue events that will be sent to Mattermost channels by selecting all of the following: + +> - Comments: created, updated, and deleted. +> - Issues: created, updated, and deleted. + +6. Select **Save**. + +### Manage channel subscriptions in Mattermost + +Mattermost channel admins can set up notifications they want to receive per channel as subscription rules based on the Jira project, event type, issue type. You can also filter out issues based on its value. + +To modify subscription, users must meet the criteria of both the Mattermost user settings and Jira group settings. If you can subscribe channels to Jira events, you can also set up rules; however, you'll only see the projects and issue types you have access to within Jira. If you can't see a project in Jira, it won't be avaialble as an option. + +If your organization's infrastructure is set up such that your Mattermost instance can't connect to your Jira instance, channel subscriptions won't be avaialable. Instead, use [legacy Webhooks](#legacy-jira-webhooks) instead to allow a Jira webhook to post to a specific channel. + +In any channel, run the `/jira subscribe` slash command to configure the following options: + +- Configure what Jira notifications are sent to the current channel. +- Specify filters including: affects versions, epic link, fix versions, labels, and priority. +- Specify custom fields including: checkboxes, labels, radio buttons, and select list (single or multiple choice). +- Review the approximate JQL output generated. This is not guaranteed to be valid JQL and is only shown as a reference to what the query may look like if converted to JQL. + +Run the `/jira subscribe list` slash command to display all subscription rules set up across all channels and teams on your Mattermost instance. + +#### Legacy Jira webhooks + +If your Mattermost instance can't connect to your Jira instance, you won't be able to subscribe Mattermost channels. You'll need to use legacy webhooks instead. + +1. To generate the webhook URL for a specific channel, run the `/jira webhook` slash command, and use the URL output in the **Legacy Webhooks** section of the output. +2. As a Jira system admin, go to **Jira Settings \> System \> WebHooks**. (For older versions of Jira, select the gear icon in bottom left corner, then go to **Advanced \> WebHooks**.) +3. Select **Create a WebHook** to create a new webhook. Enter a **Name** for the webhook, and add the Jira webhook URL `https://MATTERMOST-SITE-URL/plugins/jira/webhook?secret=MATTERMOST-WEBHOOK-SECRET&team=MATTERMOST-TEAM-URL&channel=MATTERMOST-CHANNEL-URL` (for Jira 2.1) as the URL. + +> - Replace `MATTERMOST-TEAM-URL` and `MATTERMOST-CHANNEL-URL` with the Mattermost team URL and channel URL you want the Jira events to post to, using lowercase characters. +> - Replace `MATTERMOST-SITE-URL` with the site URL of your Mattermost instance. +> - Replace `MATTERMOST-WEBHOOK-SECRET` with the secret generated in Mattermost by going to **System Console \> Plugins \> Jira**. + +For example, if the team URL is `contributors`, channel URL is `town-square`, site URL is `https://community.mattermost.com`, and the generated webhook secret is `MYSECRET`, the final webhook URL would be: `https://community.mattermost.com/plugins/jira/webhook?secret=MYSECRET&team=contributors&channel=town-square`. + +4. (Optional) Set a description and a custom JQL query to determine which tickets trigger events. For information on JQL queries, see the [Atlassian help documentation](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/). +5. Set which issue events send messages to Mattermost channels, then select **Save**. The following issue events are supported: issues created, issues deleted, and issues updated (including reopened or resolved when the assignee changes). + +By default, the legacy webhook integration publishes notifications for issue created, resolve, unresolve, reopen, and assign events. To post more events, use the following extra &-separated parameters: + +- `updated_all=1`: all events +- `updated_comments=1`: all comment events +- `updated_description=1`: updated issue description +- `updated_labels=1`: updated issue labels +- `updated_priority=1`: updated issue priority +- `updated_rank=1`: ranked issue higher or lower +- `updated_sprint=1`: assigned issue to a different sprint +- `updated_status=1`: transitioned issed to a different status, such as Done or In Progress +- `updated_summary=1`: renamed issue + +Here's an example of a webhook configured to create a post for comment events: `https://community.mattermost.com/plugins/jira/webhook?secret=MYSECRET&team=contributors&channel=town-square&updated_comments=1` + +Any previously configured webhooks set up in Jira that point to specific channels are supported and will continue to work. + +### Manage notifications + +Jira notifications are messages sent to a Mattermost channel when a particular event occurs in Jira. They can managed as [channel subscriptions](#manage-channel-subscriptions) in Mattermost, or managed as [webhooks](#configure-webhooks-in-Jira) in Jira. Notifications and metadata shown in a channel aren't protected by Jira permissions. Anyone in the channel can see what's posted to the channel. However, if users don't have the appropriate permission, they won't be able to see further details of the issue if they try to access it in Jira. + +When any webhook event is received from Jira, and it matches a notification rule, it posts a notification to the channel. If there are no subscription matches, the webhook event is discarded. + +## Enable + +Notify your teams that they can [connect their Jira accounts to Mattermost](#connect-a-jira-account-to-mattermost). + +Do more with Jira interoperabiilty as a Mattermost system admin by using the following slash commands: + +- `/jira instance alias [URL] [ALIAS-NAME]` - Assign an alias to an instance. +- `/jira instance unalias [ALIAS-NAME]` - Remove an alias from an instance. +- `/jira instance list` - List all installed Jira instances. +- `/jira instance v2 ` - Set the Jira instance to process legacy "v2" webhooks and subscriptions (which aren't prefixed with the instance ID). +- `/jira stats` - Display usage statistics. +- `/jira webhook [--instance=]` - Display the Mattermost webhook that receive JQL queries. +- `/jira v2revert` - Revert to the legacy V2 jira integration data model. + +## Use + +Users who want to use Jira interconnectivity must connect a Jira account to Mattermost. + +Once connected, you'll receive direct messages from the Jira bot in Mattermost for Jira activity. + +### Connect a Jira account to Mattermost + +1. In Mattermost, run the `/jira connect` slash command in any Mattermost channel to link your Mattermost account with your Jira account. Follow the link into your Jira instance, and select **Allow**. + +If you have multiple Jira instances, run the `/jira instance connect ` slash command instead to connect to a specific Jira instance. + +2. Once connected, run the `/jira help` slash command to see what you can do. +3. To disconnect a Jira account from Mattermost, run the `/jira disconnect` slash command in any Mattermost channel. + +### Get started + +Here are some common slash commands you can get started with: + +- `/jira info` - Display information about the current user and the Jira integration +- `/jira connect [jiraURL]` - Connect your Mattermost account to your Jira account +- `/jira disconnect [jiraURL]` - Disconnect your Mattermost account from your Jira account +- `/jira issue assign [issue-key] [assignee]` - Change the assignee of a Jira issue +- `/jira issue create [text]` - Create a new Issue with 'text' inserted into the description field +- `/jira issue transition [issue-key] [state]` - Change the state of a Jira issue +- `/jira issue unassign [issue-key]` - Unassign the Jira issue +- `/jira issue view [issue-key]` - View the details of a specific Jira issue +- `/jira instance settings` - View your user settings +- `/jira instance settings [setting] [value]` - Update your user settings. `[setting]` can be notifications and `[value]` can be `on` or `off` + +#### Create a Jira issue + +Use the `/jira issue create` slash command to create a Jira issue without leaving Mattermost. You can prepopulate the issue's summary by running `/jira issue create This is my issue's summary`. You're prompted to fill out the issue details. + +![An example of the create Jira issue workflow.](/images/create-jira-issue.png) + +#### Transition Jira issues + +You can transition issues without leaving Mattermost by using the `/jira transition <issue-key> <state>` slash command. States and issue transitions are based on your Jira project workflow configuration. For example, `/jira transition EXT-20 done` transitions the issue key EXT-20 to a `done` state. Partial matches are supported. For example, running the `/jira transition EXT-20 in` slash command transitions the issue to an `in progress` state. However, if your Jira instance includes states of both `in review` and `in progress`, the Jira integration bot will prompt you to clarify which state you want. + +#### Assign Jira issues + +Assign issues to other Jira users without leaving Mattermost using the `/jira assign` command. Partial matches on usernames, firstnames, and lastnames are supported. For example, running the slash command `/jira assign EXT-20 john` transitions the issue EXT-20 to John. + +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-jira/releases) for the latest release, available releases, and compatibiilty considerations. + +## Frequenly asked questions + +### How do I disable Jira interoperability? + +You can disable the Jira integration at any time from Mattermost by going to **System Console \> Plugins \> Jira**. Once disabled, any webhook requests coming from Jira are ignored, and users can't create Jira issues from Mattermost. + +### Why isn't the Jira integration posting messages to Mattermost? + +Try the following troubleshooting steps: + +1. Confirm that your [Mattermost Site URL](/administration-guide/configure/environment-configuration-settings#site-url) is configured, and that the webhook created in Jira is pointing to this URL. To ensure the URL is correct, run the `/jira webhook` slash command, then copy the output and paste it into Jira's webhook setup page. +2. If you specified a JQL query in your Jira webhook setup, paste the JQL to Jira issue search and make sure it returns results. If it doesn't, the query may be incorrect. Refer to the [Atlassian documentation](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/) for help. A JQL query isn't required when setting up the webhook. + +If you're using legacy webhooks: + +- Confirm the team URL and channel URL you specified in the Jira webhook URL match up with the path shown in your browser when visiting the channel. +- Only events described in the Legacy Webhook documentation are supported. +- Use a curl command to make a POST request to the webhook URL. If curl command completes with a `200 OK` response, the integration is configured correctly. For instance, you can run the following command: + +``` sh +curl -X POST -v "https:///plugins/jira/webhook?secret=&team=&channel=&user_id=admin&user_key=admin" --data '{"event":"some_jira_event"}' +``` + +Replace ``, ``, ``, and `` with your setup when configuring the Jira integration. The curl command won't post a message in your Mattermost channel. + +### Can admins restrict who can create or attach Mattermost messages to Jira issues? + +Yes, Mattermost system admins can disable this functionality by going to **System Console \> Plugins \> Jira** to disable the **Allow users to attach and create Jira issues in Mattermost** option. + +### How does Mattermost know which Jira issues users can access? + +Mattermost only displays static messages in the channel, and doesn't enforce Jira permissions on viewers in a channel. + +Any messages in a channel can be seen by all users of that channel. Subscriptions to Jira issues should be made carefully to avoid unwittingly exposing sensitive Jira issues in a public channel for example. Exposure is limited to the information posted to the channel. To transition an issue, or re-assign it the user needs to have the appropriate permissions in Jira. + +### Why must every user authenticate with Jira? + +The authentication with Jira lets the JiraBot provide personal notifications for each Mattermost/Jira user whenever they are mentioned on an issue, comment on an issue, or have an issue assigned to them. Additionally, the integration uses their authentication information to perform actions on their behalf. Tasks such as searching, viewing, creating, assigning, and transitioning issues all abide by the permissions granted to the user within Jira. + +Users will need to temporarily enable third-party cookies in their browser during the Jira authentication process. + +### What does the error message `'/(name)' not found` mean? + +If you see the error `'/(name)' not found` in Mattermost, disable the Jira integration, check the log file looking for messages that refer to plugins and health check fail, such as `ExecuteCommand`, etc. And consider [enabling debug logging](/administration-guide/manage/logging#how-do-i-enable-debug-logging) to log more verbose error events in the Mattermost system log. Then try re-enabling Jira interoperability and review the log file for clues. + +Debug logging can cause log files to expand substantially, and may adversely impact the server performance. Keep an eye on your server logs, or only enable it temporarily or in development environments, and not production enviornments. + +### Why do I get a webhooks error? + +If you see a `WebHooks can only use standard http and https ports (80 or 443)` error, it indicates that you're using a non-standard port. Jira only allows webhooks to connect to the standard ports 80 and 443. You need to set up a proxy between Jira and your Mattermost instance to let Jira communicate over port 443. + +### How do I handle credential rotation for the Jira webhook? + +Generate a new secret by going to **System Console \> Plugins \> Jira**. Paste the new webhook URL in your Jira webhook configuration. + +## Customize + +This integration contains both a server and web app portion. Visit the [Mattermost Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Mattermost Developer environment setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for information about developing, customizing, and extending Mattermost functionality. + +## Get help + +Customers with a Mattermost subscription can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). Community deployments can report a bug by opening a GitHub issue against the [Mattermost Jira plugin repository](https://github.com/mattermost/mattermost-plugin-jira), or visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + + + +Download [this Jira workflows datasheet](https://mattermost.com/mattermost-jira-datasheet/) to learn more about using Mattermost and Jira, including: + +- Key benefits to integrating Jira and Mattermost +- Common Jira Workflows on Mattermost +- How to get started with the Jira plugin for Mattermost + + diff --git a/docs/main/integrations-guide/mattermost-mission-collaboration-for-m365.mdx b/docs/main/integrations-guide/mattermost-mission-collaboration-for-m365.mdx new file mode 100644 index 000000000000..7d719e9a1052 --- /dev/null +++ b/docs/main/integrations-guide/mattermost-mission-collaboration-for-m365.mdx @@ -0,0 +1,168 @@ +--- +title: "Connect Microsoft 365, Teams, and Outlook with Mattermost" +--- + + +Mattermost Mission Collaboration for Microsoft extends Microsoft for mission-critical coordination, command and control, incident response, and DevSecOps workflows in demanding environments, including air-gapped and classified networks by embedding Mattermost inside Teams. Use data-sovereign tools like secure chat, Playbooks, and Calls directly within M365, Teams, and Outlook. + +This app is designed to work with Microsoft 365, Teams, and Outlook and is currently in [Beta](/administration-guide/manage/feature-labels#beta). From Mattermost v10.7.1, this integration supports Entra ID-based Single Sign-On (SSO) for automatic authentication. Users must exist in both Mattermost and Microsoft with matching email addresses; the integration handles authentication but does not automatically provision new users. See the [user provisioning](/administration-guide/manage/admin/user-provisioning) product documentation for details on setting up SSO. + +![Mattermost embedded as a Microsoft Teams app.](/images/mattermost-in-msteams-2.png) + +## Deploy + +Before starting the setup, review this section to familiarize yourself with the 3 components needed to integrate Mattermost with M365, including [Azure App registration](#register-an-ms-teams-app-in-azure), [Microsoft Teams App installation](#mattermost-plugin-setup), and [Mattermost plugin configuration](#install-mattermost-in-microsoft-teams). Each component plays a crucial role in ensuring seamless communication and collaboration between Mattermost and Microsoft 365 services. Then complete the following integration setup steps in the order listed below. + +### Register an MS Teams app in Azure + +An application must be registered in Microsoft Azure to enable secure authentication and authorization between Mattermost and M365 services. This app registration acts as the bridge for permissions and connectivity. The **Azure App** is responsible for authentication and managing permissions. + +1. Sign in to the [Azure portal](https://portal.azure.com/) using an admin Azure account. +2. Go to your **Azure Portal \> Microsoft Entra ID**. +3. Create a new app registration by selecting the **Add application registration** "Quick Action": + +> ![image](/images/AzureApp_New_Registration_MS_Embedded.png) +> +> - Give it a name. +> - Choose the "Accounts in this organizational directory only (single tenant)" option. +> - Leave the Redirect URI empty. +> +> ![image](/images/AzureApp_New_Registration_MS_Embedded_Application.png) + +4. Go to your newly created application and copy the **Application (client) ID** and **Directory (tenant) ID** values. You'll need those later to configure the plugin. + +> ![Go to your newly created application and copy the Application (client) ID and Directory (tenant) ID values. You'll need those later to configure the plugin.](/images/remember-tenant-client.png) + +5. Go to **Certificates and secrets** to generate a new client secret. Make a copy of the secret value, as it will only be shown once. You'll need this value to configure the plugin. + +> ![Go to Certificates and secrets to generate a new client secret. Make a copy of the secret value, as it will only be shown once. You'll need this value to configure the plugin.](/images/remember-client-secret.png) + +6. Go to **API Permissions** to complete the following steps: + +> - Ensure the `User.Read` **delegated** permission is added. See the [Microsoft SSO documentation](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-register-aad#enable-sso-in-microsoft-entra-id) for details. +> - Add the **Microsoft Graph API** `TeamsActivity.Send` **application** permission for notifications. See the [Microsoft notifications documentation](https://learn.microsoft.com/en-us/graph/teams-send-activityfeednotifications?tabs=desktop%2Chttp) for details. +> - Add the **Microsoft Graph API** `AppCatalog.Read.All` **application** permission for notifications. See the [Microsoft List teamsApp documentation](https://learn.microsoft.com/en-us/graph/api/appcatalogs-list-teamsapps?view=graph-rest-1.0&tabs=http) for details. +> - Grant admin consent for the default directory to prevent users from seeing the consent prompt. + +7. Go to **Expose an API** to complete the following steps: + +> - Add/edit a **Application ID URI** and set the value to `api://{{Mattermost Site URL Hostname}}/{{Application (client) ID}}`. +> +> - Add the `access_as_user` scope by selecting **Add a scope** and setting the following values: +> +> - **Scope name**: `access_as_user`. +> - **Who can consent?** Admins and users +> - Provide a display name and description, as well as a user consent display name and description. These will be shown to end users on the consent screen. For example: +> - **Display name**: Log in to Mattermost +> - **Description**: Used to allow O365 users to log in to the Mattermost application +> - **User consent display name**: Log in to Mattermost +> - **User consent description**: This permission is required to automatically log you in into Mattermost from Microsoft applications. +> +> See the [Microsoft API scope documentation](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-register-aad#to-configure-api-scope) for details. +> +> - Add authorised client applications for the scope. See the [Microsoft authorized client documentation](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-register-aad#to-configure-authorized-client-application) for details. +> - Select `_Add a client application_`. **You must add a client application for each target Microsoft application**: +> - **Authorised scopes**: The one we just created +> - **Client ID**: +> - **Teams web**: 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 +> - **Teams app**: 1fec8e78-bce4-4aaf-ab1b-5451cc387264 +> - **Outlook desktop** : d3590ed6-52b3-4102-aeff-aad2292ab01c +> - **Outlook web** : bc59ab01-8403-45c6-8796-ac3ef710b3e3 +> - If you want to make your application available in more Microsoft applications, keep adding client applications from [the following table](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-register-aad#to-configure-authorized-client-application:~:text=Select%20one%20of%20the%20following%20client%20IDs%3A). + +![image](/images/AzureApp_New_Registration_MSEmbedded_ExposeAPI.png) + +### Configure the Mattermost plugin + +A Microsoft Teams app is installed into Microsoft Teams. This app facilitates collaboration between Mattermost and Teams, providing a tab containing Mattermost within the Teams client. The **Teams App** is installed within Microsoft Teams to enable collaboration via a tab. + +1. Download the [latest release of the plugin](https://github.com/mattermost/mattermost-plugin-msteams-devsecops/releases). + +2. Go to **System Console \> Plugins \> Plugin Management \> Upload Plugin**, and upload the plugin binary you downloaded in the previous step. + +3. Go to **System Console \> Plugins \> Plugin Management**. In the **Installed Plugins** section, scroll to **Mattermost Mission Collaboration for Microsoft**. + +4. Enter an **Application Version**. You can start with `1.0.0`. + +5. Generate an Application ID in [version 4 UUID format](https://www.uuidgenerator.net/) and enter it in the **Application ID** field. + +6. Enter the values you noted earlier in the appropriate fields, including **Directory (tenant) ID**, **Application (client) ID**, and **Client Secret**. + + > ![In the Mattermost System Console, enter the Directory (tenant) ID, Application (client) ID, and Client Secret for the plugin.](/images/tenant-client-secret-sysconsole.png) + +7. Enter an **Application Display Name** to define how your application is named in the MS Teams App Store. Make it company specific for easy discovery. + +8. Save the changes and enable the plugin. + +9. Select the **Download Manifest** button to generate the MS Teams application as a ZIP file, containing the app manifest. Save this file as it will be used in the next steps. + +### Install Mattermost in Microsoft Teams + +Within Mattermost, the Mattermost Mission Collaboration for Microsoft plugin needs to be installed and configured. This plugin acts as the integration hub on the Mattermost side, connecting to both the Azure App and the Teams App. The **Mattermost Plugin** is the configuration point within Mattermost that unifies the integration. + +1. Go to the [Microsoft Teams admin center](https://admin.teams.microsoft.com/dashboard). + +2. Go to **Teams apps \> Manage apps**. + + > ![In MS Teams, go to Manage Apps to install the Mattermost Mission Collaboration for Microsoft 365 app.](/images/select-manage-apps.png) + +3. Go to **Actions \> Upload new app** located in the upper-right corner of the Manage apps page. + +4. Select **Upload** and select the ZIP file saved previously. + +5. Done! Your application is now available to users. + +## Use + +### Add the app + +Once the application is deployed, your users can add the Mattermost app to their Microsoft Teams environment. Inform your users to: + +1. Open Microsoft Teams and go to **Apps** in the left sidebar. +2. Search for the **Application Display Name** you configured in the plugin settings (step 7 of the [Configure the Mattermost plugin](#configure-the-mattermost-plugin) section). +3. The app will display a **Built for your org** tag, indicating it's a custom application approved for your organization. +4. Select the app and then select **Add** to install it in their Teams environment. + +Once added, users can access Mattermost directly within Microsoft Teams through the app tab. + +![image](/images/AzureApp_New_Registration_MSEmbedded_TeamsAppAdd.png) + +### Authentication + +This plugin supports automatic authentication when logged into Microsoft Teams. Teams authentication automatically logs users into Mattermost if the email addresses in both platforms match exactly. Regular authentication methods (LDAP, SAML, email/password, OpenID) can additionally be used for Mattermost. + +The integration automatically configures Content Security Policy (CSP) and Frame Ancestors settings to ensure secure embedding of Mattermost within Microsoft Teams, Outlook, and other Microsoft 365 applications. Deep linking is supported, allowing users to select links in Teams notifications and navigate directly to specific Mattermost posts or conversations. + +In air-gapped environments or during business continuity disruptions, users who can't join Microsoft Teams, can continue to access Mattermost using their Mattermost credentials by opening Mattermost in a separate app (e.g., in a new browser window). Alternatively, a Mattermost admin can pre-distribute the Mattermost desktop app using Windows MSI or the mobile app via EMM. + +![Mattermost embedded in a Microsoft Teams tab.](/images/mattermost-in-msteams.png) + +### Activity Feed notifications + +When you're mentioned in Mattermost while working in Microsoft Teams, you'll receive notifications directly in your Teams Activity Feed. This keeps you connected to important Mattermost conversations without switching applications. + +**What triggers notifications:** + +- Direct mentions using @username +- Channel-wide mentions using @channel, @all, or @here +- Direct messages sent to you + +**How it works:** + +When someone mentions you in Mattermost, a notification appears in your Microsoft Teams Activity Feed. Select the notification to open Mattermost and view the full context of the message. This feature uses the `TeamsActivity.Send` permission configured during the Azure app registration setup. + +**Disable notifications:** + +System admins can disable Activity Feed notifications for specific users or across your organization by configuring the `disable_user_activity_notifications` setting in the plugin configuration. This setting is useful if you want to reduce notification noise or if users prefer to check Mattermost manually. + + + +Activity Feed notifications require the `TeamsActivity.Send` application permission to be configured in Azure (step 6 of the [Register an MS Teams app in Azure](#register-an-ms-teams-app-in-azure) section). + + + +## Get Help + +Customers with a Mattermost subscription can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. diff --git a/docs/main/integrations-guide/microsoft-calendar.mdx b/docs/main/integrations-guide/microsoft-calendar.mdx new file mode 100644 index 000000000000..66d65ce753cb --- /dev/null +++ b/docs/main/integrations-guide/microsoft-calendar.mdx @@ -0,0 +1,129 @@ +--- +title: "Connect Microsoft Calendar to Mattermost" +--- + + +Connect your Microsoft M365 Calendar to your Mattermost instance to receive daily summaries of calendar events, synchronize your M365 status in Mattermost, and accept or decline calendar invites from Mattermost. + +## Deploy + +Setup starts in Microsoft Azure and ends in Mattermost. + +### Create a Mattermost App in Azure + +1. Sign in to [portal.azure.com](https://portal.azure.com) using an admin Azure account. +2. Navigate to [App Registrations](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps) +3. Select **New registration** at the top of the page. + +> ![In Azure, create a new app registration.](/images/ms-calendar-new-azure-registration.png) + +4. Fill out the form with the following values. Select **Register** to submit the form. + +> - **Name**: Mattermost MS Calendar Plugin +> - **Supported account types**: Default value (Single tenant) +> - **Redirect URI**: `https:///plugins/com.mattermost.mscalendar/oauth2/complete` Replace `` with your Mattermost server's Site URL. Select **Register** to submit the form. +> +> ![In Azure, create a new app registration.](/images/ms-calendar-single-tenant.png) + +5. Go to **Certificates & secrets** in the left pane. + +> ![In Azure, go to Certificates & secrets located in the left pane.](/images/ms-calendar-certs-secrets.png) + +6. Select **New client secret \> Add**, and copy the new secret in the bottom right corner of the screen. We'll use this value later in the Mattermost System Console. + +> ![In Azure, create a new client secret and copy the value for later.](/images/ms-calendar-new-client-secret.png) + +7. Go to **API permissions** in the left pane. + +> ![In Azure, go to API permissions located in the left pane.](/images/ms-calendar-api-permissions.png) + +8. Select **Add a permission**, then **Microsoft Graph** in the right pane. + +> ![In Azure, add a permission for Microsoft Graph.](/images/ms-calendar-add-permission.png) + +9. Select **Delegated permissions**, and scroll down to select the following permissions. Select **Add permissions** to submit the form: + +> - `Calendars.ReadWrite` +> - `Calendars.ReadWrite.Shared` +> - `MailboxSettings.Read` +> +> ![In Azure, select required permissions.](/images/ms-calendar-delegated-permissions.png) + +10. Add application permissions by going to **Add a permission \> Microsoft Graph \> Application permissions**, and select **Add permissions** to submit the form. +11. Select the following permissions, and then select **Grant admin consent for mattermost** to grant the permissions for the application. + +> - `Calendars.Read` +> - `MailboxSettings.Read` +> - `User.Read.All` +> +> ![In Azure, grant admin consent permissions for the application.](/images/ms-teams-meetings-grant-admin-consent.png) +> +> ![In Azure, final state of the permissions for the application.](/images/ms-teams-meeting-permissions-final-state.png) + +You're all set for configuration in the Azure portal. + +### Install the Microsoft Calendar Integration + +1. Log in to your Mattermost [workspace](/end-user-guide/end-user-guide-index) as a system admin. +2. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +3. Search for or scroll to Microsoft Calendar, and select **Install**. +4. Once installed, select **Configure**. You're taken to the System Console, directly to the **Microsoft Calendar** integration page, under **Plugins**. + + + +From Mattermost v9.11.2 (ESR) and Mattermost Cloud v10, this plugin is pre-packaged with the Mattermost Server. If your Mattermost deployment is on a release prior to v9.11.2, download the [latest plugin binary release](https://github.com/mattermost/mattermost-plugin-mscalendar/releases), and upload it to your server via **System Console \> Plugin Management**. + + + +### Enable and configure the Microsoft Calendar Integration in Mattermost + +1. In Azure, copy the **Application (client) ID** and **Directory (tenant) ID** from the Azure portal. + +> ![In Azure, copy the Client ID and Tenant ID values.](/images/ms-calendar-copy-ids.png) + +2. In Mattermost, go to **System Console \> Plugins \> Microsoft Calendar** to enable this integration. +3. Copy the **Application (client) ID** and **Directory (tenant) ID** from the Azure portal. +4. In Mattermost, enter the following values in the fields provided. Select **Save** to apply the configuration: + +> - **Admin User IDs** - A comma-separated list of [user IDs](/administration-guide/configure/user-management-configuration-settings#identify-a-user-s-id) for authorized users who can manage this integration. +> - **Copy plugin logs to admins, as bot messages** - Select the log level for logs. +> - **Display full context for each admin log message** - Show or hide full context for all log entries. +> - **Azure - Directory (tenant) ID** - Paste the **Directory (tenant) ID** from the Azure portal. +> - **Azure - Application (client) ID** - Paste the **Application (client) ID** from the Azure portal. +> - **Microsoft Office Client Secret** - Copy from the Azure portal (generated in **Certificates & secrets** earlier in these instructions). + +Notify your teams that they can [connect their Microsoft Office accounts to Mattermost](#connect-a-microsoft-calendar-account-to-mattermost). + +## Use + +Users who want to use Microsoft Calendar interconnectivity must connect a Microsoft Office account to Mattermost. + +![Example of the Connect Account prompt in Mattermost.](/images/connect-via-mscalendar-connect.png) + +Once connected, you'll receive direct messages from the Microsoft Calendar bot in Mattermost for Microsoft Calendar activity. + +![Example of the first direct message from the Microsoft Calendar bot in Mattermost.](/images/ms-calendar-intro.png) + +See your upcoming events for the current day by typing `/mscalendar today` in the message input box. + +![Example of a direct message from the Microsoft Calendar bot in Mattermost.](/images/Microsoft-Calendar-viewcal.png) + +A list of all supported slash commands are available by typing `/mscalendar help` in the message input box. + +![Example of supported slash commands for Microsoft Calendar in Mattermost.](/images/microsoft-calendar-slash-commands.png) + +You can customize your notification preferences by typing `/mscalendar settings` in the message input box. + +![Example of the Microsoft Calendar settings in Mattermost.](/images/microsoft-calendar-settings.png) + +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-mscalendar/releases) for the latest release, available releases, and compatibiilty considerations. + +## Get help + +Customers with a Mattermost subscription can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). Community deployments can report a bug by opening a GitHub issue against the [Mattermost Microsoft Calendar plugin repository](https://github.com/mattermost/mattermost-plugin-mscalendar). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. diff --git a/docs/main/integrations-guide/microsoft-teams-meetings.mdx b/docs/main/integrations-guide/microsoft-teams-meetings.mdx new file mode 100644 index 000000000000..5218afffec03 --- /dev/null +++ b/docs/main/integrations-guide/microsoft-teams-meetings.mdx @@ -0,0 +1,116 @@ +--- +title: "Connect Microsoft Teams Meetings to Mattermost" +--- + + +Start and join voice calls, video calls, and use screen sharing with your team members in Microsoft Teams without leaving Mattermost. + +## Deploy + +Setup starts in Microsoft Azure and ends in Mattermost. + +### Create a Mattermost App in Azure + +1. Sign in to the [Azure portal](https://portal.azure.com) using an admin Azure account. +2. Navigate to [App Registrations](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps). +3. Select **New registration** at the top of the page. + +> ![In Azure, create a new app registration.](/images/ms-teams-meetings-new-azure-registration.png) + +4. Fill out the form with the following values, then select **Register** to submit the form: + +> - **Name**: Mattermost Microsoft Teams Meetings Plugin +> - **Supported account types**: Default value (Single tenant) +> - **Redirect URI**: `https:///plugins/com.mattermost.msteamsmeetings/oauth2/complete`. Replace `` with your Mattermost server's Site URL. +> +> ![In Azure, create a new app registration.](/images/ms-teams-meetings-reg-info.png) + +5. Go to **Certificates & secrets** in the left pane. + +> ![In Azure, go to Certificates & secrets located in the left pane.](/images/ms-teams-meetings-certs-secrets.png) + +6. Select **New client secret \> Add**, then copy the new secret in the bottom right corner of the screen. We'll use this value later in the Mattermost System Console. + +> ![In Azure, create a new client secret and copy the value for later.](/images/ms-teams-meetings-new-client-secret.png) + +7. Go to **API permissions** in the left pane. + +> ![In Azure, go to API permissions located in the left pane.](/images/ms-teams-meetings-api-permissions.png) + +8. Select **Add a permission** and select **Microsoft Graph** in the right pane. + +> ![In Azure, add a permission for Microsoft Graph.](/images/ms-teams-meetings-add-permission.png) + +9. Select **Delegated permissions**, and scroll down to select the `OnlineMeetings.ReadWrite` permissions. Select **Add permissions** to submit the form. + +> ![In Azure, select OnlineMeetings.ReadWrite permissions.](/images/ms-teams-meetings-delegated-permissions.png) + +10. Select **Grant admin consent for mattermost** to grant the permissions for the application. + +> ![In Azure, grant admin consent permissions for the application.](/images/ms-teams-meetings-grant-admin-consent.png) + +You're all set for configuration inside of the Azure portal. + +### Install the Microsoft Teams Meetings integration + +1. Log in to your Mattermost [workspace](/end-user-guide/end-user-guide-index) as a system admin. +2. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +3. Search for or scroll to MS Teams Meetings, and select **Install**. +4. Once installed, select **Configure**. You're taken to the System Console, directly to the **MS Teams Meetings** integration page, under **Plugins**. + + + +From Mattermost v9.11.2 (ESR) and Mattermost Cloud v10, this plugin is pre-packaged with the Mattermost Server. If your Mattermost deployment is on a release prior to v9.11.2, download the [latest plugin binary release](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases), and upload it to your server via **System Console \> Plugin Management**. + + + +### Enable and configure the Microsoft Teams Meetings integration in Mattermost + +1. In Azure, copy the **Application (client) ID** and **Directory (tenant) ID** from the Azure portal. + +> ![In Azure, copy the Client ID and Tenant ID values.](/images/ms-teams-meetings-copy-ids.png) + +2. In Mattermost, go to **System Console \> Plugins \> MS Teams Meetings** to enable this integration. +3. In Mattermost, enter the following values in the fields provided. Select **Save** to apply the configuration: + +> - **Azure - Directory (tenant) ID** - Paste the **Directory (tenant) ID** from the Azure portal. +> - **Azure - Application (client) ID** - Paste the **Application (client) ID** from the Azure portal. +> - **Azure - Application (client) Secret** - Copy from the Azure portal (generated in **Certificates & secrets** earlier in these instructions). + +Notify your teams that they can [connect their Microsoft Teams Meetings accounts to Mattermost](#connect-a-microsoft-teams-account-to-mattermost). + +## Use + +Users who want to use MS Teams Meetings interconnectivity must connect a Microsoft Teams Meetings account to Mattermost. + +Once connected, you'll receive direct messages from the Microsoft Teams Meetings bot in Mattermost for Microsoft Teams Meetings activity. + +### Connect a Microsoft Teams account to Mattermost + +Use the /mstmeetings connect slash command to connect an MS Teams account to Mattermost. + +### Start a call + +Start a call either by selecting the video icon in a Mattermost channel or by running the /mstmeetings start slash command. Every meeting you start creates a new meeting room in Microsoft Teams. + + + +If you start two meetings less than 30 seconds apart you'll be prompted to confirm that you want to create the meeting. + + + +### Disconnect a Microsoft Teams account from Mattermost + +Run the /mstmeetings disconnect slash command to disconnect a Microsoft Teams account from Mattermost. + +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-mscalendar) for the latest release, available releases, and compatibiilty considerations. + +## Get help + +Customers with a Mattermost subscription can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). Community deployments can report a bug by opening a GitHub issue against the [Microsoft Teams Notifications plugin](https://github.com/mattermost/mattermost-plugin-msteams-meetings). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. diff --git a/docs/main/integrations-guide/microsoft-teams-sync.mdx b/docs/main/integrations-guide/microsoft-teams-sync.mdx new file mode 100644 index 000000000000..e1beea1c577e --- /dev/null +++ b/docs/main/integrations-guide/microsoft-teams-sync.mdx @@ -0,0 +1,153 @@ +--- +title: "Connect Microsoft Teams to Mattermost" +--- + + +Break through siloes in a mixed Mattermost and Microsoft Teams environment by forwarding real-time chat notifications from Microsoft Teams to Mattermost. + +## Deploy + +Setup starts in Microsoft Teams and ends in Mattermost. + +### Set up an OAuth application in Azure + +1. Sign into [portal.azure.com](https://portal.azure.com) using an admin Azure account. +2. Navigate to [App Registrations](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps). +3. Select **New registration** at the top of the page. + +> ![In Azure, create a new app registration.](/images/new-azure-registration.png) + +4. Fill out the form with the following values: + +> - **Name**: `Mattermost MS Teams` +> - **Supported account types**: `Default value (Single tenant)` +> - **Platform**: `Web` +> - **Redirect URI**: `https://(MM_SITE_URL)/plugins/com.mattermost.msteams-sync/oauth-redirect` + +Replace `(MM_SITE_URL)` with your Mattermost server's Site URL. Select **Register** to submit the form. + +> ![In Azure, register the new Mattermost app.](/images/register-azure-app.png) + +5. From this screen, make note of the **Application (client) ID** and **Directory (tenant) ID**, needed later to configure the plugin in Mattermost. + +> ![Note important IDs to use later.](/images/note-client-and-tenant-id.png) + +6. Navigate to **Certificates & secrets** in the left pane. +7. Select **New client secret**. Enter the description and select **Add**. After the creation of the client secret, copy the new secret value, not the secret ID. We'll use this value later in the Mattermost System Console. + +> ![In Azure, enter client secret details.](/images/azure-certs-secrets.png) + +8. Navigate to **API permissions** in the left pane. +9. Select **Add a permission**, then **Microsoft Graph** in the right pane. + +> ![In Azure, manage API permissions for the Mattermost app.](/images/azure-configured-permissions.png) + +10. Select **Delegated permissions**, and scroll down to select the following permissions: + +> - `Chat.Read` +> - `ChatMessage.Read` +> - `Files.Read.All` +> - `offline_access` +> - `User.Read` + +11. Select **Add permissions** to submit the form. +12. Next, add application permissions via **Add a permission \> Microsoft Graph \> Application permissions**. +13. Select the following permissions: + +> - `Chat.Read.All` +> - `Presence.Read.All` + +14. Select **Add permissions** to submit the form. +15. Select **Grant admin consent for...** to grant the permissions for the application. + +### Ensure you have the metered APIs enabled (and the pay subscription associated to it) + +Subscribing to chat notifications requires assocating the OAuth App with a paid Azure subscription. To complete this setup, follow the instructions at [https://learn.microsoft.com/en-us/graph/metered-api-setup](https://learn.microsoft.com/en-us/graph/metered-api-setup). + + + +If you don't configure the metered APIs, you must use the **Evaluation model** (configurable in Mattermost) that is limited to a low rate of changes per month. We strongly recommend that you avoid using the Evaluation model configuration in live production environments because you can stop receiving messages due the rate limit. See [this Microsoft documentation](https://learn.microsoft.com/en-us/graph/teams-licenses) for more details. + + + +You're all set for configuration inside Azure. + +### Install and configure the Microsoft Teams integration in Mattermost + + + +These installation instructions assume you already have a Mattermost instance running v9.8.0 (or later) and configured to use PostgreSQL. This Mattermost integration doesn't support MySQL databases. + + + +1. Log in to your Mattermost [workspace](/end-user-guide/end-user-guide-index) as a system admin. +2. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +3. Search for or scroll to MS Teams, and select **Install**. +4. Once installed, select **Configure**. You're taken to the System Console. +5. Configure the **Tenant ID**, **Client ID**, and **Client Secret** with the values obtained from setting up the OAuth App in Azure above. + +See the [Microsoft Teams plugin configuration settings](/administration-guide/configure/plugins-configuration-settings#ms-teams) documentation for additional configuration options. + + + +- From Mattermost v9.11.2 (ESR) and Mattermost Cloud v10, v2.0 of this plugin is pre-packaged with the Mattermost Server. If your Mattermost deployment is on a release prior to v9.11.2, download the [latest plugin binary release](https://github.com/mattermost/mattermost-plugin-msteams), and upload it to your server via **System Console \> Plugin Management**. +- We recommend making a copy of your webhook secret and encryption key, as it will only be visible to you once. + + + +## Monitor performance + +You can set up [performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring) and [performance alerting](/administration-guide/scale/performance-alerting) for this plugin using Prometheus and Grafana. + +- Monitoring enables you to proactively review the overall health of the plugin, including database calls, HTTP requests, and API latency. +- Alerting enables you to detect and take action as issues come up, such as the integration being offline. + +Grafana dashboards [are available on GitHub](https://github.com/mattermost/mattermost-plugin-msteams/tree/main/server/metrics/dashboards) for Mattermost Cloud deployments as a useful starting point. These dashboards are designed for use in Mattermost Cloud, and filter to a given `namespace`. + +![Example of a Grafana monitoring dashboard for a Mattermost instance connected to Microsoft Teams.](/images/grafana-dashboard-msteams.png) + + + +Modifications will be necessary for self-hosted Mattermost deployments. See the [Get help](#get-help) section below for details on how to contact us for assistance. + + + +## Use + +See the [collaborate within connected microsoft teams](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams) product documentation to start receiving Microsoft Teams notifications. + +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-msteams) for the latest release, available releases, and compatibiilty considerations. + +## Frequently asked questions + +### My email address in Mattermost doesn't match my email address in Microsoft Teams: can I still connect? + +No. Currently, only accounts with the same email addresses are allowed to be connected. Specify the email address that matches your Mattermost account. + +If connecting a Mattermost account to a Microsoft Teams account with a different email address is something your workspace requires, there is an open [GitHub issue](https://github.com/mattermost/mattermost-plugin-msteams/issues/519) for you to share your feedback. + +### How is encryption handled at rest and in motion? + +The configured client secret, stored in the Mattermost configuration, is used for app-only access to the the Microsoft Graph API. As users connect to Microsoft Teams using the integration, the resulting access tokens are encrypted and stored in the Mattermost database to be used for access on behalf of the connected user. All communication between the integration and the Microsoft Graph API is conducted via TLS. + +When notifications are enabled, chats and file attachments received by connected users will be stored as posts in the direct message channel between that user and the bot account created by the integration. + +### Are there any database or network security considerations? + +There is nothing specific to the integration that is beyond what would apply to a Mattermost instance. + +### Are there any compliance considerations (ie. GDPR, PCI)? + +There is nothing specific to the integration that is beyond what would apply to a Mattermost instance. + +### How is this integration architectured? + +The integration subscribes to change notifications from the Microsoft Graph API. These change notifications inform Mattermost about new or updated chats within Microsoft Teams. Upon receipt of the change notification, the integration uses a combination of its app-only access (via the client secret) and delegated acess (via connected users) to fetch the contents of these chats and represent them appropriately within Mattermost. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost for Microsoft Teams Notifications plugin repository](https://github.com/mattermost/mattermost-plugin-msteams). + +For questions, feedback, and assistance, join our pubic [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. diff --git a/docs/main/integrations-guide/no-code-automation.mdx b/docs/main/integrations-guide/no-code-automation.mdx new file mode 100644 index 000000000000..d55f376a686d --- /dev/null +++ b/docs/main/integrations-guide/no-code-automation.mdx @@ -0,0 +1,121 @@ +--- +title: "No-Code Automation" +--- + + +**Technical complexity:** [No-code](#no-code) + +Platforms like n8n, Zapier, or Make provide powerful visual editors that support thousands of connected tools, with triggers and actions that integrate Mattermost to external services, enabling teams to build complex workflows without writing code. Admins migrating from tools like Slack Workflow Builder can recreate familiar automations in Mattermost using these platforms. + +When used in comination with outgoing webhooks or custom slash commands, users can trigger complex workflows and automations without leaving Mattermost. By pointing a webhook or slash command at the unique URL these automation tools provide, any message or keyword in Mattermost can initiate a workflow. This allows you to capture context from conversations and pass it into external systems — for example, creating tickets, updating records, or starting multi-step automations. + +Choosing the best platform for your team depends on your specific integration requirements, hosting preferences, and technical capabilities. Learn more about the capabilities of each platform below: + +
+ +n8n + +[n8n](https://n8n.io/) is ideal for organizations prioritizing data residency and security, since it is self-hosted and can be supported in air-gapped environments where cloud solutions like Zapier and Make might not be feasible. + +Additonally, n8n supports both [no-code](#no-code) and [low-code](#low-code) approaches, making it flexible for technical and semi-technical users. Being open source means there’s a large community of people sharing their custom workflows and automations that can either be used directly or iterated on to meet your specific requirements. + +n8n stands out for offering rich AI integration, enabling you to combine automation with AI-powered workflows. Its [native AI Agent node](https://n8n.io/ai/) lets you integrate large language models, vector databases, and other AI services directly into your automations. This means you can build workflows in Mattermost that not only react to events but also analyze context, summarize discussions, or make decisions based on AI output. + +Explore building workflows with the [Mattermost n8n integration](https://n8n.io/integrations/mattermost/). + +## Supported Triggers + +- MattermostTrigger (community node): Listens for Mattermost events via WebSocket events, such as new post and users added. + +You can also use outgoing webhooks or slash commands in Mattermost as triggers using the [Webhook node](https://n8n.io/integrations/webhook/). + +## Supported Actions + +- Channels + - Add a user to a channel + - Create a new channel + - Soft delete a channel + - Restore a soft deleted channel + - Get statistics for a channel +- Messages + - Post a message into a channel + - Post an ephemeral message into a channel + - Soft delete a post +- Reactions + - Add a reaction to a post + - Remove a reaction from a post + - Get all reactions to one or more posts +- Users + - Create a new user + - Deactivate a user (archive, revoke sessions) + - Invite user to a team + +## Supported Searches + +- Search for a channel +- Get a user by email +- Get a user by ID +- Retrieve all users +- Retrieve members of a channel + +
+ +
+ +Make + +Make offers a more visual and flexible approach to automation, allowing you to build complex workflows with advanced logic and data manipulation. Make offers one of the most expansive sets of out-of-the-box triggers and actions for Mattermost. + +Make is hosted in the cloud, and excels at more complex multi-step workflows while still keeping the configuration non-technical. + +Explore building workflows with the [Mattermost Make integration](https://www.make.com/en/integrations/mattermost). + +## Supported Triggers + +- Watch New Posts: Fires when a new post is added. +- Watch New Posts Pinned for a Channel: Fires when a post is pinned in a channel. +- Watch New Users: Fires when a new user is added. + +## Supported Actions + +- Add a User to a Team: Add a user into a specific team. +- Check if the Team Exists: Verify whether a team exists by name. +- Create a Command: Add a custom command within a team. +- Create a New User: Create a user account on the Mattermost system. +- Create a Post: Post a message in a channel. +- Deactivate a User Account: Archive or disable a user account. +- Delete a Command: Remove a command by its ID. +- Delete a Post: Remove a post. +- Execute a Command: Run or trigger an existing command. + +You can also use outgoing webhooks or slash commands in Mattermost as triggers using the [Webhook app](https://www.make.com/en/integrations/gateway). + +## Supported Searches + +- Get a Channel: Retrieve a channel by its ID. +- Get a Post: Retrieve a post by its ID. +- Get a File: Retrieve an uploaded file by its ID. +- Get a User: Retrieve a user by their user ID. +- Get a Team by Name: Retrieve team information by team name. + +
+ +
+ +Zapier + +Zapier is ideal for non-technical users who want the fastest path to connect Mattermost with over 7000+ SaaS apps. It’s hosted in the cloud, easy to set up, and best for common business workflows. + +Zapier’s strength is the breadth of integrations. Without coding, you can integrate Mattermost with everything from CRMs to social media. This is perfect for non-technical users who want to automate notifications or routine tasks, such as posting daily reports or sending Mattermost channel messages when forms are submitted. Zapier provides a user-friendly wizard and template library to get started quickly. + +Explore building workflows with the [Mattermost Zapier integration](https://n8n.io/integrations/mattermost/). + +## Supported Triggers + +- Zapier does not natively support triggers in Mattermost. If you want Mattermost to trigger a Zapier workflow, you can use outgoing webhooks or slash commands in combination with [Zapier’s Webhooks trigger](https://zapier.com/apps/webhook/integrations). For example, you could configure an outgoing webhook in Mattermost to hit Zapier when a certain keyword is posted, which Zapier treats as a trigger to then perform actions in other apps. + +## Supported Actions + +- Compared with the wide range of triggers and actions supported by n8n or Make, Zapier supports only one action: posting a message. + +
diff --git a/docs/main/integrations-guide/outgoing-webhooks.mdx b/docs/main/integrations-guide/outgoing-webhooks.mdx new file mode 100644 index 000000000000..3d5e63169999 --- /dev/null +++ b/docs/main/integrations-guide/outgoing-webhooks.mdx @@ -0,0 +1,242 @@ +--- +title: "Outgoing Webhooks" +--- + + +**Technical complexity:** [Low-code](#low-code) + +Outgoing webhooks can be used to create rich, interactive experiences in Mattermost by letting external services respond with rich message attachments, such as structured fields, buttons, and menus. Additionally, these responses can trigger interactive dialog forms where users provide additional input directly in Mattermost, or interactive messages that update dynamically based on user actions. Together, these capabilities turn simple keyword triggers into powerful in-product workflows that streamline how teams interact with external systems, all with minimal coding required. + +Outgoing webhooks require no coding to configure on in Mattermost, however the external service that receives the HTTP POST request needs to process the data, and then format and send a respond with a message back to Mattermost. This usually requires light coding to parse the request and format a JSON response payload, though many [automation platforms](/integrations-guide/integrations-guide-index#build-and-automate-workflows) handle this without writing custom code. + +Learn more about [outgoing webhooks](/integrations-guide/outgoing-webhooks). + +## Example Use Cases + +Here are some example use cases for outgoing webhooks in Mattermost: + +**Issue tracking integration** + +When a user types `bug` in a channel, an outgoing webhook sends the message to an external service that parses the details and responds with an interactive dialog in Mattermost. The user can enter fields like priority, description, and assignee, and submitting the dialog automatically creates a ticket in your ticketing software. + +**Knowledge base lookup** + +A keyword like `docs` triggers an outgoing webhook that queries a documentation service and returns a rich interactive message with a list of suggested articles, each with clickable buttons or menus. Users can refine their search or open links without leaving Mattermost. + +**Security incident enrichment** + +Typing a keyword like `ioc` (indicator of compromise) in a security channel can trigger an outgoing webhook that queries a threat intelligence platform. The response can return a formatted message attachment with reputation scores, related incidents, and quick-action buttons for escalating, investigating, or dismissing the alert. + +## Create + +1. In Mattermost, go to **Product Menu \> Integrations**. If you don't have the **Integrations** option, outgoing webhooks may not be enabled on your Mattermost server or may be disabled for non-admins. A System Admin can enable them from **System Console \> Integrations \> Integration Management**. + +> ![Mattermost menu options showing the ability to work with integrations.](/images/product-menu-integrations.png) + +2. From the Integrations page, select **Outgoing Webhooks**. + +> ![Dialog box showing the option to add an outgoing webhook.](/images/manage-webhooks.png) + +3. Select **Add Outgoing Webhook**. + +> ![Dialog box showing the option to add an outgoing webhook.](/images/select-add-outgoing-webhook.png) + +4. Enter a name and description for the webhook. +5. Specify the **Content Type** for the request. + +> - `application/json` will send a JSON object. +> - `application/x-www-form-urlencoded` will encode the parameters in the URL. + +6. Specify a **Channel** and/or one or more **Trigger Words**. + +> - If you specify a channel, the webhook will only fire for messages in that channel. +> - If you specify trigger words, the webhook will only fire when a message starts with one of those words. +> - If both are specified, the message must match both conditions. +> - If you leave the channel blank, the webhook will listen to all public channels in your team. +> - If you leave the trigger words blank, the webhook will respond to all messages in the selected channel. +> +> ![Dialog box showing the outgoing webhook details.](/images/create-outgoing-webhook-details.png) + +7. Set one or more **Callback URLs** that the HTTP POST requests will be sent to. Select **Save**. + +> ![Dialog box showing the outgoing webhook callback URLs.](/images/create-outgoing-webhook-details-more.png) + +8. Copy the **Token** value. This token is used to verify that the requests are coming from Mattermost. + +![Dialog box showing the outgoing webhook token.](/images/outgoing-webhook-created.png) + +## Use + +When a message triggers the webhook, Mattermost will send an HTTP POST request to the callback URL(s) you specified. + +### Request Payload + +The request body will contain the following data (either as JSON or URL-encoded, depending on the content type you selected): + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
tokenThe token generated when you created the webhook.
team_idThe ID of the team the message was posted in.
team_domainThe domain of the team.
channel_idThe ID of the channel the message was posted in.
channel_nameThe name of the channel.
timestampThe time the message was posted.
user_idThe ID of the user who posted the message.
user_nameThe username of the user who posted the message.
post_idThe ID of the post.
textThe full text of the message.
trigger_wordThe trigger word that was matched.
+ +Your application should validate the `token` to ensure the request is from Mattermost. + +### Response Payload + +Your application can respond to the POST request with a JSON object to post a message back to Mattermost. + +``` json +{ + "text": "| Component | Tests Run | Tests Failed |\n|:-----------|:----------|:-------------|\n| Server | 948 | :white_check_mark: 0 |" +} +``` + +This would render in Mattermost as: + +![Example of a formatted table response from an outgoing webhook.](/images/webhooksTable.png) + +## Response Parameters + +The JSON response can contain the following parameters: + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
text(Required if attachments is not set) Markdown-formatted message.
response_typeSet to comment to reply to the message that triggered the webhook. Defaults to post, which creates a new message.
usernameOverrides the default username. Requires Enable integrations to override usernames to be enabled.
icon_urlOverrides the default profile picture. Requires Enable integrations to override profile picture icons to be enabled.
attachments(Required if text is not set) An array of message attachment objects.
typeSets the post type, mainly for plugins. If set, must begin with custom_.
propsA JSON object for storing metadata.
prioritySets the priority of the message. See message priorities.
+ +### Example with Parameters + +``` json +{ + "response_type": "comment", + "username": "test-automation", + "icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png", + "text": "#### Test results for July 27th, 2017\n@channel here are the requested test results.", + "props": { + "test_data": { + "server": 948, + "web": 123, + "ios": 78 + } + } +} +``` + +This response would produce a threaded reply to the original message that triggered the webhook. + +Example of a full response from an outgoing webhook. + +You can also include [message attachments](https://developers.mattermost.com/integrate/reference/message-attachments/) and [interactive messages](https://developers.mattermost.com/integrate/plugins/interactive-messages/) in your response to create more advanced workflows. + +## Do More with Outgoing Webhooks + +Turn keyword-triggered callbacks into guided, in-channel workflows by returning buttons, menus, and other interactive elements in your webhook responses so users can act immediately. + +- [Message Attachments](https://developers.mattermost.com/integrate/reference/message-attachments/): Return rich, structured results (IDs, statuses, fields, links, images) for quick confirmation and follow-up. +- [Interactive Messages](https://developers.mattermost.com/integrate/plugins/interactive-messages/): Present next-step actions (Acknowledge, Assign, Escalate) as buttons/menus directly in your response—no context switching. +- [Interactive Dialogs](https://developers.mattermost.com/integrate/plugins/interactive-dialogs/): When a button/menu click requires more info (e.g., “Acknowledge with note”, “Assign to user”), open a dialog to collect structured inputs with required fields, min/max lengths, server-driven user/channel pickers, validated defaults, inline field errors, placeholders, and help text. +- [Message Priority](https://developers.mattermost.com/integrate/reference/message-priority/): Include `priority` in your response to mark critical updates and optionally request acknowledgements or persistent notifications. + + + +- Outgoing webhook responses support attachments and interactive actions. When a user clicks an action, your integration receives a signed trigger ID and can open an interactive dialog via the dialog API. You can also control visibility with the response type (in-channel vs ephemeral). +- Need a dedicated identity, permissions scoping, or need to post outside of webhook/command flows? Use a [bot account](https://developers.mattermost.com/integrate/reference/bot-accounts/) if you need a more permanent solution than using overrides for simple branding. +- If your command backend needs to call Mattermost APIs (e.g., posting messages, ephemeral posts, opening interactive dialogs, etc.), authenticate with a bot user [personal access token](https://developers.mattermost.com/integrate/reference/personal-access-token/). We recommend avoiding human/System Admin personal access tokens for automations and rotating and storing tokens securely. +- Looking to support private channels, direct messages, and autocomplete? Use a [built-in slash command](/integrations-guide/built-in-slash-commands), or create a [custom slash command](https://developers.mattermost.com/integrate/slash-commands/custom/). You can additionally tegrate Mattermost with custom integrations hosted within your internal OAuth infrastructure [using the Client Credentials OAuth 2.0 grant type](https://developers.mattermost.com/integrate/slash-commands/outgoing-oauth-connections/). Mattermost also makes it easy to [migrate integrations written for Slack to Mattermost](https://developers.mattermost.com/integrate/slash-commands/slack/). + + diff --git a/docs/main/integrations-guide/plugins.mdx b/docs/main/integrations-guide/plugins.mdx new file mode 100644 index 000000000000..a474026bcdd8 --- /dev/null +++ b/docs/main/integrations-guide/plugins.mdx @@ -0,0 +1,28 @@ +--- +title: "Plugins" +--- +## Pre-built plugins + +**Technical complexity:** [No-code](#no-code) + +Mattermost's pre-built plugins make it simple for teams to extend Mattermost with powerful integrations for project management, incident response, monitoring, and collaboration. With simple configuration steps, you can quickly connect Mattermost to widely used tools such as Jira, GitHub, GitLab, Zoom, ServiceNow and others, enabling powerful integrations that enhance collaboration and streamline workflows out of the box. + +Learn more about what popular [pre-built integrations are available and how to install them](/integrations-guide/popular-integrations). + + + +The [Mattermost Marketplace](https://mattermost.com/marketplace/) offers an expanded selection of community supported integrations. + + + +## Custom-built plugins + +**Technical complexity:** [Pro-code](#pro-code) + +Building a custom plugin for your self-hosted deployment is a **software development** task, using `Go` for the server-side functionality and optionally `TypeScript/React` for UI components. Developers should be comfortable with Git, modern build tooling, and the [Mattermost Plugin API](https://developers.mattermost.com/integrate/reference/server/server-reference/), including lifecycle hooks, KV storage, slash commands, and interactivity. Knowledge of testing, logging, and security best practices is essential for production-ready plugins, along with experience packaging and deploying plugins through the System Console or CLI. For teams without these skills, simpler options like webhooks, slash commands, or no-code workflow tools may be more practical. + +Plugins can authenticate and interact with Mattermost through [bot accounts](https://developers.mattermost.com/integrate/reference/bot-accounts/), utilizing the [RESTful API](https://developers.mattermost.com/api-documentation/). + +From Mattermost v11.5, plugins can register a Channel Header Icon component that places an icon next to the **Files** button in the channel header. This pluggable location is designed for channel-level actions such as custom workflows, analysis, or summarization tools. + +Learn more about [building your own plugin](https://developers.mattermost.com/integrate/plugins/). diff --git a/docs/main/integrations-guide/popular-integrations.mdx b/docs/main/integrations-guide/popular-integrations.mdx new file mode 100644 index 000000000000..5e7391dece89 --- /dev/null +++ b/docs/main/integrations-guide/popular-integrations.mdx @@ -0,0 +1,128 @@ +--- +title: "Popular Pre-Built Integrations" +draft: true +--- +Accelerate your operational and technical workflows by connecting Mattermost with your mission-critical tools through pre-built integrations. + +## Mattermost Integrations + +Designed for teams that need reliability, auditability, and ownership of their collaboration stack, the following Mattermost collaboration integrations keep your data all inside your secure Mattermost ecosystem. Reduce tool sprawl, strengthen security, improve compliance posture, all with a seamless user experience. + + +++ + + + + + + + + + + + + + + +
+

Mattermost Integration | How to Get It | What It Does |

+
+
+
================================================================================================+===================================================================+============================================================================================================+
+
+

Mattermost Channel Export | product-list > App Marketplace | Exports channel history and data for compliance purposes.

+
+
Mattermost Legal Hold | Manual Upload | Keeps a copy of messages and files so they cannot be deleted for legal or compliance needs. |
Mattermost Metrics | product-list > App Marketplace | Shows numbers about system performance when people use Mattermost.
Mattermost User Survey | product-list > App Marketplace | Collects feedback by asking questions directly in Mattermost channels.
+ +## Microsoft Integrations + +If your organization relies on Microsoft tools, Mattermost offers deep integrations with M365, Teams, Outlook, and Calendar to keep collaboration seamless and secure. These integrations allow you to enhance and extend Microsoft tools while maintaining Mattermost as your central hub. By connecting Mattermost with Microsoft apps, you reduce context switching, strengthen reliability through secure fallback options, and ensure your workflows stay efficient across both platforms. + + +++ + + + + + + + + + + + + + + +
+

Microsoft Integration | Where to Get It | What It Does |

+
+
+
==================================================================================+======================================+===============================================================================================+
+
+

Mattermost Embedded for M365, Teams, and | Manual Upload | Embed Mattermost in Microsoft apps. | Outlook | | Use Outlook and Teams together with Mattermost for secure backup and extra features. |

+
+
Microsoft Calendar | product-list > App Marketplace | Sends your Microsoft Calendar reminders into Mattermost so you don’t miss events.
Microsoft Teams Meetings | product-list > App Marketplace | Lets you start or join Microsoft Teams meetings directly from Mattermost.
Microsoft Teams Sync | product-list > App Marketplace | Copies messages from Microsoft Teams into Mattermost (one-way) to keep conversations in sync.
+ +The following integrations bring key external tools (DevOps, ITSM, monitoring, and meetings) into Mattermost, so teams can see updates, take action, and collaborate faster without leaving their secure chat environment. + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Third-Party Integration | Where to Get It | What It Does |

+
+
+
=========================================================================+===================================================================+=========================================================================================================================+
+
+

GitHub | product-list > App Marketplace | Shows GitHub updates, like new pull requests, commits, or issues, in Mattermost channels.

+
+
GitLab | product-list > App Marketplace | Sends GitLab activity (code pushes, merge requests, CI/CD pipeline updates) into Mattermost channels.
Jira | product-list > App Marketplace | Lets you see, create, and update Jira issues inside Mattermost.
PexipMattermost MarketplaceLets you start and join Pexip video meetings from Mattermost.
ServiceNow | product-list > App Marketplace | Sends ServiceNow updates (like tickets or incidents) into Mattermost and lets you take action from chat.
SplunkMattermost MarketplaceSends Splunk alerts and search results directly into Mattermost channels.
Zoom | product-list > App Marketplace | Lets you start and join Zoom meetings from inside Mattermost.
+ +## More on Marketplace + +More integrations are available on the [Mattermost Marketplace](https://mattermost.com/marketplace/). You can install these integrations directly from the Marketplace, by uploading them in the System Console, or by using the REST API. + + + +- Installed plugins are persisted to the configured file store and unpacked on server startup. It's imperative that your file store be accessible to the server immediately on startup. If using a shared filesystem, ensure the mount completes successfully before starting the server. +- We strongly recommend testing integration updates in a staging environment before deploying to production, and regularly backing up integrations. + + diff --git a/docs/main/integrations-guide/restful-api.mdx b/docs/main/integrations-guide/restful-api.mdx new file mode 100644 index 000000000000..442a6dd46742 --- /dev/null +++ b/docs/main/integrations-guide/restful-api.mdx @@ -0,0 +1,32 @@ +--- +title: "RESTful API" +--- + + +**Technical complexity:** [Pro-code](#pro-code) + +Full developer control for automation, bots, and integrations. + +The [Mattermost API](https://developers.mattermost.com/api-documentation/) provides a comprehensive set of endpoints that let you programmatically interact with your Mattermost workspace. With the API, you can manage users, teams, channels, posts, and more, making it possible to automate administrative tasks, integrate external systems, and build custom applications that extend Mattermost functionality. Whether you’re writing lightweight scripts or developing full-scale integrations, the API offers flexible building blocks to tailor Mattermost to your workflows. + +Using the API is a pro-code approach meant for developers who want to write scripts to automate specific workflows or build deeply customized integrations using the plugin framework to connect external systems. + +The API is often used in combination with [bot accounts](https://developers.mattermost.com/integrate/reference/bot-accounts/) to authenticate and interact with Mattermost. + +## Example Use Cases + +Here are some example use cases for API integration in Mattermost: + +**User provisioning** + +Write a script to automatically create and manage user accounts in Mattermost, ensuring that new team members are added to the right teams and channels as part of your onboarding process. + +**Channel management** + +Use the API to programmatically create, archive, or update channels, making it easy to align collaboration spaces with your project lifecycle or organizational changes. + +**Message automation** + +Build a script or integration that posts messages or reminders into specific channels on a schedule, such as daily stand-up prompts, release announcements, or security notifications. + +Learn more about using the [API and available endpoints](https://developers.mattermost.com/api-documentation/). diff --git a/docs/main/integrations-guide/run-slash-commands.mdx b/docs/main/integrations-guide/run-slash-commands.mdx new file mode 100644 index 000000000000..8eaa5d7c7dac --- /dev/null +++ b/docs/main/integrations-guide/run-slash-commands.mdx @@ -0,0 +1,14 @@ +--- +title: "Run Slash Commands" +--- + + +Using a slash command is as easy as composing a message. Instead of message text, you start slash commands with a slash character: `/`. + +For example, if you want to log out of Mattermost using only your keyboard, you can enter `/logout` in the message text box and select **Send**. + +Because your message starts with a slash `/`, Mattermost knows it's a slash command, and performs the action defined for that command. + +## Create custom slash commands + +Interested in creating new custom slash commands for your Mattermost instance? Visit our [developer documentation](https://developers.mattermost.com/integrate/slash-commands/custom/) to learn more about creating custom slash commands for your work processes. diff --git a/docs/main/integrations-guide/servicenow.mdx b/docs/main/integrations-guide/servicenow.mdx new file mode 100644 index 000000000000..1403531f89e2 --- /dev/null +++ b/docs/main/integrations-guide/servicenow.mdx @@ -0,0 +1,150 @@ +--- +title: "Connect ServiceNow to Mattermost" +--- + + +Minimize distractions and reduce context switching by bridging the gap between IT service management (ITSM) and team communication. Create and manage incident reports, change requests, and service tickets, as well as manage event-driven notification subscriptions for ServiceNow record changes, in real-time, and automate routine tasks to decrease response times without leaving Mattermost. + +## Deploy + +Setup starts in ServiceNow and finishes in Mattermost. + +### Create an OAuth app in ServiceNow + +1. Go to your ServiceNow instance and then to **All \> System OAuth \> Application Registry**. +2. Select New in the top right corner, and then select **Create an OAuth API endpoint for external clients**. +3. Enter the name for your app and set the redirect URL to: `https:///plugins/mattermost-plugin-servicenow/api/v1/oauth2/complete`, replacing `YOUR-MATTERMOST-URL` with the Mattermost URL you want the ServiceNow events to post to, using lowercase characters. + + + +A client secret is generated automatically. Copy the secret and the Client ID. You'll need these values for the Mattermost configuration. + + + +### Upload the update set in ServiceNow + +Changing your ServiceNow instance to support subscriptions, record changes, and send change notifications to Mattermost is done by a Mattermost and ServiceNow system admin using an [update set](https://docs.servicenow.com/bundle/washingtondc-application-development/page/build/system-update-sets/concept/system-update-sets.html). Once created, you can download the update set from Mattermost and upload it into ServiceNow. + +1. In the Mattermost System Console, download the update set XML file. +2. In your ServiceNow instance, go to **All \> System Update Sets \> Retrieved Update Sets**. +3. Select the **Import Update Set from XML** link at the bottom of the page. +4. Select the downloaded XML update set file and upload it. You'll see an update set named **ServiceNow for Mattermost Notifications**. +5. Select that update set, and then select **Preview Update Set**. +6. Select **Commit Update Set**. +7. Confirm the data loss notification, and select **Proceed with Commit**. Your update set is uploaded and committed to ServiceNow. + +### Set up user permissions in ServiceNow + +Once the update set is uploaded, it creates a new role called `x_830655_mm_std.user`. Users must have this role in ServiceNow to add or manage Mattermost subscriptions. You need to be a ServiceNow system admin to add the `x_830655_mm_std.user` role to all users who should have the ability to add or manage subscriptions through Mattermost. + +1. In your ServiceNow instance, go to **All \> User Administration \> Users**. +2. On the Users page, open a user's profile where you want the role added. +3. Select the **Roles** tab in the table, and select **Edit**. +4. Search for the `x_830655_mm_std.user` role, and add that role to the user's **Roles** list, and select **Save**. That user can now add or manage Mattermost subscriptions. + +### Update the API secret on the change of ServiceNow Webhook Secret + +1. In Mattermost, copy the **Webhook Secret** from your Mattermost instance by going to **System Console \> Plugins \> ServiceNow**. +2. In your ServiceNow instance, go to **All \> x_830655_mm_std_servicenow_for_mattermost_notifications_auth.list**. (**Note**: You must enter the complete name and search.) +3. On the page, select the row containing your Mattermost Server URL. If that row doesn't exist, create it manually by selecting **New** located in the top-right corner, and adding your Mattermost Server URL. +4. Update the **API Secret** in the ServiceNow instance with the **Webhook Secret** from Mattermost, and select **Update**. + +#### What changes are made to ServiceNow instance? + +- **GetStates scripted REST API**: Returns different states available for the records. Records supported: incident, task, change_task, and cert_follow_on_task +- An application with the name **ServiceNow for Mattermost Notifications**. + +> - **ServiceNow for Mattermost Notifications** application handles the storing of subscription details and sending notifications on the subscribed events. +> - **ServiceNow for Mattermost Notifications** `Auth` table to store different Mattermost server URLs with their webhook secrets. +> - **ServiceNow for Mattermost** `Subscriptions` table to store the subscription details. +> - **Business rules** to handle different events (example: new record created, comment added on record, record state updated, etc.) +> - **Script actions** to send notifications based on the subscription events. +> - **Events registration** to register different record-type events. + +#### ServiceNow tables accessible in Mattermost + +- `incident` +- `problem` +- `change_request` +- `kb_knowledge` +- `task` +- `change_task` +- `cert_follow_on_task` +- `x_830655_mm_std_servicenow_for_mattermost_notifications_auth` +- `x_830655_mm_std_servicenow_for_mattermost_subscriptions` +- All the tables extending these tables above + + + +Subscriptions are only supported for `incident`, `problem`, and `change_request` record types. + + + +### Mattermost configuration + +A Mattermost system admin must perform the following steps in Mattermost. + +Install the ServiceNow integration from the in-product App Marketplace: + + + +We recommend making a copy of your webhook and encryption secret, as it will only be visible to you once. + + + +1. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +2. Search for or scroll to ServiceNow, and select **Install**. +3. Once installed, select **Configure**. You're taken to the System Console. +4. On the ServiceNow configuration page, enable and configure ServiceNow interoperability as follows, and then select **Save**: + +> - **ServiceNow Server Base URL**: Enter the base URL of your ServiceNow instance. +> - **ServiceNow Webhook Secret**: Regenerate the webhook secret for ServiceNow. Regenerating this key will stop the subscription notifications. See the documentation on [creating an OAuth app in ServiceNow](#create-an-oauth-app-in-servicenow) for details on updating the secret in the ServiceNow instance and start receiving notifications again. +> - **ServiceNow OAuth Client ID**: The clientID of your registered OAuth app in ServiceNow. +> - **ServiceNow OAuth Client Secret**: The client secret of your registered OAuth app in ServiceNow. +> - **Encryption Secret**: Select **Regenerate** to generate a new encryption secret. This encryption secret is used to encrypt and decrypt the OAuth token. Regenerating this secret will require all users to reconnect their ServiceNow accounts. +> - **Download ServiceNow Update Set**: Download the update set XML file to upload to ServiceNow. + +## Enable + +Notify your teams that they can [connect their ServiceNow accounts to Mattermost](#connect-a-servicenow-account-to-mattermost). + +## Upgrade + +We recommend updating this integration as new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-servicenow/releases) for the latest release, available releases, and compatibility considerations. + +## Use + +Users who want to use ServiceNow interconnectivity must connect a ServiceNow account to Mattermost. + +Once connected, you'll receive direct messages from the ServiceNow bot in Mattermost for ServiceNow activity. + +### Connect a ServiceNow account to Mattermost + +1. In Mattermost, run the `/servicenow connect` slash command in any Mattermost channel to link your Mattermost account with your ServiceNow account. Follow the link into your ServiceNow instance, and select **Allow**. You can disconnect your accounts by running the `/servicenow disconnect` slash command. Alternatively, select the **ServiceNow** icon in the apps bar on the right to connect your ServiceNow account. +2. Once connected, run the `/servicenow help` slash command to see what you can do. + +Available slash commands include `/servicenow subscriptions` to manage notification subscriptions, `/servicenow share` to search and share ServiceNow records in a channel, and `/servicenow incident create` to create a new incident directly from Mattermost. + +## Customize + +This integration contains both a server and web app portion. + +ServiceNow itself provides developer instances to anyone who wishes to develop on ServiceNow. Developers can get a ServiceNow developer instance by logging in to their ServiceNow developer account, and selecting **Request Instance** in the top right corner. Once the instance is created, open the menu from the top right corner, go to **Manage Instance Password**, and log in to the developer instance in a new tab. + +See the [Development](https://github.com/mattermost/mattermost-plugin-servicenow/blob/master/docs/developer_docs.md#development) section of the Mattermost ServiceNow Plugin GitHub repository for details on customizing this integration. + +Visit the [Mattermost Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Mattermost Developer environment setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for information about developing, customizing, and extending Mattermost functionality. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost ServiceNow plugin repository](https://github.com/mattermost/mattermost-plugin-servicenow). + +For questions, feedback, and assistance, join our public [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. + + + +Watch [this on-demand webinar on incident response with Mattermost and ServiceNow](https://mattermost.com/video/streamline-incident-response-with-mattermost-and-servicenow/) to learn how to streamline incident response. + + diff --git a/docs/main/integrations-guide/slash-commands.mdx b/docs/main/integrations-guide/slash-commands.mdx new file mode 100644 index 000000000000..66047050c741 --- /dev/null +++ b/docs/main/integrations-guide/slash-commands.mdx @@ -0,0 +1,42 @@ +--- +title: "Slash Commands" +--- + + +Execute actions with simple commands inside Mattermost. Learn how to [run Mattermost slash commands](/integrations-guide/run-slash-commands). + +## Built-in slash commands + +**Technical complexity:** [No-code](#no-code) + +These out-of-the-box commands enable command line interaction with users, channels, and conversations. Examples of pre-built slash commands include `/invite` to add teammates to a channel, `/header` to set a channel description, or `/call` to start or join a call in a channel. + +Additionally, you can interact with the data model programmatically using [API endpoints](https://api.mattermost.com/). Responses are posted as the user who invoked the command, with possible username/icon overrides. + +Learn more about [built-in slash commands](/integrations-guide/built-in-slash-commands) available in Mattermost. + +## Custom slash commands + +**Technical complexity:** [Low-code](#low-code) + +Slash commands are similar to an outgoing webhooks, but instead of listening for keywords in a channel they are triggered by users explicitly typing a preconfigured command. Using slash commands is similar to using a command line within a channel. This means if you type in a slash command it will execute without posting a message, whereas an outgoing webhook is only triggered by posted messages. The external service then processes the request and can return a response, such as plain text, rich message content, interactive buttons or forms, directly into the channel. + +Mattermost's slash command format is Slack compatible, so you can easily migrate your commands from Slack. + +Learn more about [building custom slash commands](https://developers.mattermost.com/integrate/slash-commands/custom/). + +### Example Use Cases + +Here are some example use cases for slash commands in Mattermost: + +**Project management** + +Typing `/jira create` opens an interactive dialog where you can file a new Jira issue directly from Mattermost, including fields like summary, description, and priority. + +**Incident response** + +Using `/pagerduty trigger` can open a form to start a new incident, notify on-call responders, and post details back into the channel so the team can coordinate. + +**Knowledge retrieval** + +A command like `/docs search authentication` queries your documentation system and returns a list of relevant articles as interactive message attachments with links. diff --git a/docs/main/integrations-guide/webhook-integrations.mdx b/docs/main/integrations-guide/webhook-integrations.mdx new file mode 100644 index 000000000000..d518e9fcab76 --- /dev/null +++ b/docs/main/integrations-guide/webhook-integrations.mdx @@ -0,0 +1,25 @@ +--- +title: "Webhooks" +--- + + +Imagine your CI/CD pipeline just finished a build. Rather than digging through logs, a Mattermost channel instantly shows a new message: + +✅ Build Successful – Project X, Version 2.3 deployed to staging. + +That’s the power of Mattermost webhooks. They provide a simple yet powerful way to connect Mattermost with external systems, applications, and services so that information flows in real time, and your team stays aligned without constant manual updates. + +With webhooks, you can: + +- Receive updates in Mattermost from other systems via [Incoming Webhooks](/integrations-guide/incoming-webhooks). +- Send data out of Mattermost to external endpoints via [Outgoing Webhooks](/integrations-guide/outgoing-webhooks) based on channel activity. + +Because webhooks use lightweight HTTP POST requests with JSON payloads, they're easy to set up with virtually any tool or platform, whether you need quick notifications or deep integration with enterprise workflows. + +Common uses include: + +- Posting monitoring alerts directly to your incident-response channel. +- Sending deployment updates from CI/CD pipelines. +- Triggering external actions like creating tickets or running scripts from inside Mattermost. + +Mattermost webhooks bridge your collaboration hub with the rest of your toolset, enabling faster decisions, smoother operations, and teams that can act on information the moment it matters. Learn more about how to set up and use webhooks in the sections below: diff --git a/docs/main/integrations-guide/zoom.mdx b/docs/main/integrations-guide/zoom.mdx new file mode 100644 index 000000000000..7b60a0242800 --- /dev/null +++ b/docs/main/integrations-guide/zoom.mdx @@ -0,0 +1,155 @@ +--- +title: "Connect Zoom to Mattermost" +--- + + +Reduce friction and time lost to coordinating meetings and switching between apps by integrating Zoom with Mattermost. Make it easy for your teams to start spontaneous video calls directly from Mattermost channels. Receive Zoom cloud recordings and transcripts directly in Mattermost once they're available. + +## Deploy + +Setup starts in Zoom and configuration ends in Mattermost. + +### Register an OAuth app in Zoom + +A Zoom system admin must perform the following steps in Zoom. + +Zoom supports OAuth authentication, and there are 2 types of OAuth Zoom Apps you can register: **Account-Level** and **User-Level**. You can use either type based on your organization's security and preferences. + +- **Account-Level**: Individual users in Mattermost are verified by checking their Mattermost email and requesting their Personal Meeting ID via the Zoom API. The user's email address in both Mattermost and Zoom must match. Create a User Level Zoom app instead if you prefer that each user to authorize individually. +- **User-Managed**: Individual users in Mattermost are required to authorize the Mattermost App to access their Zoom account. Create an Account-Level app instead if you prefer that an admin authorizes access on behalf of the whole Zoom organization. + + + +For Account-Level apps, only Zoom users associated with the Zoom Account that created the app can use this integration. You can add users from the **Manage Users** section in the Zoom Account settings. + + + +
+ +Account-Level + +Complete the following steps to create an account-level Zoom app for Mattermost. + +1. Go to [https://marketplace.zoom.us/](https://marketplace.zoom.us/) and log in as an admin. +2. In the top right, select **Develop** and then select **Build App**. +3. On top, select **Development**. We would choose **Production** if we were publishing to marketplace, but we won't be doing that here. +4. You can edit the name of your app from top left side by clicking on edit icon. +5. Choose **Admin-managed app** as the app type. +6. Next you'll find your **Client ID** and **Client Secret**. Please copy this as these will be needed when you set up Mattermost to use the plugin. +7. Enter a valid **Redirect URL for OAuth** (https://SITEURL/plugins/zoom/oauth2/complete) and add the same URL under **Add Allow List**. Note that SITEURL should be your Mattermost server URL. +8. To add user scopes to the app, select **Scopes**, and add the following scopes: `meeting:read:meeting` (retrieve meeting details), `meeting:write:meeting` (create and update meetings), `user:read:user` (read user profile info), `cloud_recording:read:recording` (access cloud recording files), `archiving:read:list_archived_files` (list archived files). + +
+ +
+ +User-Managed + +Complete the following steps to create a user-managed Zoom app for Mattermost. + +1. Go to [https://marketplace.zoom.us/](https://marketplace.zoom.us/) and log in as an admin. +2. In the top right select **Develop** and then **Build App**. +3. On top, select **Development**. We would choose **Production** if we were publishing to marketplace, but we won't be doing that here. +4. You can edit the name of your app from top left side by clicking on edit icon. +5. Choose **User-managed app** as the app type. +6. Next you'll find your **Client ID** and **Client Secret**. Please copy this as these will be needed when you set up Mattermost to use the plugin. +7. Enter a valid **Redirect URL for OAuth** (https://SITEURL/plugins/zoom/oauth2/complete) and add the same URL under **Add Allow List**. Note that SITEURL should be your Mattermost server URL. +8. To add user scopes to the app, select **Scopes**, and add the following scopes: `meeting:read:meeting` (retrieve meeting details), `meeting:write:meeting` (create and update meetings), `user:read:user` (read user profile info), `cloud_recording:read:recording` (access cloud recording files), `archiving:read:list_archived_files` (list archived files). + +
+ +### Configure webhook events + +When a Zoom meeting ends, the original post shared in the channel can be automatically changed to indicate the meeting has ended and how long it lasted. To enable this functionality, create a webhook subscription in Zoom that tells the Mattermost server every time a meeting ends. The Mattermost server then updates the original Zoom message. + +1. While editing the app in Zoom, select **Access** under the **Features** tab on the left. +2. Select **Add New Event Subscription**, and give it a name, such as `Zoom for Mattermost`. +3. Select the **Add Events** button and add: **All Recordings have completed**, **Recording Transcript files have completed**, **Start Meeting**, and **End Meeting**. +4. Enter a valid **Event notification endpoint URL** `https://SITEURL/plugins/zoom/webhook?secret=WEBHOOKSECRET`, replacing `SITEURL` with your Mattermost URL. `WEBHOOKSECRET` is generated during [Mattermost configuration](#mattermost-configuration). +5. Select **Save** to save the webhook configuration. +6. Verify the webhook is active by selecting **Test Event** in the Zoom webhook configuration. Confirm that Mattermost returns an HTTP 200 response or that the Mattermost plugin logs show a successful delivery. Also confirm that the **Secret Token** shown in the UI matches the `WEBHOOKSECRET` value used in the **Event notification endpoint URL** from step 4. +7. Copy the **Secret Token** value at the top of the page for use in the next section. + +### Mattermost configuration + +A Mattermost system admin must perform the following steps in Mattermost. + +Install the Zoom integration from the in-product App Marketplace: + + + +We recommend making a copy of your webhook secret and encryption key, as it will only be visible to you once. + + + +1. In Mattermost, from the Product menu Navigate between Channels, collaborative playbooks, and boards using the product menu icon., select **App Marketplace**. +2. Search for or scroll to Zoom, and select **Install**. +3. Once installed, select **Configure**. You'll be taken to the System Console. +4. On the Zoom configuration page, enable and configure Zoom interoperability as follows, and then select **Save**. +5. For self-hosted Zoom deployments, enter the **Zoom URL** and **Zoom API URL** for the Zoom server when you're using a self-hosted private cloud or on-premises Zoom server, such as `https://YOUR-ZOOM.com` and `https://api.YOUR-ZOOM.com/v2` respectively, replacing `YOUR-ZOOM` with your Zoom server URL. Leave this field blank if you're using Zoom's vendor-hosted SaaS service. +6. If you've created an [account level Zoom app for Mattermost](#register-an-oauth-app-in-zoom), set **OAuth by Account Level App** to **true**. Leave this value as **false** if you've created a user level Zoom app for Mattermost. +7. Connect your users to Zoom using OAuth. Enter the **Client ID** and **Client Secret** generated when [registering the oauth app in Zoom](#register-an-oauth-app-in-zoom). +8. Select **Regenerate** next to the **At Rest Token Encryption Key** field to generate an AES encryption key. You just need to generate this value, and won't use it anywhere else. +9. If you're configuring webhook events, select **Regenerate** next to the **Webhook Secret** field. This is the `WEBHOOKSECRET` value to use in your webhook URL pointing to Mattermost. +10. Paste the **Secret Token** from the Zoom webhook configuration page into the plugin setting **Zoom Webhook Secret**. +11. (Optional) Enable **Restrict Meeting Creation** to restrict users from creating meetings in public channels. +12. Select **Save** to save your changes. + +## Enable + +Notify your teams that they can [connect their Zoom accounts to Mattermost](#usage). + +To subscribe a channel to a recurring Zoom meeting (a meeting scheduled to repeat on a regular basis, such as daily or weekly, or with no fixed time using Zoom's **Recurrence** option), use the following slash command: `/zoom subscription add [meeting ID]`. You can find the meeting ID in the Zoom desktop or web client by opening the meeting's details page, or from the meeting invitation email. The channel will receive a notification when the meeting starts, along with an access link. If cloud recordings are enabled and the meeting was recorded, the recording and transcript are posted as replies to the initial message once they are available. + +## Upgrade + +We recommend updating this integration when new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-zoom/releases) for information on the latest release, previous releases, and compatibility considerations. + +## Usage + +You need a paid Zoom account to start a Zoom call within Mattermost. The first time you create a Zoom meeting, you may be prompted to connect your account. Follow the instructions to connect your Zoom account using your credentials. + +Start a call by selecting the Zoom icon in the right pane, or by running the `/zoom start` slash command in any channel or thread. All channel members can then join the meeting. The meeting host is the person who started the call. + +Join the meeting by selecting the call invitation in the channel. + +Run the `/zoom settings` slash command to set your preference for using your Zoom personal meeting ID as a meeting host. You can choose to always use your personal meeting ID, always use a new unique meeting id, or set Mattermost to prompt you for your preference each time you start a call. + +Subscribe a Mattermost channel to a recurring Zoom meeting with `/zoom subscription add [meeting ID]`. Cloud recordings and transcripts must be enabled in your paid Zoom account in order to receive them in Mattermost. To enable this, sign in to the [Zoom web portal](https://zoom.us/) as an account owner or admin, go to **Account Management \> Account Settings**, select the **Recording** tab, and enable **Allow hosts to record and save the session in the cloud**. Then, under **Advanced cloud recording settings**, select the **Audio Transcript** checkbox. Alternatively, enable these settings at the user level and assign recording permission to the meeting host. See [Zoom's cloud recording settings documentation](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0064676) and [audio transcription documentation](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0065911) for step-by-step guidance. Once enabled, you'll receive a notification in Mattermost when the recording and transcript are available for recorded meetings. + +If you create a new meeting using the Zoom button in the Mattermost RHS, then the recording and transcript are similarly posted as replies to the initial message once they are available, if cloud recordings are enabled and the meeting was recorded. + +Additional slash commands: + +- `/zoom help` - Display available commands +- `/zoom channel-settings` - Set whether meetings in the current channel use your personal meeting ID or unique meeting ID +- `/zoom channel-settings list` - List all channel preferences +- `/zoom subscription list` - List all subscribed channels +- `/zoom subscription add [meeting ID]` - Subscribe a Mattermost channel to a recurring Zoom meeting +- `/zoom subscription remove [meeting ID]` - Unsubscribe a Mattermost channel from a recurring Zoom meeting + +For User-Managed apps only: + +- `/zoom connect` - Connect your Zoom account to Mattermost +- `/zoom disconnect` - Disconnect your Zoom account from Mattermost + +## Customize + +This [integration](https://github.com/mattermost/mattermost-plugin-zoom) contains both a server and web app portion. + +- Server: Inside the `/server` directory, you'll find the Go files that make up the server-side of the integration. Within there, build the plugin like you would any other Go application. +- Web App: Inside the `/webapp` directory, you will find the JS and React files that make up the client-side of the plugin. Within there, modify files and components as necessary. Test your syntax by running `npm run build`. + +Visit the [Mattermost Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Mattermost Developer environment setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for information about developing, customizing, and extending Mattermost functionality. + +## Upgrade + +We recommend updating this integration when new versions are released. Generally, updates are seamless and don't interrupt the user experience in Mattermost. Visit the [Releases page](https://github.com/mattermost/mattermost-plugin-zoom/releases) for information on the latest release, previous releases, and compatibility considerations. + +## Get help + +Mattermost customers can open a [Mattermost support case](https://support.mattermost.com/hc/en-us/requests/new). To report a bug, please open a GitHub issue against the [Mattermost Zoom plugin repository](https://github.com/mattermost/mattermost-plugin-zoom). + +For questions, feedback, and assistance, join our public [Integrations and Apps channel](https://community.mattermost.com/core/channels/integrations) on the [Mattermost Community Server](https://community.mattermost.com/) for assistance. + +Mattermost Team Edition and Free customers can visit the Mattermost [peer-to-peer troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) to access the global Mattermost Community for assistance. diff --git a/docs/main/product-overview/accessibility-compliance-policy.mdx b/docs/main/product-overview/accessibility-compliance-policy.mdx new file mode 100644 index 000000000000..0823c8023b24 --- /dev/null +++ b/docs/main/product-overview/accessibility-compliance-policy.mdx @@ -0,0 +1,39 @@ +--- +title: "Accessibility Compliance Policy" +--- +Digital accessibility removes barriers to ensure full participation with digital experiences. People with disabilities may use assistive technology like screen readers or alternative input devices. We prioritize accessibility to deliver an experience that works for everyone, involving accessible designs, compatible code, and a logical, functional user interface for all. + +This policy outlines our commitment to accessibility through the Voluntary Product Accessibility Template (VPAT), which documents our product's compliance with accessibility standards. + +## Policy and commitment + +At Mattermost, we strive to create a fair environment for everyone. We work continuously to ensure our digital products are accessible for all and are committed to following the W3C Web Content Accessibility 2.1 Guidelines and other applicable web accessibility laws including [WCAG 2.1](https://www.w3.org/TR/WCAG21/) Level AA (W3C) and Section 508 of the Rehabilitation Act (United States) for federal accessibility requirements. + +We leverage expert accessibility partners, such as [Level Access](https://www.levelaccess.com/), to achieve and sustain conformance to accessibility standards. Their digital accessibility platform is used to evaluate our digital properties in accordance with best practices and is supported by a diverse team of accessibility professionals, including users with disabilities. + +To provide feedback about Mattermost’s accessibility, contact us at [accessibility@mattermost.com](mailto:accessibility@mattermost.com). + +## Scope + +This policy applies to all products offered by Mattermost, including web applications, software, digital content, and related services that may be used by individuals with disabilities. The policy applies to both internal and external stakeholders, including potential customers, partners, and government agencies seeking accessibility information. + +## VPAT creation process + +1. **Initial Assessment**: Each product is reviewed for accessibility compliance based on the relevant standards. This assessment is conducted by trained accessibility personnel or certified third-party auditors. +2. **VPAT Documentation**: A VPAT is created based on the findings from the initial assessment. This document details each accessibility criterion and the level of conformance achieved, along with explanations for any known gaps or alternative solutions. +3. **Review and Approval**: VPATs are reviewed by our accessibility compliance team to ensure accuracy, completeness, and consistency. Any areas not in full compliance are documented with explanations and, where possible, a roadmap for future improvements. +4. **Publishing and Distribution**: Once approved, VPATs are made available upon request for customers, partners, and other stakeholders. + +Accessibility standards and regulations evolve, and our products and services continue to improve. VPATs will be reviewed and updated on a regular basis, at minimum annually, to reflect the current state of our accessibility compliance. + +## Roles and responsibilities + +- **Product Accessibility Team**: Conducts assessments, documents accessibility features, and prepares VPATs. +- **Legal and Compliance Team**: Reviews VPATs to ensure legal requirements are met and accessibility claims are accurate. +- **Customer Support Team**: Handles requests for VPATs and assists customers with accessibility questions. + +## Customer and partner requests + +Customers and partners may request access to specific VPATs or additional accessibility information. The organization is committed to providing accurate and timely responses and will work to accommodate requests. + +To request a VPAT document, contact us at [accessibility@mattermost.com](mailto:accessibility@mattermost.com). diff --git a/docs/main/product-overview/certifications-and-compliance.mdx b/docs/main/product-overview/certifications-and-compliance.mdx new file mode 100644 index 000000000000..3ff565c2b6d7 --- /dev/null +++ b/docs/main/product-overview/certifications-and-compliance.mdx @@ -0,0 +1,211 @@ +--- +title: "Certifications and Compliance Overview" +sidebar_label: "Certifications and Compliance" +--- +This overview summarizes how Mattermost can help users in support of their internal compliance initiatives, including: + +- GDPR Compliance +- U.S. Export Compliance + +## GDPR compliance + +The following overview summarizes how Mattermost software can be used to assist in compliance programs covering the European Union's General Data Protection Regulation, also known as Regulation (EU): 2016/679 ([See full text](https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32016R0679&from=EN)) and how Mattermost, Inc., itself, adheres to regulatory requirements. + +### Continual commitment to the principles of GDPR + +Mattermost is a collaboration hub for highly-trusted organizations and is committed to supporting the principles of GDPR to protect the data of people in the European Union. Mattermost adheres to this mission through the use of: + +- **Security Infrastructure:** Continual investment in security, privacy and compliance capabilities. +- **Contractual Obligations:** Appropriate contractual obligations through our terms of service, including the [Data Processing Addendum](https://mattermost.com/data-processing-addendum/) in our standard [Terms of Service](https://mattermost.com/terms-of-use/). +- **Privacy Measures:** Privacy measures are outlined in our [Privacy Policy](https://mattermost.com/privacy-policy/). +- **Product Features:** To ensure data management and data portability. + +To stay up to date with our efforts, please subscribe to [our regular newsletter](https://mattermost.com/newsletter/). + +### Security infrastructure + +Mattermost enables organizations to protect their information, and the information of their users and customers, through self-hosted communication infrastructure that has been developed with a high standard of security. The features of this security infrastructure include: + +- **Security Features** in Mattermost open source and commercial offerings that enable deployment of your organization’s own infrastructure. +- **Responsible Disclosure Policy** for security researchers around the world to confidentially report suspected vulnerabilities, which can be addressed in updates to Mattermost software. +- **Security Reviews** conducted by both our own internal security review team and external security researchers. +- **ISO 27001 Standards** which are met to achieve alignment with international security guidelines. + +### Contractual obligations + +Mattermost adheres to contractual obligations for ensuring the proper management of data through: + +- **GDPR-Compliant Data Processing Addendum** included with Mattermost’s standard terms. +- **Mattermost Privacy Policy** sharing how data is handled on the online infrastructure controlled by Mattermost, Inc. + +### Privacy measures + +Mattermost outlines security measures to maintain the safety of personal data submitted by our customers and partners in our [Privacy Policy](https://mattermost.com/privacy-policy/). + +### Product features + +Mattermost supports features that ensure data management and data portability. + +#### Data management + +- **Data Retention:** Use [data retention](/administration-guide/comply/data-retention-policy) to automatically erase data after a set period of time, a feature that meets the Right to Erasure principle. In Team Edition, you can use database scripts to achieve the same result. +- **Profile Deletion:** Delete a user’s personal information via [mmctl user delete](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-delete). This permanently deletes all user information including messages created by the user. +- **Self-Hosted Push Notification Service:** Self-host your own push notification service, or deploy mobile apps with any EMM provider that supports [AppConfig](https://www.appconfig.org/) to meet security and compliance policies. See [our Mobile App deployment documentation](/deployment-guide/mobile/mobile-app-deployment) to learn more. + +#### Data portability + +- **Data Import:** Use the [bulk loading tool](/administration-guide/onboard/bulk-loading-data) to migrate data from an existing messaging system, or for pre-populating a new installation with data. [Review our migrate from Slack guidance](/administration-guide/onboard/migrate-from-slack) which summarizes the different approaches and meets the [Right to Data Portability](https://gdpr-info.eu/art-20-gdpr/) principle. +- **Data Export:** Use [compliance exports](/administration-guide/comply/compliance-export) to export conversations from public, private and direct message channels in XML or EML format. Those in Team Edition can export conversations directly from the database, both in PostgreSQL and in MySQL. + +## Accessibility compliance + +See the [accessibility compliance policy](/product-overview/accessibility-compliance-policy) documentation for details. + +Adherence with accessibility standards is assisted in the following ways: + +- **508 Compliance:** VPATs are made available upon request for customers, partners, and other stakeholder seeking to confirm 508 compliance. +- **WCAG 2.0L:** For meeting Web Contact Accessibility Guidelines 2.0 (WCAG), Mattermost has received a third-party "A" rating and is working towards an "AA" rating. +- **ADA:** Mattermost compliance with the Americans with Disabilities Act (ADA) is achieved by offering the accessibility support detailed in the VPAT and WCAG 2.0 guidelines with Mattermost's online experience as the interface to accessibility tools. +- **Remediation:** Any technical issue in a current or future product release that would prevent compliance with accessibility ratings stated in product documentation would be considered a product defect and Mattermost would welcome the [public filing of an issue report against the defect](https://developers.mattermost.com/contribute/why-contribute/#youve-found-a-bug) so that it may be resolved. + +## U.S. trade compliance + +Mattermost, Inc. implements a number of controls and processes to comply with U.S. trade compliance laws. + +1. **IP blocking:** We use IP blocking to deny access from certain countries to our commercial systems, such as signing up for our commercial and proprietary offerings. +2. **Automated compliance scanning:** We use an automated export compliance tool called Descartes. In Salesforce account records there is a prominent **Descartes** box in the top right indicating safety levels. Accounts that are flagged need to be released wtihin the Descartes System by Legal or their designate. +3. **Manual compliance review:** At times announcements about changes to sanctions regulations happen faster than our export compliance tool can adapt. In the cases where sanctions have been announced, we can proactively review our business and make changes to enforce sanctions ahead of the automated solution being updated. +4. **Legal restrictions:** Our commercial software contains legal terms that apply to both administrators and end users prohibiting use that would violate U.S. trade laws. + +U.S. trade laws referenced here can be found online at: [https://www.bis.gov](https://www.bis.gov) and [https://ofac.treasury.gov/](https://ofac.treasury.gov/). + +If you feel your organization is miscategorized under U.S. trade laws or sanctions, please email [compliance@mattermost.com](mailto:compliance@mattermost.com). + +### What is the process to end a customer relationship due to new U.S. trade laws or sanctions? + +The customer is contacted via email with either manually or through an automated process with [compliance@mattermost.com](mailto:compliance@mattermost.com) cc'd and the communication is written back into SFDC for record keeping. + +## U.S. export compliance overview + +### Summary Table + + ++++ + + + + + + + + + + + + + + + + +
Mattermost ProductExport Control Classification Number (ECCN)
Mattermost Enterprise Edition (includes Mattermost Professional & Enterprise)ECCN 5D002 with a License Exception available of ENC
Mattermost Team EditionNot subject to the U.S. Export Administration Regulations (EAR) given software is publicly available and fully available to compile from publicly available source code at https://github.com/mattermost/
+ +### Overview + +The U.S. government regulates the transfer of information, commodities, technology and software considered to be strategically important to the U.S. in the interest of national security, economic and/or foreign policy concerns. Many countries outside of the U.S. have similar controls on exports for the same reasons. + +There is a complex network of U.S. agencies and inter-related regulations that govern exports collectively referred to as “Export Controls." + +It is the policy of Mattermost to comply with all export compliance laws in all countries in which it transacts business. Because Mattermost is a U.S.-based global company, our products, collectively referred to as “Commodities," which include our software as well as our equipment, materials and services, are subject to the export laws and regulations of every country in which we conduct business. Non-compliance with export control regulations can subject Mattermost and its affiliates, including its customers, employees and business partners to criminal and civil penalties, the seizure of assets, the denial of export privileges, and suspension or debarment from Government Contracts. + +For these reasons, please take the time to familiarize yourself with applicable export (and import) controls in the jurisdictions in which you operate. Although Mattermost cannot provide advice on export matters, this web page provides the information needed in order to export Mattermost products. + +This overview is specific to the U.S. Export Administration Regulations (EAR); however, business operations may subject you to other regulations such as the [International Traffic in Arms Regulations](https://www.pmddtc.state.gov/regulations_laws?id=ddtc_kb_article_page&sys_id=24d528fddbfc930044f9ff621f961987). + +### General information + +Start by taking a look at the [U.S. Bureau of Industry and Security](https://www.bis.gov/) website. Then, navigate to [Part 730](https://www.bis.doc.gov/index.php/documents/regulation-docs/410-part-730-general-information/file) of the U.S. Export Administration Regulations to understand what the regulations cover and what is “Subject to the EAR” under [734.2](https://www.bis.doc.gov/index.php/documents/regulation-docs/412-part-734-scope-of-the-export-administration-regulations/file) (“export controlled”). + +### Export classification and licensing + +Although what is subject to the Export Administration Regulations is quite broad, that does not mean an export license is required for every transaction. The foundation of understanding export controls related to hardware, software and technology can be found within the [Commerce Control List](https://www.bis.doc.gov/index.php/regulations/commerce-control-list-ccl) (CCL), which has 10 categories, 0-9, and is set up as a positive list. The first step is determining if the item to be exported is subject to the EAR. + +At Mattermost, our fully open source, publicly available software is [outside the scope of the EAR](https://www.bis.doc.gov/index.php/policy-guidance/encryption/1-encryption-items-not-subject-to-the-ear), as it is derived from publicly available encryption source code and the complete software package for both the source code ([https://github.com/mattermost/](https://github.com/mattermost/)) and binary versions are publicly available. Mattermost enterprise software is found in [Category 5, Part 2](https://www.bis.doc.gov/index.php/documents/regulations-docs/federal-register-notices/federal-register-2014/951-ccl5-pt2/file) of the CCL as Telecommunications and Information Security items (hardware, software and technology). Most items in this category have encryption. + +Often a license exception under [Part 740](https://www.bis.doc.gov/index.php/documents/regulation-docs/415-part-740-license-exceptions/file) is available where a Commerce Control List item lists the available license exception(s) specific to an Export Control Classification Number (ECCN), based on a combination of factors. + +Mattermost Enterprise Edition (includes Mattermost Professional & Enterprise) is found under [ECCN 5D002](https://www.bis.doc.gov/index.php/documents/regulations-docs/federal-register-notices/federal-register-2014/951-ccl5-pt2/file), with a license exception available from [“ENC”](https://www.bis.doc.gov/index.php/documents/regulation-docs/415-part-740-license-exceptions/file) for our Enterprise and Professional software, with encryption features derived from open-source software. Encryption products, under the export regulations, have multiple levels of controls and requirements. BIS has a separate section of their website that has an overview, and many links, covering encryption under [Encryption and Export Administration Regulations (EAR)](https://www.bis.doc.gov/index.php/policy-guidance/encryption) that you may want to review. These guidelines include helpful flow charts for determining if an item is subject to encryption controls, tables and other details. + +The other key areas to be aware of for an export of Mattermost software or technology are: + +**Sanctions**: There are comprehensive sanctions to Cuba, Iran, North Korea, Syria, and other countries/territories with specific prohibitions, such as Crimea, Donetsk, and Luhansk regions of Ukraine, Belarus, Russia, Venezuela, Myanmar/Burma, and Cambodia. Details can be located at [BIS](https://www.bis.gov/). The countries and their sanctions are subject to change. + +**WMD (Weapons of Mass Destruction)**: Mattermost, its customers and its business partners may not export to parties involved in [proliferation](https://www.bis.doc.gov/index.php/documents/regulation-docs/413-part-736-general-prohibitions/file) of weapons of mass destruction, along with other prohibited end-uses under the U.S. Export Administration Regulations (“EAR”). + +**General Prohibitions**: Information on General Prohibitions under the EAR is located [here](https://www.bis.doc.gov/index.php/documents/regulations-docs/413-part-736-general-prohibitions/file). Application of the applicability of these General Prohibitions is based on a combination of factors. These include: classification of the commodity, destination, end-user, end-use and conduct. + +**Restricted Parties**: You may not export to parties listed on the US government's [restricted parties lists](https://www.bis.doc.gov/index.php/policy-guidance/lists-of-parties-of-concern), and should be screening against these prior to export. There is a [consolidated screening list](https://www.trade.gov/consolidated-screening-list) provided by the U.S. government at export.gov at no charge that can be used for screening. Additionally, there are specific restrictions on export to military end-users and military intelligence end-users. + +**Deemed Exports**: Release of controlled technology to foreign persons in the U.S. is "deemed" to be an export to the person’s country or countries of nationality and is found in [734.2(b)](https://www.bis.doc.gov/index.php/documents/regulation-docs/412-part-734-scope-of-the-export-administration-regulations/file) of the EAR, which you can read about under the Export Administration Regulations on the BIS website. + +**Know Your Customer**: By reviewing the BIS website, you will notice that it is very important to “know your customers," and to be aware of “Red Flags”. Be sure to screen business partners and customers to ensure compliance. + +### Disclaimer + +Mattermost makes this data available for informational purposes only. It may not reflect the most current legal developments, and Mattermost does not represent, warrant or guarantee that it is complete, accurate or up to date. This information is subject to change without notice. The materials on this site are not intended to constitute legal advice or to be used as a substitute for specific legal advice. You should not act (or refrain from acting) based upon information on this site without obtaining professional advice regarding particular facts and circumstances. + +## Frequently asked questions + +### To be compliant with GDPR, do I need to remove message contents of email notifications? + +Based on our interpretation of GDPR, it is not required to hide message contents in email notifications to remain compliant for the following reasons: + +1. Every user has the ability to disable email notifications in **Settings**. Therefore, every user has the ultimate control over whether or not they want information sent via email. This option aligns with most other products, but we will follow updates on interpretations of GDPR closely to see if we need to make changes in this area. +2. Mattermost offers [TLS encryption](/administration-guide/configure/environment-configuration-settings#web-server-connection-security) to protect communication between the Mattermost server and the SMTP email server. +3. If you're uncertain whether the first two points cover GDPR compliance, you can [disable notifications completely](/administration-guide/configure/site-configuration-settings#enable-email-notifications) on your Mattermost server. To use Mattermost in production with no email notifications, you also need to [disable a "preview mode" notice banner](/administration-guide/configure/site-configuration-settings#enable-preview-mode-banner). + +### What information is shared when I select **Contact us** on a Mattermost Admin Advisor notification? + +Selecting **Contact us** in the Mattermost Admin Advisor will send some information to us. This may include the email address and name associated with your Mattermost account as well as the number of registered users on your system, the site URL, and a Mattermost diagnostic server ID number. This information is used to contact you as requested and to help us better understand your needs. + + + +[Mattermost Admin Advisor notices are disabled](/administration-guide/manage/in-product-notices) in v5.35 and later. + + + +### Are the server access logs containing IP addresses a GDPR compliance issue? + +Based on our interpretation of [article 49 of GDPR](https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32016R0679&from=EN), processing personal data for the purpose of ensuring network and information security is acceptable. Moreover: + +- You can control access to the logs via restricted access to the System Console and the server. +- As a self-hosted software, you have full control and ownership of the logs, with the ability to set up a purge schedule to meet your needs. +- You can use a reverse proxy to provide obfuscation to IP addresses. + +### Do you have Fed or Department of Defense (DOD) Certification? + +We are in the process of acquiring Authority to Operate (ATO) and Certificate of Networthiness (CON) certifications. + +### How do you ensure personal data stays within European Union? + +When the customer’s installation of Mattermost is self-hosted, Mattermost does not process any personal data under the jurisdiction of the data privacy laws governing within the European Union. The Mattermost support team leverages Zendesk customer service software, which hosts Mattermost information within the United States. For more information on Zendesk, please see their [Privacy and Data Protection](https://www.zendesk.com/trust-center/) page. + +Zendesk privacy and data protection safeguards notwithstanding, the provision of support services is part of the contractual obligations between Mattermost and its customers. In order for Mattermost to provide such support, a customer must be able to identify as a licensed user, therefore requiring the user to provide personal data to the support agent. Regardless of where the support agent is located, the personal data will indeed be hosted outside of the EU. + +However, pursuant to Section (b) of Article 49 of GDPR, transfers of personal data which are "necessary for the performance of a contract between the data subject and the controller" may be transferred to a third country or international organization. Accordingly these transfers would be done in alignment with the requirements of GDPR. For more information, see our [Mattermost Privacy Policy](https://mattermost.com/privacy-policy/) page. + +**\*DISCLAIMER:** MATTERMOST DOES NOT POSITION ITS PRODUCTS AS “GUARANTEED COMPLIANCE SOLUTIONS”. WE MAKE NO GUARANTEE THAT YOU WILL ACHIEVE REGULATORY COMPLIANCE USING MATTERMOST PRODUCTS. YOUR LEVEL OF SUCCESS IN ACHIEVING REGULATORY COMPLIANCE DEPENDS ON YOUR INTERPRETATION OF THE APPLICABLE REGULATION, AND THE ACTIONS YOU TAKE TO COMPLY WITH THEIR REQUIREMENTS. SINCE THESE FACTORS DIFFER ACCORDING TO INDIVIDUALS AND BUSINESSES, WE CANNOT GUARANTEE YOUR SUCCESS, NOR ARE WE RESPONSIBLE FOR ANY OF YOUR ACTIONS. NO GUARANTEES ARE MADE THAT YOU WILL ACHIEVE ANY SPECIFIC COMPLIANCE RESULTS FROM THE USE OF MATTERMOST OR FROM ANY RECOMMENDATIONS CONTAINED ON OUR WEBSITES, AND AS SUCH, THIS SHOULD NOT BE A SUBSTITUTE TO CONSULTING WITH YOUR OWN LEGAL AND COMPLIANCE REPRESENTATIVES ON THESE MATTERS. + +### Are you IPv6 compliant? + +Yes, the Mattermost platform is compliant with IPv6 when Audio & Screen Sharing is disabled, both for our [self-hosted and Cloud offerings](/product-overview/editions-and-offerings). + +We plan to add IPv6 compliance for [Audio & Screen Sharing](/administration-guide/configure/calls-deployment-guide) in future. + +### Are you 508 compliant? + +Yes, the Mattermost platform is compliant with 508. See the [accessibility compliance policy](/product-overview/accessibility-compliance-policy) documentation for details. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/product-overview/cloud-dedicated.mdx b/docs/main/product-overview/cloud-dedicated.mdx new file mode 100644 index 000000000000..ed333b01a09e --- /dev/null +++ b/docs/main/product-overview/cloud-dedicated.mdx @@ -0,0 +1,84 @@ +--- +title: "Cloud Dedicated" +--- +import Inc0_cloud_supported_integrations from './cloud-supported-integrations.mdx'; + +Mattermost Cloud Dedicated is designed for larger organizations with higher demands for performance, scalability, customizability, and compliance looking to offload operational overhead and focus on more business-critical tasks. + +Your own private Mattermost instance running [Mattermost Enterprise](/product-overview/editions-and-offerings) is a Kubernetes cluster hosted and managed by Mattermost that runs on dedicated cloud infrastructure, where resources are exclusively available for your organization. + +## Reference architecture + +![An architecture diagram showing the components of the Mattermost Cloud Dedicated solution.](/images/mattermost-cloud-dedicated-reference-architecture.png) + +## Available features + +### Zero-downtime upgrades + +Mattermost releases biweekly updates and leverages recurring maintenance windows to keep your instance up-to-date with new stable or beta features behind feature flags, fix security issues, and ensure the overall reliability and performance of your environment. Maintenance windows are announced in advance on [https://status.mattermost.com/](https://status.mattermost.com/) + +Additional support options, including quicker response times, dedicated support personnel, and stronger service level agreements (SLAs), are also available. + +### Disaster Recovery + +Mattermost Cloud Dedicated supports data failover to a secondary region/site should the primary instance experiences an unrecoverable outage with guaranteed recovery times. + +Mattermost supports a **multi-AZ (availability zones)** strategy in the same site/region. + +Daily backups of the database, object storage, and high availability clusters are captured and retained for 30 days. + +In addition, highly available observability tools with automated alerting, long-term metrics, and logs retention are retained for a duration of 1 year, or longer, if requred. + +### Security + +You have access to all the resources required to run the Mattermost application with the highest security standards, including data encryption at rest and in transit. + +Your pre-configured cluster is secure by default, based on industry best practices including Data encryption at rest and in transit, TLS certificates life cycle management, and automatic security updates. + +Mattermost maintains control over network and security policies, including [encryption](#encryption), database, data, object storage, backup schedules, and compliance certifications. + +### Authentication and authorization + +Mattermost offers advanced security and authentication options for integrating with corporate directories, including [Active Directory/LDAP](/administration-guide/onboard/ad-ldap), [Okta](/administration-guide/onboard/sso-saml-okta), [OneLogin](/administration-guide/onboard/sso-saml-onelogin), [SAML](/administration-guide/onboard/sso-saml), [Google](/administration-guide/onboard/sso-google), [EntraID](/administration-guide/onboard/sso-entraid), and [OpenID](/administration-guide/onboard/sso-openidconnect). + +### Secure networking + +Mattermost Cloud Dedicated supports [IP filtering](/administration-guide/manage/cloud-ip-filtering) through CIDR-based IP ranges, providing flexibility for system administrators to include various authorized IPs or IP ranges for seamless access control. Users attempting to access their [workspace](/end-user-guide/end-user-guide-index) from IPs outside defined ranges are restricted from entry. Cloud system admins can [configure IP filtering](/administration-guide/manage/cloud-ip-filtering#configure-ip-filtering) through their Mattermost System Console. + +### Encryption + +Mattermost provides encryption-in-transit and encryption-at-rest capabilities. Mattermost supports [TLS encryption](/deployment-guide/server/setup-tls), including AES-256 with 2048-bit RSA on all data transmissions, between Mattermost client applications and the Mattermost server. You may either set up TLS on the Mattermost Server or [install a proxy such as NGINX](/deployment-guide/server/setup-nginx-proxy), and set up TLS on the proxy. + +Connections to [Active Directory/LDAP](/administration-guide/onboard/ad-ldap) can [optionally be secured with TLS or stunnel](/administration-guide/configure/authentication-configuration-settings#ad-ldap-port). + +Connections to calls are secured with a combination of: + +- TLS: The existing WebSocket channel is used to secure the signaling path. +- DTLS v1.2 (mandatory): Used for initial key exchange. Supports `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` and `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA` algorithms. +- SRTP (mandatory): Used to encrypt all media packets (i.e. those containing voice or screen share). Supports `AEAD_AES_128_GCM` and `AES128_CM_HMAC_SHA1_80` algorithms. + +### Cloud native exports + +Mattermost supports optional [filestore configuration settings](/administration-guide/configure/environment-configuration-settings#enable-dedicated-export-filestore-target) to direct compliance and bulk export data to a separate S3 bucket from standard files. This separate bucket can be configured to allow for secure access by Mattermost Cloud teams as well as admins who manage a given Mattermost deployment. The exports can also be accessed by generating unique download links as needed. + +The following diagram provides a high-level view of how this functionality works: + +![An architecture diagram showing a high-level view of how Mattermost Cloud Native exports works.](/images/mattermost-cloud-native-export-architecture-diagram.png) + +### SMTP + +Email sent from Mattermost Cloud Dedicated uses SendGrid, and the connection to SendGrid is encrypted. + +### Audit and observability + +Mattermost Cloud Dedicated provides access to [audit and system logs](/administration-guide/manage/logging) generated by the application. + +### Customization + +The following Mattermost plugins are available for cloud-based deployments: + + + +## Migrate from a self-hosted instance + +See our [self-hosted to cloud migration](/administration-guide/manage/cloud-data-export#migrate-from-self-hosted-to-cloud) documentation to learn more about migrating from a self-hosted to a Mattermost Cloud instance. diff --git a/docs/main/product-overview/cloud-shared.mdx b/docs/main/product-overview/cloud-shared.mdx new file mode 100644 index 000000000000..cfb33366eaf3 --- /dev/null +++ b/docs/main/product-overview/cloud-shared.mdx @@ -0,0 +1,86 @@ +--- +title: "Cloud Shared" +--- +import Inc0_cloud_supported_integrations from './cloud-supported-integrations.mdx'; + +Mattermost Cloud Shared is designed as a cost-effective solution for companies who don't have strict security and compliance requirements that need a straightforward, managed communication platform without the necessity for extensive customization or dedicated resources. + +Your Mattermost deployment is isolated, is fully hosted and managed by Mattermost, and runs [Mattermost Enterprise](/product-overview/editions-and-offerings) on shared infrastructure where resources are shared among multiple Mattermost customers, which might affect performance during peak times. + +## Reference architecture + +![An architecture diagram showing the components of the Mattermost Cloud Shared solution.](/images/mattermost-cloud-dedicated-reference-architecture.png) + +## Available features + +### Zero-downtime upgrades + +Mattermost releases biweekly updates and leverages recurring maintenance windows to keep your instance up-to-date with new stable or beta features behind feature flags, fix security issues, and ensure the overall reliability and performance of your environment. Maintenance windows are announced in advance on [https://status.mattermost.com/](https://status.mattermost.com/) + +Additional support options, including quicker response times, dedicated support personnel, and stronger service level agreements (SLAs), are also available. + +### Disaster Recovery + +Mattermost Cloud Dedicated supports data failover to a secondary region/site should the primary instance experiences an unrecoverable outage with guaranteed recovery times. + +Mattermost supports a **multi-AZ (availability zones)** strategy in the same site/region. + +Daily backups of the database, object storage, and high availability clusters are captured and retained for 30 days. + +In addition, highly available observability tools with automated alerting, long term metrics, and logs retention are retained for a duration of 1 year. + +### Security + +You have access to all the resources required to run the Mattermost application with the highest security standards, including data encryption at rest and in transit. + +Your pre-configured cluster is secure by default, based on industry best practices including Data encryption at rest and in transit, TLS certificates life cycle management, and automatic security updates. + +Mattermost maintains control over network and security policies, including [encryption](#encryption), database, data, object storage, backup schedules, and compliance certifications. + +### Authentication and authorization + +Mattermost offers advanced security and authentication options for integrating with corporate directories, including [Active Directory/LDAP](/administration-guide/onboard/ad-ldap), [Okta](/administration-guide/onboard/sso-saml-okta), [OneLogin](/administration-guide/onboard/sso-saml-onelogin), [SAML](/administration-guide/onboard/sso-saml), [Google](/administration-guide/onboard/sso-google), [EntraID](/administration-guide/onboard/sso-entraid), and [OpenID](/administration-guide/onboard/sso-openidconnect). + +### Secure networking + +Enterprise customers with a Mattermost Cloud Shared deployment can [configure IP filtering](/administration-guide/manage/cloud-ip-filtering#configure-ip-filtering) through CIDR-based IP ranges, within the Mattermost System Console to specify authorized IPs or IP ranges for seamless access control. Users attempting to access their [workspace](/end-user-guide/end-user-guide-index) from IPs outside defined ranges are restricted from entry. + +### Encryption + +Mattermost provides encryption-in-transit and encryption-at-rest capabilities. Mattermost supports [TLS encryption](/deployment-guide/server/setup-tls), including AES-256 with 2048-bit RSA on all data transmissions, between Mattermost client applications and the Mattermost server. You may either set up TLS on the Mattermost Server or [install a proxy such as NGINX](/deployment-guide/server/setup-nginx-proxy), and set up TLS on the proxy. + +Connections to [Active Directory/LDAP](/administration-guide/onboard/ad-ldap) can [optionally be secured with TLS or stunnel](/administration-guide/configure/authentication-configuration-settings#ad-ldap-port). + +Connections to calls are secured with a combination of: + +- TLS: The existing WebSocket channel is used to secure the signaling path. +- DTLS v1.2 (mandatory): Used for initial key exchange. Supports `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` and `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA` algorithms. +- SRTP (mandatory): Used to encrypt all media packets (i.e. those containing voice or screen share). Supports `AEAD_AES_128_GCM` and `AES128_CM_HMAC_SHA1_80` algorithms. + +### Cloud native exports + +Mattermost supports optional [filestore configuration settings](/administration-guide/configure/environment-configuration-settings#enable-dedicated-export-filestore-target) to direct compliance and bulk export data to a separate S3 bucket from standard files. This separate bucket can be configured to allow for secure access by Mattermost Cloud teams as well as deployment admins who manage a given installation. The exports can also be accessed by generating unique download links as needed. + +The following diagram provides a high-level view of how this functionality works: + +![An architecture diagram showing a high-level view of how Mattermost Cloud Native exports works.](/images/mattermost-cloud-native-export-architecture-diagram.png) + +### SMTP + +Email sent from Mattermost Cloud Dedicated uses SendGrid, and the connection to SendGrid is encrypted. + +### Audit and observability + +Mattermost Cloud Dedicated provides access to [audit and system logs](/administration-guide/manage/logging) generated by the application. + +### Customization + +Approved plugins developed and/or tested by Mattermost are supported and available in the [Mattermost Cloud Marketplace](https://mattermost.com/marketplace/), including: + + + +Custom plugins and integrations outside of Mattermost Marketplace aren’t currently supported. + +## Migrate from a self-hosted instance + +See our [self-hosted to cloud migration](/administration-guide/manage/cloud-data-export#migrate-from-self-hosted-to-cloud) documentation to learn more about migrating from a self-hosted to a Mattermost Cloud instance. diff --git a/docs/main/product-overview/cloud-subscriptions.mdx b/docs/main/product-overview/cloud-subscriptions.mdx new file mode 100644 index 000000000000..8d7bc9ed8f4d --- /dev/null +++ b/docs/main/product-overview/cloud-subscriptions.mdx @@ -0,0 +1,155 @@ +--- +title: "Cloud" +draft: true +--- +Mattermost offers secure, cloud-based collaboration for fast moving enterprises that’s private, scaleable, and low maintenance. Cloud-native architecture supports organizations of any size for a deployment that scales with your team, without any resource planning. + +Enterprises can choose between dedicated and shared infrastructure based on your organizations’ size, budget, technical requirements, and level of control and customization needed: + +- [Mattermost Cloud Dedicated](/product-overview/cloud-dedicated): Better suited for larger organizations or those with specific needs around security, compliance, and customization, who are willing to pay a premium for dedicated resources and enhanced support. +- [Mattermost Cloud Shared](/product-overview/cloud-shared): A cost-effective solution for companies who don't have strict security and compliance requirements that need a straightforward, managed communication platform without the necessity for extensive customization or dedicated resources. +- [Cloud VPC Private Connectivity](/product-overview/cloud-vpc-private-connectivity): Learn how to access Mattermost Cloud within your own internal network. + +## Compare offerings + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Resource

+
+
+
===============================
+
+

Mattermost High Availability cluster-based deployment

+
+
+

Dedicated | Shared |

+
+
+
===============+=============+
+
+
+
checkmark | checkmark
+
+
            |
+
+
+
+
Network policycheckmark | checkmark
Namespacecheckmark | checkmark
Networkcheckmark | |
Kubernetes High Availabilitycheckmark | |
Database High Availabilitycheckmark | |
Object storagecheckmark | |
Encryption keyscheckmark | |
Custom backup schedulecheckmark | |
IP Filteringcheckmark | checkmark
Bring your own keycheckmark | |
+ +## Frequently asked questions about Mattermost Cloud + +### How do I buy a Mattermost Cloud subscription? + +Mattermost Cloud subscriptions are offered as an annual subscription. Contact a [Mattermost Expert](https://mattermost.com/contact-sales/) to buy a new subscription, or to renew, change, or cancel your existing subscription. + +If you’re currently using a Mattermost Cloud trial, contact a [Mattermost Expert](https://mattermost.com/contact-sales/) to upgrade to Mattermost Enterprise. Your plan immediately changes to your upgraded plan. You will be invoiced as specified in your sales agreement. + +### What is the minimum number of users I can purchase on a subscription? + +The minimum purchase for a Mattermost license subscription is 100 users, with no set maximum. You can buy as many user seats as needed. + +### Is Mattermost Cloud subject to taxes? + +Yes. Mattermost reserves the right to assess applicable taxes as required by local law. Depending on location, you may be charged transaction taxes when purchasing our product. [Prices](https://mattermost.com/pricing/) on our website are exclusive of sales tax or VAT. + +### Where does instance and data reside? + +Dedicated instance and data, including logs and backups, resides in the **AWS us-east-1 region**, located in Virginia, United States. + +For data residency options outside of the US, contact a [Mattermost Expert](https://mattermost.com/contact-sales/), or work with a [Mattermost partner](https://mattermost.com/partners/). + +### When will more region support be available? + +[Mattermost Cloud Dedicated](/product-overview/cloud-dedicated) will support data residency based on feedback from our customers. + +If you require your data to reside in an area outside of the United States, please contact a [Mattermost Expert](https://mattermost.com/contact-sales/) or consider deploying one of our [self-hosted options](https://mattermost.com/download/) that provides you with full control of your data. + +### Do you provide cross-region failover in the event of an outage in AWS us-east-1 region? + +Mattermost Cloud is hosted in AWS us-east-1 region. Cross-region failover is planned, but not yet in the roadmap. If you have feedback or require cross-region failover, please reach out to a [Mattermost Expert](https://mattermost.com/contact-sales/). + +### Is Mattermost Cloud a dedicated instance running on AWS systems? + +Mattermost Cloud Dedicated can be deployed as a dedicated Mattermost environment running with separate infrastructure for your requirements (e.g., separate database, separate VMs, separate Kubernetes cluster). + +### How is customer data in Mattermost Cloud Dedicated encrypted? + +Mattermost uses AWS-provided functionality to enable encryption-at-rest for both databases and file stores. See [Encrypting Amazon RDS resources - Amazon Relational Database Service](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html) and [Protecting data using server-side encryption - Amazon Simple Storage Service](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html) for details. + +Whether customer data should be stored in Mattermost Cloud depends heavily on the nature of the data and compliance requirements. We recommend that customers set up their own internal policies or controls around what can and cannot be put into Mattermost. + +### Are S3-managed keys used for server-side encryption? + +Yes, with Mattermost Cloud Dedicated. You can also bring your own keys for database and Amazon S3. + +### Are you SOC2 Type 2 certified? + +Yes. + +### Who is responsible for server maintenance and upgrades? + +For Mattermost Cloud deployments, Mattermost is responsible for regular security patches, software updates/releases, performance tuning, and ensuring uptime commitments. + +Mattermost performs monthly upgrades to your instance with the latest patch release during your preferred maintenance window. + +Mattermost may conduct unscheduled maintenance to address high-severity issues affecting the security, availability, or reliability of your instance. Maintenance windows are announced in advance on [https://status.mattermost.com/](https://status.mattermost.com/) + +Mattermost Cloud uses a Cloud-First Release Strategy with Ring-Based staged releases aligned to Mattermost licenses with a 24 hour soak time for [Mattermost Cloud Dedicated](/product-overview/cloud-dedicated) and for Enterprise customers using [Mattermost Cloud Shared](/product-overview/cloud-shared). + +### Can I use a custom URL at my organization's domain? + +No. Custom URLs are not currently supported for Mattermost Cloud deployments. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/product-overview/cloud-supported-integrations.mdx b/docs/main/product-overview/cloud-supported-integrations.mdx new file mode 100644 index 000000000000..d1182352fce6 --- /dev/null +++ b/docs/main/product-overview/cloud-supported-integrations.mdx @@ -0,0 +1,11 @@ +--- +--- +- [Microsoft Teams Sync](/integrations-guide/microsoft-teams-sync) +- [Microsoft Calendar Integration](/integrations-guide/microsoft-calendar) +- [Microsoft Teams Meetings](/integrations-guide/microsoft-teams-meetings) +- [GitHub](/integrations-guide/github) +- [GitLab](/integrations-guide/gitlab) +- [Jira](/integrations-guide/jira) +- [ServiceNow](/integrations-guide/servicenow) +- [User Survey](/administration-guide/configure/manage-user-surveys) +- [Zoom](/integrations-guide/zoom) diff --git a/docs/main/product-overview/cloud-vpc-private-connectivity.mdx b/docs/main/product-overview/cloud-vpc-private-connectivity.mdx new file mode 100644 index 000000000000..ae498c51c3e7 --- /dev/null +++ b/docs/main/product-overview/cloud-vpc-private-connectivity.mdx @@ -0,0 +1,32 @@ +--- +title: "Cloud VPC Private Connectivity" +--- + + +Virtual Private Cloud (VPC) Private Connectivity (Private Link) offers Enterprise Cloud customers tailored solutions for private connectivity needs with Mattermost Cloud. These options enable customers to access Mattermost Cloud through AWS's network without using the public internet, or allow the Mattermost Infrastructure team to manage a Mattermost instance hosted in the customer's VPC via an EKS cluster. It also provides the ability for customers to connect from Mattermost Cloud to their private webhooks,endpoints and integrations. + +The key objectives of this offering are to: + +- Allow customers to access Mattermost Cloud within their internal network. +- Enable the Mattermost Infrastructure team to perform operations on a Mattermost instance hosted in the customer’s VPC, upon request. +- Establish connectivity between the customer's VPC and Mattermost exclusively through AWS’s network, without exposure to the public internet. +- Ensure the setup process is straightforward and easy to implement. +- Adhere to all security best practices. + +## Architecture + +![A generic overview of the Cloud VPC Private Connectivity Architecture](/images/private-link-architecture.png) + +## Configure VPC Private Connectivity + +- Mattermost will provide Terraform modules tailored to the customer’s requirements. +- Both Mattermost and customer Infrastructure teams will collaborate to establish connectivity on both sides. +- AWS Private Link will be used to connect AWS accounts. + +### Requirements + +- Customers must own their AWS Account. + +### Considerations + +- Proper communication is essential for setting expectations and scheduling changes. diff --git a/docs/main/product-overview/common-esr-support-rst.mdx b/docs/main/product-overview/common-esr-support-rst.mdx new file mode 100644 index 000000000000..1678f2c95a06 --- /dev/null +++ b/docs/main/product-overview/common-esr-support-rst.mdx @@ -0,0 +1,7 @@ +--- +--- + + +Support for Mattermost Server v10.5 [Extended Support Release](/product-overview/release-policy#extended-support-releases) has come to the end of its life cycle on November 15, 2025. Upgrading to [Mattermost Server v10.11 or later](/product-overview/mattermost-server-releases) is required. + + diff --git a/docs/main/product-overview/common-esr-support-upgrade.mdx b/docs/main/product-overview/common-esr-support-upgrade.mdx new file mode 100644 index 000000000000..0dd33fbfec7d --- /dev/null +++ b/docs/main/product-overview/common-esr-support-upgrade.mdx @@ -0,0 +1,9 @@ +--- +--- +{/* Snippet include; not intended to be a standalone page */} + +- Support for Mattermost Server v10.5 [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) has come to the end of its life cycle on November 15, 2025. Upgrading to Mattermost Server v10.11 or later is required. +- Upgrading from one Extended Support Release (ESR) to the next ESR (``major`` -> ``major_next``) is fully supported and tested. However, upgrading across multiple ESR versions (``major`` to ``major+2``) is supported, but not tested. If you plan to skip versions, we strongly recommend upgrading only between ESR releases. For example, if you're upgrading from v8.1 ESR, upgrade to the v9.5 ESR or the v9.11 ESR before attempting to upgrade to the [v10.5 ESR](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-5-extended-support-release) or the [v10.11 ESR](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-11-extended-support-release). +- See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) documentation for details on upgrading to a newer release. +- See the [changelog in progress](https://bit.ly/2nK3cVf) for details about the upcoming release. +- All Mattermost users must accept Mattermost's [Acceptable Use Policy](https://mattermost.com/terms-of-use/#acceptable-use-policy) and [Privacy Policy](https://mattermost.com/privacy-policy/) when creating an account or accessing Mattermost. For customers with a Mattermost subscription, including self-hosted deployments, organizations may replace or override the Acceptable Use Policy in the [Mattermost System Console](https://docs.mattermost.com/administration-guide/configure/site-configuration-settings.html#terms-of-use-link) with their own acceptable use or conduct policies, based on contractual terms with Mattermost, so long as your own terms either incorporate the Acceptable Use Policy or include equivalent terms. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Acceptable Use Policy for Mattermost software. diff --git a/docs/main/product-overview/common-esr-support.mdx b/docs/main/product-overview/common-esr-support.mdx new file mode 100644 index 000000000000..0b61d92ebc5b --- /dev/null +++ b/docs/main/product-overview/common-esr-support.mdx @@ -0,0 +1,6 @@ +--- +--- +{/* Snippet include; not intended to be a standalone page */} + +- Support for Mattermost Server v10.5 [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) has come to the end of its life cycle on November 15, 2025. Upgrading to [Mattermost Server v10.11](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-11-extended-support-release) or later is required. +- All Mattermost users must accept Mattermost's [Acceptable Use Policy](https://mattermost.com/terms-of-use/#acceptable-use-policy) and [Privacy Policy](https://mattermost.com/privacy-policy/) when creating an account or accessing Mattermost. For customers with a Mattermost subscription, including self-hosted deployments, organizations may replace or override the Acceptable Use Policy in the [Mattermost System Console](https://docs.mattermost.com/administration-guide/configure/site-configuration-settings.html#terms-of-use-link) with their own acceptable use or conduct policies, based on contractual terms with Mattermost, so long as your own terms either incorporate the Acceptable Use Policy or include equivalent terms. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Acceptable Use Policy for Mattermost software. diff --git a/docs/main/product-overview/corporate-directory-integration.mdx b/docs/main/product-overview/corporate-directory-integration.mdx new file mode 100644 index 000000000000..9be099e28fa5 --- /dev/null +++ b/docs/main/product-overview/corporate-directory-integration.mdx @@ -0,0 +1,61 @@ +--- +title: "Corporate Directory Integration" +--- +Mattermost offers advanced security and authentication options for integrating with corporate directories. This guide outlines the options available. + +## Basic authentication + +By default, Mattermost offers authentication via email and password, which offers basic features including: + +- Account sign up using email and password. +- Password reset via email. +- Ability to use the same credentials to log into web, desktop, and mobile app experiences. +- Ability to use a username and password in place of email and password. + +## Security features for authentication + +A core set of features is available with all authentication options to help increase security: + +- Ability to [set session length](/administration-guide/configure/environment-configuration-settings#session-lengths) to define how long a user can use Mattermost before needing to re-enter credentials. +- Ability for users to remotely sign out of devices. +- Ability for IT admin to force sign out of a user from devices. +- Ability to set rate limits on authentication API calls to deter password-guessing attacks. +- Ability to require multi-factor authentication on log in. +- For advanced deployments, password requirements for length and special characters can be added. + +## AD/LDAP authentication + +[AD/LDAP](/administration-guide/onboard/ad-ldap) is the most popular corporate directory integration option for deploying Mattermost behind a corporate firewall. Features include: + +- Account creation using AD/LDAP credentials. +- AD/LDAP user filters to define which users get access to Mattermost in the form of a query. +- Ability to use a low-privileged AD/LDAP account to run queries over a secure TLS or STARTTLS connection. +- Attribute mapping to place First Name, Last Name, Nickname, and other attributes from AD/LDAP into Mattermost. +- Customization of login screen to specify whether users are logging in with email, username, or other attribute. +- Synchronization with AD/LDAP to disable, enable, and update Mattermost users based on AD/LDAP. + + + +\- New user accounts are created when new users log in with their AD/LDAP credentials. You can optionally pre-create user accounts using the [bulk loading](/administration-guide/onboard/bulk-loading-data) tool. - If you're using email or username and password authentication [users can switch to AD/LDAP manually](/administration-guide/onboard/ad-ldap#getting-started), and the conversion to AD/LDAP can also be done using the [mmctl user migrate auth](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-migrate-auth) command by an IT admin. + + + +For very large AD/LDAP instances you can also configure max page size to divide a Mattermost AD/LDAP query into several pieces to not overtax the authentication server when synchronizing. + +## Authentication options outside of a private network + +When deploying Mattermost to a DMZ location outside the security of a private network, additional authentication options include: + +- [Okta integration via SAML](/administration-guide/onboard/sso-saml-okta) +- [OneLogin integration via SAML](/administration-guide/onboard/sso-saml-onelogin) +- [Active Directory Federation Services via SAML](/administration-guide/onboard/sso-saml-adfs) +- [SAML 2.0 authentication](/administration-guide/onboard/sso-saml) +- [Google Apps](/administration-guide/onboard/sso-google) +- [Entra ID](/administration-guide/onboard/sso-entraid) +- [OpenID Connect](/administration-guide/onboard/sso-openidconnect) + +Generic OAuth is not currently supported. + +## Future authentication methods + +Mattermost releases new improvements monthly. Several additional authentication methods are planned, but not yet scheduled. If you're an enterprise interested in deploying with an option not yet provided in our documentation, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) to discuss further. diff --git a/docs/main/product-overview/deprecated-features.mdx b/docs/main/product-overview/deprecated-features.mdx new file mode 100644 index 000000000000..b1d362039622 --- /dev/null +++ b/docs/main/product-overview/deprecated-features.mdx @@ -0,0 +1,247 @@ +--- +title: "Removed and Deprecated Features" +--- +This page describes features that are removed from support for Mattermost, or will be removed in a future update (deprecated), and provides early notice about future changes that might affect your use of Mattermost. This information is subject to change with future releases, and might not include each deprecated feature. + +## Upcoming deprecations + +- There are no planned deprecations at this time. + +## Removed features by Mattermost version + +### Mattermost Desktop App v6.1 (March 2026) + +- The in-app auto-updater for Windows and Linux AppImage installations has been deprecated. See more details in [this forum post](https://forum.mattermost.com/t/important-update-changes-to-desktop-app-auto-updater/25657). + +### Mattermost Server v11.4 (February 2026) + +- Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments. This change has also been applied to v11.3.1, v11.2.3, and v10.11.11 (Extended Support Release) dot releases. + +### Mattermost Mobile App v2.36.4 (January 2026) + +- Removed support for iOS v15 and updated the iOS minimum version to v16. See more details in [this forum post](https://forum.mattermost.com/t/mobile-app-ios-version-support-update-v2-36-1-and-v2-36-2/25664). + +### Mattermost Server v11.1 (November 2025) + +- The version of React used by the Mattermost web app has been updated from React 17 to React 18. See more details in [this forum post](https://forum.mattermost.com/t/upgrading-the-mattermost-web-app-to-react-18-v11/25000). + +### Mattermost Server v11.0 (October 2025) + +- GitLab SSO has been deprecated from Team Edition. Deployments using GitLab SSO can remain on v10.11 ESR (with 12 months of security updates) while transitioning to our new free offering Mattermost Entry, or can explore commercial/nonprofit options. See more details in [this forum post](https://forum.mattermost.com/t/mattermost-v11-changes-in-free-offerings/25126). + +- The `TeamSettings.ExperimentalViewArchivedChannels` setting has been deprecated. Archived channels will always be accessible, subject to normal channel membership. The server will fail to start if this setting is set to `false`. To deny access to archived channels, mark them as private and remove affected channel members. See more details in [this forum post](https://forum.mattermost.com/t/viewing-accessing-archived-channels-v11/22626). + +- Playbooks has stopped working for Team Edition. Entry, Professional, Enterprise, and Enterprise Advanced plans are automatically upgraded to Playbooks v2 with no expected downtime. See more details in [this forum post](https://forum.mattermost.com/t/clarification-and-update-on-the-playbooks-plugin-v11/25192). + +- Experimental Bleve Search functionality has been retired. If Bleve is enabled, search will not work until `DisableDatabaseSearch` is set to `false`. See more details in [this forum post](https://forum.mattermost.com/t/transitioning-from-bleve-search-in-mattermost-v11/22982). + +- Support for MySQL has ended. Our [Migration Guide](https://docs.mattermost.com/deployment-guide/postgres-migration.html) outlines the steps, tools and support available for migrating to PostgreSQL. See more details in [this forum post](https://forum.mattermost.com/t/transition-to-postgresql/19551). + +- The `registerPostDropdownMenuComponent` hook in the web app’s plugin API has been removed in favour of `registerPostDropdownMenuAction`. See more details in [this forum post](https://forum.mattermost.com/t/deprecating-a-post-dropdown-menu-component-plugin-api-v11/25001). + +- The web app is no longer exposing the [Styled Components](https://styled-components.com/) dependency for use by web app plugins. See more details in [this forum post](https://forum.mattermost.com/t/removing-styled-components-export-for-web-app-plugins-v11/25002). + +- Omnibus support has been deprecated. The last `mattermost-omnibus` release was v10.12. See more details in [this forum post](https://forum.mattermost.com/t/mattermost-omnibus-to-reach-end-of-life-v11/25175). + +- Deprecated `include_removed_members` option in `api/v4/ldap/sync` has been removed. Admins can use the LDAP setting `ReAddRemovedMembers`. + +- Customers that have the NPS plugin enabled can remove it as it no longer sends the feedback over through telemetry. + +- Format query parameter requirement in the `/api/v4/config/client` endpoint has been deprecated. + +- Removed deprecated mmctl commands and flags: + - `channel add` - use `channel users add` + - `channel remove` - use `channel users remove` + - `channel restore` - use `channel unarchive` + - `channel make-private` - use `channel modify --private` + - `command delete` - use `command archive` + - `permissions show` - use `permissions role show` + - `mmctl user email` - use `mmctl user edit email` + - `mmctl user username` - use `mmctl user edit username` + +- Experimental certificate-based authentication feature has been removed. `ExperimentalSettings.ClientSideCertEnable` must be `false` to start the server. + +- Added logic to migrate the password hashing method from bcrypt to PBKDF2. The migration will happen progressively, migrating the password of a user as soon as they enter it; e.g. when logging in or when double-checking their password for any sensitive action. There is an edge case where users might get locked out of their account: if a server upgrades to v11 and user A logs in (i.e., they need to enter their password), and then the server downgrades to v10.12 or previous, user A will no longer be able to log in. In this case, admins will need to manually reset the password of such users, through the system console or through the [mmctl user reset-password \[users\]](mm-ref:administration-guide%2Fmanage%2Fmmctl-command-line-tool%3Ammctl%20user%20reset-password) command. The new password hashing method is more CPU-intensive. Admins of servers with password-based login should monitor the performance on periods where many users log in at the same time. + +- `/api/v4/teams/{team_id}/channels/search_archived` has been deprecated in favour of `/api/v4/channels/search` with the deleted parameter. + +- Separate notification log file has been deprecated. If admins want to continue using a separate log file for notification logs, they can use the `AdvancedLoggingJSON` configuration. An example configuration to use is: + +``` sh +{ + "LogSettings": { + "AdvancedLoggingJSON": { + "notifications_file": { + "type": "file", + "format": "json", + "levels": [ + {"id": 300, "name": "NotificationError"}, + {"id": 301, "name": "NotificationWarn"}, + {"id": 302, "name": "NotificationInfo"}, + {"id": 303, "name": "NotificationDebug"}, + {"id": 304, "name": "NotificationTrace"} + ], + "options": { + "filename": "notifications.log", + "max_size": 100, + "max_age": 0, + "max_backups": 0, + "compress": true + }, + "maxqueuesize": 1000 + } + } + } +} +``` + +- Stopped supporting manually installed plugins as per [https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192](https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192). +- Support for PostgreSQL v13 has been removed. The new minimum PostgreSQL version is v14+. See the [minimum supported PostgreSQL version policy](/deployment-guide/software-hardware-requirements#minimum-postgresql-database-support-policy) documentation for details. + +### Mattermost Server v10.8.0 + +- Support for legacy SKUs E10 and E20 licenses was removed. If you need assistance, [talk to a Mattermost expert](https://mattermost.com/contact-sales/). + +### Mattermost Server v10.6.0 + +- Support for PostgreSQL v11 and v12 have been removed. The new minimum PostgreSQL version is v13+. See the [minimum supported PostgreSQL version policy](/deployment-guide/software-hardware-requirements#minimum-postgresql-database-support-policy) documentation for details. + +### Mattermost Server v10.5.0 + +- The Mattermost server has stopped supporting manual plugin deployment. Plugins were deployed manually when an administrator or some deployment automation copies the contents of a plugin bundle into the server's working directory. If a manual or automated deployment workflow is still required, administrators can instead prepackage the plugin bundles. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192). +- Mattermost has stopped official Mattermost server builds for the Microsoft Windows operating system. Administrators should migrate existing Mattermost server installations to use the official Linux builds. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-server-builds-for-microsoft-windows/21498). + +### Mattermost Mobile App v2.25.0 + +- In the Mattermost Mobile App v2.25, Mattermost has stopped supporting iOS versions 13 and 14. Users should update their iOS version to v15.1 or newer. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-ios-13-and-14-versions/21845). + +### Mattermost Server v10.4.0 + +- The ability to import Slack themes as Mattermost themes is no longer supported. + +### Mattermost Server v10.3.0 + +- The Classic Mobile App has been phased out. Please download the new v2 Mobile App from the [Apple App Store](https://apps.apple.com/us/app/mattermost/id1257222717) or [Google Play Store](https://play.google.com/store/apps/details?id=com.mattermost.rn). See more details in the [classic mobile app deprecation](https://forum.mattermost.com/t/classic-mobile-app-deprecation/18703) Mattermost forum post. + +### Mattermost Server v10.2.0 + +- Docker Content Trust (DCT) for signing Docker image artifacts has been replaced by Sigstore Cosign in v10.2 (November, 2024). If you rely on artifact verification using DCT, please [transition to using Cosign](https://edu.chainguard.dev/open-source/sigstore/cosign/how-to-install-cosign/). See [this forum post](https://forum.mattermost.com/t/upcoming-dct-deprecation/19275) for more details. + +### Mattermost Server v10.0.0 + +- We no longer support new installations using MySQL starting in v10. All new customers and/or deployments will only be supported with the minimum supported version of the PostgreSQL database. End of support for MySQL is targeted for Mattermost v11. +- Apps Framework is deprecated for new installs. Please extend Mattermost using webhooks, slash commands, OAuth2 apps, and plugins. +- Fully deprecated the `/api/v4/image` endpoint when the image proxy is disabled. +- Removed deprecated `Config.ProductSettings`, `LdapSettings.Trace`, and `AdvancedLoggingConfig` configuration fields. +- Removed deprecated `pageSize` query parameter from most API endpoints. +- Deprecated the experimental Strict CSRF token enforcement. This feature will be fully removed in Mattermost v11. + +### Mattermost Server v9.9.0 + +- Removed support for self-serve purchases of Mattermost Subscriptions in various flows, throughout Cloud and Self Hosted environments. +- Removed support for self-serve true up review submission in the **System Console**. + +### Mattermost Server v9.5.0 + +- MySQL v5.7 is at end of life. We recommend all customers to upgrade to at least 8.x. From Mattermost v9.5, which is the latest Extended Support Release, we have stopped supporting MySQL v5.7 altogether. + +### Mattermost Server v9.0.0 + +- Mattermost Boards and various other plugins have transitioned to being fully community supported. See this [forum post](https://forum.mattermost.com/t/upcoming-product-changes-to-boards-and-various-plugins/16669) for more details. +- Removed the deprecated Insights feature. + +### Mattermost Server v8.0.0 + +- Removed `ExperimentalSettings.PatchPluginsReactDOM`. If this setting was previously enabled, confirm that: + - All Mattermost-supported plugins are updated to the latest versions. + - Any other plugins have been updated to support React 17. See the [Important Upgrade Notes](/administration-guide/upgrade/important-upgrade-notes) for v7.7 for more information. +- Deprecated Insights for all new instances and for existing servers that upgrade to Mattermost v8.0. +- Removed deprecated `PermissionUseSlashCommands`. +- Removed deprecated `model.CommandArgs.Session`. +- Removed support for PostgreSQL v10. The new minimum PostgreSQL version is now v11. +- Deprecated the `AdvancedLoggingConfig` fields, and replaced them with `AdvancedLoggingJSON` fields which accept inline JSON or a filename. + +### Mattermost Server v6.0.0 + +- [Legacy Command Line Tools](/administration-guide/manage/command-line-tools). Most commands have been replaced by [mmctl](/administration-guide/manage/mmctl-command-line-tool) and new commands have been added over the last few months, making this tool a full and robust replacement. +- Slack Import via the web app. The Slack import tool accessible via the Team Setting menu is being replaced by the mmetl tool that is much more comprehensive for the types of data it can assist in uploading. +- MySQL versions below 5.7.12. Minimum support will now be for 5.7.12. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). +- Elasticsearch 5 and 6. [Versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 will be Elasticsearch version 7.0. +- Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We will no longer provide support for the desktop app issues on Windows 7. +- [DisableLegacyMFAEndpoint](/administration-guide/configure/deprecated-configuration-settings#disable-legacy-mfa-api-endpoint) configuration setting. +- [Experimental Timezone](/administration-guide/configure/deprecated-configuration-settings#timezone) configuration setting. +- All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access custom, collapsible channel categories among many other channel organization features. The settings being deprecated include: + - [EnableLegacySidebar](/administration-guide/configure/deprecated-configuration-settings#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](/administration-guide/configure/deprecated-configuration-settings#town-square-is-read-only) + - [ExperimentalHideTownSquareinLHS](/administration-guide/configure/deprecated-configuration-settings#town-square-is-hidden-in-left-hand-sidebar) + - [EnableXToLeaveChannelsFromLHS](/administration-guide/configure/deprecated-configuration-settings#enable-x-to-leave-channels-from-left-hand-sidebar) + - [CloseUnusedDirectMessages](/administration-guide/configure/deprecated-configuration-settings#autoclose-direct-messages-in-sidebar) + - [ExperimentalChannelOrganization](/administration-guide/configure/deprecated-configuration-settings#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](/administration-guide/configure/deprecated-configuration-settings#experimental-sidebar-features) +- [All configuration settings previously marked as “Deprecated”](/administration-guide/configure/configuration-settings#deprecated-configuration-settings). +- Changes to mattermost-server/model for naming consistency. + +### Mattermost Server v5.38.0 + +- In the v5.38 release (August 16, 2021), the “config watcher” (the mechanism that automatically reloads the “config.json“ file), has been removed in favor of the “mmctl config“ command that will need to be run to apply configuration changes after they are made. This change will improve configuration performance and robustness. + +### Mattermost Server v5.37.0 + +- The “platform“ binary and “–platform” flag have been removed. If you are using the “–platform” flag or are using the “platform“ binary directly to run the Mattermost server application via a systemd file or custom script, you will be required to use only the “mattermost“ binary. + +### Mattermost Server v5.32.0 + +- TLS versions 1.0 and 1.1 have been deprecated by browser vendors. Starting in Mattermost Server v5.32 (February 16), mmctl returns an error when connected to Mattermost servers deployed with these TLS versions and System Admins will need to explicitly add a flag in their commands to continue to use them. We recommend upgrading to TLS version 1.2 or higher. + +### Mattermost Server v5.30.0 + +- PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). From v5.26 Mattermost officially supports PostgreSQL version 10 as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL 9.4. PostgreSQL 9.4 and all 9.x versions are now fully deprecated in our v5.30 release (December 16). Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). + +### Mattermost Server v5.16.0 + +- Removed support for Internet Explorer (IE11) in Mattermost v5.16.0. Learn more in our [forum post](https://forum.mattermost.com/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575). + +### Mattermost Server v5.12.0 + +- ExperimentalEnablePostMetadata setting was removed. Post metadata, including post dimensions, is now stored in the database to correct scroll position and eliminate scroll jumps as content loads in a channel. + +### Mattermost Server v5.6.0 + +- Removed support for WebRTC in beta, and replaced it with other video and audio calling solutions. +- Removed support for IE11 Mobile View due to low usage and instability in order to invest that effort in maintaining a high quality experience on other more used browsers. End users on IE11 will thus have an increased minimum screen size. Mobile View is still supported on Chrome, Firefox, Safari, Edge as well as the desktop apps. + +### Mattermost Server v5.0.0 + +- All API v3 endpoints removed. API v3 endpoints are no longer supported as of Mattermost v4.6 release on January 16th, 2018, and are replaced by API v4 endpoints which were released on July 16th, 2017. See [https://api.mattermost.com](https://api.mattermost.com) to learn more. +- Desktop Notification Duration in Account Settings removed due to inconsistencies on various browsers and operating systems. +- An unused “ExtraUpdateAt” field removed from the channel model. +- `platform` binary renamed to mattermost for a clearer install and upgrade experience. All command line tools, including the bulk loading tool and developer tools, also renamed from platform to mattermost. +- Slash commands configured to receive a GET request now have the payload encoded in the query string instead of receiving it in the body of the request, consistent with standard HTTP requests. Although unlikely, this could break custom slash commands that use GET requests incorrectly. +- A new `config.json` setting to whitelist types of protocols for auto-linking added. +- A new `config.json` setting to disable the [permanent APIv4 delete team parameter](https://api.mattermost.com/#tag/teams%2Fpaths%2F~1teams~1%7Bteam_id%7D%2Fput) added. The setting is off by default for all new and existing installs, except those deployed on GitLab Omnibus. A System Admin can enable the API v4 endpoint from the `config.json` file. + +### Mattermost Server v4.9.0 + +- A number of permissions configuration settings will be migrated to roles in the database, and changing their config.json values will no longer take effect. These permissions can still be modified by their respective System Console settings. See [changelog](/product-overview/unsupported-legacy-releases) for more details. + +### Mattermost Server v4.0.0 + +- System Console settings in **Files \> Images**, including: + - Image preview height and width + - Profile picture height and width + - Image thumbnail height and width +- Font setting in **Account Settings \> Display** +- Teammate Name Display setting moved to the System Console + +### Mattermost Server v3.8.0 + +- Old CLI tool (replaced by [an upgraded CLI tool](/administration-guide/manage/command-line-tools)) +- APIv3 endpoints: + - “GET at /channels/more” (replaced by “/channels/more/{offset}/{limit}”) + - “POST at /channels/update_last_viewed_at” (replaced by “/channels/view”) + - “POST at /channels/set_last_viewed_at” (replaced by “/channels/view”) + - “POST at /users/status/set_active_channel” (replaced by “/channels/view”) + +### Mattermost Server v3.7.0 + +- “ServiceSettings: SegmentDeveloperKey” setting in `config.json` diff --git a/docs/main/product-overview/desktop-app-changelog.mdx b/docs/main/product-overview/desktop-app-changelog.mdx new file mode 100644 index 000000000000..f9ebf4c9e07e --- /dev/null +++ b/docs/main/product-overview/desktop-app-changelog.mdx @@ -0,0 +1,2659 @@ +--- +title: "Desktop App Changelog" +--- +import Inc0_common_esr_support from './common-esr-support.mdx'; + +This changelog summarizes updates to Mattermost desktop app releases for [Mattermost](https://mattermost.com). + +```{Important} + +(release-v6-1)= +## Release v6.1 + +- **v6.1.2, released 2026-04-21** + + - Fixed an issue where the desktop app failed to start on Linux when GPU hardware acceleration was disabled. + +- **v6.1.1, released 2026-04-08** + + - Mattermost Desktop App v6.1.1 contains low to medium severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Upgraded to Electron v40.8.4. + - Fixed additional issues around URL parsing with special characters. + - Fixed an issue where new views would not load if the URL to open contained query parameters. + - Fixed an issue where plugins other than Calls could not request desktop screen sharing sources. + - Fixed an issue where content running inside a server view could close the view or cause the app to become unresponsive. + +- **v6.1.0, released 2026-03-02** + + - Original v6.1.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v6.1.2) + +### Important Upgrade Notes + +- The in-app auto-updater for Windows and Linux AppImage installations has been deprecated. See more details in [this forum post](https://forum.mattermost.com/t/important-update-changes-to-desktop-app-auto-updater/25657). + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/product-overview/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 144+. + +### Improvements + +#### macOS + +- Removed MAS (Mac App Store) migration logic. +- Changed the name of the macOS ARM64 DMG from ``m1`` to ``arm64``. + +#### Windows + +- Forced [MSI to install per-machine](https://docs.mattermost.com/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install.html) by default. See Known Issues below for more details. +- Removed the [Windows EXE installer](https://docs.mattermost.com/deployment-guide/desktop/silent-windows-desktop-distribution.html). + +#### Linux +- Added [Flatpak](https://docs.mattermost.com/deployment-guide/desktop/linux-desktop-install.html) to Linux-packaged builds. + +#### All Platforms + +- Added support for servers with passwordless authentication with [Magic Link for guest users](https://docs.mattermost.com/end-user-guide/access/access-your-workspace.html#magic-link-login-for-guests) (requires Enterprise license). +- Added [Sentry error tracking](https://docs.mattermost.com/deployment-guide/desktop/desktop-app-deployment.html#privacy-and-data-handling). +- Added [in-app notifications for new versions](https://docs.mattermost.com/end-user-guide/access/install-desktop-app.html#upgrade-the-desktop-app), including for Mac App Store and the Windows MSI. + +### Architectural Changes + +- Major version upgrade of Electron to v40.6.0. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### macOS + +- Fixed an issue where macOS permission dialogs were specifically referencing Jitsi instead of using general wording. + +#### Windows + +- Fixed an issue where installing over top of an old Desktop App on Windows could break the shortcut. NOTE: You may need to [remake your shortcut](https://docs.mattermost.com/deployment-guide/desktop/desktop-troubleshooting.html) in the taskbar once after this change. +- Fixed an issue where the notification badge on Windows could get out of sync. + +#### All Platforms + +- Fixed a potential crash in the context menu. +- Fixed an unnecessary exception handler dialog box appearing when clicking **Clear All Data**. +- Fixed an issue where Microsoft Teams, SharePoint, and OneNote links were incorrectly rejected as "Invalid Link" due to special characters in their URLs. +- Fixed an issue where clicking the tray menu items would not open the main window. +- Fixed an issue where clicking the tray menu items would not open the main window if it was occluded. +- Fixed an issue where Sentry and anonymous server metrics were not enabled by default. +- Fixed an issue where the Desktop App wouldn't load content from the JIRA plugin in certain cases. + +### Open Source Components + +- Added ``@sentry/electron`` and removed ``electron-updater`` from https://github.com/mattermost/desktop. + +### Known Issues + +- For Calls to work properly with Desktop 6.1, one must use RTCD v1.2.5 (if using external RTCD server) or Calls plugin v1.11.1 (if using integrated RTCD). +- Desktop App v6.1 has been tested against our existing EXE and MSI installers, with a few caveats: + - When installing over top of the MSI installer for versions below v5.9, an extra shortcut may be left in the user's start menu. This can be safely deleted. + - When installing over top of the MSI installer for versions from v5.9 to v6.0.4, if the installation was done per-user (as is the default), the new installer will not replace the old one. This is due to the fact that MSIs cannot modify across contexts, so as a one-time fix, users will have to manually uninstall the old one. We recommend doing this before installing the new one. +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users//Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users//AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [lieut-data](https://github.com/lieut-data), [lifeisafractal](https://github.com/lifeisafractal), [NARSimoes](https://github.com/NARSimoes), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan). + +(release-v6-0)= +## Release v6.0 + +- **v6.0.4, released 2026-01-20** + + - Added an in-app notice for auto-update deprecation for users who have auto-updates enabled. See more details in [this forum post](https://forum.mattermost.com/t/important-update-changes-to-desktop-app-auto-updater/25657). + +- **v6.0.3, released 2026-01-16** + + - Mattermost Desktop App v6.0.3 contains medium to high severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +- **v6.0.2, released 2025-12-10** + + - Fixed the missing Cmd/Ctrl+W shortcut for closing windows. + - Fixed an issue where quitting the app while the last server set was a GPO server would corrupt the config file. + - Fixed an issue where a global shortcuts window would pop up on every start of the app on Linux. + - Fixed a visual issue with the **Settings** modal while scrolling. + - Fixed an issue where the URL view could end up in the middle of the screen. + - Fixed an issue where links in the Calls widget did not open in an external tab. + - Fixed an issue where redirection would not focus the pop-out window when popping out a thread from a window. + - Fixed an issue where the Windows tray icon theme would not respect the system theme. + - Fixed an issue where the Calls Widget would not allow popouts. + +- **v6.0.1, released 2025-11-18** + + - Fixed a crash when hovering over an external URL in a re-docked pop-out window. + - Fixed an issue where the app would crash on errored servers. + - Fixed an issue upgrading configuration files on Windows. + - Fixed a potential race condition when writing the JSON config file. + +- **v6.0.0, released 2025-11-14** + + - Original v6.0.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v6.0.4) + +```{Note} +Mattermost Desktop App v6.0.0 contains low severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/product-overview/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 140+ and updated Windows minimum supported version to v11+. + +### Highlights + +#### Desktop App Multi-View Architecture + - Mattermost Desktop App v6.0 introduces a new Multi-View Architecture that replaces the previous fixed-tab layout. This enhancement introduces a dynamic, flexible system where users can open, close, and manage multiple views or windows, including any part of the Mattermost app (e.g., Channels, Boards, Playbooks). This architectural update provides a more customizable and efficient workspace experience while laying the foundation for advanced multi-window and pop-out features in future releases. + +![image](/images/desktop-multi.png) + +### Improvements + +#### All Platforms + +- Added parent-child popout window support, with listeners to facilitate communication. +- Added pre-auth headers to the server modal. This header is injected into all requests to that server. +- Unified and polished basic authentication, client certificate and pre-auth header authentication methods. +- Added default theme syncing with the web app. +- Added server version information to the **Help** menu. +- Created a **File** menu on macOS, and added **New Window/Tab** and **Close Window/Tab** to the **File** menu. +- Added **clear the cache and reload** link to the error screen. +- Disallowed other servers to end the current call, showing an error message. +- Adjusted colors to be more accurate to Mattermost theming. + +### Architectural Changes + +- Major version upgrade of Electron to 38.2.1. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed various issues with the newer modals. +- Fixed UX issues with the checkbox component. +- Fixed an issue where configuration files could be corrupted by interleaving writes. + +### Open Source Components + +- Switched to ``registry-js`` native module for Windows registry reading in https://github.com/mattermost/desktop/. + +### Known Issues + +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [BenCookie95](https://github.com/BenCookie95). + +(release-v5-13)= +## Release v5.13 (Extended Support Release) + +- **v5.13.5, released 2026-03-24** + + - Mattermost Desktop App v5.13.5 contains low to medium severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where the app threw an error on a malformed URL. + - Fixed an issue where content running inside a server view could close the view or cause the app to become unresponsive. + +- **v5.13.4, released 2026-01-29** + + - Mattermost Desktop App v5.13.4 contains a medium severity level security fix. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +- **v5.13.3, released 2026-01-22** + + - Mattermost Desktop App v5.13.3 contains low to high severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +- **v5.13.2, released 2025-10-16** + + - Upgraded Electron to v37.6.1. + +- **v5.13.1, released 2025-09-10** + + - Mattermost Desktop App v5.13.1 contains low to medium severity level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Upgraded to Electron 37.4.0. + +- **v5.13.0, released 2025-08-15** + + - Original v5.13.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.13.5) + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/product-overview/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 138+. + +### Improvements + +#### All Platforms + +- Enhanced ``mattermost://`` protocol handling to open in-app links within the desktop application instead of external protocol dialogs. + +### Architectural Changes + +- Major version upgrade of Electron to 37.2.2. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue with URL preview stealing focus from the app. +- Fixed an issue with the zoom-in keyboard shortcut. +- Fixed an issue where the **Enter** key would not confirm most modals. + +### Open Source Components + +- Added ``electron-devtools-installer`` and ``registry-js``, and removed ``electron-connect`` and ``electron-extension-installer`` from https://github.com/mattermost/desktop/. + +### Known Issues + +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [hmhealey](https://github.com/hmhealey), [toffguy77](https://github.com/toffguy77). + +(release-v5-12)= +## Release v5.12 + +- **v5.12.1, released 2025-05-31** + + - Fixed an issue where focus was lost when tabbing to an external URL on Windows/Linux. + - Disabled server management in the **Settings** modal when disabled via group policy. + +- **v5.12.0, released 2025-05-16** + + - Original v5.12.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.12.1) + +```{Note} +Mattermost Desktop App v5.12.0 contains a medium severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 134+. + +### Improvements + +#### All Platforms + +- Refreshed the **Settings** modal designs. +- Refreshed all built-in dialogs with new designs. +- Added a changelog link for when the app auto-updates. +- Updated the certificate error message. +- Removed bootstrap and dependencies. + +### Architectural Changes + +- Major version upgrade of Electron to 35.2.0. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where server loading was blocked on contact with each configured server. + +### Open Source Components + +- Added ``@floating-ui/react`` to https://github.com/mattermost/desktop. + +### Known Issues + +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [j0794](https://github.com/j0794). + +(release-v5-11)= +## Release v5.11 (Extended Support Release) + +- **v5.11.3, released 2025-05-23** + + - Fixed an issue where focus was lost when tabbing to an external URL on Windows/Linux. + - Fixed an issue where server loading was blocked on contact with each configured server. + +- **v5.11.2, released 2025-03-12** + + - Fixed an issue where the incompatible server screen showed by default when the server info was not present. + +- **v5.11.1, released 2025-03-01** + + - Mattermost Desktop App v5.11.1 contains a high severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a server incompatible version screen. Users with servers running Mattermost v9.3 and earlier versions are not supported by this upgrade. Mattermost v9.4 or later is required. + - Fixed an issue where the server drop-down wouldn't render properly on first load. + - Updated the error page with new visuals. + +- **v5.11.0, released 2025-02-14** + + - Original v5.11.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.11.3) + +```{Note} +Mattermost Desktop App v5.11.0 contains a low severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 132+. + +### Improvements + +#### Linux + +- Modified rpm-digest to utilize sha256 instead of md5 to all for rpm installation on FIPS mode enabled Enterprise Linux systems. + +#### All Platforms + +- Added two menu items to help users forcibly clear out cache and session data. +- Improved the help options in the **Help** menu. +- Updated the styling of the **Downloads** menu to improve text fitting and to prevent text overlap. +- Refreshed loading and welcome screens. +- Server URLs are now auto-filled when deep-linking into the Desktop App if the server isn't configured. +- Removed legacy code for older unsupported Mattermost servers. +- Calls: while the popout window is open, the widget window's visibility will change so that it is not always on top of other windows. + +### Architectural Changes + +- Major version upgrade of Electron to 34.0.1. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### macOS + +- Fixed an issue where the MAS migration from DMG would always fail, fixed a potential crash case. + +#### Windows + +- Fixed an issue with per-server permission checks for GPO-configured servers on Windows. +- Fixed an issue where the app could crash loading a thumbnail on Windows. + +#### Linux + +- Fixed an issue for Linux users where the app could crash when trying to add the first server. + +#### All Platforms + +- Fixed an issue where autocompleting did not stop while the user was typing `https://`. +- Fixed an issue preventing the screen sharing selection modal to show when the app was focused on a different tab (e.g. Playbooks, Boards). +- Fixed an issue trying to download images using right-click > **Save As...**. +- Fixed an issue where the URL view would trap focus when tabbing over a link. + +### Known Issues + +- Users with servers running Mattermost v9.3 and earlier versions are not supported by this upgrade. Mattermost v9.4 or later is required. +- Boards is not using the new Desktop API, causing issues in v5.11+. Users of v5.11 will need to upgrade their Boards plugin version to v9.1.0+ avoid the issue. +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [andr-sokolov](https://github.com/andr-sokolov), [devinbinnie](https://github.com/devinbinnie), [jonathan-dove](https://github.com/jonathan-dove), [pvev](https://github.com/pvev), [s1Sharp](https://github.com/s1Sharp), [streamer45](https://github.com/streamer45). + +(release-v5-10)= +## Release v5.10 + +- **v5.10.2, released 2024-12-17** + + - Fixed an issue where the new MSI installer would not uninstall versions before v5.9 installed via MSI. + - Fixed an issue where the MSI kept auto-update on for per-machine installation. + - Fixed a potential error thrown by the MSI when trying to uninstall the EXE. + - Fixed an issue where minimizing on Linux would cause the window to re-appear immediately. + - Added support for downgrading using the MSI installer. + - Fixed an issue where the application would not focus the browser window when opening an external link. + - Upgraded to Electron v33.2.0. + +- **v5.10.1, released 2024-11-20** + + - Fixed an issue where the app would not restore when opened again from cold. + - Fixed an issue where deep linking from cold didn't work on Linux. + +- **v5.10.0, released 2024-11-15** + + - Original v5.10.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.10.2) + +```{Note} +Mattermost Desktop App v5.10.0 contains a low severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 130+. + +### Improvements + +#### Windows + +- Started using ``titleBarOverlay`` for Windows instead of the buttons that were baked-in to the app. + +#### Linux + +- Full screen mode is now disabled on Linux. This decision was made for a number of reasons outlined at https://github.com/mattermost/desktop/pull/3151#issue-2539440389. + +#### All Platforms + +- Implemented a ``performanceMonitor`` to collect and send anonymous usage data to server dashboards. +- Plugins are now allowed to open ``about:blank`` popup windows using ``window.open()``. +- Added support for plugins to ask for desktop source for screen sharing through the ``desktopAPI.getDesktopSources`` call. +- Added ``Developer Mode`` settings to help debug performance issues. +- Upgraded ``electron-log`` and turned on async logging. + +### Architectural Changes + +- Major version upgrade of Electron to 33.0.2. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### macOS + +- Fixed an issue with resizing the app when the welcome screen was open on macOS, and forced the button to always appear on the welcome screen. + +#### Linux + +- Fixed a crash in Linux when trying to create a thumbnail from an image. + +#### All Platforms + +- Fixed a potential crash where the app menu could regenerate when ``currentServerId`` wasn't set. +- Fixed an issue with dark-mode style for download location in settings. +- Fixed an issue where logging out from the Boards/Playbooks tabs and trying to navigate after logging back in would force an unexpected logout. +- Fixed an issue with the Download button being hidden on Windows/Linux. +- Fixed an issue where pre-defined servers couldn't edit permissions, and the dropdown would not show badges. +- Fixed issues with loading the app from cold when deep linking. + +### Open Source Components + +- Added ``@emotion/react`` to https://github.com/mattermost/desktop. + +### Known Issues + +- Clicking on links does not put the Desktop app in the background to show the external browser. +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [streamer45](https://github.com/streamer45), [theaino](https://github.com/theaino). + +(release-v5-9)= +## Release v5.9 (Extended Support Release) + +- **v5.9.2, released 2024-12-17** + + - Fixed an issue where the new MSI installer would not uninstall versions before v5.9 installed via MSI. + - Fixed an issue where the MSI kept auto-update on for per-machine installation. + - Fixed a potential error thrown by the MSI when trying to uninstall the EXE. + - Fixed an issue where minimizing on Linux would cause the window to re-appear immediately. + - Added support for downgrading using the MSI installer. + +- **v5.9.1, released 2024-11-20** + + - Fixed a crash in Linux when trying to create a thumbnail from an image. + - Fixed an issue with the **Download** button being hidden on Windows/Linux. + +- **v5.9.0, released 2024-08-16** + + - Original v5.9.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.9.2) + +```{Note} +Mattermost v5.9.0 contains low to medium severity level security fixes. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +```{Note} +v5.9.0 is the first Extended Support Release for the Desktop App. See more details in [this documentation](https://docs.mattermost.com/about/release-policy.html#extended-support-releases). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 126+. + +### Improvements + +#### Linux + +- Changed the window buttons on the Linux client to use the native ones provided by Electron, removed the frame. + +#### All Platforms + +- Dropped support for 32-bit Windows and added support for ARM64 (beta). +- Dropped support for the EXE/NSIS installer, shipping only the MSI. +- Added a permissions manager user interface in the **Edit Server** modal, and improved permission checks to be less missable. + +### Architectural Changes + +- Major version upgrade of Electron to 31.2.1. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### Windows + +- Fixed an issue where the window size would get smaller on Windows after a restart if the primary monitor was used and was scaled. +- Fixed an issue where snapping the window on Windows would sometimes cause the inner ``BrowserView`` not to resize. + +#### All Platforms + +- Fixed an issue where reloading the webapp would not always take the user back to the same URL. +- Fixed an issue with a missing context menu upon right-clicking in the calls popout window. +- Fixed an issue where the window could be rendered off-screen in multi-monitor setups. + +### Open Source Components + +- Removed ``@aws-sdk/client-s3``, ``@aws-sdk/lib-storage``, ``@electron/rebuild``, ``axios``, ``chai``, ``electron-mocha``, ``mochawesome``, ``nan``, ``node-abi``, ``node-gyp``, ``playwright``, ``ps-node``, ``recursive-readdir`` and ``robotjs`` from https://github.com/mattermost/desktop. + +### Known Issues + +- Sometimes the app will not restart after an auto-update. This is normal, and if this occurs the app can be safely launched manually. +- Sometimes during installation you may see this message: ``Warning 1946. Property 'System.AppUserModel.ID' for shortcut 'Mattermost.Ink' could not be set``. This message can be safely ignored. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [enzowritescode](https://github.com/enzowritescode), [devinbinnie](https://github.com/devinbinnie), [mvitale1989](https://github.com/mvitale1989), [Rajat-Dabade](https://github.com/Rajat-Dabade), [streamer45](https://github.com/streamer45), [tnir](https://github.com/tnir), [toninis](https://github.com/toninis), [yasserfaraazkhan](https://github.com/yasserfaraazkhan). + +(release-v5-8)= +## Release v5.8 + +- **v5.8.1, released 2024-06-13** + + - Fixed an issue where notifications would not show on macOS in certain cases. + - Fixed an issue where clicking a notification would clear unreads for the wrong channel. + - Fixed an issue where scaled monitors in multi-monitor setups may have caused the window to be opened across two screens. + - Fixed an issue with Do Not Disturb mode on Windows. + +- **v5.8.0, released 2024-05-16** + + - Original v5.8.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.8.1) + +```{Note} +Mattermost v5.8.0 contains low to medium severity level security fixes. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 122+. + +### Improvements + +#### All Platforms + +- Moved the **Settings** window into a new modal. +- Disabled the `--inspect` tag. + +### Architectural Changes + +- Minor version upgrade of Electron to 29.3.0. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### macOS + +- Fixed an issue for macOS 13+ users on the Mac App Store build where the OS-level **Do Not Disturb** user status was not respected. +- Fixed the settings window disappearing on macOS when dragged to another monitor. + +#### All Platforms + +- Fixed an issue where removing a server did not clear mentions. +- Fixed an issue where right-clicking on **Save Image** crashed the app. +- Fixed an issue where typing in the local server followed by a port would trip up the URL validation. +- Fixed an issue where restoring the window from the tray icon could cause a strange state if the window was previously maximized. +- Fixed the permission prompt to **Deny** on closing the dialog. + +### Open Source Components + +- Added and removed several open source components at https://github.com/mattermost/desktop. + +### Known Issues + +- Desktop App Windows 10: The taskbar might not flash on receipt of a new message when the setting is enabled. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [toninis](https://github.com/toninis), [yasserfaraazkhan](https://github.com/yasserfaraazkhan). + +---- + +(release-v5-7)= +## Release v5.7 + +**Release Date: March 15, 2024** + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/v5.7.0) + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 120+. + +### Improvements + +#### All Platforms + +- Added a new **View > Developer Tools** submenu that contains items to access the developer tools for all desktop created windows. +- Added a new menu item to open the developers tools for the Call widget window. +- Reworked and updated the preload script to use an updated and more robust wep app API. +- Promoted Simplified Chinese language to Beta. + +### Architectural Changes + +- Major version upgrade of Electron to 28.2.2. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where the user's URL would be cleared after being entered in the **Add Server** modal. +- Fixed an issue where users couldn't add a second server with a similar subpath as the configured server. +- Fixed a potential crash in diagnostics. + +### Open Source Components + +- Added `@aws-sdk/client-s3`, `@aws-sdk/lib-storage` and `@mattermost/desktop-api`, and removed `aws-sdk` from https://github.com/mattermost/desktop. + +### Known Issues + +- Error might be experienced when quitting v5.7 desktop app on macOS Ventura. +- In the **Settings** modal, the search text in the **Check spelling** dropdown is not visible. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [ctlaltdieliet](https://github.com/ctlaltdieliet), [devinbinnie](https://github.com/devinbinnie), [hasancankucuk](https://github.com/hasancankucuk), [streamer45](https://github.com/streamer45), [trivikr](https://github.com/trivikr), [wiebel](https://github.com/wiebel). + +---- + +(release-v5-6)= +## Release v5.6 + +**Release Date: December 15, 2023** + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.6.0) + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 118+. + +### Improvements + +#### All Platforms + +- Added Vietnamese as a new language (Beta). +- Removed `gconf` dependency for Debian/Ubuntu. +- Stopped auto-opening Boards/Playbooks tabs. + +### Architectural Changes + +- Major version upgrade of Electron to v27.0.2. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where some notifications did not navigate to the channel. +- Set the category for the main menu correctly for installations with Debian package. +- Fixed an issue where servers on a subpath could not grant the `media` permission. +- Fixed an issue where users could not fullscreen embedded videos. +- Fixed a deep linking issue for servers with subpaths. +- Fixed an issue where the "session expired" badge wasn't displayed. + +#### macOS + +- Fixed an issue where clicking on a link to an unregistered protocol on macOS would cause the app to crash. + +### Open Source Components + +- Added `electron-extension-installer` and `node-gyp` to https://github.com/mattermost/desktop. + +### Known Issues + +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [BaumiCoder](https://github.com/BaumiCoder), [ctlaltdieliet](https://github.com/ctlaltdieliet), [devinbinnie](https://github.com/devinbinnie), [larkox](https://github.com/larkox). + +---- + +(release-v5-5)= +## Release v5.5 + +- **v5.5.1, released 2023-10-03** + - Mattermost v5.5.1 contains low severity level security fixes. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Upgraded to Electron v26.2.1, which mitigates `CVE-2023-4863` of the third-party library libwebp. + - Fixed an issue where logging was stuck to `info` level. + - Fixed an issue where the downloads dropdown would not open on auto-update notification. + +- **v5.5.0, released 2023-09-15** + + - Original v5.5.0 release + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.5.1) + +```{Note} +Mattermost v5.5.0 contains a medium severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any currently supported [Mattermost server version](https://docs.mattermost.com/about/mattermost-desktop-releases.html#latest-releases). +- Updated Chromium minimum supported version to 116+. + +### Improvements + +#### All Platforms + +- Set the minimum window width to 600px. + +### Architectural Changes + +- Major version upgrade of Electron to v26.1.0. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed a crash in diagnostics when the server was unreachable. +- Fixed bad user feedback on the server URL validation when plugins were disabled. +- Fixed an issue where auto-updating the app wouldn't be properly disabled. +- Fixed an issue where changes in the OS dark/light mode did not reflect immediately in the window top bar. + +### Known Issues + +- Users are unable to login to Desktop app v5.5 on servers with subpaths. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually delete their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost`, for Windows in `Users/<username>/AppData/Roaming/Mattermost` and for Linux in `~/config/Mattermost` (where `~` is the home directory). +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [apollo13](https://github.com/apollo13), [cpoile](https://github.com/cpoile), [devinbinnie](https://github.com/devinbinnie), [Partizann](https://github.com/Partizann). + +---- + +(release-v5-4)= +## Release v5.4 + +**Release Day: June 19, 2023** + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.4.0) + +### Compatibility + +- Desktop App is supported on any supported Extended Support Release or a newer Mattermost server version. +- Updated Chromium minimum supported version to 112+. + +### Improvements + +#### All Platforms + +- Improved URL validation and the add/edit server experience. +- Made `ExtraBar` dark when using dark mode. +- Improved the tray icon click behaviour across operating systems. + +### Architectural Changes + +- Major version upgrade of Electron to v24.3.1. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Calls: Fixed duplicate desktop notifications when calls popout was open. +- Fixed an issue where YubiKeys did not work on the MAS build. +- Fixed an issue where servers on subpaths would not properly navigate to external URLs on the same domain. +- Fixed an issue where spellcheck highlighting would persist after text was deleted. +- Fixed an issue for the MAS build where the default downloads directory would be invalid after upgrade. +- Fixed an issue where the default download location did not respect `XDG_DOWNLOAD_DIR` where it was set. +- Fixed an issue where the popup window was not refocused if it already existed. + +### Known Issues + +- Mattermost is not detected in the **Add Server** screen if the server has plugins disabled. +- When running "Run Diagnostics" from the **Help** menu, the app crashes. +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually remove their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost` and for Windows it is located in `Users/<username>/AppData/Roaming/Mattermost`. +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [cpoile](https://github.com/cpoile), [devinbinnie](https://github.com/devinbinnie), [jnsgruk](https://github.com/jnsgruk), [streamer45](https://github.com/streamer45), [zoltan-ofir](https://github.com/zoltan-ofir). + +---- + +(release-v5-3)= +## Release v5.3 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.3.1) + +- **v5.3.1, released 2023-04-04** + + - Calls: fixed an issue where, after opening the calls popout then closing it (without leaving the call), subsequent clicks would cause a crash. + +- **v5.3.0, released 2023-03-30** + + - Original v5.3.0 release + +```{Note} +Mattermost v5.3.0 contains a medium severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any supported Extended Support Release or a newer Mattermost server version. +- Support for Windows v8 and v8.1 have been dropped. Minimum supported Windows version was updated to 10+. +- Updated Chromium minimum supported version to 110+. + +### Highlights + +- Added application diagnostics. +- Implemented a global calls widget window. + +### Improvements + +#### All Platforms + +- Added support for starting a call from an existing thread through the `/call start` slash command. +- Added support for Gnome's "do-not-disturb" status. +- Added a menu item for showing the logs folder. +- Improved performance by reducing the number of calls for URL detection. +- Changed the tray behavior on left-click. Left-clicking on the system tray Mattermost icon now hides the application to system tray if it's already visible. +- Defaulted to opening a file when it's selected from the download list. + +### Architectural Changes + +- Major version upgrade of Electron to v23.1.2. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where a user could open a blank Electron window using the main window. +- Fixed an issue where image thumbnails did not always display in the downloads for MAS builds. +- Fixed an issue where the Boards/Playbooks tabs sometimes didn't appear automatically when a server was added. +- Fixed an issue where RPM conflicted with other Electron-based applications. +- Fixed an issue where a custom certificate wasn't applied to the WebSocket connection along with the HTTP connection. +- Fixed an issue where opening the app with a deeplink could cause the app not to redirect to the correct URL. +- Fixed an issue with closing the Downloads drop-down menu when selecting **Show in folder**. +- Fixed an issue with maximizing the main window when a monitor is removed. +- Fixed an issue where special characters in the server name caused the top bar of the Desktop App to disappear. +- Fixed an issue where OneLogin users wouldn't have their credentials remembered. +- Fixed an issue with plugin navigation displaying a white empty bar between the plugin UI and the Desktop Apps Bar. + +### Known Issues + +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually remove their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost` and for Windows it is located in `Users/<username>/AppData/Roaming/Mattermost`. +- On Linux, a left-click on the Mattermost tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients due to an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the Mattermost system tray icon via Desktop Settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [cpoile](https://github.com/cpoile), [cs4p](https://github.com/cs4p), [devinbinnie](https://github.com/devinbinnie), [JtheBAB](https://github.com/JtheBAB), [kevfocke](https://github.com/kevfocke), [kyeongsoosoo](https://github.com/kyeongsoosoo), [m1lt0n](https://github.com/m1lt0n), [streamer45](https://github.com/streamer45), [tboul shootis](https://github.com/tboulis). + +---- + +(release-v5-2)= +## Release v5.2 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.2.2) + +- **v5.2.2, released 2022-12-06** + + - Added ARM64 build (beta) for Windows/Linux. + - Fixed an issue on Windows installers where the onboarding screen was displayed even when there was a preconfigured server list. + - Fixed an issue where a crash could occur when a download list included corrupt data. + - Fixed an issue where `AppImageLauncher` still created a bad shortcut that caused the app not to launch. + - Fixed an issue where notifications were not displayed on Windows v8 and v8.1. + - Fixed an issue where users could get stuck after finished the Getting Started flow. + - Fixed an issue where the window resize did not work on some Windows machines. + - Fixed an issue on Windows where the three-dot menu remained focused after clicking elsewhere. + +- **v5.2.1, released 2022-11-15** + + - Fixed an issue on `.exe` installers where the onboarding screen was still displayed even when there was a preconfigured server list. + - Fixed an issue where the default downloads location was not set on macOS. + - Fixed an issue where users were able to edit or remove a pre-configured server provided by GPO on Windows. + - Fixed an issue where the tray icon colour on Windows didn't obey the setting. + +- **v5.2.0, released 2022-10-31** + + - Original v5.2.0 release + +### Compatibility + +- Desktop App is supported on any supported Extended Support Release up to v8.1 ESR. +- Desktop App v5.2 is incompatible with server versions v9.1 and later. + +### Highlights + +- Onboarding screen improvements: Added new **Configure Server** and first user onboarding screens when starting the app without servers configured. +- Added a Downloads dropdown menu that displays file upload progress and recently downloaded files. + +### Improvements + +#### Linux + +- Dropped support for Linux IA32 (Linux 32-bit builds). + +#### All Platforms + +- The Desktop App configured URL is now forced to be changed to the SiteURL configured by the system adminstrator. +- Added localization support to the Desktop App (Beta). +- Zoom in/out now works when `CTRL/CMD+SHIFT+=` is pressed. +- Changed the order of fields in the Add Server modal so that the server URL is filled in first and the display name after. +- The app window now reloads only when the URL changes, not when a server's name changes. +- Updated the default window size to 1280x800, so that users can now see other login options as well on first load. +- Swapped the dark and light theme tray icons on Linux and Windows to the expected behavior. +- Disabled the auto-update functionality explicitly for all MSI installers except the Windows EXE installer and the Linux AppImage. +- Dropped support for asterisk-based unreads in Mattermost Self-Hosted versions older than v5.28. +- Improved the performance of window resizing. + +### Architectural Changes + +- Major version upgrade of Electron to v21.2.0. Electron is the underlying technology used to build the Desktop App. + +### Bug Fixes + +#### Linux + +- To fix notification issues for Linux users, the configuration setting `notifications.flashWindow` default value was changed to `0` for Linux. + +#### All Platforms + +- Fixed an issue where an Operating System could register Mattermost as the default web browser / mail app. +- Fixed an issue where the download notification showed the wrong file name. +- Fixed an issue where it was possible to drag the Minimize/Close buttons. +- Fixed an issue where a misleading error message from a remote certificate would imply that the Mattermost server had an issue. +- Fixed an issue where users still received notifications when their status was set to **Do Not Disturb**. +- Fixed an issue where users could not replace files in the **Downloads** folder. +- Fixed improper reporting of app version when the `--version` or `-v` command-line flags were passed. +- Fixed an issue where MAS users couldn't easily replace files. + +### Open Source Components + +- Added `macos-notification-state`, `windows-focus-assist`, and `react-intl` to https://github.com/mattermost/desktop. + +### Known Issues + +- Users seeing an endless "Loading..." screen when attempting to log in to the app may need to manually remove their cache directory. For macOS it is located in `/Users/<username>/Library/Containers/Mattermost/Data/Library/Application Support/Mattermost` and for Windows it is located in `Users/<username>/AppData/Roaming/Mattermost`. +- On Linux, a left click on the tray icon doesn't open the app window but opens the tray menu. +- Crashes might be be experienced in some Linux desktop clients. This is an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the system tray icon in the Desktop settings. +- On apps using GPO configurations, when adding a second server tab, it's possible to drag and drop tabs, but they'll jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [julmondragon](https://github.com/julmondragon), [m1lt0n](https://github.com/m1lt0n), [saturninoabril](https://github.com/saturninoabril), [tboulis](https://github.com/tboulis), [vaaas](https://github.com/vaaas). + +---- + +(release-v5-1)= +## Release v5.1 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.1.1) + +- **v5.1.1, released 2022-06-27** + + - Upgraded to Electron v18.3.0. + - Fixed an issue where a channel name matching the server subpath would not be navigable. + - Fixed an issue where the `hideOnStart` setting didn't work. + - Fixed an issue where the certificate error dialog box would reappear infinitely. + - Fixed an issue where the first client certificate could not be selected. + - Restored Windows ZIP builds. + +- **v5.1.0, released 2022-05-16** + + - Original v5.1.0 release + +```{Note} +Mattermost v5.1.0 contains a low severity level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any supported Extended Support Release up to v8.1 ESR. +- Desktop App v5.1 is incompatible with server versions v9.1 and later. + +### Highlights + +- Added [a Desktop App auto-updater](https://docs.mattermost.com/end-user-guide/access/install-desktop-app.html). The app now automatically checks for new updates on app start up. Note that the Mac builds provided on GitHub do not support auto-updates. + +### Improvements + +#### macOS + +- Mattermost can now be installed on the [Mac App Store](https://apps.apple.com/us/app/mattermost-desktop/id1614666244?mt=12). Even if you’re already using Mattermost desktop on Mac, you can download and install it via the Mac App Store to access future automatic updates. + +#### Linux + +- Updated the Linux closing behaviour to allow the app to close complely when pressing `X`. +- Changed the default setting for **Leave app running in notification area when application window is closed** on Linux to `false` by default. + +#### All Platforms + +- Added the ability in Calls to select which window to share when screensharing. +- Added a new config setting "Launch app minimized" to be able to auto-launch the app minimized when the application is launched on startup. +- When the **Add Server** modal pops up for the first time when the app is launched, the modal now stays open instead of closes on mouse click until the first server has been added. +- Added a new setting/preference to always open the Desktop App in full screen. +- The app now uses `ctrl+=` and `cmd+=` to zoom in to match the behavior of Chrome and Firefox. +- Changed the wording in the **File > View** menu from `Tab` to `Server` to reflect recent changes in the user interface. +- Added the ability to copy the version string into clipboard from **Menu > Help > Version**. +- Added a menu item **Window > Show Servers** to show a list of servers. +- Removed the reference to the flashing window on the Settings page to avoid confusion when the window doesn't flash. + +### Architectural Changes + +- Major version upgrade of Electron to v18.0.3. Electron is the underlying technology used to build the Desktop app. + +### Bug Fixes + +#### Linux + +- Fixed an issue where the app window and taskbar did not flash when notifications were received. + +#### All Platforms + +- Fixed an issue where customized URIs were not supported on the desktop app. +- Fixed an issue where parsed, but technically invalid URIs could not be opened in the browser. +- Fixed an issue where a channel name with an asterisk at the front would cause unreads to return a false positive. +- Fixed an issue where opening a new tab view caused the original view to go to the requested link as well. +- Fixed an issue where users could add the same server name or URL twice. +- Fixed an issue where the URL view prevented users from clicking a button directly above it. +- Fixed an issue where the tray icon theme toggle was not hidden when the icon itself wasn't enabled. +- Fixed an issue where a redundant icon was present in Windows 10+ notifications. +- Fixed an issue where unreads on a different team wouldn't trigger an unread badge in the Desktop App. +- Fixed an issue where retrying to load tabs indefinitely instead of stopping after a few tries was not supported. +- Fixed issues with the loading screen to make it more reliable. +- Fixed an issue where `Shift+Alt` moved the focus to the top menu. +- Fixed an issue where external links at the bottom of the page were not clickable. +- Fixed an issue where mentions/unreads did not take precedence when setting the badge/tray icon. +- Fixed an issue where the macOS dock would stay open after clicking the tray icon. +- Fixed an issue where the URL view would persist once the user had moved their mouse off of an external URL. + +### Known Issues + +- On Linux, a left click on the tray icon doesn't open the app window but opens the tray menu. +- Mattermost Desktop App v5.1.0 cannot be launched twice on Windows servers with the role "Remote Desktop Session Host". +- Desktop App may become unresponsive and crash when initiating a screen reader. +- Crashes might be experienced in some Linux desktop clients. This is an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the system tray icon in the Desktop settings. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +- [ChristophKaser](https://github.com/ChristophKaser), [coltoneshaw](https://github.com/coltoneshaw), [devinbinnie](https://github.com/devinbinnie), [JulienTant](https://github.com/JulienTant), [oh6hay](https://github.com/oh6hay), [Profesor08](https://github.com/Profesor08), [shadowshot-x](https://github.com/shadowshot-x), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [Willyfrog](https://github.com/Willyfrog). + +---- + +(release-v5-0)= +## Release v5.0 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v5.0.4) + +- **v5.0.4, release 2022-02-04** + + - Fixed an issue where Desktop App toast notifications didn't work in v5.0.3. + - Restored **Minimize to tray** option for Windows, and added the ability to override the tray icon color. + +- **v5.0.3, released 2022-02-01** + + - Fixed an issue where a user might get an erroneous "Your session has expired" error and be unable to login. + - Fixed an issue where the app could crash while trying to reload a page that is currently loading. + - Fixed an issue where OS-level shortcuts could cause an unexpected focus behavior in the app. + - Fixed an issue where Linux users might not see the **Add Server** modal. + - Fixed an issue that prevented the export channel log from being downloaded from Playbooks. + +- **v5.0.2, released 2021-11-15** + + - Fixed an issue where the Desktop app crashed intermittently when switching between tabs while a tab was loading. + - Fixed an issue where the app didn't raise the window from the tray icon when clicking on the taskbar icon. + +- **v5.0.1, released 2021-10-22** + + - Fixed issue with desktop notification sounds not working correctly. + - Fixed an issue where using a proxy server with the Desktop app caused the app to crash. + - Fixed the new server modal not being accessible on Linux when no other servers existed. + - Fixed an issue where switching from Boards/Playbooks to Channels caused a reload in the Channels view. + - Fixed an issue with GPO and built-in servers not working correctly with Boards/Playbooks tabs. + - Fixed an issue where the top bar buttons on Windows 8 were missing. + - Reduced the size of some builds by removing unnecessary files. + +- **v5.0.0, released 2021-10-13** + + - Original v5.0.0 release + +```{Note} +Mattermost v5.0.0 contains a low level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop App is supported on any supported Extended Support Release up to v8.1 ESR. +- Desktop App v5.0 is incompatible with server versions v9.1 and later. + +### Breaking Changes / Upgrade Notes + +- Some keyboard shortcuts and menu items were updated to work with the new Desktop App layout. `Ctrl+#` is used for changing tabs and `Ctrl+Shft+#` is used for changing servers. + +### Highlights + +- Redesigned title bar allows users to seamlessly work in Channels, Playbooks, and Boards across multiple servers with minimal context switching. + +### Improvements + +### macOS + +- Made the window menu on macOS more consistent with system standards. + +#### All Platforms + +- Added support for multiple languages to be used by the spellchecker. This can be configured in the desktop preferences. +- Updated loading screen visuals. +- Added a dark mode for settings and modals. +- Changed the server selection to use a dropdown instead of tabs. +- Added support for dragging and dropping of the server dropdown items to re-order servers. +- Converted the tabs interface to support multiple configurable tabs based on the added server to easily access Boards and Playbooks via tabs in the window header. +- Removed the **Server Management** screen from **Settings**, and added Edit/Delete buttons to the new dropdown, as users can now configure and edit their servers from the server dropdown menu. +- Added a checkbox to certificate error modal that allows users to permanently distrust a certificate. + +### Architectural Changes + +- Major version upgrade of Electron to v14.1. Electron is the underlying technology used to build the Desktop app. +- Added a RPM build option to the Electron builder. +- Added Universal binaries for macOS users. +- Migrated to Bootstrap v4 and refreshed the interface. Migrated to `react-beautiful-dnd` instead of `react-smooth-dnd` for a cleaner experience. + +### Bug Fixes + +#### Linux + +- Fixed the tray icon size on Linux. +- Fixed an issue where pressing `Alt+<somekey>` could cause the menu bar to disable and overlap the top bar on Linux. + +#### All Platforms + +- Fixed an issue where resizing the app while in the System Console caused a white bar to appear at the top. +- Fixed an issue where the right-click menu was missing from the `jira connect` modal. +- Fixed an issue where the app would render off screen and the user would have trouble getting the window in view. + +### Known Issues + +- Unread messages icon may be missing from the taskbar on Windows following 4.7.0 upgrade. +- Crashes might be be experienced in some Linux desktop clients. This is an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the system tray icon in the Desktop settings. +- On some Linux distros, a sandbox setting is preventing apps from opening links in the browser (see https://github.com/electron/electron/issues/17972#issuecomment-486927073). While this is fixed for most installers, it is not on the tgz. In this case manual intervention is required via `$ chmod 4755 <installpath>/chrome-sandbox`. +- Pressing Enter multiple times during Basic Authentication causes a crash. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [elsiehupp](https://github.com/elsiehupp), [jtwillis92](https://github.com/jtwillis92), [koox00](https://github.com/koox00), [svelle](https://github.com/svelle), [Westacular](https://github.com/Westacular), [Willyfrog](https://github.com/Willyfrog). + +---- + +(release-v4-7)= +## Release v4.7 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.7.2) + +- **v4.7.2, released 2021-09-13** + + - Upgraded to Electron v12.0.16. + - Fixed an issue where the **Add Server** screen appeared on each startup on servers with GPO. + - Fixed an issue where the window would flash on Windows and Linux when a new mention arrived regardless of the setting to turn it on/off. + - Added desktop notifications for followed threads. + +- **v4.7.1, released 2021-08-03** + +- Mattermost v4.7.1 contains a medium level security fix. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added support to allow users to specify a different download location for Hunspell dictionaries. + - Fixed an issue where the notification badge did not get cleared when reading a channel with unread messages until navigating away from the channel. + - Fixed an issue where the top bar menu, and the minimize, maximize and close icons did not work on 4.7.0 on Windows 10 if GPU acceleration was disabled. + - Reverted to Electron v12.0.1 to fix an issue where clicking in the searchbox to highlight search terms dragged the desktop window. + - Fixed an issue to prevent a crash on malformed default download locations. + +- **v4.7.0, released 2021-06-23** + + - Original v4.7.0 release + +```{Note} +Mattermost v4.7.0 contains low to medium level security fixes. Upgrading is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Compatibility + +- Desktop Apps is supported on any supported Extended Support Release or a newer Mattermost server version. + +### Highlights + +- Added support for Electron BrowserView, an underlying architecture change that improves performance and offers snappier interactions (i.e., less lag), lower CPU usage, and faster launch times. + +### Improvements + +#### Windows + +- Windows desktop now automatically switches between light and dark themes based on the operating system settings. + +#### All Platforms + +- Added a setting to specify the default desktop app download location. +- Improved the launch screen and loading indicator. +- Restored deeplinking. +- Improved the spell check dictionary to provide more accurate spelling suggestions in more languages. The spell check language is now automatically based on the operating system setting. +- Added improvements to be consistent with the use of URL and URL libraries. +- Ctrl/CMD + F functionality has been replaced with in-channel search (requires Mattermost server v5.36+). +- Updated the Content Security Policy for Desktop App to avoid warnings in the dev tools. +- On Linux and Windows, each settings menu is now in a separate window. +- Shortened the maximum length (width) for server tab names to 224px. +- Updated the menu bar and system tray icons for improved contrast. +- Removed `libappnotify1` as a dependency requirement in Debian installers as it's no longer shipped in Debian's Bullseye. It's still recommended to install where available. + +### Architectural Changes + +- Major version upgrade of Electron to v12.0.10. Electron is the underlying technology used to build the Desktop app. +- Added support for Electron BrowserView. +- Added support for M1 architecture (beta) in the build pipeline. + +### Bug Fixes + +#### Windows + +- Fixed an issue where Windows desktop notifications did not auto-dismiss when another notification arrived. +- Fixed an issue on Windows where the **Pin to Taskbar** icon got lost during an upgrade. +- Fixed an issue with the MSI build that caused notifications to not open the application and navigate to the correct channel. + +#### macOS + +- Fixed an issue where changing the theme from the **System Preferences** changed the tray icon, but the red/blue dot indicating unreads got removed. +- Fixed an issue where there was an invisible Mattermost icon in the top menu bar. + +#### Linux + +- Fixed an issue where Shift+Alt moved the focus to the main menu instead of changing keyboard layout. + +#### All Platforms + +- Fixed an issue where special characters were not shown for server names using GPO. +- Fixed an issue where the close/back button in permanent link media previews was missing. +- Fixed an issue where the text input focus was lost when closing the **Settings** window. +- Fixed an issue where saving the desktop app settings didn't remove the **saving** indicator in the settings window. +- Fixed an issue where the jewel indicating the number of mentions was not shown in the tab. +- Fixed an issue where the desktop linting didn't match the webapp linting. +- Fixed an issue where clicking on a notification did nothing when the wrong server tab was selected. +- Fixed an issue where users were unable to copy text from desktop **About** window. + +### Known Issues + +- The new spellchecker connects to Google servers for downloading updated dictionaries. +- Unread messages icon may be missing from the taskbar on Windows following 4.7.0 upgrade. +- Clicking on **View > Find** doesn't work. +- Right click menu is missing from the `jira connect` modal. +- Search field is focused on first start of the app. +- The `create_desktop_file.sh` script is removed from the .tar.gz release. As a workaround, it can be downloaded from [GitHub here](https://github.com/mattermost/desktop/blob/master/src/assets/linux/create_desktop_file.sh). +- An error may occur when installing the MSI Installer on any Windows version. +- Crashes might be be experienced in some Linux desktop clients. This is an upstream bug in the `libnotifyapp` library. A recommended workaround is to disable the system tray icon in the Desktop settings. +- On some Linux distros, a sandbox setting is preventing apps from opening links in the browser (see https://github.com/electron/electron/issues/17972#issuecomment-486927073). While this is fixed for most installers, it is not on the tgz. In this case manual intervention is required via `$ chmod 4755 <installpath>/chrome-sandbox`. +- Pressing Enter multiple times during Basic Authentication causes a crash. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +- [devinbinnie](https://github.com/devinbinnie), [FalseHonesty](https://github.com/FalseHonesty), [nevyangelova](https://github.com/nevyangelova), [petermcj](https://github.com/petermcj), [wget](https://github.com/wget), [Willyfrog](https://github.com/Willyfrog). + +---- + +(release-v4-6)= +## Release v4.6 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.6.2) + +- **v4.6.2, released 2021-01-25** + + - Fixed an issue where logging in to `gitlab.com` did not work on the Desktop App. + - Fixed an issue where macOS entitlements had not been enabled for using camera and microphone on the Desktop App for third-party plugins such as Jitsi. + +- **v4.6.1, released 2020-10-26** + + - Fixed an issue where desktop app notification sounds did not work on Desktop App v4.6.0. + +- **v4.6.0, released 2020-10-16** + + - Original v4.6.0 release + +### Improvements + +#### All Platforms + +- Added a setting to be able to select different desktop notification sounds (Requires Mattermost server v5.28+). +- `Show Mattermost icon in the menu bar` setting is now enabled by default for new installs on Mac, and `Show icon in the notification area` and `Leave app running in the notification area when application window is closed` settings are are now enabled by default for new installs on Ubuntu. +- The default window frame and server tabs are now used on older Windows and Linux OS versions. +- Added Russian and Ukrainian language spellcheckers. +- Added support for allowing access to managed resources. +- The same default protocols as in the server are now used in the autolink plugin. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where the app window started as maximized when the "Start app on login" setting was enabled. The Desktop App no longer shows in the system tray and the parameter `--hidden` was removed. This setting is not respected when AppImage file (Unofficial) is used. +- Fixed an issue where the **Add server** modal fields were missing the right-click menu. +- Fixed an issue where users did not see the right-click menu with Copy and Paste options on the login page when using the desktop app to login to an external application. +- Fixed an issue where the URL bar was shown in the bottom left corner when hovering over a timestamp or internal links. +- Fixed an issue where a Javascript error occurred when a separate OAuth window was open. +- Fixed an issue where users were unable to resize the desktop app vertically from the top tab bar. +- Fixed an issue where some links pointing to the System Console did not work on the desktop app. + +### Known Issues + +- Unlocking the Desktop App on macOS marks the currently viewed channel as read. +- On Ubuntu, auto-focus is lost when using ALT+TAB to switch between windows. +- Crashes might be be experienced in some Linux desktop clients. This is an upstream bug in the `libnotifyapp` library and a recommended workaround is to disable the system tray icon in the Desktop settings. +- On some Linux distros, a sandbox setting is preventing apps from opening links in the browser (see https://github.com/electron/electron/issues/17972#issuecomment-486927073). While this is fixed for most installers, it is not on the tgz. In this case manual intervention is required via `$ chmod 4755 <installpath>/chrome-sandbox`. +- Pressing Enter multiple times during Basic Authentication causes a crash. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [devinbinnie](https://github.com/devinbinnie), [dpanic](https://github.com/dpanic), [jekill](https://github.com/jekill), [jupenur](https://github.com/jupenur), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [nevyangelova](https://github.com/nevyangelova), [rvillablanca](https://github.com/rvillablanca), [wget](https://github.com/wget), [Willyfrog](https://github.com/Willyfrog). + +---- + +(release-v4-5)= +## Release v4.5 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.5.4) + +- **v4.5.4, released 2020-09-11** + + - Fixed an issue where Help and Report a Problem website links configured to point to Mattermost channels didn't work. + +- **v4.5.3, released 2020-08-25** + + - Fixed an issue where users were unable to log in to the desktop app when users had to select a certificate for authentication that requires a pin even when there was only one option to manage a certificate login. + +- **v4.5.2, released 2020-07-20** + + - Fixed an issue on Linux app started as a blank screen when both “Show icon in the notification area" and "Start app on login" were enabled. + +- **v4.5.1, released 2020-07-13** + + - Mattermost v4.5.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +- **v4.5.0, released 2020-06-16** + + - Original v4.5.0 release + +### Improvements + +#### All Platforms + +- Added a spell checker for Polish language. +- Added support for triggering a desktop notification when a file download is complete. +- Added support for the cursor focus to be on the Server Name field when clicking on the `+` tab to add a new server. +- Defaulted "Flash app window and taskbar icon when a new message is received" setting to `True`. + +#### macOS + +- On Mac, a closed window now reopens with `CMD+Tab` keyboard shortcut. + +### Architectural Changes + +- Major version upgrade of Electron to v7.0.0. Electron is the underlying technology used to build the Desktop apps. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where the Desktop app could not authenticate with SAML with an IdP relay. +- Fixed an issue where a moved server tab did not stay in focus. +- Fixed an issue where right-clicking and then clicking "Save Image" didn't work. +- Fixed an issue where trusting self-signed certificates kept asking for trust. +- Fixed an issue where a link to the root of a server caused a "Channel not Found" error if the URL didn't end with a `/`. +- Fixed an issue where using ESC or Cancel to close the Add Server modal did not return focus to previously selected text input. +- Fixed an issue where OneLogin links opened up in the app itself making it impossible to go back to the app. +- Fixed an issue where links on "Cannot connect to Mattermost" error didn't work. + +#### Windows + +- Fixed an issue where Windows Desktop notifications were delayed compared to other notification channels. +- Fixed an issue where Windows Desktop Menu option was read as "Unlabel 0 button". +- Fixed an issue where a white bar was present on the right-hand side of the Settings screen when Add Server modal was open. + +#### macOS + +- Fixed an issue where double clicking the top bar no longer minimized or maximized the window. +- Fixed an issue where users were unable to reposition the app by using click, hold and drag on the left side of the header. +- Fixed an issue where server display name field lost focus when using `CMD+Tab` to navigate away and back to the app. +- Fixed an issue where a long server address didn't wrap correctly in the new server settings page. +- Fixed an issue where copy and pasting into Atlassian login fields pasted text in the wrong place. + +### Known Issues + +- A visible cursor focus is missing on the login screen directly after adding a new server via "+" to the right of the server tabs. +- Right-click menu is missing on "Add server" modal fields. +- Double notifications are received on Ubuntu for at-mentions. +- The current window frame and server tabs are not styled consistently with the rest of the OS in Windows 7 or Linux. +- Crashes might be be experienced in some linux desktop clients. This is an upstream bug in the `libnotifyapp` library and a recommended workaround is to disable the system tray icon in the Desktop settings. +- On some Linux distros, a sandbox setting is preventing apps from opening links in the browser (see https://github.com/electron/electron/issues/17972#issuecomment-486927073). While this is fixed for most installers, it is not on the tgz. In this case manual intervention is required via `$ chmod 4755 <installpath>/chrome-sandbox`. +- Pressing Enter multiple times during Basic Authentication causes a crash. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [hanzei](https://github.com/hanzei), [hunterlester](https://github.com/hunterlester), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justledbetter](https://github.com/justledbetter), [nevyangelova](https://github.com/nevyangelova), [wget](https://github.com/wget), [Willyfrog](https://github.com/Willyfrog). + +---- + +(release-v4-4)= +## Release v4.4 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.4.2) + +- **v4.4.2, released 2020-05-11** + + - Fixed an issue on Windows where a channel was marked as read if the app was closed on a channel where the message was posted. + +- **v4.4.1, released 2020-04-22** + + - Fixed an issue where the Desktop client opened to a blank white Window when using GPO-set teams. + - Fixed an issue where Google oAuth with Gmail addresses did not work on the Desktop app for plugins. + - Fixed an issue where Windows Desktop notifications were delayed. + - Fixed an issue where the app sometimes didn't restore to the right position but "jumped" to a different place in the display when minimizing the app and then maximizing it. + - Fixed an issue where users were not able to paste text into the login screen. + - Fixed an issue where back/forward navigation on the OAuth window caused the app to crash. + +- **v4.4.0, released 2020-02-16** + + - Original v4.4.0 release + +```{Note} +Mattermost v4.4.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Breaking Changes + +- Due to moving to a new configuration version to support the new tabbar for the ability to rearrange the server tab order, it is recommended to do a backup of previous config if you want to downgrade your Desktop App version afterwards. + +### Improvements + +#### All Platforms + +- Added support for Certificate Authentication, including PIV Card authentication. +- Improved server tab organization and visuals with the ability to reorder server tabs via drag-and-drop, notification updates that make it easier to tell when new messages or mentions come in, and a new dark theme. +- Added a spell checker for Italian language. +- Added auto focus on Server Display Name input field. + +### Architectural Changes + +- Major version upgrade of Electron to v6.0.0. Electron is the underlying technology used to build the Desktop apps. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where downgrading the app caused login issues. +- Fixed an issue where Ctrl+C or Ctrl+V didn't work on Electron modals or developer tools. +- Fixed an issue where navigation with Ctrl/Cmd+Tab stopped on disconnected server. +- Fixed an issue where a new desktop window was created after clicking on a permalink to a channel on a different server. +- Fixed an issue where changing the spellchecker on the app did not suggest words in that language. +- Fixed an issue where the app window didn't save "floating" app position. +- Fixed an issue where copying and pasting into Atlassian login fields pasted text in the wrong place. + +#### Windows + +- Fixed an issue where installing v4.3.1 MSI installer did not remove the previous desktop app version. +- Fixed an issue where an attachment name would lose its extension if it was edited during download. +- Fixed an issue where the unread mention badge broke with more than 100 mentions. + +#### macOS + +- Fixed an issue where the DMG install window user interface was missing styling. +- Updated the look of Add New Server icon on the Settings page. +- Fixed an issue where the app could not recover from a connection error after leaving a computer to sleep for a few days. + +### Known Issues + +- The current window frame and server tabs are not styled consistently with the rest of the OS in Windows 7 or Linux. +- No notification on Windows if the app is closed on the channel where the message is posted. +- Crashes might be be experienced in some linux desktop clients. This is an upstream bug in the `libnotifyapp` library and a recommended workaround is to disable the system tray icon in the Desktop settings. +- On some Linux distros, a sandbox setting is preventing apps from opening links in the browser (see https://github.com/electron/electron/issues/17972#issuecomment-486927073). While this is fixed for most installers, it is not on the tgz. In this case manual intervention is required via `$ chmod 4755 <installpath>/chrome-sandbox`. +- Pressing Enter multiple times during Basic Authentication causes a crash. +- The confirmation dialog from UAC names MSI installers with random numbers. +- On apps using GPO configurations, when adding a second server tab, it is possible to drag and drop tabs but they will jump back to the original position when releasing the mouse. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [allenlai18](https://github.com/allenlai18), [cpanato](https://github.com/cpanato), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [hunterlester](https://github.com/hunterlester), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [kethinov](https://github.com/kethinov), [rascasoft](https://github.com/rascasoft), [Willyfrog](https://github.com/Willyfrog), [xalkan](https://github.com/xalkan). + +---- + +(release-v4-3)= +## Release v4.3 + +**Download Binaries:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/4.3.2) + +- **v4.3.2, released 2019-11-29** + +- Mattermost v4.3.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- Fixed an issue where the app started into white screen after a system reboot on Windows. +- Fixed an issue where `CMD+Z` didn't undo on the Mac desktop app. +- Fixed an issue where users were unable to zoom in/out except on the first server tab. +- Fixed an issue where right-click + "Copy" did not work in some instances. +- Fixed an issue where email links in profile popovers didn't work. + +- **v4.3.1, released 2019-10-22** + + - Fixed an issue where Mac desktop app was not notarized correctly for installing on macOS Catalina. + +- **v4.3.0, released 2019-10-17** + + - Original v4.3.0 release + +```{Note} +Mattermost v4.3.0 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Breaking Change + +The Mattermost Desktop v4.3.0 release includes a change to how desktop notifications are sent from non-secure URLs (http://). Organizations using non-secure Mattermost Servers (http://) will need to update to Mattermost Server versions 5.16.0+, 5.15.1, 5.14.4 or 5.9.5 (ESR) to continue receiving desktop notifications when using Mattermost Desktop v4.3.0 or later. + +### Improvements + +#### All Platforms + +- Added support for maintaining a user's online status while the desktop app is in the background but the user is interacting with their computer. Requires Mattermost Server v5.16.0, v5.15.1, v5.14.4 or later. +- Updated spellchecker dictionaries for English. +- Added support for exposing Webview Developer Tools via View Menu. +- Improved the styling of the session expiry mention badge in the tab bar. +- Improved the wording of the invalid certificate dialog. +- Improved accessibility support for the menu bar items. + +#### Windows + +- Added support for MSI installer (Beta) to allow deploying Mattermost desktop app to the computer program files (accessible by any user accounts rather than a specific user account on the machine). +- Added support for Group Policies (GPO) to allow admins to set default servers and enable/disable the ability to add/remove servers. + +#### macOS + +- Added a flag to enable macOS dark mode title bar. + +### Architectural Changes + +- Major version upgrade of Electron to v5.0.0. Electron is the underlying technology used to build the Desktop apps. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where opening the emoji picker froze the desktop app. +- Fixed an issue where jumbo emoji didn't render for unsupported unicode emojis. +- Fixed an issue where username and password were not being passed for HTTP basic authentication. +- Fixed an issue where switching server tabs on app load caused a visual size glitch. +- Fixed various desktop app notification issues. +- Fixed an issue where the unread count changed after opening the quick switcher. +- Fixed an issue where clicking on some links in System Console opened the links on the app itself. +- Fixed an issue where the "Help" button opened in a new browser tab instead of below the textbox in the default system browser. +- Fixed an issue where Mattermost opened both on fullscreen and on a smaller window when closing the app in fullscreen. +- Fixed an issue to prevent the app from restarting in full-screen mode. +- Fixed an issue where the dot and mention counts in server tab jewels were not centered. +- Fixed an issue where the dot in notification badges was off centre. + +#### Windows + +- Fixed an issue where Ctrl+M shortcut minimized the Windows app and sent a message. +- Fixed an issue where clicking the tooltip button dismissed the tooltip. + +#### macOS + +- Fixed an issue where using the red Close button to close the window caused a blank screen when the window was maximized. +- Fixed an issue where `Cmd + Option + Shift + v` and `Cmd + Shift + v` didn't work on macOS desktop app. +- Fixed an issue where the timezones were incorrect in OSX High Sierra. + +### Known Issues + +- Users are unable to zoom in/out on the desktop app. This bug will be fixed after a major version upgrade of Electron to v6.0.0. +- `CMD+Z` doesn't undo on the Mac desktop app. +- Unable to exit full screen YouTube videos. +- "RIght-click + Copy" does not work. +- Notifications appear in sequence rather than stacking on Windows. +- Clicking on notifications when using the MSI installer(s) doesn't focus the app or the channel that triggered the notification. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [asaadmahmood](https://github.com/asaadmahmood), [aswathkk](https://github.com/aswathkk), [crspeller](https://github.com/crspeller), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [esethna](https://github.com/esethna), [jespino](https://github.com/jespino), [JtheBAB](https://github.com/JtheBAB), [manland](https://github.com/manland), [mickmister](https://github.com/mickmister), [MikeNicholls](https://github.com/MikeNicholls), [PeterDaveHello](https://github.com/PeterDaveHello), [sethitow](https://github.com/sethitow), [steevsachs](https://github.com/steevsachs), [svelle](https://github.com/svelle), [wget](https://github.com/wget), [Willyfrog](https://github.com/Willyfrog), [yuya-oc](https://github.com/yuya-oc). + +---- + +(release-v4-2-3)= +## Release v4.2.3 + +This release contains a bug fix for all platforms. + +- **Release date:** August 9, 2019 +**Download Binary:** [Windows 32-bit](https://releases.mattermost.com/desktop/4.2.3/mattermost-setup-4.2.3-win32.exe) | [Windows 64-bit](https://releases.mattermost.com/desktop/4.2.3/mattermost-setup-4.2.3-win64.exe) | [Mac](https://releases.mattermost.com/desktop/4.2.3/mattermost-desktop-4.2.3-mac.dmg) | [Linux 64-bit](https://releases.mattermost.com/desktop/4.2.3/mattermost-desktop-4.2.3-linux-x64.tar.gz) +- **View Source Code:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.2.3) + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where the server URL entry prior to v4.2.2 could include malformed URLs that failed in v4.2.2 and later due to stricter validation. https://github.com/mattermost/desktop/pull/1015 + +---- + +(release-v4-2-2)= +## Release v4.2.2 + +This release contains a bug fix for all platforms. + +- **Release date:** August 7, 2019 + +### Bug Fixes + +#### All Platforms + +- Mattermost v4.2.2 contains high level security fixes. [Upgrading](https://mattermost.com/apps) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +---- + +(release-v4-2-1)= +## Release v4.2.1 + +This release contains a bug fix for all platforms. + +- **Release date:** March 20, 2019 +**Download Binary:** [Windows 32-bit](https://releases.mattermost.com/desktop/4.2.1/mattermost-setup-4.2.1-win32.exe) | [Windows 64-bit](https://releases.mattermost.com/desktop/4.2.1/mattermost-setup-4.2.1-win64.exe) | [Mac](https://releases.mattermost.com/desktop/4.2.1/mattermost-desktop-4.2.1-mac.dmg) | [Linux 64-bit](https://releases.mattermost.com/desktop/4.2.1/mattermost-desktop-4.2.1-linux-x64.tar.gz) +- **View Source Code:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.2.1) + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where some links opened in a smaller window in the Mattermost app. This issue only affected installations with a [Site URL](https://docs.mattermost.com/configure/environment-configuration-settings.html#web-siteurl) configured to use a subpath. + +---- + +(release-v4-2-0)= +## Release v4.2.0 + +- **Release date:** November 27, 2018 +**Download Binary:** [Windows 32-bit](https://releases.mattermost.com/desktop/4.2.0/mattermost-setup-4.2.0-win32.exe) | [Windows 64-bit](https://releases.mattermost.com/desktop/4.2.0/mattermost-setup-4.2.0-win64.exe) | [Mac](https://releases.mattermost.com/desktop/4.2.0/mattermost-desktop-4.2.0-mac.dmg) | [Linux 64-bit](https://releases.mattermost.com/desktop/4.2.0/mattermost-desktop-4.2.0-linux-x64.tar.gz) +- **View Source Code:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/releases/tag/v4.2.0) + +```{Note} +Mattermost v4.2.0 contains a high level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Improvements + +#### All Platforms + +- Added English (UK), Portuguese (BR), Spanish (ES) and Spanish (MX) to the spell checker. +- Added `Ctrl/Cmd+F` shortcut to work as browser-like search. +- Preserved case of first letter in spellcheck. +- Added support for session expiry notification. + +#### Windows + +- Set "app start on login" preference as enabled by default and synchronized its state with config.json. + +#### Mac + +- Added **.dmg** package to support installation. +- Added "Hide" option to Login Items in Preferences. + +#### Linux + +- [tar.gz] Added support for using SVG icons for Linux application menus in place of PNG icons. +- Updated categories in order to be listed under the appropriate submenu of the application starter. +- Set "app start on login" preference as enabled by default and synchronized its state with config.json. +- Added AppImage packages as an unofficial build. + +### Architectural Changes + +- Major version upgrade of Electron to v2.0.12. Electron is the underlying technology used to build the Desktop apps. +- Artifact names are now configured via `electron-builder.json`. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [danmaas](https://github.com/danmaas), [hmhealey](https://github.com/hmhealey), [j1mc](https://github.com/j1mc), [jasonblais](https://github.com/jasonblais), [lieut-data](https://github.com/lieut-data), [rodcorsi](https://github.com/rodcorsi), [scherno2](https://github.com/scherno2), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [torlenor](https://github.com/torlenor), [yuya-oc](https://github.com/yuya-oc). + +---- + +(release-v4-1-2)= +## Release v4.1.2 + +This release contains a bug fix for all platforms. + +- **Release date:** May 25, 2018 +**Download Binary:** [Windows 32-bit](https://releases.mattermost.com/desktop/4.1.2/mattermost-setup-4.1.2-win32.exe) | [Windows 64-bit](https://releases.mattermost.com/desktop/4.1.2/mattermost-setup-4.1.2-win64.exe) | [Mac](https://releases.mattermost.com/desktop/4.1.2/mattermost-desktop-4.1.2-mac.zip) | [Linux 64-bit](https://releases.mattermost.com/desktop/4.1.2/mattermost-desktop-4.1.2-linux-x64.tar.gz) +- **View Source Code:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/tree/v4.1.2) + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where the popup dialog to authenticate a user to their proxy or server didn't work. + +---- + +(release-v4-1-1)= +## Release v4.1.1 + +This release contains multiple bug fixes for Mac due to an incorrect build for v4.1.0. Windows and Linux apps are not affected. + +- **Release date:** May 17, 2018 +**Download Binary:** [Windows 32-bit](https://releases.mattermost.com/desktop/4.1.1/mattermost-setup-4.1.1-win32.exe) | [Windows 64-bit](https://releases.mattermost.com/desktop/4.1.1/mattermost-setup-4.1.1-win64.exe) | [Mac](https://releases.mattermost.com/desktop/4.1.1/mattermost-desktop-4.1.1-mac.zip) | [Linux 64-bit](https://releases.mattermost.com/desktop/4.1.1/mattermost-desktop-4.1.1-linux-x64.tar.gz) +- **View Source Code:** [Mattermost Desktop on GitHub](https://github.com/mattermost/desktop/tree/v4.1.1) + +### Bug Fixes + +Each of the issues listed below are already fixed for Windows and Linux v4.1.0. + +#### macOS + +- Fixed an issue where right-clicking an image, then choosing "Save Image", did nothing. +- Fixed an issue that prevented typing in the form fields on the add server dialog when launched from the server tab bar. +- Fixed an issue that could cause an error message on the add new server dialog to be misleading. +- Fixed an issue where timestamps in message view showed no URL on hover. +- Fixed an issue where quitting and reopening the app required the user to log back in to Mattermost. +- Fixed an issue where adding a new server sometimes caused a blank page. +- Fixed deep linking via `mattermost://` protocol spawning a new copy of the Desktop App on the taskbar. + +---- + +(release-v4-1-0)= +## Release v4.1.0 + +Release date: May 16, 2018 + +### Improvements + +### All Platforms + +- Improved stability and performance + + - Reduced memory usage by periodically clearing cache. + - Fixed app crashing when a server tab was drag-and-dropped to the message view. + - Added an option to disable GPU hardware acceleration in App Settings to improve stability in some systems. + - Fixed Windows crash issues during installation. + - Fixed Mac and Linux crashing after toggling "Show Mattermost icon in menu bar" app setting. + +- Updated design for loading animation icon. +- Improved appearance of server tabs. +- Enabled [Certificate Transparency](https://certificate.transparency.dev/) verification in HTTPS. + +#### Windows + +- [Windows 7/8] Desktop notifications now respect the duration setting set in the Control Panel. + +### Architectural Changes + +- Major version upgrade of Electron from v1.7.13 to v1.8.4. Electron is the underlying technology used to build the Desktop apps. +- Mac download files now use Zip packages rather than tar.gz files. +- ES6 `import` and `export` now replace the `require` and `modul.export` modules for better development. +- Storybook added to more easily develop React componets without executing the desktop app. + +### Bug Fixes + +#### All Platforms + +- Fixed an issue where an incorrect spellchecker language was used for non `en-US` locales on initial installation. +- Fixed an issue where error page appeared when U2F device was used for multi-factor authentication through single sign-on. +- Fixed an issue where right-clicking an image, then choosing "Save Image", did nothing. +- Fixed an issue that prevented typing in the form fields on the add server dialog when launched from the server tab bar. +- Fixed an issue that could cause an error message on the add new server dialog to be misleading. + +#### Windows + +- Fixed an issue where `file://` protocol was not working. Note that localhost URLs are not yet supported. + +### Known Issues + +#### All Platforms + +- Clicking on a video preview opens another Mattermost window in addition to downloading the file. +- Insecure connection produces hundreds of log messages. + +#### Windows + +- App window doesn't save "floating" app position. +- [Windows 7] Sometimes app tries to render a page inside the app instead of in a new browser tab when clicking links]. +- [Windows 10] Incorrect task name in Windows 10 startup list. +- Mattermost UI sometimes bleeds over a file explorer. +- When auto-starting the desktop app, the application window is included in Windows tab list. + +#### macOS + +- The application crashes when a file upload dialog is canceled without closing Quick Look. +- When the app auto-starts, app page opens on screen instead of being minimized to Dock. + +#### Linux (Beta) + +- [Ubuntu - 64 bit] Right clicking taskbar icon and choosing **Quit** only minimizes the app. +- [Ubuntu - 64 bit] Direct message notification sometimes comes as a streak of line instead of a pop up. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [Autre31415](https://github.com/Autre31415), [dmeza](https://github.com/dmeza), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [kethinov](https://github.com/kethinov), [lieut-data](https://github.com/lieut-data), [lip-d](https://github.com/lip-d), [mkraft](https://github.com/mkraft), [yuya-oc](https://github.com/yuya-oc). + +---- + +(release-v4-0-1)= +## Release v4.0.1 + +Release date: March 28, 2018 + +This release contains multiple security updates for Windows, Mac and Linux, and it is highly recommended that users upgrade to this version. + +### Architectural Changes + +- Minor version upgrade of Electron from v1.7.11 to v1.7.13. Electron is the underlying technology used to build the Desktop apps. + +### Bug Fixes + +#### All Platforms + +- Disabled Certificate Transparency verification that produced unnecessary certificate errors. + +---- + +(release-v4-0-0)= +## Release 4.0.0 + +Release date: January 29, 2018 + +This release contains multiple security updates for Windows, Mac and Linux, and it is highly recommended that users upgrade to this version. + +### Improvements + +#### All Platforms + +- Added a dialog to allow the user to reopen the desktop app if it quits unexpectedly. +- Mattermost animation icon is now displayed when loading a page, instead of a blank screen. +- Added a dialog to request permissions to show desktop notifications or to use microphone and video for video calls from untrusted origins. +- The "Saved" indicator now appears for both Server Management and App Options on the Settings page. +- Close button on the Settings page now has a hover effect. +- Added new admin configuration settings for: + + - Disabling server management where the user cannot add or edit the server URL. + - Setting one or more pre-configured server URLs for the end user. + - Customizing the link in **Help > Learn More..**. + +#### Windows + +- Added support for protocol deep linking where the desktop app opens via `mattermost://` link if app is already installed. +- Added the ability to more easily white-label the Mattermost taskbar icon on custom builds. + +#### macOS + +- Added support for protocol deep linking where the desktop app opens via `mattermost://` link if app is already installed. +- Added `Ctrl+Tab` and `Ctrl+Shift+Tab` shortcuts to switch between server tabs. +- Added the option to bounce the Dock icon when receiving a notification. + +### Architectural Changes + +- Major version upgrade of Electron from v1.6.11 to v1.7.11. Electron is the underlying technology used to build the Desktop apps. +- The app now uses CSS to style the user interface. Styles are also divided into React's inline `style` and CSS. +- Yarn is now used to manage dependencies across Windows, Mac and Linux builds. +- Build is now run automatically before packaging the apps with `npm run package`. +- Removed hardcoded product name references. +- Added an `rm` command to `npm`, which removes all dynamically generated files to make it easy to reset the app between builds and branches. + +### Bug Fixes + +#### All Platforms + +- Fixed the close button of the Settings page not working on first installation. +- Fixed the app publisher referring to Yuya Ochiai instead of Mattermost, Inc. +- Fixed font size not always persisting across app restarts. +- Fixed an automatic reloading of the app when a DNS or network error page is manually reloaded with CTRL/CMD+R. +- Fixed an issue where changing font size caused rendering issues on next restart. +- Fixed an issue where after adding a server on the Settings page, focus remained on the "Add new server" link. +- Fixed an issue where SAML certificate file couldn't be uploaded from the file upload dialog. + +#### Windows + +- Fixed desktop notifications not working when the window was minimized from an inactive state. +- Fixed the uninstaller not removing all files correctly. + +#### macOS + +- Fixed an issue where after uploading a file, focus wasn't put back to the text box. +- Fixed a mis-aligned `+` button in the server tab bar. + +#### Linux (Beta) + +- Fixed the main window not being minimized when the app is launched via "Start app on Login" option. + +### Known Issues + +#### All Platforms + +- Insecure connection produces hundreds of log messages. + +#### Windows + +- App window doesn't save "floating" app position. +- Windows 7: Sometimes the app tries to render the page inside the app instead of in a new browser tab when clicking links. +- Windows 10: Incorrect task name in Windows 10 start-up list. + +#### Mac + +- The application crashes when a file upload dialog is canceled without closing Quick Look. +- When the app auto-starts, app page opens on screen instead of being minimized to Dock. +- You have to click twice when a window is out of focus to have actions performed. + +#### Linux (Beta) + +- Ubuntu - 64 bit: Right clicking taskbar icon and choosing **Quit** only minimizes the app. +- Ubuntu - 64 bit: Direct message notification sometimes renders as a streak or line instead of a pop up. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [csduarte](https://github.com/csduarte), [dmeza](https://github.com/dmeza), [jasonblais](https://github.com/jasonblais), [jarredwitt](https://github.com/jarredwitt), [wvds](https://github.com/wvds), [yuya-oc](https://github.com/yuya-oc). + +---- + +(release-v3-7-1)= +## Release 3.7.1 + +Release date: August 30, 2017 + +This release contains a security update for Windows, Mac and Linux, and it is highly recommended that users upgrade to this version. + +### Improvements and Bug Fixes + +#### Windows + +- Client no longer freezes intermittently, such as when receiving desktop notifications. +- [Windows 8.1/10] Added support for running the desktop app across monitors of different DPI. +- [Windows 7/8] Clicking on a desktop notification now opens the message. + +---- + +(release-v3-7-0)= +Release 3.7.0 +-------------- + +Release date: May 9th, 2017 + +### Improvements + +#### All Platforms + +- Added an inline spell checker for English, French, German, Spanish, and Dutch. +- Removed an obsolete "Display secure content only" option, following an [upgrade of the Electron app to Chrome v56](https://github.com/electron/electron/commit/2e0780308c7ef2258422efd34c968091d7cd5b65) +- Reset app window position when restoring it off-screen from a minimized state. +- Improved page loading and app view rendering. + +#### Windows + +- [Windows 7/8] Added support for sound when a desktop notification is received. +- Removed obsolete support for Japanese fonts. +- The application window now respects 125% display resolution. + +### Bug Fixes + +#### All Platforms + +- An extra row is no longer added after switching channels with CTRL/CMD+K shortcut. +- Fixed an issue where an unexpected extra app window opened after clicking a public link of an uploaded file. +- Fixed JavaScript errors when refreshing the page. +- Fixed vertical alignment of the Add Server "+" button in the server tab bar. + +#### Windows + +- Focus is now set to the next top-level window after closing the main app window. +- Fixed an issue where the app remained in the ["classic" ALT+TAB window switcher](https://www.askvg.com/how-to-get-windows-xp-styled-classic-alttab-screen-in-windows-vista-and-7/) after closing the main app window. + +#### macOS + +- Fixed an issue where the application was not available on the Dock after a computer reboot. +- Fixed an issue where Quick Look couldn't be closed after opening the file upload dialog. + +#### Linux (Beta) + +- Fixed an issue where the setting was not saved after changing the tray icon theme. + +### Known Issues + +#### All Platforms + +- [If you click twice on the tab bar, and then attempt to use the "Zoom in/out" to change font size, the app window doesn't render properly](https://github.com/mattermost/desktop/issues/334) +- [Holding down CTRL, SHIFT, or ALT buttons and clicking a channel opens a new application window](https://github.com/mattermost/desktop/issues/406) +- [Unable to upload a SAML certificate file from the file upload dialog](https://github.com/mattermost/desktop/issues/497) + +#### Windows + +- [Windows 7] [Sometimes the app tries to render the page inside the app instead of in a new browser tab when clicking links](https://github.com/mattermost/desktop/issues/369) + +#### macOS + +- [After uploading a file with a keyboard shortcut, focus isn't set back to the message box](https://github.com/mattermost/desktop/issues/341) +- The application crashes when a file upload dialog is canceled without closing Quick Look. + +#### Linux (Beta) + +- [Ubuntu - 64 bit] [Right clicking taskbar icon and choosing **Quit** only minimizes the app](https://github.com/mattermost/desktop/issues/90#issuecomment-233712183) +- [Ubuntu - 64 bit] [Direct message notification comes as a streak of line instead of a pop up](https://github.com/mattermost/mattermost-server/issues/3589) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [yuya-oc](https://github.com/yuya-oc). + +Thanks also to those who reported bugs that benefited the release, in alphabetical order: + +- [esethna](https://github.com/esethna) ([#524](https://github.com/mattermost/desktop/issues/524)), [hanzei](https://github.com/hanzei) ([#523](https://github.com/mattermost/desktop/issues/523)) + +---- + +(release-v3-6-0)= +## Release 3.6.0 + +Release date: February 28, 2017 + +Upgrading to Mattermost server 3.6 or later is recommended, as new features for the desktop app have been added following the release of the team sidebar. + +### Improvements + +- Added support for unread indicators following the release of team sidebar in Mattermost server 3.6 +- Removed a confusing CTRL/CMD+S shortcut for searching within a Mattermost team +- Added support for SAML OneLogin and Google authentication for Enterprise users +- Switching to a server from the system tray icon, from "Window" menu bar item, or through CTRL/CMD+{n} shortcut now works while viewing the Settings page +- Streamlined desktop server management: + + - "Team Management" changed to "Server Management" following the release of team sidebar in Mattermost server 3.6 + - Added a "+" icon to the desktop server tab bar to more easily sign into a new Mattermost server + - Added an option to sign in to another Mattermost server from **File > Sign in to Another Server** + - Clicking "Add new server" on the Settings page opens a dialog instead of a new row + - Clicking "Remove" next to a server now requires a confirmation to prevent a user from removing the server by accident + - Clicking "Edit" next to a server on the Settings page opens a dialog + - Clicking on a server on the Settings page opens the corresponding server tab + +- Simplified desktop app options: + + - App options now auto-save when changed + - Added supporting help text for each option + - Removed "Leave app running in menu bar when application window is closed" setting for Mac, which is not applicable for that platform + - Removed "Toggle window visibility when clicking on the tray icon" setting for Windows, given the behavior is inconsistent with typical Windows app behavior + - Removed "Hide menu bar" setting to avoid users not being able to use the menu bar and the Settings page + +### Bug Fixes + +#### All Platforms + +- Mattermost window no longer opens on a display screen that has been disconnected +- Mention badges no longer persist after logging out of a Mattermost server +- After right-clicking an image or a link, the "Copy Link" option no longer moves around when clicking different places afterwards +- Fixed an issue where minimum window size is not set +- Changed target resolution size to 1000x700 to prevent unintended issues on the user interface +- Fixed an issue where the application menu is not updated when the config file is saved in the Settings page +- Fixed login issues with local development environment +- Removed a white screen which was momentarily displayed on startup + +#### Windows + +- Fixed an issue where an unexpected window appears while installing or uninstalling +- Fixed an issue where the maximized state of the application window was not restored on re-launch if "Start app on Login" setting is enabled + +#### Linux (Beta) + +- Fixed an issue where tray icon wasn't shown by default even when "Show icon in the notification area" setting is enabled +- Fixed an issue where the maximized state of the application window was not restored on re-launch if "Start app on login" setting is enabled + +### Known Issues + +#### All Platforms + +- [If you click twice on the tab bar, and then attempt to use the "Zoom in/out" to change font size, the app window doesn't render properly](https://github.com/mattermost/desktop/issues/334) +- [After using CTRL+K, an added row appears in the message box](https://github.com/mattermost/desktop/issues/426) +- [Holding down CTRL, SHIFT or ALT buttons and clicking a channel opens a new application window](https://github.com/mattermost/desktop/issues/406) + +#### Windows + +- [Windows 7] [Sometimes the app tries to render the page inside the app instead of in a new browser tab when clicking links](https://github.com/mattermost/desktop/issues/369) + +#### macOS + +- [After uploading a file with a keyboard shortcut, focus isn't set back to the message box](https://github.com/mattermost/desktop/issues/341) + +#### Linux (Beta) + +- [Ubuntu - 64 bit] [Right clicking taskbar icon and choosing **Quit** only minimizes the app](https://github.com/mattermost/desktop/issues/90#issuecomment-233712183) +- [Ubuntu - 64 bit] [Direct message notification comes as a streak of line instead of a pop up](https://github.com/mattermost/mattermost-server/issues/3589) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [asaadmahmood](https://github.com/asaadmahmood), [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [yuya-oc](https://github.com/yuya-oc). + +---- + +(release-v3-5-0)= +## Release v3.5.0 + +Release date: December 14, 2016 + +### Improvements + +#### All Platforms + +- URL address is shown when hovering over links with a mouse +- Added CTRL+SHIFT+MINUS as a shortcut for decreasing font size (zooming out) +- Reduce upgrade issues by properly clearing cache when updating the desktop app to a new version (the application cache will be purged whenever the desktop app version changes) +- When launching the app from the command line interface, unnecessary warning messages are no longer sent if connecting to a trusted https connection without a `certificate.json` file + +#### Windows + +- Link addresses can now be copied and pasted inside the app + +### Bug Fixes + +#### All Platforms + +- YouTube previews now work, even if mixed content is allowed +- Fixed an incorrect cursor mode for "Edit" and "Remove" buttons on the Settings page +- Fixed an issue where "Zoom in/out" settings did not properly work +- When disconnected from Mattermost, the "Cannot connect to Mattermost" page is now properly aligned at the top of the window + +#### Windows + +- The menu bar option for "Redo" is now properly shown as CTRL+Y + +#### macOS + +- Fixed an issue where the default download folder was `Macintosh HD` +- Removed an unexpected "Show Tab Bar" menu item on macOS 10.12 + +#### Linux (Beta) + +- Fixed an issue where the option "Leave app running in notification area when the window is closed" was never enabled. + +### Known Issues + +#### All Platforms + +- [If you click twice on the tab bar, and then attempt to use the "Zoom in/out" to change font size, the app window doesn't render properly](https://github.com/mattermost/desktop/issues/334) +- [Direct messages cause notification icons to appear on all team tabs, which don't clear until you click on each team](https://github.com/mattermost/desktop/issues/160) +- [After right-clicking an image or a link, the "Copy Link" option sometimes moves around when clicking different places afterwards](https://github.com/mattermost/desktop/issues/340) + +#### Windows + +- [Windows 7] [Sometimes the app tries to render clicked linked inside the app, instead of in a new browser tab](https://github.com/mattermost/desktop/issues/369>) + +#### macOS + +- [After uploading a file with a keyboard shortcut, focus isn't set back to the message box](https://github.com/mattermost/desktop/issues/341) + +#### Linux (Beta) + +- [Ubuntu - 64 bit] [Right clicking taskbar icon and choosing Quit only minimizes the app](https://github.com/mattermost/desktop/issues/90#issuecomment-233712183) +- [Ubuntu - 64 bit] [Direct message notification pop ups do not properly render](https://github.com/mattermost/mattermost-server/issues/3589) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [itsmartin](https://github.com/itsmartin), +- [jasonblais](https://github.com/jasonblais), +- [jcomack](https://github.com/jcomack), +- [jnugh](https://github.com/jnugh), +- [kytwb](https://github.com/kytwb), +- [magicmonty](https://github.com/magicmonty), +- [Razzeee](https://github.com/Razzeee), +- [yuya-oc](https://github.com/yuya-oc). + +Thanks also to those who reported bugs that benefited the release, in alphabetical order: + +- ellisd ([#383](https://github.com/mattermost/desktop/issues/383)), [it33](https://github.com/it33) ([#384](https://github.com/mattermost/desktop/issues/384)), [jnugh](https://github.com/jnugh) ([#392](https://github.com/mattermost/desktop/issues/392)), [lfbrock](https://github.com/lfbrock) ([#382](https://github.com/mattermost/desktop/issues/382)), [yuya-oc](https://github.com/yuya-oc) ([#391](https://github.com/mattermost/desktop/issues/391)). + +---- + +(release-v3-4-1)= +## Release v3.4.1 + +Release date: September 30, 2016 + +This release contains a security update and it is highly recommended that users upgrade to this version. + +Version number updated to 3.4 to make numbering consistent with Mattermost server and mobile app releases. This change will not imply monthly releases. + +- v3.4.1, released 2016-09-30 + + - (Mac) Fixed an issue where the app window pops up second to foreground when a new message is received + +- v3.4.0, released 2016-09-22 + + - Original v3.4 release + +### Improvements + +#### All Platforms + +- Current team and channel name shown in window title bar +- Team tab is bolded for unread messages and has a red dot with a count of unread mentions +- Added new shortcuts: + + - CTRL+S; CMD+S on Mac: sets focus on the Mattermost search box + - ALT+Left Arrow; CMD+[ on Mac: go to previous page in history + - ALT+Right Arrow; CMD+] on Mac: go to next page in history + +- Upgraded the Settings page user interface +- The app now tries to reconnect periodically if a page fails to load +- Added validation for name and URL when adding a new team on the Settings page + +#### Windows + +- Added access to the settings menu from the system tray icon +- Only one instance of the desktop application will now load at a time +- Added an option to configure whether a red badge is shown on taskbar icon for unread messages + +#### macOS + +- Added an option to configure whether a red badge is shown on taskbar icon for unread messages + +#### Linux (Beta) + +- Added an option to flash taskbar icon when a new message is received +- Added a badge to count mentions on the taskbar icon (for Unity) +- Added a script, `create_desktop_file.sh` to create `Mattermost.desktop` desktop entry to help [integrate the application into a desktop environment](https://wiki.archlinux.org/title/Desktop_entries) more easily +- Added access to the settings menu from the system tray icon +- Only one instance of the desktop application will now load at a time + +### Bug Fixes + +#### All Platforms + +- Cut, copy and paste are shown in the user interface only when the commands are available +- Copying link addresses now work properly +- Saving images by right-clicking the image preview now works +- Refreshing the app page no longer takes you to the team selection page, but keeps you on the current channel +- Fixed an issue where the maximized state of the app window was lost in some cases +- Fixed an issue where shortcuts didn't work when switching applications or tabs in some cases + +#### Windows + +- Removed misleading shortcuts from the system tray menu +- Removed unclear desktop notifications when the application page fails to load +- Fixed the Mattermost icon for desktop notifications in Windows 10 +- Fixed an issue where application icon at the top left of the window was pixelated +- Fixed an issue where the application kept focus after closing the app window + +#### Linux (Beta) + +- Removed misleading shortcuts from the system tray menu +- Removed unclear desktop notifications when the application page fails to load + +### Known Issues + +#### All Platforms + +- YouTube videos do not work if mixed content is enabled from app settings + +#### Windows + +- Copying a link address and pasting it inside the app doesn't work + +#### Linux (Beta) + +- [Ubuntu - 64 bit] Right clicking taskbar icon and choosing **Quit** only minimizes the app +- [Ubuntu - 64 bit] [Direct message notification comes as a streak of line instead of a pop up](https://github.com/mattermost/mattermost-server/issues/3589) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [akashnimare](https://github.com/akashnimare), +- [asaadmahmood](https://github.com/asaadmahmood), +- [jasonblais](https://github.com/jasonblais), +- [jgis](https://github.com/jgis), +- [jnugh](https://github.com/jnugh), +- [Razzeee](https://github.com/Razzeee), +- [St-Ex](https://github.com/St-Ex), +- [timroes](https://github.com/timroes), +- [yuya-oc](https://github.com/yuya-oc). + +-------------- + +(release-v1-3-0)= +## Release v1.3.0 + +Release date: 2016-07-18 + +[Download the latest version here](https://mattermost.com/apps) + +### Improvements + +#### All Platforms + +- Added auto-reloading when tab fails to load the team. +- Added the ability to access all of your teams by right clicking the system tray icon. + +##### Menu Bar + +- New Keyboard Shortcuts + + - Adjust text size + + - CTRL+0 (Menu Bar -> View -> Actual Size): Reset the zoom level. + - CTRL+PLUS (Menu Bar -> View -> Zoom In): Increase text size + - CTRL+MINUS (Menu Bar -> View -> Zoom Out): Decrease text size + + - Control window + + - CTRL+W (Menu Bar -> Window -> Close): On Linux, this minimizes the main window. + - CTRL+M (Menu Bar -> Window -> Minimize) + + - Switch teams (these shotcuts also reopen the main window) + + - CTRL+{1-9} (Menu Bar -> Window -> [Team name]): Open the *n*-th tab. + - CTRL+TAB or ALT+CMD+Right (Menu Bar -> Window -> Select Next Team): Switch to the next window. + - CTRL+SHIFT+TAB or ALT+CMD+Left (Menu Bar -> Window -> Select Previous Team): Switch to the previous window. + - Right click on the tray item, to see an overview of all your teams. You can also select one and jump right into it. + + - Added **Help** to the Menu Bar, which includes + + - Link to [Mattermost Docs](https://docs.mattermost.com) + - Field to indicate the application version number. + +##### Settings Page + +- Added a "+" button next to the **Teams** label, which allows you to add more teams. +- Added the ability to edit team information by clicking on the pencil icon to the right of the team name. + +#### Windows + +- Added an installer for better install experience. +- The app now minimizes to the system tray when application window is closed. +- Added an option to launch application on login. +- Added an option to blink the taskbar icon when a new message has arrived. +- Added tooltip text for the system tray icon in order to show count of unread channels/mentions. +- Added an option to toggle the app to minimize/restore when clicking on the system tray icon. + +#### macOS + +- Added colored badges to the menu icon when there are unread channels/mentions. +- Added an option to minimize the app to the system tray when application window is closed. + +#### Linux (Beta) + +- Added an option to show the icon on menu bar (requires libappindicator1 on Ubuntu). +- Added an option to launch application on login. +- Added an option to minimize the app to the system tray when application window is closed. + +### Other Changes + +- Application license changed from MIT License to Apache License, Version 2.0. + +### Bug Fixes + +#### All platforms + +- Fixed authentication dialog not working for proxy. + +#### Windows + +- Fixed the blurred system tray icon. +- Fixed a redundant description appearing in the pinned start menu on Windows 7. + +#### macOS + +- Fixed two icons appearing on a notification. + +### Known Issues + +#### Linux (Beta) + +- [Ubuntu - 64 bit] Right clicking taskbar icon and choosing **Quit** only minimizes the app +- [Ubuntu - 64 bit] [Direct message notification comes as a streak of line instead of a pop up](https://github.com/mattermost/mattermost-server/issues/3589) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [CarmDam](https://github.com/CarmDam), +- [it33](https://github.com/it33), +- [jasonblais](https://github.com/jasonblais), +- [jnugh](https://github.com/jnugh), +- [magicmonty](https://github.com/magicmonty), +- [MetalCar](https://github.com/MetalCar), +- [Razzeee](https://github.com/Razzeee), +- [yuya-oc](https://github.com/yuya-oc). + +-------------- + +(release-v1-2-1-Beta)= +## Release v1.2.1 (Beta) + +Release date: 2016-05-24 + +This release contains a security update and it is highly recommended that users upgrade to this version. + +- v1.2.1, released 2016-05-24 + + - Fixed an issue where "Electron" appeared in the title bar on startup. + - Added a dialog to confirm use of non-http(s) protocols prior to opening links. For example, clicking on a link to `file://test` will open a dialog to confirm the user intended to open a file. + - (Windows and OS X) Added a right-click menu option for tray icon to open the Desktop application. + +- v1.2.0, released 2016-05-13 + + - Original v1.2 release + +### Improvements + +#### All Platforms + +- Improved the style for tab badges. +- Added **Allow mixed content** option to render images with `http://`. +- Added the login dialog for `http` authentication. + +#### macOS + +- Added an option to show a black dot indicating unread messages on the team tab bar. + +#### Linux + +- Added **.deb** packages to support installation. + +### Bug Fixes + +#### All Platforms + +- Node.js environment is enabled in the new window. +- The link other than `http://` and `https://` is opened by clicking. + +#### Linux + +- Desktop notification is shown as a dialog on Ubuntu 16.04. + +### Known issues + +- The shortcuts can't switch teams twice in a row. +- The team pages are not correctly rendered until the window is resized when the zoom level is changed. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +- [asaadmahmood](https://github.com/asaadmahmood), +- [jeremycook](https://github.com/jeremycook), +- [jnugh](https://github.com/jnugh), +- [jwilander](https://github.com/jwilander), +- [mgielda](https://github.com/mgielda), +- [lloeki](https://github.com/lloeki), +- [yuya-oc](https://github.com/yuya-oc). + +(release-v1-1-1-Beta)= +## Release v1.1.1 (Beta) + +Release date: 2016-04-13 + +This release contains a security update and it is highly recommended that users upgrade to this version. + +- v1.1.1, released 2016-04-13 + + - If the specified team URL on the **Settings** page contains an additional space, the app now properly redirects to the team page + - ALT+SHIFT now opens the menu on Cinnamon desktop environment. + +- v1.1.0, released 2016-03-30 + + - Original v1.1 release + +The `electron-mattermost` project is now the official desktop application for the Mattermost open source project. + +### Changes + +#### All platforms + +- Rename project from `electron-mattermost` to `desktop` +- Rename the executable file from `electron-mattermost` to `Mattermost` +- The configuration directory is also different from previous versions. +- Should execute following command to take over `config.json`. + + - Windows: + `mkdir %APPDATA%\Mattermost and copy %APPDATA%\electron-mattermost\config.json %APPDATA%\Mattermost\config.json` + - OS X: + `ditto ~/Library/Application\ Support/electron-mattermost/config.json ~/Library/Application\ Support/Mattermost/config.json` + - Linux: + `mkdir -p ~/.config/Mattermost && cp ~/.config/electron-mattermost/config.json ~/.config/Mattermost/config.json` + +### Improvements + +#### All platforms + +- Refined the application icon. +- Show error messages when the application fails to load the Mattermost server. +- Show confirmation dialog to continue connection when there is a certificate error. +- Added validation to check whether **Name** or **URL** are blank when adding or editing a team on the **Settings** page. +- Added simple basic HTTP authentication (requires a command line). + +#### Windows + +- Show a small circle on the tray icon when there are new messages. + +### Bug Fixes + +#### Windows + +- **File** > **About** now shows the version number dialog. + +#### Linux + +- **File** > **About** now shows the version number dialog. +- Ubuntu: Notifications now work properly. +- The view mp longer crashes when freetype 2.6.3 is used on the system. + +### Known issues + +#### All platforms + +- Basic authentication is not working and requires a command line. +- Some keyboard shortcuts are missing (e.g. CTRL+W, CMD+PLUS). + +#### Windows + +- Application does not appear properly in Windows volume mixer. + +**List of releases before the project was promoted as the official desktop application for Mattermost.** + +[Release v1.0.7 (Unofficial) - 2016-02-20](https://github.com/mattermost/desktop/releases/tag/v1.0.7) + +[Release v1.0.6 (Unofficial) - 2016-02-16](https://github.com/mattermost/desktop/releases/tag/v1.0.6) + +[Release v1.0.5 (Unofficial) - 2016-02-13](https://github.com/mattermost/desktop/releases/tag/v1.0.5) + +[Release v1.0.4 (Unofficial) - 2016-02-12](https://github.com/mattermost/desktop/releases/tag/v1.0.4) + +[Release v1.0.3 (Unofficial) - 2016-02-03](https://github.com/mattermost/desktop/releases/tag/v1.0.3) + +[Release v1.0.2 (Unofficial) - 2016-01-16](https://github.com/mattermost/desktop/releases/tag/v1.0.2) + +[Release v1.0.1 (Unofficial) - 2016-01-06](https://github.com/mattermost/desktop/releases/tag/v1.0.1) + +[Release v1.0.0 (Unofficial) - 2015-12-27](https://github.com/mattermost/desktop/releases/tag/v1.0.0) + +[Release v0.5.1 (Unofficial) - 2015-12-12](https://github.com/mattermost/desktop/releases/tag/v0.5.1) + +[Release v0.5.0 (Unofficial) - 2015-12-06](https://github.com/mattermost/desktop/releases/tag/v0.5.0) + +[Release v0.4.0 (Unofficial) - 2015-11-03](https://github.com/mattermost/desktop/releases/tag/v0.4.0) + +[Release v0.3.0 (Unofficial) - 2015-10-24](https://github.com/mattermost/desktop/releases/tag/v0.3.0) + +[Release v0.2.0 (Unofficial) 2015-10-14](https://github.com/mattermost/desktop/releases/tag/v0.2.0) + +[Release v0.1.0 (Unofficial) 2015-10-10](https://github.com/mattermost/desktop/releases/tag/v0.1.0) diff --git a/docs/main/product-overview/desktop.mdx b/docs/main/product-overview/desktop.mdx new file mode 100644 index 000000000000..3b68da6b96e0 --- /dev/null +++ b/docs/main/product-overview/desktop.mdx @@ -0,0 +1,11 @@ +--- +title: "Mattermost Desktop App" +--- +The Mattermost desktop app is available for Linux, Mac, and Windows operating systems. The Desktop App supports all the features of the web experience. Desktop users can additionally [connect to multiple Mattermost servers](/end-user-guide/preferences/connect-multiple-workspaces) and [keep multiple workspace contexts open at once](/end-user-guide/preferences/connect-multiple-workspaces#open-multiple-workspace-contexts) from a single interface, navigate using [keyboard shortcuts](/end-user-guide/collaborate/keyboard-shortcuts#navigation-in-the-desktop-app), and [customize their desktop user experience](/end-user-guide/preferences/customize-desktop-app-experience). + +Learn more about: + +- [Desktop releases](/product-overview/mattermost-desktop-releases) +- [Desktop changelog](/product-overview/desktop-app-changelog) + +See the [desktop app software requirements](/deployment-guide/software-hardware-requirements#desktop-apps) for details on supported operating systems and releases. diff --git a/docs/main/product-overview/editions-and-offerings.mdx b/docs/main/product-overview/editions-and-offerings.mdx new file mode 100644 index 000000000000..de673b177d0a --- /dev/null +++ b/docs/main/product-overview/editions-and-offerings.mdx @@ -0,0 +1,111 @@ +--- +title: "Editions and Offerings" +--- +Mattermost is an open core, self-hosted platform for delivering sovereign collaborative workflow to defense, intelligence, security and critical infrastructure enterprises. Our on-prem and private cloud offerings enable mission-critical workflows including cyber defense, DevSecOps and mission operations. + +**Try it Now with a 1-Hour Preview**: Experience features of Mattermost Enterprise Advanced in a live environment with our [1-hour preview](https://mattermost.com/sign-up/). See how it can support your secure, mission-critical collaboration, from Security Operations and DevSecOps pipelines to sensitive joint operations. + +As an open core platform, we maintain and secure the [Mattermost open-source project](https://github.com/mattermost/mattermost) to enable customers and community to vet and verify our software supply chain. Our code base regularly passes through automated security scanning, customer review and crowd-sourced security review through [Bugcrowd](https://bugcrowd.com/engagements/mattermost-mbb-public) under our [responsible disclosure policy](https://mattermost.com/security-vulnerability-report/). The Mattermost open source project is used to produce Mattermost’s commercial Enterprise Edition that provides proprietary capabilities through paid subscriptions. + +## Mattermost Enterprise Edition + +Our commercial self-hosted software, Mattermost Enterprise Edition, is distributed as a compiled Linux binary that includes advanced and subscription-based features. It is offered under a [commercial license](https://mattermost.com/enterprise-edition-license/) that prohibits reverse engineering or tampering with the license key mechanism used to unlock paid functionality, supporting a fair and compliant business model. + +Once you’ve installed Mattermost Enterprise Edition in your preferred environment, you can run it as-is in a free mode, known as Entry, or activate a trial or subscription to unlock additional features. + +## Mattermost Entry + +Mattermost Entry gives small, forward-leaning teams a **free self-hosted Intelligent Mission Environment** to get started on improving their mission-critical secure collaborative workflows. Entry has all features of **Enterprise Advanced** with the following server-wide limitations and omissions: + +- 10,000 Channel messages history across all channels (older messages remain in the database but aren't viewable or searchable) +- 1000 Board cards\* +- 5 Active Playbook runs / month\* +- 250 Agent queries/ month\* +- 40-minute Calls\* +- 10,000 push notifications / month\* +- No Compliance features (compliance monitoring, exports, legal hold, data retention) +- No Delegated Granular System Administrative Roles +- No High Availability (cluster-based deployment, horizontal scale, Enterprise search) +- [Community support only](https://mattermost.com/support/). + +\* *Limits will take effect in a future release.* + +Mattermost Entry is best suited for teams less than 50 users. Organizations with larger deployments are encouraged to obtain a supported commercial subscription to ensure reliable operations and access to enterprise-grade support. + +The following sections outline our paid offerings which provide commercial support and remove free limitations. + +## Mattermost Enterprise Advanced + +Built for **multi-domain secure operations**, Enterprise Advanced builds on all Enterprise-level secure collaborative workflow capabilities with specialized features for environments requiring the strictest security, compliance, and operational integrity, including: + +- [Classified and Sensitive Information Controls](/end-user-guide/collaborate/display-channel-banners) +- [Zero Trust Security](/administration-guide/manage/admin/attribute-based-access-control) with dynamic attribute-based policy controls, environmental atributes, and User Authoritative Source integration +- [Mobile security](/security-guide/mobile-security) controls +- [Air-gapped deployment workflows](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) + +## Mattermost Enterprise + +Mattermost Enterprise supports large-scale, mission-critical **secure collaborative workflows** with robust security, compliance, and productivity tooling. It builds on core ChatOps capabilities from the Professional offering, plus: + +- [Enterprise-scale search with dedicated indexing and usage resourcing via cluster support](/administration-guide/scale/enterprise-search). +- [Sychronization of access controls, channels, and teams with AD/LDAP Groups](/administration-guide/onboard/ad-ldap-groups-synchronization). +- [eDiscovery and compliance export automation](/administration-guide/comply/compliance-export). +- [Enterprise mobile device management with custom EMM support via AppConfig](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider). +- [Advanced legal controls with customizable end-user terms of service and re-acceptance duration](/administration-guide/comply/custom-terms-of-service). +- [Private mobility with ID-only push notifications](/administration-guide/configure/site-configuration-settings#push-notification-contents). +- [Enhanced compliance with global and custom retention policies for messages and files](/administration-guide/comply/data-retention-policy). +- [Collaborative playbooks with ad hoc add/remove tasks, automated triggers, and stakeholders dashboard](/end-user-guide/workflow-automation/learn-about-playbooks). +- [Deleted granular administrative control](/administration-guide/onboard/delegated-granular-administration). +- [Advanced configuration of playbook permissions, and analytics dashboards](/end-user-guide/workflow-automation/share-and-collaborate) +- [Channel export](/administration-guide/comply/export-mattermost-channel-data) +- [Enhanced compliance controls and granular audit logs with data export](/administration-guide/manage/logging#audit-logging). +- [Advanced collaboration with connected workspaces across Mattermost instances](/administration-guide/onboard/connected-workspaces). +- [High availability support with multi-node database deployment](/administration-guide/scale/high-availability-cluster-based-deployment). +- [Horizontal scaling through cluster-based deployment](/administration-guide/scale/scaling-for-enterprise). +- [Advanced performance monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring). +- [Server health checks](/administration-guide/manage/request-server-health-check). +- [Eligibility for Premier Support add-on](https://mattermost.com/support/). +- Contextual AI-based [summarization](/end-user-guide/agents#record-calls-to-summarize-meetings), real-time [channel briefing](/end-user-guide/agents#analyze-threads-and-channels), and [composition](/end-user-guide/agents#access-ai-features) +- Private, air-gapped & DDIL [AI operations](/administration-guide/configure/agents-admin-guide) +- PQ&A with [access-controlled backend systems](/security-guide/security-guide-index) +- 99.9% uptime SLA guarantee (Cloud only, via dedicated virtual secure Cloud add-on option). + +## Mattermost Professional + +Professional best serves technical and operational teams of up to 250 users looking to run **Sovereign ChatOps workflows**, with advanced collaboration and security controls. This offering provides robust collaboration and administration tools including: + +- Teams and channels for one-to-one and group messaging, file sharing, and unlimited search history with threaded messaging, emoji, and custom emoji. +- Native apps for iOS, Android, Windows, macOS, and Linux. +- Pre-packaged integrations with most common developer tools, including Jira, GitHub, GitLab, Zoom, and more. +- Tools for [custom branding](/administration-guide/configure/custom-branding-tools) and [themes](/end-user-guide/preferences/customize-your-theme). +- [Multi-factor authentication](/administration-guide/onboard/multi-factor-authentication). +- Single Sign-on with [GitLab](/administration-guide/onboard/sso-gitlab) using the OAuth 2.0 standard. +- [Granular system permissions](/administration-guide/onboard/advanced-permissions). +- Highly customizable [third-party bots, integrations](https://mattermost.com/marketplace/#publicApps), and [command line tools](/administration-guide/manage/mmctl-command-line-tool). +- Extensive integration support via [webhooks, APIs, drivers](https://developers.mattermost.com/integrate/getting-started/), and [third-party extensions](https://mattermost.com/marketplace/). +- Multiple languages including English (Australian, US), Bulgarian, Chinese (Simplified and Traditional), Dutch, French, German, Hungarian, Italian, Japanese, Korean, Persian, Polish, Portuguese (Brazil), Romanian, Russian, Spanish, Swedish, Turkish, Ukrainian, and Vietnamese. +- [Guest access](/administration-guide/onboard/guest-accounts) and [custom user groups](/end-user-guide/collaborate/organize-using-custom-user-groups). +- [Active Directory/LDAP Single Sign-on and user synchronization](/administration-guide/onboard/ad-ldap). +- Single Sign-on with [GitLab](/administration-guide/onboard/sso-gitlab) using the OpenID Connect standard, [Google](/administration-guide/onboard/sso-google), [OpenID Connect](/administration-guide/onboard/sso-openidconnect), [SAML](/administration-guide/onboard/sso-saml) or [Entra ID](/administration-guide/onboard/sso-entraid). +- [MFA enforcement](/administration-guide/onboard/multi-factor-authentication#enforcing-mfa). +- [Advanced team permissions](/administration-guide/onboard/advanced-permissions#team-override-scheme). +- [Read-only announcement channels](/administration-guide/manage/team-channel-members#advanced-access-controls). +- [System-wide announcement banners](/administration-guide/manage/system-wide-notifications). +- O365 integration with [Microsoft Teams Meetings](https://mattermost.com/marketplace/microsoft-teams-meetings/) and [Jira multi-server](https://mattermost.com/marketplace/jira-plugin/). +- [Next business day support via online ticketing system](https://mattermost.com/support/). +- [Interactive AI bot support](/end-user-guide/agents#access-ai-features) +- Flexible [bring-your-own-LLM integration](/administration-guide/configure/agents-admin-guide) + +See a complete list of Mattermost features for all paid offerings at [https://mattermost.com/pricing](https://mattermost.com/pricing) . + +## Mattermost Team Edition + +Team Edition is a free-to-use, open source, self-hosted collaboration platform that offers the core productivity benefits of competing SaaS ChatOps solutions. It is deployed as a single Linux binary with PostgreSQL and is licensed under MIT. Team Edition is intended for small teams, hobbyists, or personal use under 250 activated users where single sign-on (SSO) is not required. It is not recommended for government or sensitive commercial workloads. + +Since 2016, Mattermost has partnered with GitLab to include Team Edition in the GitLab Omnibus package. Originally designed for teams of 25–50 users, it included GitLab SSO and DevSecOps integrations. Over time, Team Edition was widely over-deployed, sometimes to thousands of users, leading to performance issues and confusion between free and commercial offerings. Additionally, GitLab SSO was used as a gateway to other identity providers, overlapping with SSO capabilities reserved for paid Enterprise editions. + +In 2025, GitLab began evaluating the removal of Mattermost from the Omnibus package to reduce its size. This prompted both companies to redefine their shared offering. As part of this transition, SSO is being removed from the Team Edition, aligning it with its intended scope for small teams and hobbyist use. Advanced access controls features will continue to be available in the commercial editions, including Mattermost Entry (free). Gitlab Omnibus will ship with the v10.11 ESR, enabling continued use of Gitlab SSO until a redefinition of the partnership is determined. Please see more details in [this forum post](https://forum.mattermost.com/t/mattermost-v11-changes-in-free-offerings/25126). + +Mattermost, Inc. offers its software under different licenses, including open source. An open source “community edition” of the offering is compiled from the [Mattermost open source project](https://github.com/mattermost/mattermost) under a reciprocal open source license agreement, and in accordance with the [Mattermost trademark policy](https://mattermost.com/trademark-standards-of-use), which requires Mattermost wordmark and trademark be replaced, unless in some circumstances special permission is extended. The purpose of the reciprocal open source license, known as AGPLv3 or “GNU Affero General Public License”, is to have the benefits of open source reach the broader community. Community members creating derivative works of the open source code base are required to use the same reciprocal open source license, AGPLv3, to downstream beneficiaries. + +Organizations who prefer not to use a reciprocal open source license can choose to use one of the Enterprise Edition offerings under a commercial license. diff --git a/docs/main/product-overview/faq-enterprise.mdx b/docs/main/product-overview/faq-enterprise.mdx new file mode 100644 index 000000000000..d152e0623ffc --- /dev/null +++ b/docs/main/product-overview/faq-enterprise.mdx @@ -0,0 +1,95 @@ +--- +title: "Enterprise Edition" +--- +## What is Mattermost Enterprise Edition? + +Mattermost Enterprise Edition is a commercial workplace messaging solution for large organizations operating under compliance and security requirements built on top of the open source Mattermost Team Edition. + +## How can U.S. government customers procure Mattermost licenses? + +Please review our U.S. government offerings at [https://mattermost.com/solutions/industries/government/](https://mattermost.com/solutions/industries/government/) to contact channel partners and resellers. You can also contact Carahsoft regarding Mattermost by phone or email with the information at [https://www.carahsoft.com/mattermost](https://www.carahsoft.com/mattermost). + +## How can government organizations outside the U.S. procure Mattermost licenses? + +Governmental organizations outside the U.S. that need to procure licenses through resellers can contact the Mattermost sales organization at [https://mattermost.com/contact-sales/](https://mattermost.com/contact-sales/) to connect with existing resellers by country and geographic region, or to onboard new approved resellers. + +## I’d like to buy Mattermost through a reseller--or I am a reseller--how do I get in touch? + +Please contact the Mattermost sales team at [https://mattermost.com/contact-sales/](https://mattermost.com/contact-sales/) to find a reseller for your geography and organization. Resellers can read about our partner programs at [https://handbook.mattermost.com/operations/sales/partner-programs](https://handbook.mattermost.com/operations/sales/partner-programs). + +## How are Mattermost licenses sold? + +Mattermost Enterprise and Mattermost Professional licenses are sold as prepaid annual subscriptions based on the number of annual seat licenses purchased, or “seats”. Each seat license purchased entitles a customer to an “activated user”, which is a user registered on a specific Mattermost server and not deactivated. Administrators can view user status in the System Console and activate and deactivate registered users at any time. Deactivated users have history and preferences saved. + +Guests in exactly one channel are tracked separately as single-channel guests and are free up to a 1:1 ratio with licensed seats. Guests in multiple channels continue to count as activated users. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. + +## What happens when activated users exceed the number of licensed seats? + +During the period of the annual license, when the number of activated users exceeds the number of seat licenses purchased, additional seats should be purchased on a quarterly “true forward” basis. + +For example, if activated users exceed licensed seats in the first quarter since annual licenses were purchased, then additional seat licenses should be purchased for the remaining three quarters until renewal, with an invoice amount prorated for the annual cost of the license. + +Single-channel guests are counted separately from activated users. If the single-channel guest count exceeds the 1:1 allowance, system admins see warnings in reporting and on the **Edition and License** page, but Mattermost doesn't enforce a hard block. + +## Where can I find more information on subscriptions and billing? + +Please visit ouere [subscription overview](/product-overview/subscription) documentation for details. + +## Where can I find a full list of feature comparisons between plans? + +You can see the full list of capabilities by visiting the [Mattermost Pricing page](https://mattermost.com/pricing/). + +## Does Mattermost have a Software-as-a-Service offering? + +Yes, Enterprises can inquire about [Mattermost Cloud Enterprise](https://mattermost.com/enterprise/cloud/), as a single-tenant cloud-managed service for Mattermost Enterprise hosted by Mattermost, Inc. The system is offered on the same Kubernetes-based platform as the self-hosted edition, and managed by Mattermost, Inc. + +For more information, contact the Mattermost Sales organization at [https://mattermost.com/contact-sales/](https://mattermost.com/contact-sales/) + +For small businesses, [Mattermost Professional](/product-overview/editions-and-offerings) is available as a self-serve, multi-tenant, software-as-a-service offering. + +## Do you offer special programs for non-profit organizations, open source projects, or educational institutions? + +Yes. See the [non-profit subscriptions](/product-overview/non-profit-subscriptions) documentation for details. + +## How can I be assured that my data will not be locked in to commercial software? + +You always have control over your own server and databases, where the entirety of your Mattermost deployment is stored. Users of [Mattermost Enterprise Edition](/product-overview/editions-and-offerings#mattermost-enterprise-edition) can downgrade to the [open source version](/product-overview/editions-and-offerings#mattermost-team-edition) at any time, without losing any data. + +## How does Mattermost scale from teams to enterprises? + +Growing your Mattermost installation from supporting a team to supporting an enterprise requires two types of scaling: + +1. Technical scaling: Maintaining system responsiveness as large quantities of new users are added. +2. Functional scaling: Adding advanced features to support the increased complexity of large organizations. + +**Technical Scaling:** Whether used for teams or enterprises, the Mattermost server is designed to support tens of thousands of users on a single server with appropriate hardware. The server is built using Golang, the language developed by Google to create internet-scale applications, and supports highly scalable databases. Beyond tens of thousands of users, Mattermost Enterprise Edition can offer high availability cluster-based/horizontal scaling configurations using multiple servers to support even larger organizations. + +**Functional Scaling:** Scaling from a team to an enterprise is like going from a "virtual office" to a "virtual campus". Advanced features like enterprise authentication, granular permissions, compliance and auditing, and advanced reporting become increasingly important as organizations grow beyond teams. Organizations needing this flexibility can easily upgrade from Mattermost Team Edition to Mattermost Enterprise Edition as well as downgrade without data loss, should their needs change. + +For more information on how Mattermost scales, technically, and functionally, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/), and [read about scaling for Enterprise](/administration-guide/scale/scaling-for-enterprise). + +## What does it take to manage a Mattermost deployment? + +For a small deployment of Mattermost up to a few hundred users, we'd recommend a part-time, mid-level IT admin with a senior IT admin for supervision and as a backup resource. They should have the ability to administer a basic Linux server, a PostgreSQL database, and web proxy configuration with web sockets. + +For a medium deployment of 500 to 2000 users, we'd recommend a senior IT administrator who has the capability to configure Mattermost in a High Availability cluster-based deployment with redundant database and application servers. They should also be able to activate performance monitoring and health check features in Prometheus and Grafana. + +## How do you manage multiple messaging solutions in an enterprise? + +Our customers address multiple collaboration solutions in different ways depending on whether the organization is more top down or bottom up. + +**For top-down, customers want to simplify and leverage investments in a central, flexible, innovative solution that can scale.** There's generally a lot of pain with different teams and departments running their own messaging tools, creating silos, redundancy, and significant productivity loss. They'll roll out Mattermost as an official solution and centralize communication there. Visit the [Mattermost customers page](https://mattermost.com/customers/) for examples. + +**For bottom-up, customers want to supplement for strategic advantage.** We've seen teams flock to Mattermost because of its productivity benefits for DevOps, remote work, rapid response, and scaling large teams where people are overloaded with email. Those organizations, which can have hundreds to thousands of users, will use Mattermost in parallel with general-purpose messaging that doesn't meet their specific needs. + +One example is Wargaming, one of the world's largest real-time online video game operators, with over 150 million players on their system. They've moved their DevOps, design, analytics and support teams to Mattermost to supplement Skype for Business. This is their company-wide, general-purpose messenger that isn't optimized for large DevOps organizations and the degree of integration and flexibility they need - specifically for DevOps. People want support for Linux and Mac desktops, lots of APIs and hooks to integrate. They also need help for plugins to embed certain types of reports and interactive controls into messages, friendly keyboard shortcuts, and dozens of other enhancements that provide a distinct advantage to their counterparts at other companies. + +## What happens when the Enterprise Edition subscription expires? + +Sixty days prior to expiry, Mattermost system administrators receive notifications that the Enterprise Edition license key will expire on the anniversary of its purchase. After expiry, there is a 10-day grace period to upload a new license key. After the grace period, Enterprise features will be disabled. At any time, Enterprise Edition can be downgraded to the free Team Edition without data loss by switching off any Enterprise features enabled and then removing the license key. + +## How does the licensing key work? + +See our [frequently asked questions about licensing](/product-overview/faq-license). + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/product-overview/faq-federal-procurement.mdx b/docs/main/product-overview/faq-federal-procurement.mdx new file mode 100644 index 000000000000..dcff16d0fb0f --- /dev/null +++ b/docs/main/product-overview/faq-federal-procurement.mdx @@ -0,0 +1,74 @@ +--- +title: "U.S. Federal Procurement FAQ" +--- +## Is Mattermost FedRAMP authorized (High or Moderate)? + +Yes. Mattermost is currently FedRAMP High authorized via partner FedHIVE and listed on the [FedRAMP Marketplace](https://marketplace.fedramp.gov/products/FR1802451335). + +## Has it been granted a DoD ATO (Authority to Operate)? + +Yes. Mattermost has received a Certificate to Field under Platform One’s Continuous Authority to Operate (CATO). + +## What IL level (IL4/IL5/IL6) has Mattermost been deployed at? + +Mattermost has been deployed in IL4, IL5, and IL6 environments, as well as in JWICS and other classified IC networks. + +## Are there any export restrictions (e.g., ITAR, EAR) that would limit sharing with foreign partners? + +Our software is classified as ECCN 5D002 with License Exception ENC. Additional [export compliance details](/product-overview/certifications-and-compliance#u-s-export-compliance-overview) are available. As of July 21, 2025, no export-control limitations affect sharing the Mattermost Professional, Enterprise, or Enterprise Advanced software with foreign entities. + +## Can external partner users be added under a U.S. license (i.e., shared licensing model)? + +Yes. External partners can be added as [guest or standard end user accounts](/end-user-guide/collaborate/learn-about-roles). They count towards licensing and are billed at the standard end user rate under the buyer’s subscription. + +## Does it support FOIA and records compliance (e.g., message retention, audit logs, eDiscovery)? + +Yes. Mattermost supports configurable retention policies, audit logs, legal hold, and eDiscovery tools, enabling compliance with FOIA and records management requirements. Full capabilities depend on configuration. Please visit the [Compliance page](https://mattermost.com/compliance/) online for more details. + +## Do you support air-gapped or self-hosted deployments? + +Yes. Mattermost can be deployed on-premises, in private clouds, or air-gapped networks, ensuring data sovereignty and control. See the [server deployment planning](/deployment-guide/server/server-deployment-planning) guide for more information. + +## Is CAC/SAML/LDAP integration available? + +Yes. Mattermost supports [SAML 2.0](/administration-guide/onboard/sso-saml#saml-single-sign-on) (compatible with Okta, ADFS, OneLogin, Azure AD, PingFederate, etc.), CAC via SAML integration (configuration details may vary), and [AD/LDAP integration](/administration-guide/onboard/ad-ldap) for centralized identity, user provisioning, and group sync in Enterprise editions. + +## Can it be used securely on BYOD mobile? + +Yes. Mattermost supports [mobile security controls](/security-guide/mobile-security) like restricting file downloads, screen capture, and external sharing. + +## Can it be used securely on mobile with MDM controls? + +Yes. Mattermost supports [mobile device management (MDM) policies](/security-guide/mobile-security), while also including [mobile security controls](/security-guide/mobile-security) like restricting file downloads, screen capture, and external sharing. + +## Do you have existing STIGs or documentation to support RMF/ATO efforts? + +Yes, available after confirmation of appropriate governmental use. Please [contact us](https://mattermost.com/contact/). + +## Are you listed on the GSA? + +Yes, you can find more information [via Carasoft](https://www.carahsoft.com/mattermost/contracts). + +## Are there other contract vehicles for purchasing Mattermost for other Federal, State and Local and Educational purposes? + +Yes, you can find more information [here](https://www.carahsoft.com/mattermost/contracts). + +## What is the entity name, address and CAGE code for Mattermost, Inc.? + +- Entity Name: Mattermost, Inc. +- Address: 2100 Geng Road, Suite 210, Office 243, Palo Alto, CA, 94303, USA +- CAGE Code: 7ZTZ9 +- NAICS Code: 513210 +- SAM.gov Unique Entity ID: J7QLN24NAEN7 + +## What is the entity name, address and CAGE code Mattermost Federal, Inc? + +- Entity Name: Mattermost Federal, Inc. +- Address: 1900 Reston Metro Plaza, Suite \#613, Reston, VA, 20190-5952, USA +- CAGE Code: 9TG37 +- NAICS Code: 513210 +- SAM.gov Unique Entity ID: RN3UJ3CK94Q3 + +## What if my question is not answered here? + +For any questions not answered here, please [contact us](https://mattermost.com/contact/). diff --git a/docs/main/product-overview/faq-general.mdx b/docs/main/product-overview/faq-general.mdx new file mode 100644 index 000000000000..7418e3cab89f --- /dev/null +++ b/docs/main/product-overview/faq-general.mdx @@ -0,0 +1,46 @@ +--- +title: "General Mattermost" +--- +## Why was Mattermost created? + +Mattermost was created to offer an alternative to proprietary SaaS services. For more information, please see the article [Why we built Mattermost](https://mattermost.com/about-us/). + +## Why does the open source repository contain code specific to the commercial version of Mattermost? + +The [commercial version of Mattermost](/product-overview/editions-and-offerings#mattermost-enterprise-edition) is designed to never lock-in your data. Portions of the commercial version are shared with the [open source version](/product-overview/editions-and-offerings#mattermost-team-edition) to ensure upgrade and downgrade across editions happens without data loss. + +## Does Mattermost support 508 Compliance? + +Yes. See the [accessibility compliance policy](/product-overview/accessibility-compliance-policy) documentation for details. Mattermost Enterprise Edition has been purchased by multiple US public sector organizations, including US federal agencies and the Department of Defense. + +## What's the largest Mattermost deployment you have? + +Our largest contractual obligation is for over a quarter of a million registered users. Our most typical large enterprise deployment size is between 10,000 and 40,000 users in Dev and Ops organizations who use Mattermost for DevOps workflows, remote work, mission-critical and rapid response, and to address email overload. + +We have done performance testing of 60,000 concurrent users and 60 million posts in the database, with a peak concurrent utilization safety factor of between 10 to 1 and 3 to 1, depending on the distribution of an organization across time zones. Peak concurrent usage in a single timezone is generally around the start of the day, probably 9am, and lunchtime when people are messaging to meet for a meal. Our monthly releases are tested at 20 million posts in the database. + +Mattermost provides an open source, well-documented [load test simulator](https://github.com/mattermost/mattermost-load-test) to verify that your Mattermost deployment can achieve the stated scale benchmarks ahead of production deployment. + +## What happens if I have more than 10,000 messages in my database and have upgraded to Entry? + +Entry limits the number of messages shown in the end user inteface for channel history and search. All records are retained in the database. Upgrading to a paid version of Mattermost will unlock this and other Entry limitations. Migrating to Team Edition will also unlock full history of channels, but will limit what features are available. + +## What are the limitations for embargoed countries? + +We greatly appreciate your interest in Mattermost. Due to recent sanctions from the United States government, we must pause interactions with your organization until the sanctions are lifted. + +This includes: + +- We must pause on selling, issuing, or renewing a Mattermost license key to your organization. If you have a Mattermost license key, or a trial key, we ask that you do not use it. +- We are not permitted to provide you technical support for our software. Moreover, we cannot answer questions about our software. +- We are not permitted to provide our software, including any updates, upgrades or cloud-hosted versions to your organization. We must ask that you do not use any software or online services provided by Mattermost, Inc., including any versions that have been provided online to the general public. + +We deeply apologize for the inconvenience. We must abide by United States laws. We hope after sanctions are lifted that we can support your interest once again. Please reach out to [compliance@mattermost.com](mailto:compliance@mattermost.com) for any questions around current export limitations. + +## How do I report illicit use of Mattermost software? + +Illicit use of Mattermost software to harm others, infringe on their rights, break laws or policies is explicitly against our [Terms of Use](https://mattermost.com/terms-of-use/). + +If the illicit use is happening on a web address ending in `“mattermost.com”`, it means the suspected perpetrators are using Mattermost software controlled by our company, Mattermost, Inc. In this case, please get in touch with us at `compliance@mattermost.com` to report the issue for us to investigate. + +If the illicit use is happening on a different web address, then it means the suspected perpetrators may be using Mattermost software controlled by a person or company other than Mattermost, Inc. In this case, you need to contact the person or company who controls the web address by using a lookup service such as [https://www.whois.com/](https://www.whois.com/) to find the contact email to report abuse. You can use a link to this FAQ as a reference to our [Terms of Use](https://mattermost.com/terms-of-use/) policy for Mattermost software. diff --git a/docs/main/product-overview/faq-license.mdx b/docs/main/product-overview/faq-license.mdx new file mode 100644 index 000000000000..96eef4720702 --- /dev/null +++ b/docs/main/product-overview/faq-license.mdx @@ -0,0 +1,225 @@ +--- +title: "Business & Licensing" +--- +## What are Mattermost's policies around licensing, terms of use, and privacy? + +The following outlines the licensing, terms of use and privacy policies across Mattermost software and services. See the [source available license](/product-overview/faq-mattermost-source-available-license) documentation to learn what the Mattermost source available license offers. + +### Mattermost Software + + ++++++ + + + + + + + + + + + + + + +

Software

====================================================

Mattermost Team Edition (Open Source)

License | Terms and Conditions | Privacy Policy |

============================================================================================================================+===============================================================================================================================+=============================================================================================+
Open Source MIT License. | Mattermost Trademark Policy | Mattermost Server Privacy Policy |
                                                                                                                              | with GDPR Data Processing Addendum. |

Open Source Add-ons available under Apache v2 and other licenses. | Mattermost Terms of Use |

----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------+ |
Commercial Enterprise Edition License. | No subscription terms apply when operating without a subscription | |
                                                                                                                              | |

You are welcome to use the Enterprise Edition of Mattermost free of charge in perpetuity when the subscription feature | | | are not enabled by a license key. +-------------------------------------------------------------------------------------------------------------------------------+ | | Self Managed Subscription Terms | | If you choose to purchase a subscription for paid features, terms and conditions are offered | | | as part of the subscription purchase (see “Terms”). | Enterprise Edition Subscription Terms for Purchase by Resale | | | | | | Cloud Subscription Agreement | |

Mattermost Enterprise Edition with no subscription
Mattermost Enterprise Edition with subscription
+ +#### Mattermost Service Agreements + + +++++ + + + + + + + + + + + + + + + + + + + + + + +
ServiceTerms and ConditionsPrivacy Policy
Mattermost Enterprise Edition Support, including Premier SupportMattermost Support TermsMattermost Server Privacy Policy with GDPR Data Processing Addendum.
Mattermost Hosted Push Notification ServiceHosted Push Notifications Service Terms
Mattermost Professional ServicesTo be posted.
+ +### Mattermost Websites + + ++++++ + + + + + + + + + + + + + + + + +
WebsiteLicenseTerms and ConditionsPrivacy Policy

Mattermost Websites:

  • about.mattermost.com
  • mattermost.com
  • mattermost.org
  • forum.mattermost.org
  • docs.mattermost.com
Open source under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License (CC BY-NC-SA 3.0).Mattermost Terms of UseMattermost Websites Privacy Policy
+ +### Mattermost Partnership Agreements + + ++++ + + + + + + + + + + + + +
Partnership AgreementAgreement
Mattermost Authorized Reseller AgreementMattermost Authorized Reseller Agreement
+ +### Mattermost Confidentiality Agreements + + ++++ + + + + + + + + + + + + +
Confidentiality AgreementAgreement
Mattermost Mutual Non-Disclosure AgreementMattermost Mutual Non-Disclosure Agreement
+ +### Working for Mattermost + + ++++ + + + + + + + + + + + + + + + + +
ServiceTerms and Conditions
Mattermost Professional Consulting ServicesMattermost Professional Consulting Services Agreement
Mattermost ConsultingMattermost Consulting Terms
+ +## How do I fork Mattermost? + +If you wish to create a forked version of the Mattermost source code, you must comply with the applicable licenses under which the source code is made available. + +For example, the Mattermost server source code is and always has been made available under the AGPLv2 license. Therefore, all third-party open source forks of the Mattermost server source code must comply with the AGPLv2 license in both source code and compiled versions. If you encounter a third-party fork of the publicly available source code of Mattermost server that claims to be licensed under an alternate license, it is incorrect. + +For clarity, this license information regarding forking the source specifically refers to the use (and compilation) of the Mattermost source code by third parties. Third parties are obligated to comply with the open source licenses referenced above in connection with their derivative works. Compiled versions and derivative works of Mattermost prepared by third parties may not be made available under any license other than those under which the applicable source code is made available. + +In contrast, Mattermost, as the copyright holder to the collection of the Mattermost source code, has exercised its exclusive right to make compiled versions of the Mattermost source code available under various other licenses (such as the MIT license and the Mattermost Commercial Enterprise License, as more specifically made clear in the table here: [https://docs.mattermost.com/about/faq-license.html](https://docs.mattermost.com/about/faq-license.html)). + +## How can I create an open source derivative work of Mattermost? + +If you're looking to customize the look and feel of Mattermost, see the [customization](/administration-guide/configure/customize-mattermost) documentation. For advanced customization, the system's user experience is available in different repositories for web, mobile apps, and desktop apps and custom experiences can be developed and integrated via the system APIs and custom plugins. + +If, instead of using Mattermost Team Edition or Mattermost Enterprise Edition, you choose to compile your own version of the system using the open source code from `/mattermost`, there are a number of factors to consider: + +### Security + +- If you run a fork of the Mattermost server, we highly recommend you only deploy the system securely behind a firewall and to pay close attention to [Mattermost security updates](https://mattermost.com/security-updates/). Mattermost Team Edition and Mattermost Enterprise Edition release security update patches when reports of new attacks are received and verified. Mattermost waits until 30 days after a security patch is released before publicly detailing its nature so that users and customers can upgrade before the security vulnerability is widely known. A malicious user can potentially make use of Mattermost security disclosures to exploit a fork of Mattermost if the security upgrade is not promptly incorporated into the forked version. + +### Rebranding + +- When you create a derivative version of Mattermost and share it with others as a product, you need to replace the Mattermost name and logo from the system, among other requirements, per the [Mattermost trademark policy](https://mattermost.com/trademark-standards-of-use/). +- You can rebrand your system using [custom branding tools](/administration-guide/configure/custom-branding-tools). +- For advanced whitelabelling, you can manually update files on the Mattermost server [per product documentation.](https://github.com/mattermost/docs/issues/1006) This can also be done without forking. + +### Copyright and Licensing of `/mattermost` open source code + +- Compiling and distributing your own version of the open source Mattermost `/mattermost` repo requires a) compliance with licenses in the repo, including [NOTICE.txt](https://github.com/mattermost/mattermost/blob/master/NOTICE.txt), and b) the compiled version of the `/mattermost` source code should have the same open source license as the source code, [per our licensing policy](/product-overview/faq-license). + +### Other considerations + +- Mattermost has a default [Terms of Use](/administration-guide/configure/site-configuration-settings#terms-of-use-link) agreement for the Terms of Use link at the bottom of login screen that should be incorporated into any additional Terms of Use you may add. +- The Mattermost copyright notices on the user interface should remain. +- There may be additional legal and regulatory issues to consider and we recommend you employ legal counsel to fully understand what's involved in creating and selling a derivative work. + +## Can I create a derivative work of the Mattermost /mattermost repository that is not open source? + +The Mattermost open source project was created by [a group of developers who had their data paywalled by a proprietary online messaging service](https://mattermost.com/about-us/) and felt it was unfair. + +Because of this, the Mattermost /mattermost repository uses an open source license that requires derivative works to use the same open source license. This prevents the creation of derivative works that are not open source, and the situation where end users would not have access to the source code of the systems they use, and hence be at risk of "lock in". + +For companies purchasing Enterprise Edition subscriptions for use by internal staff, who need to modify /mattermost, and who also have legal departments that won't allow their staff to work under an open source software license, a special "Advanced Licensing Option" can be purchased to modify /mattermost for internal use under a commercial software license. This option is not available for companies that would offer a modified, non-open source version of Mattermost to external parties. + +## Does Mattermost answer questions about open source licenses authored by other organizations? + +No, if you have questions about an open source license, please consult the original author, or FAQs they offer. + +## Why does Mattermost have a discount for certain kinds of non-profits but not for others? + +While we welcome anyone to use the open source version of Mattermost Team Edition free of charge, Mattermost, Inc., like any software company, has specific discounting programs for its commercial Mattermost Enterprise Edition based on business objectives. Objectives of the discounting programs include the suitability of potential case studies, references, word-of-mouth promotion and public promotion of solutions, among many other factors. + +See our [non-profit subscriptions](/product-overview/non-profit-subscriptions) documentation for details. + +## Will Mattermost, Inc. offer the ability to resell Mattermost software without a reseller agreement? + +No. + +If there is a case where the reseller agreement is under review and a customer urgently needs an order, Mattermost may, with internal approvals, accept a reseller purchase order with the following language: + +"Any statements, clauses, or conditions included on or referenced by buyer's purchase order forms, which forms modify, add to, or are inconsistent with Mattermost’s standard terms and conditions are expressly rejected. Such orders will only be accepted by Mattermost upon the condition and with the express understanding that despite any such statements, clauses, or conditions contained in any order forms of the buyer are void and have no effect. + +EXCEPT AS OTHERWISE EXPRESSLY AGREED BY THE PARTIES IN WRITING, MATTERMOST MAKES NO WARRANTIES OR REPRESENTATIONS WITH RESPECT TO ANY MATTERMOST PRODUCTS, DOCUMENTATION OR SUPPORT, AND HEREBY DISCLAIMS ALL OTHER EXPRESS AND ALL IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT." + +## Will Mattermost complete questionnaires requiring confidential data without an NDA? + +No, Mattermost will not complete questionnaires requiring confidential data without a non-disclosure agreement. diff --git a/docs/main/product-overview/faq-mattermost-source-available-license.mdx b/docs/main/product-overview/faq-mattermost-source-available-license.mdx new file mode 100644 index 000000000000..2fa5b64926a1 --- /dev/null +++ b/docs/main/product-overview/faq-mattermost-source-available-license.mdx @@ -0,0 +1,98 @@ +--- +title: "Mattermost Source Available License" +--- +## What is the Mattermost Source Available License? + +A source available license gives access to source code, but places restrictions on its use. The Mattermost Source Available License allows free-of-charge and unrestricted use of the source code in development and testing environments, but requires a valid Mattermost Enterprise Edition License in a production environment. + +## How can I identify code licensed as source available? + +When the Mattermost Source Available `LICENSE` file appears at the root of a repository, the restrictions apply to all source code within the repository. A note in the `README.md` often identifies the use of this license and links to this FAQ. + +When the Mattermost Source Available `LICENSE` file appears in a specific directory, the restrictions apply to all source code within that directory. This directory is often called "enterprise". For additional clarity, an additional `LICENSE.enterprise` file may appear in the root directory, symlinked to the `enterprise/LICENSE` file. + +In all cases, any third party components remain licensed under their original license. + +An example directory layout, using an Enterprise license, is shown below: + +![An example directory layout shows how Enterprise subscription plan restrictions apply to Mattermost source code based on where the Mattermost Source Available license file appears in the Mattermost deployment directory.](/images/source-available-license.png) + +## Why are you changing the licensing model? + +Our plugin framework delivers substantial value to our enterprise customers but requires significant development and support resources. This change to the licensing model allows us to continue developing open source features while selectively charging for features. + +## How are repositories changing? + +As we add enterprise-only functionality, we will update the license on affected Mattermost-authored plugin repositories. The intent is to work alongside the existing, open source functionality in our plugins while reserving certain enterprise functionality to customers who pay us for enterprise licenses. + +## To which repositories does this apply? + +We plan to apply this license to the enterprise directories of our [Jira](https://github.com/mattermost/mattermost-plugin-jira), [Microsoft Calendar Integration](https://github.com/mattermost/mattermost-plugin-mscalendar), and [Microsoft Teams Meetings](https://github.com/mattermost/mattermost-plugin-msteams-meetings) plugins. We also intend to release [Collaborative playbooks](/end-user-guide/workflow-automation) and [Channel Export](https://github.com/mattermost/mattermost-plugin-channel-export) plugins under the Mattermost Source Available License. New, Mattermost-authored plugins will generally be released under the Mattermost Source Available License. When we update the licenses, we will release a new version and note the change in the `README.md` file of the GitHub repository and any release notes. + +We expect to keep plugins without an enterprise component under our open source license. No licensing changes are planned to non-plugin repositories, such as [mattermost](https://github.com/mattermost/mattermost) or [mattermost webapp](https://github.com/mattermost/mattermost/tree/master/webapp). + +## Will the repositories be public? + +Yes, existing repositories will stay public. We are now also able to make public several enterprise-only plugins under the Mattermost Source Available License previously developed in private. + +## Can I still contribute? + +Yes, we continue to welcome all contributions. Mattermost may select some contributions as enterprise features and license them under the Mattermost Source Available License. We will aim to communicate such decisions as early as possible in the contribution process. + +As with all Mattermost repositories, you will still need to sign the [Mattermost CLA](https://mattermost.com/mattermost-contributor-agreement/). We will not accept contributions without signing the Mattermost CLA. + +## Do I need to re-sign the [Mattermost CLA](https://mattermost.com/mattermost-contributor-agreement/)? + +No, if you have already signed the [Mattermost CLA](https://mattermost.com/mattermost-contributor-agreement/), you do not need to sign it again. + +## Can I compile your plugins by myself? + +Yes. If you have a Mattermost Enterprise Edition license, you are free to compile and use a plugin under the Mattermost Source Available License. Furthermore, if you are developing against or testing with such a plugin, you are free to compile and test a plugin even without a Mattermost Enterprise Edition license. Without an Enterprise Edition license, source available plugins may have reduced functionality or refuse to start altogether. Request a [trial license](https://mattermost.com/trial/) if your testing requires access to enterprise functionality. + +Several of our customers value complete access to our source code and compile our plugins from source before deploying to their production servers. By adopting the Mattermost Source Available License, we can develop enterprise-only features in public without impacting this workflow. + +## Will you distribute open source plugin binaries without any licensing restrictions? + +At this time, we have no plans to distribute more than one version of each of our plugins. Without a Mattermost Enterprise Edition License, plugins may have reduced functionality or refuse to start altogether. + +## Can I continue to use the existing open source repositories without restriction? + +Yes, the Mattermost Source Available License will only apply from the date it is added and to the versions in which it is included. + +## Do I need to use the Mattermost Source Available License for plugins I create? + +You are free to license your own code as you see fit. We will not apply the Mattermost Source Available License either to the [starter-template](https://github.com/mattermost/mattermost-plugin-starter-template) or [demo](https://github.com/mattermost/mattermost-plugin-demo) plugins, leaving them under a permissive open source license to give you the freedom to develop your own plugins. + +## Can I publish my own plugin and rely on enterprise specific functionality? + +As before, you are free to license your own code as you see fit. Note that some server functionality is only enabled with a Mattermost Enterprise license regardless of how you license your plugin. + +## Can’t someone compile out any license restrictions? + +We trust our community to honor the Mattermost Source Available License and work alongside us to develop features across our free and paid offerings. Our Support team does not provide support to unlicensed, enterprise-only functionality. + +## If I make my own plugin using your source available code, can I remove the license restriction? + +No, the Mattermost Source Available License continues to apply to modifications. + +## Will you pursue legal action if this license is violated? + +Yes, if necessary. But we would always rather collaborate, so if you need to negotiate a different license, please ask us. + +## Is this a legal document? + +No. This FAQ is informational only. The Mattermost Source Available License stands on its own, and this FAQ does not affect its meaning. + +## What is the full text of the Mattermost Source Available License? + +"The Mattermost Source Available License (the “Source Available License”) (c) Mattermost, Inc. 2015-present. + +With regard to the Mattermost Software: + +This software and associated documentation files (the "Software") may only be used in production, if you (and any entity that you represent) have agreed to, and are in compliance with all of the following: (a) the Mattermost Terms of Use, available at [https://mattermost.com/terms-of-use/](https://mattermost.com/terms-of-use/) (the "TOU"), (b) and the Mattermost Software License Agreement, available at [https://mattermost.com/enterprise-edition-terms/](https://mattermost.com/enterprise-edition-terms/) (the “SLA”) or other licensing agreement governing your use of the Software, as agreed by you and Mattermost, and otherwise have a valid Mattermost Enterprise for the correct number of Registered Authorized Users the Software. Subject to the foregoing, you are free to modify this Software and publish patches to the Software. You agree that Mattermost and/or its licensors (as applicable) retain all right, title and interest in and to all such modifications and/or patches, and all such modifications and/or patches may only be used, copied, modified, displayed, distributed, or otherwise exploited with a valid license or Subscription for the correct number of Registered Authorized Users of the Software. Notwithstanding the foregoing, you may copy and modify the Software for development and testing purposes, without requiring a valid license or Subscription. You agree that Mattermost and/or its licensors (as applicable) retain all right, title and interest in and to all such modifications. You are not granted any other rights beyond what is expressly stated herein. Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, and/or sell the Software. + +The full text of this Source Available License shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +For all third party components incorporated into the Mattermost Software, those components are licensed under the original license provided by the owner of the applicable component." diff --git a/docs/main/product-overview/frequently-asked-questions.mdx b/docs/main/product-overview/frequently-asked-questions.mdx new file mode 100644 index 000000000000..719229a2bc55 --- /dev/null +++ b/docs/main/product-overview/frequently-asked-questions.mdx @@ -0,0 +1,9 @@ +--- +title: "Frequently Asked Questions" +--- +The following pages will answer many of your frequently asked questions about Mattermost: + +- [General](/product-overview/faq-general) - Learn more about Mattermost, its largest deployment, and answers to commonly asked questions. +- [Enterprise](/product-overview/faq-enterprise) - Learn about Mattermost Enterprise Edition. +- [Federal Procurement](/product-overview/faq-federal-procurement) - Learn about Mattermost in federal government environments. +- [Business & Licensing](/product-overview/faq-license) - Learn more about Mattermost licenses. diff --git a/docs/main/product-overview/mattermost-desktop-releases.mdx b/docs/main/product-overview/mattermost-desktop-releases.mdx new file mode 100644 index 000000000000..a087e7b0635e --- /dev/null +++ b/docs/main/product-overview/mattermost-desktop-releases.mdx @@ -0,0 +1,36 @@ +--- +title: "Desktop Releases" +--- +import Inc0_common_esr_support from './common-esr-support.mdx'; + +```{Important} + +## Frequency + +Mattermost releases a new desktop app version every 4 months, in February, May, August, and November in [binary form](https://docs.mattermost.com/end-user-guide/access/install-desktop-app.html). See the [Desktop app changelog](/product-overview/desktop-app-changelog) for release details. + +```{Important} +- From Mattermost v9.11, Mattermost server extended releases are now paired with Mattermost desktop app extended releases. For an optimal user experience and for the latest security fixes, we strongly recommend updating desktop clients to the latest version your Mattermost server supports. See the table below for server compatibility, and see the [Mattermost extended support releases](#extended-support-releases) documentation to learn more about extended releases. +- If you prefer to control the server and client releases, we recommend disabling automatic client updates to prevent users from upgrading their desktop client to a version your server doesn't support. See the [install Mattermost desktop app](https://docs.mattermost.com/end-user-guide/access/install-desktop-app.html) documentation for platform-specific details on automatic app updates. +``` + +## Latest releases + +| **Release** | **Support** | **Compatible with** | +|:---|:---|:---| +| v6.1 [Download](https://github.com/mattermost/desktop/releases/tag/v6.1.2) \| [Changelog](#release-v6-1) \| [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 | [v11.6](#release-v11-6-feature-release), [v11.5](#release-v11-5-feature-release), [v11.4](#release-v11-4-feature-release), [v11.3](#release-v11-3-feature-release), [v11.2](#release-v11-2-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v6.0 [Download](https://github.com/mattermost/desktop/releases/tag/v6.0.4) \| [Changelog](#release-v6-0) \| [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 | [v11.4](#release-v11-4-feature-release), [v11.3](#release-v11-3-feature-release), [v11.2](#release-v11-2-feature-release), [v11.1](#release-v11-1-feature-release), [v11.0](#release-v11-0-major-release), [v10.12](#release-v10-12-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v5.13 [Download](https://github.com/mattermost/desktop/releases/tag/v5.13.5) \| [Changelog](#release-v5-13) \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v5.13.5/sbom-desktop-v5.13.5.json) | Released: 2025-08-15
Support Ends: 2026-08-15 [EXTENDED](#release-types) | [v11.0](#release-v11-0-major-release), [v10.12](#release-v10-12-feature-release), [v10.11](#release-v10-11-extended-support-release), [v10.10](#release-v10-10-feature-release), [v10.9](#release-v10-9-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v5.12 [Download](https://github.com/mattermost/desktop/releases/tag/v5.12.1) \| [Changelog](#release-v5-12) \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v5.12.1/sbom-desktop-v5.12.1.json) | Released: 2025-05-16
Support Ends: 2025-08-15 | [v10.10](#release-v10-10-feature-release), [v10.9](#release-v10-9-feature-release), [v10.8](#release-v10-8-feature-release), [v10.7](#release-v10-7-feature-release), [v10.6](#release-v10-6-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v5.11 [Download](https://github.com/mattermost/desktop/releases/tag/v5.11.3) \| [Changelog](#release-v5-11) | Released: 2025-02-14
Support Ends: 2025-11-15 | [v10.7](#release-v10-7-feature-release), [v10.6](#release-v10-6-feature-release), [v10.5](#release-v10-5-extended-support-release), [v10.4](#release-v10-4-feature-release), [v10.3](#release-v10-3-feature-release), [v9.11](#release-v9-11-extended-support-release) | +| v5.10 [Download](https://github.com/mattermost/desktop/releases/tag/v5.10.2) \| [Changelog](#release-v5-10) | Released: 2024-11-15
Support Ends: 2025-02-13 | [v10.2](#release-v10-2-feature-release), [v10.1](#release-v10-1-feature-release), [v10.0](#release-v10-0-major-release), [v9.11](#release-v9-11-extended-support-release), [v9.5](#release-v9-5-extended-support-release) | +| v5.9 [Download](https://github.com/mattermost/desktop/releases/tag/v5.9.2) \| [Changelog](#release-v5-9) | Released: 2024-08-16
Support Ends: 2025-05-15 | [v9.11](#release-v9-11-extended-support-release), [v9.10](#release-v9-10-feature-release), [v9.9](#release-v9-9-feature-release), [v9.8](#release-v9-8-feature-release), [v9.5](#release-v9-5-extended-support-release) | +| v5.8 [Download](https://github.com/mattermost/desktop/releases/tag/v5.8.0) \| [Changelog](#release-v5-8) | Released: 2024-05-16
Support Ends: 2024-08-15 | [v9.9](#release-v9-9-feature-release), [v9.8](#release-v9-8-feature-release), [v9.7](#release-v9-7-feature-release), [v9.6](#release-v9-6-feature-release), [v9.5](#release-v9-5-extended-support-release), [v8.1](#release-v8-1-extended-support-release) | +| v5.7 [Download](https://github.com/mattermost/desktop/releases/tag/v5.7.0) \| [Changelog](#release-v5-7) | Released: 2024-03-15
Support Ends: 2024-05-15 | [v9.6](#release-v9-6-feature-release) | +| v5.6 [Download](https://github.com/mattermost/desktop/releases/tag/v5.6.0) \| [Changelog](#release-v5-6) | Released: 2023-12-15
Support Ends: 2024-03-14 | [v9.3](#release-v9-3-feature-release) | +| v5.5 [Download](https://github.com/mattermost/desktop/releases/tag/v5.5.1) \| [Changelog](#release-v5-5) | Released: 2023-09-15
Support Ends: 2023-12-14 | [v9.0](#release-v9-0-major-release) | +| v5.4 [Download](https://github.com/mattermost/desktop/releases/tag/v5.4.0) \| [Changelog](#release-v5-4) | Released: 2023-06-19
Support Ends: 2023-09-14 | [v7.10](#release-v7-10-feature-release) | +| v5.3 [Download](https://github.com/mattermost/desktop/releases/tag/v5.3.1) \| [Changelog](#release-v5-3) | Released: 2023-03-30
Support Ends: 2023-06-18 | [v7.9](#release-v7-9-feature-release) | +| v5.2 [Download](https://github.com/mattermost/desktop/releases/tag/v5.2.2) \| [Changelog](#release-v5-2) | Released: 2022-10-31
Support Ends: 2023-03-29 | [v7.4](#release-v7-4-feature-release) | +| v5.1 [Download](https://github.com/mattermost/desktop/releases/tag/v5.1.1) \| [Changelog](#release-v5-1) | Released: 2022-05-16
Support Ends: 2022-10-30 | [v6.7](#release-v6-7-feature-release) | +| v5.0 [Download](https://github.com/mattermost/desktop/releases/tag/v5.0.4) \| [Changelog](#release-v5-0) | Released: 2021-10-13
Support Ends: 2022-05-15 | [v6.0](#release-v6-0-feature-release) | diff --git a/docs/main/product-overview/mattermost-mobile-releases.mdx b/docs/main/product-overview/mattermost-mobile-releases.mdx new file mode 100644 index 000000000000..789f51fa2065 --- /dev/null +++ b/docs/main/product-overview/mattermost-mobile-releases.mdx @@ -0,0 +1,74 @@ +--- +title: "Mobile Releases" +--- +import Inc0_common_esr_support from './common-esr-support.mdx'; + +```{Important} + +## Frequency + +Mattermost releases a new mobile app version every month. + +See the [Mobile app changelog](/product-overview/mobile-app-changelog) for release details, and see the [iOS mobile app](/end-user-guide/access/install-ios-app) and the [Android mobile app](/end-user-guide/access/install-android-app) documentation for installation details. + +```{Important} +We strongly recommend using the latest mobile app release available that contains the latest security fixes and user experience enhancements. Mobile app releases are compatible with and tested against [supported Mattermost server and extended support releases](https://docs.mattermost.com/product-overview/mattermost-server-releases.html#latest-releases). +``` + +## Latest releases + +| **Release** | **Support** | **Compatible with** | +|:---|:---|:---| +| v2.39 [FEATURE](#release-v2-39-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.39.0) \| [Changelog](#release-v2-39-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.39.0/sbom-mattermost-mobile-v2.39.0.json) | Released: 2026-04-16
Support Ends: 2026-05-15 | [v11.6](#release-v11-6-feature-release), [v11.5](#release-v11-5-feature-release), [v11.4](#release-v11-4-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.38 [FEATURE](#release-v2-38-3) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.38.3) \| [Changelog](#release-v2-38-3) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.38.3/sbom-mattermost-mobile-v2.38.3.json) | Released: 2026-03-16
Support Ends: 2026-04-15 | [v11.5](#release-v11-5-feature-release), [v11.4](#release-v11-4-feature-release), [v11.3](#release-v11-3-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.37 [FEATURE](#release-v2-37-2) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.37.2) \| [Changelog](#release-v2-37-2) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.37.2/sbom-mattermost-mobile-v2.37.2.json) | Released: 2026-02-16
Support Ends: 2026-03-15 | [v11.4](#release-v11-4-feature-release), [v11.3](#release-v11-3-feature-release), [v11.2](#release-v11-2-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.36 [FEATURE](#release-v2-36-4) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.36.4) \| [Changelog](#release-v2-36-4) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.36.4/sbom-mattermost-mobile-v2.36.4.json) | Released: 2026-01-16
Support Ends: 2026-02-15 | [v11.3](#release-v11-3-feature-release), [v11.2](#release-v11-2-feature-release), [v11.1](#release-v11-1-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.35 [FEATURE](#release-v2-35-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.35.0) \| [Changelog](#release-v2-35-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.35.0/sbom-mattermost-mobile-v2.35.0.json) | Released: 2025-12-16
Support Ends: 2026-01-15 | [v11.2](#release-v11-2-feature-release), [v11.1](#release-v11-1-feature-release), [v11.0](#release-v11-0-major-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.34 [FEATURE](#release-v2-34-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.34.0) \| [Changelog](#release-v2-34-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.34.0/sbom-mattermost-mobile-v2.34.0.json) | Released: 2025-11-14
Support Ends: 2025-12-15 | [v11.1](#release-v11-1-feature-release), [v11.0](#release-v11-0-major-release), [v10.12](#release-v10-12-feature-release), [v10.11](#release-v10-11-extended-support-release) | +| v2.33 [FEATURE](#release-v2-33-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.33.1) \| [Changelog](#release-v2-33-1) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.33.1/sbom-mattermost-mobile-v2.33.1.json) | Released: 2025-10-16
Support Ends: 2025-11-15 | [v11.0](#release-v11-0-major-release), [v10.12](#release-v10-12-feature-release), [v10.11](#release-v10-11-extended-support-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.32 [FEATURE](#release-v2-32-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.32.0) \| [Changelog](#release-v2-32-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.32.0/sbom-mattermost-mobile-v2.32.0.json) | Released: 2025-09-15
Support Ends: 2025-10-15 | [v10.12](#release-v10-12-feature-release), [v10.11](#release-v10-11-extended-support-release), [v10.10](#release-v10-10-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.31 [FEATURE](#release-v2-31-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.31.0) \| [Changelog](#release-v2-31-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.31.0/sbom-mattermost-mobile-v2.31.0.json) | Released: 2025-08-15
Support Ends: 2025-09-15 | [v10.11](#release-v10-11-extended-support-release), [v10.10](#release-v10-10-feature-release), [v10.9](#release-v10-9-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.30 [FEATURE](#release-v2-30-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.30.0) \| [Changelog](#release-v2-30-0) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.30.0/sbom-mattermost-mobile-v2.30.0.json) | Released: 2025-07-16
Support Ends: 2025-08-15 | [v10.10](#release-v10-10-feature-release), [v10.9](#release-v10-9-feature-release), [v10.8](#release-v10-8-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.29 [FEATURE](#release-v2-29-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.29.1) \| [Changelog](#release-v2-29-1) \| [SBOM download](https://github.com/mattermost/mattermost-mobile/releases/download/v2.29.1/sbom-mattermost-mobile-v2.29.1.json) | Released: 2025-06-16
Support Ends: 2025-07-15 | [v10.9](#release-v10-9-feature-release), [v10.8](#release-v10-8-feature-release), [v10.7](#release-v10-7-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.28 [FEATURE](#release-v2-28-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.28.1) \| [Changelog](#release-v2-28-1) | Released: 2025-05-16
Support Ends: 2025-06-15 | [v10.8](#release-v10-8-feature-release), [v10.7](#release-v10-7-feature-release), [v10.6](#release-v10-6-feature-release), [v10.5](#release-v10-5-extended-support-release) | +| v2.27 [FEATURE](#release-v2-27-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.27.1) \| [Changelog](#release-v2-27-1) | Released: 2025-04-16
Support Ends: 2025-05-15 | [v10.7](#release-v10-7-feature-release), [v10.6](#release-v10-6-feature-release), [v10.5](#release-v10-5-extended-support-release), [v9.11](#release-v9-11-extended-support-release) | +| v2.26 [FEATURE](#release-v2-26-2) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.26.2) \| [Changelog](#release-v2-26-2) | Released: 2025-03-16
Support Ends: 2025-04-15 | [v10.6](#release-v10-6-feature-release), [v10.5](#release-v10-5-extended-support-release), [v10.4](#release-v10-4-feature-release), [v9.11](#release-v9-11-extended-support-release) | +| v2.25 [FEATURE](#release-v2-25-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.25.1) \| [Changelog](#release-v2-25-1) | Released: 2025-02-16
Support Ends: 2025-03-15 | [v10.5](#release-v10-5-extended-support-release), [v10.4](#release-v10-4-feature-release), [v10.3](#release-v10-3-feature-release), [v9.11](#release-v9-11-extended-support-release) | +| v2.24 [FEATURE](#release-v2-24-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.24.1) \| [Changelog](#release-v2-24-1) | Released: 2025-01-16
Support Ends: 2025-02-15 | [v10.4](#release-v10-4-feature-release), [v10.3](#release-v10-3-feature-release), [v10.2](#release-v10-2-feature-release), [v9.11](#release-v9-11-extended-support-release) | +| v2.23 [FEATURE](#release-v2-23-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.23.1) \| [Changelog](#release-v2-23-1) | Released: 2024-12-16
Support Ends: 2025-01-15 | [v10.3](#release-v10-3-feature-release), [v10.2](#release-v10-2-feature-release), [v10.1](#release-v10-1-feature-release), [v9.11](#release-v9-11-extended-support-release) | +| v2.22 [FEATURE](#release-v2-22-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.22.0) \| [Changelog](#release-v2-22-0) | Released: 2024-11-15
Support Ends: 2024-12-15 | [v10.2](#release-v10-2-feature-release), [v10.1](#release-v10-1-feature-release), [v10.0](#release-v10-0-major-release), [v9.11](#release-v9-11-extended-support-release), [v9.5](#release-v9-5-extended-support-release) | +| v2.21 [FEATURE](#release-v2-21-0) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.21.0) \| [Changelog](#release-v2-21-0) | Released: 2024-10-16
Support Ends: 2024-11-15 | [v10.1](#release-v10-1-feature-release), [v10.0](#release-v10-0-major-release), [v9.11](#release-v9-11-extended-support-release), [v9.10](#release-v9-10-feature-release), [v9.5](#release-v9-5-extended-support-release) | +| v2.20 [FEATURE](#release-v2-20-1) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.20.1) \| [Changelog](#release-v2-20-1) | Released: 2024-09-16
Support Ends: 2024-10-15 | [v10.0](#release-v10-0-major-release), [v9.11](#release-v9-11-extended-support-release), [v9.10](#release-v9-10-feature-release), [v9.9](#release-v9-9-feature-release), [v9.5](#release-v9-5-extended-support-release) | +| v2.19 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.19.2) \| [Changelog](#release-v2-19-2) | Released: 2024-08-16
Support Ends: 2024-09-15 | [v9.11](#release-v9-11-extended-support-release), [v9.10](#release-v9-10-feature-release), [v9.9](#release-v9-9-feature-release), [v9.8](#release-v9-8-feature-release), [v9.5](#release-v9-5-extended-support-release) | +| v2.18 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.18.1) \| [Changelog](#release-v2-18-1) | Released: 2024-07-16
Support Ends: 2024-08-15 | [v9.10](#release-v9-10-feature-release) | +| v2.17 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.17.1) \| [Changelog](#release-v2-17-1) | Released: 2024-06-16
Support Ends: 2024-07-15 | [v9.9](#release-v9-9-feature-release) | +| v2.16 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.16.0) \| [Changelog](#release-v2-16-0) | Released: 2024-05-16
Support Ends: 2024-06-15 | [v9.8](#release-v9-8-feature-release) | +| v2.15 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.15.0) \| [Changelog](#release-v2-15-0) | Released: 2024-04-16
Support Ends: 2024-05-15 | [v9.7](#release-v9-7-feature-release) | +| v2.14 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.14.0) \| [Changelog](#release-v2-14-0) | Released: 2024-03-15
Support Ends: 2024-04-15 | [v9.6](#release-v9-6-feature-release) | +| v2.13 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.13.0) \| [Changelog](#release-v2-13-0) | Released: 2024-02-16
Support Ends: 2024-03-14 | [v9.5](#release-v9-5-extended-support-release) | +| v2.12 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.12.2) \| [Changelog](#release-v2-12-2) | Released: 2024-01-16
Support Ends: 2024-02-15 | [v9.4](#release-v9-4-feature-release) | +| v2.11 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.11.0) \| [Changelog](#release-v2-11-0) | Released: 2023-12-16
Support Ends: 2024-01-15 | [v9.3](#release-v9-3-feature-release) | +| v2.10 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.10.1) \| [Changelog](#release-v2-10-1) | Released: 2023-11-16
Support Ends: 2023-12-15 | [v9.2](#release-v9-2-feature-release) | +| v2.9 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.9.0) \| [Changelog](#release-v2-9-1) | Released: 2023-10-16
Support Ends: 2023-11-15 | [v9.1](#release-v9-1-feature-release) | +| v2.8 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.8.2) \| [Changelog](#release-v2-8-2) | Released: 2023-09-15
Support Ends: 2023-10-15 | [v9.0](#release-v9-0-major-release) | +| v2.7 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.7.0) \| [Changelog](#release-v2-7-0) | Released: 2023-08-16
Support Ends: 2023-09-14 | [v8.1](#release-v8-1-extended-support-release) | +| v2.6 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.6.0) \| [Changelog](#release-v2-6-0) | Released: 2023-07-16
Support Ends: 2023-08-15 | [v8.0](#release-v8-0-major-release) | +| v2.5 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.5.1) \| [Changelog](#release-v2-5-1) | Released: 2023-06-16
Support Ends: 2023-07-15 | [v7.10](#release-v7-10-feature-release) | +| v2.4 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.4.0) \| [Changelog](#release-v2-4-0) | Released: 2023-05-17
Support Ends: 2023-06-15 | [v7.10](#release-v7-10-feature-release) | +| v2.3 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.3.0) \| [Changelog](#release-v2-3-0) | Released: 2023-04-16
Support Ends: 2023-05-16 | [v7.10](#release-v7-10-feature-release) | +| v2.2 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.2.0) \| [Changelog](#release-v2-2-0) | Released: 2023-03-17
Support Ends: 2023-04-15 | [v7.9](#release-v7-9-feature-release) | +| v2.1 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.1.0) \| [Changelog](#release-v2-1-0) | Released: 2023-02-16
Support Ends: 2023-03-16 | [v7.8](#release-v7-8-extended-support-release) | +| v2.0 [FEATURE](#release-types) \| [Download](https://github.com/mattermost/mattermost-mobile/releases/tag/v2.0.1) \| [Changelog](#release-v2-0-1) | Released: 2023-01-16
Support Ends: 2023-02-15 | [v7.7](#release-v7-7-feature-release) | + +## Future releases + +Note that the below versions have not yet been tested. The information below is subject to change. + +| **Release** | **Support** | **Compatible with** | +|:---|:---|:---| +| v2.45 | Releasing: 2026-10-16
Support Ends: 2026-11-15 | v11.12, v11.11, v11.10, v11.7 | +| v2.44 | Releasing: 2026-09-16
Support Ends: 2026-10-15 | v11.11, v11.10, v11.9, v11.7 | +| v2.43 | Releasing: 2026-08-16
Support Ends: 2026-09-15 | v11.10, v11.9, v11.8, v11.7, v10.11 | +| v2.42 | Releasing: 2026-07-16
Support Ends: 2026-08-15 | v11.9, v11.8, v11.7, v10.11 | +| v2.41 | Releasing: 2026-06-16
Support Ends: 2026-07-15 | v11.8, v11.7, v11.6, v10.11 | +| v2.40 | Releasing: 2026-05-16
Support Ends: 2026-06-15 | v11.7, v11.6, v11.5, v10.11 | diff --git a/docs/main/product-overview/mattermost-server-releases.mdx b/docs/main/product-overview/mattermost-server-releases.mdx new file mode 100644 index 000000000000..8ffb3872ecac --- /dev/null +++ b/docs/main/product-overview/mattermost-server-releases.mdx @@ -0,0 +1,45 @@ +--- +title: "Server Releases" +--- +import Inc0_common_esr_support_upgrade from './common-esr-support-upgrade.mdx'; + +(mattermost-server-releases)= + +{/* TODO: eval-rst block left verbatim, port manually */} +``` +.. meta:: + :page_title: Mattermost Server Releases +``` + +```{Important} + +## Frequency +Mattermost releases a new server version on the 16th of each month in [binary form](https://docs.mattermost.com/administration-guide/upgrade/upgrading-mattermost-server.html). +- See the [v11 changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html) for details on what's coming and changing in the next major release. +- See the [unsupported Mattermost legacy releases](https://docs.mattermost.com/product-overview/unsupported-legacy-releases.html) documentation for details on older, unsupported Mattermost releases. + +## Latest releases + +| **Release** | **Released on** | **Support ends** | +|:---|:---|:---| +| v11.6 [Download](https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz) \| [Changelog](#release-v11-6-feature-release) \|
SBOM
| 2026-04-16 | 2026-07-15 | +| v11.5 [Download](https://releases.mattermost.com/11.5.4/mattermost-11.5.4-linux-amd64.tar.gz) \| [Changelog](#release-v11-5-feature-release) \|
SBOM
| 2026-03-16 | 2026-06-15 | +| v11.4 [Download](https://releases.mattermost.com/11.4.5/mattermost-11.4.5-linux-amd64.tar.gz) \| [Changelog](#release-v11-4-feature-release) \|
SBOM
| 2026-02-16 | 2026-05-15 | +| v11.3 [Download](https://releases.mattermost.com/11.3.3/mattermost-11.3.3-linux-amd64.tar.gz) \| [Changelog](#release-v11-3-feature-release) \|
SBOM
| 2026-01-16 | 2026-04-15 | +| v11.2 [Download](https://releases.mattermost.com/11.2.4/mattermost-11.2.4-linux-amd64.tar.gz) \| [Changelog](#release-v11-2-feature-release) \|
SBOM
| 2025-12-16 | 2026-03-15 | +| v11.1 [Download](https://releases.mattermost.com/11.1.3/mattermost-11.1.3-linux-amd64.tar.gz) \| [Changelog](#release-v11-1-feature-release) \|
SBOM
| 2025-11-14 | 2026-02-15 | +| v11.0 [Download](https://releases.mattermost.com/11.0.7/mattermost-11.0.7-linux-amd64.tar.gz) \| [Changelog](#release-v11-0-major-release) \|
SBOM
| 2025-10-16 | 2026-01-15 | +| v10.12 [Download](https://releases.mattermost.com/10.12.4/mattermost-10.12.4-linux-amd64.tar.gz) \| [Changelog](#release-v10-12-feature-release) \|
SBOM
| 2025-09-16 | 2025-12-15 | +| v10.11 [Download](https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz) \| [Changelog](#release-v10-11-extended-support-release) \|
SBOM
| 2025-08-15 | 2026-08-15 [EXTENDED](#release-types) | +| v10.10 [Download](https://releases.mattermost.com/10.10.3/mattermost-10.10.3-linux-amd64.tar.gz) \| [Changelog](#release-v10-10-feature-release) \|
SBOM
| 2025-07-16 | 2025-10-15 | +| v10.9 [Download](https://releases.mattermost.com/10.9.5/mattermost-10.9.5-linux-amd64.tar.gz) \| [Changelog](#release-v10-9-feature-release) \|
SBOM
| 2025-06-16 | 2025-09-15 | +| v10.8 [Download](https://releases.mattermost.com/10.8.4/mattermost-10.8.4-linux-amd64.tar.gz) \| [Changelog](#release-v10-8-feature-release) \|
SBOM
| 2025-05-16 | 2025-08-15 | +| v10.7 [Download](https://releases.mattermost.com/10.7.4/mattermost-10.7.4-linux-amd64.tar.gz) \| [Changelog](#release-v10-7-feature-release) \|
SBOM
| 2025-04-16 | 2025-07-15 | +| v10.6 [Download](https://releases.mattermost.com/10.6.6/mattermost-10.6.6-linux-amd64.tar.gz) \| [Changelog](#release-v10-6-feature-release) \|
SBOM
| 2025-03-16 | 2025-06-15 | +| v10.5 [Download](https://releases.mattermost.com/10.5.14/mattermost-10.5.14-linux-amd64.tar.gz) \| [Changelog](#release-v10-5-extended-support-release) \|
SBOM
| 2025-02-16 | 2025-11-15 [EXTENDED](#release-types) | +| v10.4 [Download](https://releases.mattermost.com/10.4.5/mattermost-10.4.5-linux-amd64.tar.gz) \| [Changelog](#release-v10-4-feature-release) \|
SBOM
| 2025-01-16 | 2025-04-15 | +| v10.3 [Download](https://releases.mattermost.com/10.3.4/mattermost-10.3.4-linux-amd64.tar.gz) \| [Changelog](#release-v10-3-feature-release) \|
SBOM
| 2024-12-16 | 2025-03-15 | +| v10.2 [Download](https://releases.mattermost.com/10.2.3/mattermost-10.2.3-linux-amd64.tar.gz) \| [Changelog](#release-v10-2-feature-release) \|
SBOM
| 2024-11-15 | 2025-02-15 | +| v10.1 [Download](https://releases.mattermost.com/10.1.7/mattermost-10.1.7-linux-amd64.tar.gz) \| [Changelog](#release-v10-1-feature-release) \|
SBOM
| 2024-10-16 | 2025-01-15 | +| v10.0 [Download](https://releases.mattermost.com/10.0.4/mattermost-10.0.4-linux-amd64.tar.gz) \| [Changelog](#release-v10-0-major-release) \|
SBOM
| 2024-09-16 | 2024-12-15 | +| | | | diff --git a/docs/main/product-overview/mattermost-v10-changelog.mdx b/docs/main/product-overview/mattermost-v10-changelog.mdx new file mode 100644 index 000000000000..e7e1d1789cd4 --- /dev/null +++ b/docs/main/product-overview/mattermost-v10-changelog.mdx @@ -0,0 +1,1509 @@ +--- +title: "v10 Changelog" +--- +import Inc0_common_esr_support_upgrade from './common-esr-support-upgrade.mdx'; + +{/* TODO: eval-rst block left verbatim, port manually */} +``` +.. meta:: + :page_title: Mattermost Server v10 Release Notes +``` + +```{Important} + + + +Platform and OS scope reflects reported and tested environments and may not represent all affected configurations. + + + +(release-v10.12-feature-release)= +## Release v10.12 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **10.12.4, released 2025-11-21** + ```{Attention} + **Critical Fixes** + - Mattermost v10.12.4 contains a Critical severity level security fix in the Jira plugin. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Jira plugin version [v4.4.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.1). + - Mattermost v10.12.4 contains no database or functional changes. +- **10.12.3, released 2025-11-17** + - Mattermost v10.12.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams Meetings plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.3.0). + - Pre-packaged Calls plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.0). + - Fixed a configuration retention issue where even active configuration got deleted. + - Mattermost v10.12.3 contains no database or functional changes. +- **10.12.2, released 2025-10-28** + ```{Attention} + **Critical Fixes** + - Mattermost v10.12.2 contains Critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Boards plugin [v9.1.7](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.7). + - Mattermost v10.12.2 contains no database or functional changes. +- **10.12.1, released 2025-10-15** + - Mattermost v10.12.1 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin [v2.2.2](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.2). + - Upgraded to go version 1.24.6. + - Mattermost v10.12.1 contains no database or functional changes. +- **10.12.0, released 2025-09-16** + - Original 10.12.0 release. + +```{Important} +If you upgrade from a release earlier than v10.10, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated minimum Edge and Chrome versions to 138+. + +### Improvements + +#### User Interface (UI) + - Improved screen reader readouts and accessibility of various autocomplete components. + +#### Administration + - Added an endpoint to check for upgradability. Also, a correct error message is now shown and the “Upgrade Server and Start trial” button is disabled if an upgrade is not possible. + +### Bug Fixes + - Fixed an issue where pasting a link when a text was selected didn't format the selected text as a Markdown link when editing the message. + - Fixed an issue where emoji picker items were being selected by pressing the space bar. + - Fixed a potential crash in ``UpdatePost``. + - Fixed 403 errors that occurred when loading custom profile attributes for unauthenticated users. + - Fixed an issue where the **Back** button was not showing on the desktop external login redirect page. + - Fixed an issue where unread messages from muted channels were shown in the favicon/desktop app. + - Fixed an issue where extra content was not accounted for in the focus order. + - Fixed an issue where search filters were not readable by screen readers when a search term had not been typed in before reading the number of results. + - Fixed an issue where the content of webhook posts did not display. + - Fixed an issue where the channel URL got updated when the channel display name was changed. + +### Go Version + - v10.12 is built with Go ``v1.24.6``. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [adityadav1987](https://github.com/adityadav1987), [agarciamontoro](https://github.com/agarciamontoro), [AhsanSarwar0413](https://github.com/AhsanSarwar0413), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [arush-vashishtha](https://github.com/arush-vashishtha), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [calebroseland](https://github.com/calebroseland), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [dgwhited](https://github.com/dgwhited), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [electronicmilk](https://translate.mattermost.com/user/electronicmilk), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henriquevmac](https://github.com/henriquevmac), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jgheithcock](https://github.com/jgheithcock), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://translate.mattermost.com/user/kaakaa), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [neflyte](https://github.com/neflyte), [nickmisasi](https://github.com/nickmisasi), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://translate.mattermost.com/user/Reinkard), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [stafot](https://github.com/stafot), [svelle](https://github.com/svelle), [tnir](https://github.com/tnir), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.11-extended-support-release)= +## Release v10.11 - [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **10.11.15, released 2026-04-22** + - Mattermost v10.11.15 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.13.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.13.0). + - Pre-packaged GitHub plugin version [v2.7.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.7.0). + - Pre-packaged Boards plugin [v9.2.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.4). + - Updated URL validation in integration actions to make them more secure. + - Improved response handling for outgoing webhook requests. + - Added support for Elasticsearch v9 alongside v8. + - Upgraded Go to 1.25.8. + - Mattermost v10.11.15 contains no database or functional changes. +- **10.11.14, released 2026-04-15** + - Mattermost v10.11.14 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin version [v1.11.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.4). + - Pre-packaged Playbooks plugin version [v2.4.4](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.4.4). + - Pre-packaged MS Teams Meetings plugin version [v2.4.1](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.4.1). + - Pre-packaged GitLab plugin version [v1.12.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.12.1). + - Fixed an issue where membership changes from remote clusters could operate on a different channel than the one validated in the sync message. + - Fixed an issue where image proxies did not detect content-types accurately in certain cases. + - Fixed an issue with edit post permissions. + - Fixed an issue with file attachment processing for certain archive types. + - Fixed an issue where remote cluster invite confirmations could accept a ``RefreshedToken`` that matched the original invite token, preventing proper token rotation. + - Fixed an issue with custom slash command response URL construction. + - Fixed typing issues in the **Find Channels** modal caused by interference with IMEs. + - Mattermost v10.11.14 contains no database or functional changes. +- **10.11.13, released 2026-03-16** + - Mattermost v10.11.13 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved security hardening for the user authentication update API endpoint. + - Improved token handling in the guest magic link authentication flow. + - Pre-packaged Calls plugin version [v1.11.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.1). + - Fixed an issue where the configuration wasn't kept when the plugin system was re-enabled. + - Mattermost v10.11.13 contains no database or functional changes. +- **10.11.12, released 2026-02-23** + - Mattermost v10.11.12 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.12.0). + - Pre-packaged Playbooks plugin version [v2.4.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.4.3). + - Fixed an issue with link preview metadata processing and image validation. + - Fixed an issue where rate limiting was missing from the login endpoint (5 requests/second, 10 burst). + - Mattermost v10.11.12 contains no database or functional changes. +- **10.11.11, released 2026-02-13** +```{Attention} +**Breaking Changes** + - Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments. +``` + - Mattermost v10.11.11 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.2.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.2). + - Fixed an issue where the channel URL got updated when the channel display name was changed. + - Added [audit logs](https://docs.mattermost.com/administration-guide/comply/embedded-json-audit-log-schema.html) for when admins access posts on channels they are not a member of. + - Fixed a performance regression that caused the requests to populate the **Recent mentions** right-hand side (RHS) to timeout. This, in turn, re-introduces a known bug in searches with quoted strings, that may include results not exactly matching the quoted string (reported on web and desktop clients and all server systems). + - Fixed an issue with PSD file previews. + - Added a new ``MM_LOG_PATH`` environment variable to restrict log file locations. Log files must now be within a configured root directory. + - Fixed an issue where the ``/mute`` slash command could be used to enumerate private channels. + - Fixed an issue with permalink preview information after losing channel or team permissions. + - User's actual authentication method is now validated before processing authentication type switch. + - Fixed an issue where users removed from a private team could still enumerate public channels in that team via the channel search API. + - Fixed an issue with permalink embeds arriving from websocket messages. + - Fixed a memory allocation issue by updating ``mscfb`` and ``msoleps`` dependencies. + - ``/api/v4/access_control_policies/{policy_id}/activate`` has been deprecated. + - Fixed an issue with memory use during integration actions. + - Updated the POST `/api/v4/teams` team creation API to omit the `invite_id` value in the response when the requesting user does not have permission to invite members to the new team. + - ``ImportSettings.Directory`` can no longer be modified through the REST API. Infrastructure operators can still modify this setting via configuration file, environment variables, or mmctl in local mode. + - Fixed a permission validation issue when attaching files to posts. + - Mattermost v10.11.11 contains no database or functional changes. +- **10.11.10, released 2026-01-15** + - Mattermost v10.11.10 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a server panic that occurred when a bot created a post with persistent notifications enabled. + - Pre-packaged Zoom plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.11.0). + - Pre-packaged Jira plugin version [v4.5.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.5.0). + - Mattermost v10.11.10 contains no database or functional changes. +- **10.11.9, released 2025-12-17** + - Mattermost v10.11.9 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where pressing ``Shift+Up`` in the channel textbox to reply to a thread could cause the right‑hand sidebar (RHS) reply textbox to not focus. + - Mattermost v10.11.9 contains no database or functional changes. +- **10.11.8, released 2025-11-21** + ```{Attention} + **Critical Fixes** + - Mattermost v10.11.8 contains a Critical severity level security fix in the Jira plugin. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Jira plugin version [v4.4.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.1). + - Mattermost v10.11.8 contains no database or functional changes. +- **10.11.7, released 2025-11-17** + - Mattermost v10.11.7 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams Meetings plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.3.0). + - Pre-packaged Calls plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.0). + - Pre-packaged Agents plugin version [v1.4.0](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.4.0). + - Pre-packaged GitHub plugin version [v2.5.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.5.0). + - Mattermost v10.11.7 contains no database or functional changes. +- **10.11.6, released 2025-11-04** + - Fixed an issue where guest users could not log in via SAML when "Ignore Guest Users when Synchronizing with AD/LDAP" was enabled. + - Fixed a configuration retention issue where even active configurations got deleted. + - Pre-packaged MS Teams Meeting plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.3.0). + - Mattermost v10.11.6 contains no database or functional changes. +- **10.11.5, released 2025-10-28** + ```{Attention} + **Critical Fixes** + - Mattermost v10.11.5 contains Critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Boards plugin [v9.1.7](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.7). + - Mattermost v10.11.5 contains no database or functional changes. +- **10.11.4, released 2025-10-15** + - Mattermost v10.11.4 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin [v2.2.2](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.2). + - Upgraded to go version 1.24.6. + - Fixed an issue with the mmctl system status to return non-zero exit codes when health checks fail, ensuring proper integration with container orchestration health check systems. + - Mattermost v10.11.4 contains no database or functional changes. +- **10.11.3, released 2025-09-16** + - Mattermost v10.11.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where unread messages from muted channels were shown in the favicon/desktop app. + - Mattermost v10.11.3 contains no database or functional changes. +- **10.11.2, released 2025-08-22** + - Mattermost v10.11.2 contains high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where the content of webhook posts did not display. + - Mattermost v10.11.2 contains no database or functional changes. +- **10.11.1, released 2025-08-15** + - Fixed an issue with login being kept in a web view instead of redirecting to the mobile app when using OAuth for login (reported on iOS and Android). + - Upgraded to go1.24.5, and reverted to bullseye to maintain glibc <2.34 compatibility for older deployment environments. + - Mattermost v10.11.1 contains no database or functional changes. +- **10.11.0, released 2025-08-15** + - Original 10.11.0 release. + +```{Important} +If you upgrade from a release earlier than v10.10, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). +``` + +### Highlights + - Enabled **System Console** user interface for ``AuditSettings`` by default. + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.10.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.10.0). + - Pre-packaged Boards plugin [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Pre-packaged Playbooks plugin [v2.3.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.3.0). + - Improved the date and time picker usability across **Custom Status**, **Scheduled Messages**, **Do Not Disturb**, and **Reminder** modals. The entire input area is now clickable, keyboard navigation works properly in time selection menus, and consistent relative date formatting is used throughout. + - Improved the **Permissions** table expand/collapse animation and prevented text from overflowing. + - Added an aria-label to the file preview back/forward buttons. + - Modified the input to have the minimum/maximum length validation work the same as the validation around ``required``, and replaced **Create Team** input with an **Input** component. + - Improved the YouTube video preview user interface. + - Removed the minimum-width for the right-hand side when the window size is <400px. + - Added a status region for the channel filter dropdown in the **Browse Channels** modal. + - Removed the NPS plugin from pre-packaged plugins. + +#### Administration + - Signatures are now always validated for pre-packaged plugins. + - Disabled the **Add a license** button when the license is set by an environment variable. + - Improved database connection spikes on user disconnect by processing status updates in batches. + - Improved the efficiency of getting sidebar categories from the database. + - Added a database schema dump to the Support Packet. + +#### mmctl Changes + - Added ``AuthData`` to mmctl user search output. + - mmctl: Added ``compliance export list`` command. + - mmctl: Added ``compliance export show`` and ``cancel`` commands. + - mmctl: Added ``compliance export download`` command. + - mmctl: Added ``compliance export create`` command. + +### Bug Fixes + - Fixed an issue with the onboarding checklist being cut off when on multiple teams. + - Fixed an issue where the **Thread Menu** would not have its actions read by a screen reader. + - Fixed an issue where some users would not get a warning when joining a private channel. + - Fixed an issue with the overflow formatting on the suggestion list. + - Fixed an issue with the **Delete** button aria-label on **User Groups** list modal. + - Fixed some semantic HTML issues with the use of ``header``. + - Fixed various accessibility issues for the **Create Channel** modal. + - Fixed more accessibility issues around search. + - Fixed **Create User Group** modal accessibility issues. + - Fixed mobile view accessibility issues. + - Fixed an issue with accents. + - Fixed an issue with rendering of remote user at-mentions in the web app. + - Fixed a potential panic when running the ``mmctl ldap job show`` without the required argument. + - Fixed an issue in the LDAP sync, such that users with an updated attribute were being accidentally added to the groups of another LDAP record, if that LDAP record had a blank ID. + - Fixed an issue with the ``in:`` filter not showing an autocomplete on small screens. + - Fixed an issue with the color of borders in **Browse Channels** and **Direct Message** modals. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``DeleteAccountLink`` configuration setting to add a configurable account deletion link. + - Under ``ClusterSettings`` in ``config.json``: + - Added ``EnableGossipEncryption`` to replace ``EnableExperimentalGossipEncryption`` to transition Gossip Encryption functionality to Generally Available. For new installations, the setting will now default to ``on``. Any existing values will still be preserved. + +#### Changes to Professional and Enterprise plans: + - Added a ``ContentFlaggingSettings`` configuration section. + +#### Changes to Enterprise Advanced plan: + - Under ``NativeAppSettings`` in ``config.json``: + - Added two new configuration settings ``MobileEnableSecureFilePreview`` and ``MobileAllowPdfLinkNavigation`` available on Enterprise Advanced to further lock down files on mobile. + - Under ``AccessControlSettings`` in ``config.json``: + - Added ``EnableUserManagedAttributes`` configuration setting to allow using user-editable attributes. These attributes are not allowed by default. + +### API Changes + - Introduced new Plugin APIs to support audit logging. + - Updated the patch channel API doc to include channel banners. + +### Go Version + - v10.11 is built with Go ``v1.24.6``. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akeiss](https://translate.mattermost.com/user/akeiss), [alexis](https://translate.mattermost.com/user/alexis), [alirezaalavi87](https://github.com/alirezaalavi87), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Arusekk](https://github.com/Arusekk), [asaadmahmood](https://github.com/asaadmahmood), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyrusjc](https://github.com/cyrusjc), [danielsischy](https://github.com/danielsischy), [danilvalov](https://github.com/danilvalov), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jesperfj](https://translate.mattermost.com/user/jesperfj), [jgheithcock](https://github.com/jgheithcock), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [luca.palomba](https://translate.mattermost.com/user/luca.palomba), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [neflyte](https://github.com/neflyte), [neil-karania](https://github.com/neil-karania), [nickmisasi](https://github.com/nickmisasi), [panoramix360](https://github.com/panoramix360), [pineoak-audio](https://github.com/pineoak-audio), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [roberson-io](https://github.com/roberson-io), [rohithchandran-mattermost](https://github.com/rohithchandran-mattermost), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [rtfm98](https://github.com/rtfm98), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [ThrRip](https://github.com/ThrRip), [tnir](https://translate.mattermost.com/user/tnir), [toffguy77](https://github.com/toffguy77), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.10-feature-release)= +## Release v10.10 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.10.3, released 2025-09-16** + - Mattermost v10.10.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.10.3 contains no database or functional changes. +- **10.10.2, released 2025-08-14** + - Mattermost v10.10.2 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Fixed an issue with the onboarding checklist being cut off when on multiple teams. + - Upgraded to go1.24.5, and reverted to bullseye to maintain glibc <2.34 compatibility for older deployment environments. + - Mattermost v10.10.2 contains no database or functional changes. +- **10.10.1, released 2025-07-16** + - Mattermost v10.10.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.10.1 contains no database or functional changes. +- **10.10.0, released 2025-07-16** + - Original 10.10.0 release. + +### Important Upgrade Notes + - Added a new column ``DefaultCategoryName`` to the ``Channels`` table. This is nullable and stores a category name to be added/created when new users join a channel. This is only used if the ``ExperimentalChannelCategorySetting`` is enabled. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Added new columns ``RemoteId`` and ``ChannelId`` to the ``PostAcknowledgements`` table. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Added a new column ``LastMembersSyncAt`` to the ``SharedChannelRemotes`` table and added ``LastMembershipSyncAt`` to ``SharedChannelUsers``. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Added a new column ``LastGlobalUserSyncAt`` to the ``RemoteClusters`` table. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +```{Important} +If you upgrade from a release earlier than v10.9, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.9.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.9.1). + - Pre-packaged GitLab plugin [v1.10.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.10.0). + - Pre-packaged GitHub plugin [v2.4.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.4.0). + - Pre-packaged Boards plugin [v9.1.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.4). + - Pre-packaged Agents plugin [v1.2.4](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.2.4). + - Resolved inconsistent styling issues in new integration pages. + - Improved the visual styling of blockquotes and comment threads for better readability and a modern appearance. + - Improved screen reader support for autocompletes and channel switcher. + - Added an aria-live region for improved accessibility of file preview modal carousel position updates. + - Add focusability to react-select remove button in notifications settings. + - Updated **Profile** settings client-side validation to use more modern/accessible paradigms. + - Enhanced the accessibility of login and password reset functionality. + - Stopped the Threads textbox from automatically taking focus when it contained a draft. + - Added a display setting for users to toggle rendering of emoticons (e.g., :D) as emojis (e.g., 😄). + - Added support for the ``from:`` search filter in cross-team searches. + - Standardized button styling by consolidating color variables and removing redundant theme definitions. + - Ignored email domain in user searches on the client side. + - Automatically detected and updated timezone changes without requiring a client refresh. + +#### Administration + - Connected Workspaces has been promoted from Beta to General Availability. Formally known as Shared Channels. + - Added support for group messages in Connected Workspaces. + - Hid plugin components in Connected Workspaces and introduced ``EnableSharedChannelsPlugins`` to re-enable them if needed. + - Added new feature flags (default off) ``EnableSharedChannelsMemberSync`` and ``EnableSyncAllUsersForRemoteCluster`` for Connected Workspaces. + - Added an LDAP Wizard with various enhancements, including a **Test Group Attributes** button for feedback on matching group attributes, a **Test Connection** button with improved error reporting, a **Test Attributes** button showing attribute success and matching user count, a **Test Filters** button with failure feedback, an expandable **User Filters** section with "More info" hover texts, and a help text explaining the possible delay when running tests on large LDAP servers. + - Added support for [licenses that enforce seat counts](https://docs.mattermost.com/administration-guide/manage/admin/error-codes.html#error-licensed-users-limit-exceeded) with a configurable ``ExtraUsers`` field for exact control over allowed overages. + - Organized cluster files into directories for the Support Packet. + - Partially sanitized database datasources for the Support Packet. + - Added deactivation status to the mmctl user search output. + +#### Performance + - Improved memory performance of post list scrolling. + - Improved the performance of sidebar update APIs slightly. + +### Bug Fixes + - Fixed an issue where a ``MESSAGES`` badge appeared in the search bar after clearing text and closing the search box. + - Fixed an issue where overridden webhook usernames did not appear in replies when Threaded Discussions were disabled. + - Fixed indentation issues in Markdown lists containing checkboxes. + - Fixed desktop notifications for posts without text content to display "posted a message" instead of "did something new". + - Fixed the height of the automatic replies text area to align with proper dimensions. + - Fixed various accessibility issues in the User Groups modals. + - Fixed accessibility issues in Profile Settings to enhance usability. + - Fixed dialog dropdowns to ensure they were not cut off visually. + - Fixed an issue where deactivated users still maintained their previous status. + - Fixed an issue with plugin dialogs triggering errors upon submission. + - Fixed the version number of Support Packet v2. + - Fixed an issue with MIME type detection for video files (e.g., MP4, MOV, AVI, WEBM, WMV, MKV, MPG/MPEG) uploaded to S3 storage, enabling inline video playback in browsers. + - Fixed Support Packet caching issues. + - Fixed the **Threads** textbox changing width when a message was typed on certain screens. + - Fixed an issue with log messages including blank "user_id" field when request session was not valid or had a blank user_id. + - Fixed an issue where the emoji picker focus did not return to button when not selecting an emoji. + - Fixed the label in notification settings for the notification sound combo box. + - Fixed an issue where an incorrect username and email were shown for remote users. + - Fixed an issue with the keyboard navigation in the user settings sidebar (reported on Firefox / macOS). + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``ExperimentalChannelCategorySorting`` configuration setting to add the ability to automatically sort channels into categories upon creation/renaming. + +#### Changes to Enterprise plan: + - Under ``DataRetentionSettings`` in ``config.json``: + - Added ``PreservePinnedPosts`` configuration setting. If it's set to ``true``, pinned posts will not be deleted by data retention. + +#### Changes to Enterprise Advanced plan: + - Under ``ConnectedWorkspacesSettings`` in ``config.json``: + - Added ``MemberSyncBatchSize``, ``SyncUsersOnConnectionOpen``, ``GlobalUserSyncBatchSize`` configuration settings to allow remote users to be discoverable in the Direct/Group Message modal. + +### API Changes + - Added property fields and value methods to the plugin API. + - Improved the semantics of Groups API errors when invalid parameters were specified. + +### Open Source Components + - Added ``mholt/archives`` and removed ``code.sajari.com/docconv`` from https://github.com/mattermost/mattermost. + +### Go Version + - v10.10 is built with Go ``v1.24.3``. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [Akhilbisht798](https://github.com/Akhilbisht798), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [AulakhHarsh](https://github.com/AulakhHarsh), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [Carloswaldo](https://translate.mattermost.com/user/Carloswaldo), [catalintomai](https://github.com/catalintomai), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [Ekaterine](https://translate.mattermost.com/user/Ekaterine), [EkaterinePapava](https://github.com/EkaterinePapava), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [equalsgibson](https://github.com/equalsgibson), [esarafianou](https://github.com/esarafianou), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [iamleson98](https://github.com/iamleson98), [irdi-cloud68](https://translate.mattermost.com/user/irdi-cloud68), [isacikgoz](https://github.com/isacikgoz), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kasyap1234](https://github.com/kasyap1234), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [ldez](https://github.com/ldez), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [neil-karania](https://github.com/neil-karania), [nickmisasi](https://github.com/nickmisasi), [panoramix360](https://github.com/panoramix360), [polinapianina](https://github.com/polinapianina), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [spirosoik](https://github.com/spirosoik), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [uday-rana](https://github.com/uday-rana), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.9-feature-release)= +## Release v10.9 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.9.5, released 2025-08-15** + - Mattermost v10.9.5 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.9.5 contains no database or functional changes. +- **10.9.4, released 2025-07-22** + - Mattermost v10.9.4 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Mattermost v10.9.4 contains no database or functional changes. +- **10.9.3, released 2025-07-08** + - Mattermost v10.9.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.4). + - Fixed an issue with the keyboard navigation in the user settings sidebar. + - Mattermost v10.9.3 contains no database or functional changes. +- **10.9.2, released 2025-06-19** + - Mattermost v10.9.2 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.9.2 contains no database or functional changes. +- **10.9.1, released 2025-06-17** + - Mattermost v10.9.1 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where Direct/Group Messages were missing on initial load. + - Pre-packaged Boards plugin version [v9.1.3](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.3). + - Mattermost v10.9.1 contains no database or functional changes. +- **10.9.0, released 2025-06-16** + - Original 10.9.0 release. + +### Compatibility + - Updated the minimum supported versions of Edge and Chrome to 134+, and Firefox to 128+. + +### Important Upgrade Notes + - A new index to the ``CategoryId`` column in ``SidebarChannels`` table was added to improve query performance. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Schema changes in the form of a new materialized view (``AttributeView``) was added that aggregates user attributes into a separate table. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - When ``SamlSettings.EnableSyncWithLdap`` is enabled, Mattermost will now check if a user exists on the connected LDAP server during login. If the user doesn't exist on the LDAP server, login will fail. Previously, users not present on the LDAP server could login, but would be deactivated on the next LDAP sync. + +```{Important} +If you upgrade from a release earlier than v10.8, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### New Enterprise Advanced License + - Added support for a new Enterprise Advanced license. This new license is supported starting v10.9 and is supported on PostgreSQL only. Enterprise plugins need to be updated to support the new license (most of which are pre-packaged in v10.9). + +### Improvements + +#### User Interface (UI) + - Consolidated all channel editing functionality into a single, accessible modal located in the channel header menu. Users can now update channel names, URL slugs, convert to private, modify/add a purpose and header (with a live markdown preview), manage channel banners, and archive the channel—all in one place. Updates include safeguards for unsaved edits, improved URL-slug editing, and enhanced keyboard and navigation accessibility. + - Pre-packaged MS Teams plugin [v2.2.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.1). + - Pre-packaged Playbooks plugin [v2.2.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.2.0) and [v1.41.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.1). + - Pre-packaged Calls plugin [v1.8.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.8.0). + - Pre-packaged Jira plugin version [v4.3.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.3.0). + - Pre-packaged Metrics plugin version [v0.7.0](https://github.com/mattermost/mattermost-plugin-metrics/releases/tag/v0.7.0). + - Introduced a configurable [channel banner feature](https://docs.mattermost.com/end-user-guide/collaborate/display-channel-banners.html) for channel admins, visible across desktop, web, and mobile platforms. This feature requires an Enterprise Advanced license. + - Added more descriptive page titles to the login, account creation, and password reset pages. + - Improved the **Drafts** list by implementing virtualization. + - Enhanced the behavior for reporting issues in the platform. + - Introduced minor layout tweaks in theme settings for improved usability. + +#### Administration + - Added support for user attributes for Enterprise Advanced licensed servers. Defined policies that automatically grant channel memberships based on user attributes. Membership updates happen automatically when user attributes change — no need for manual role adjustments. + - Added Policy Management user interface and API to easily create and manage attribute-based rules via an admin interface. + - Added support for AES-256-GCM encryption in SAML. + - Updated the email validation logic to ensure Mattermost no longer accepts email addresses enclosed in angle brackets (e.g., ``[billy@example.com](mailto:billy@example.com)``). Although these comply with RFC 5322 and RFC 6532 standards, they introduce unnecessary complexity. If a user already has such an email in your installation, they may face issues like being unable to update their profile. To resolve this, the email must be modified manually using the command: ``mmctl user email "[affecteduser@domain.com](mailto:affecteduser@domain.com)" affecteduser@domain.com``. + - Added a license load metric to the **About** screen to display current license usage. + - Upgraded the logr dependency to version 2.0.22. + - Removed telemetry tracking from Redux selectors. + - Made it possible to [view JSON logs in plain text](https://docs.mattermost.com/administration-guide/configure/reporting-configuration-settings.html#server-logs) within the **System Console**. + - Enhanced the **System Console** search functionality to include all log fields. + - Enhanced error reporting related to cluster management. + - Added an LDAP setting to re-add removed members. + - Added support for SSO while Mattermost is embedded in an iframe. + - Set the Custom Profile Attributes feature flag to ``true`` by default. + +#### Performance + - Optimized the team-switching operation by eliminating unnecessary calls to retrieve channels and channel members. + - Improved websocket re-opening speed when network conditions change. + +### Bug Fixes + - Fixed various issues on the **Create Team** screen. + - Fixed several accessibility issues across the login process, account creation, and MFA setup. + - Fixed an issue where horizontal rule (HR) elements were not visible in preview mode in the right-hand sidebar (RHS). + - Fixed an issue with inconsistent sizing of markdown images in preview mode. + - Fixed a keyboard navigation issue within thread items (reported on Firefox / macOS). + - Fixed layout issues with the emoji picker on mobile browsers. + - Fixed an issue with the positioning of **Edited** text and tooltips in certain scenarios. + - Fixed the accessibility of the search box. + - Fixed an issue where post list scrolling didn’t work when pressing the **Page Up** or **Page Down** keys. + - Fixed issues with screen reader support in the **Threads** view. + - Fixed keyboard navigation issues in the **Threads** view. + - Fixed accessibility issues in the **Invite** modal. + - Fixed various accessibility issues in the **Browse Channels** modal. + - Fixed an issue that prevented team admin permissions from being modified when missing in the **All Members** section. + - Fixed possible deadlocks when updating ``SidebarCategories`` and ``SidebarChannels`` tables. + - Fixed an issue where unreads from deleted teams would display in the titlebar/Desktop App. + - Fixed an issue with ``icon_emoji`` property not working for webhook posts. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``SupportSettings`` in ``config.json``: + - Added ``ReportAProblemType``, ``ReportAProblemMail``, ``AllowDownloadLogs`` configuration settings to enhance the behavior for reporting issues in the platform. + +#### Changes to Enterprise plans: + - Under ``ExperimentalAuditSettings`` in ``config.json``: + - Added ``Certificate`` configuration setting to accept a certificate to be used for audit logging egress. + - Under ``LdapSettings`` in ``config.json``: + - Added ``ReAddRemovedMembers`` configuration setting to add a LDAP setting to re-add removed members. + +### API Changes + - Exposed two new plugin APIs for syncables. + +### Open Source Components + - Added ``monaco-editor`` and ``monaco-editor-webpack-plugin``, and removed ``dynamic-virtualized-list``, ``popper.js``, ``react-hot-loader``, ``react-popper`` from https://github.com/mattermost/mattermost. + +### Go Version + - v10.9 is built with Go ``v1.23.7``. + +### Known Issues + - Permissions lists exceed content area for **All Members** and **System Admins** in the System Console. + - Setting the license file location through an environment variable still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the environment variable. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [AnmiTaliDev](https://translate.mattermost.com/user/AnmiTaliDev), [Aryakoste](https://github.com/Aryakoste), [AshishDhama](https://github.com/AshishDhama), [AulakhHarsh](https://github.com/AulakhHarsh), [BenCookie95](https://github.com/BenCookie95), [bndn](https://translate.mattermost.com/user/bndn), [bshumylo](https://github.com/bshumylo), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chicchu4157](https://translate.mattermost.com/user/chicchu4157), [cinlloc](https://github.com/cinlloc), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyrusjc](https://github.com/cyrusjc), [danilvalov](https://github.com/danilvalov), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [evituzas](https://translate.mattermost.com/user/evituzas), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [gentcod](https://github.com/gentcod), [Gesare5](https://github.com/Gesare5), [guenjun](https://translate.mattermost.com/user/guenjun), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [iyampaul](https://github.com/iyampaul), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [joho1968](https://github.com/joho1968), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kasyap1234](https://github.com/kasyap1234), [kayazeren](https://translate.mattermost.com/user/kayazeren), [Kimbohlovette](https://github.com/Kimbohlovette), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [ldez](https://github.com/ldez), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [marcelhintermann](https://github.com/marcelhintermann), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [nickmisasi](https://github.com/nickmisasi), [oonid](https://translate.mattermost.com/user/oonid), [panoramix360](https://github.com/panoramix360), [pineoak-audio](https://github.com/pineoak-audio), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [Theo024](https://github.com/Theo024), [ThrRip](https://github.com/ThrRip), [toninis](https://github.com/toninis), [Vasfed](https://github.com/Vasfed), [vasilybels](https://github.com/vasilybels), [VDALuky](https://github.com/VDALuky), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.8-feature-release)= +## Release v10.8 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.8.4, released 2025-07-22** + - Mattermost v10.8.4 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Mattermost v10.8.4 contains no database or functional changes. +- **10.8.3, released 2025-06-18** + - Mattermost v10.8.3 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v1.41.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.1). + - Pre-packaged Boards plugin version [v9.1.3](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.3). + - Fixed an issue where the ``icon_emoji`` property was not working for webhook posts. + - Added support for SSO while Mattermost is embedded in an iframe. + - Mattermost v10.8.3 contains no database or functional changes. +- **10.8.2, released 2025-05-29** + - Mattermost v10.8.2 contains high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin [v2.2.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.1). + - Mattermost v10.8.2 contains no database or functional changes. +- **10.8.1, released 2025-05-21** + - Mattermost v10.8.1 contains a Critical severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v2.2.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.2.0). + - Fixed an issue where Team Admin permissions couldn't be changed if they were missing in **All members** section. + - Updated ``golang.org/x/net`` version to v0.39.0. + - Mattermost v10.8.1 contains no database or functional changes. +- **10.8.0, released 2025-05-16** + - Original 10.8.0 release. + +### Important Upgrade Notes + - New tables ``AccessControlPolicies`` and ``AccessControlPolicyHistory`` will be created. The migration is fully backwards-compatible, non-locking, and zero downtime is expected. + - Support for legacy SKUs E10 and E20 licenses was removed. If you need assistance, [talk to a Mattermost expert](https://mattermost.com/contact-sales/). + +```{Important} +If you upgrade from a release earlier than v10.7, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin version [v1.7.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.7.1). + - Pre-packaged Metrics plugin version [v0.6.0](https://github.com/mattermost/mattermost-plugin-metrics/releases/tag/v0.6.0). + - Added an improved channel menu. + - Updated email notification settings to provide clearer wording and descriptions for both batched and non-batched scenarios. The settings dialog now reflects the selected status more accurately in both collapsed and expanded views, enhancing consistency and usability. + - Added the ability to [display the nickname or full name](https://docs.mattermost.com/end-user-guide/preferences/manage-your-profile.html) in Threads based on settings. + - Improved the error message for failed file copies. + +#### Administration + - Added Custom Profile Attribute field type, visibility, and related options in **System Console -> System Properties**. + - Added support for LDAP/SAML sync with Custom Profile Attributes (disabled behind a feature flag). + - Stopped building and packaging Windows and MacOS releases. + - ``EnableLocalMode`` is now automatically enabled during development. + - Log messages are now added if post props are invalid. + - Stopped logging websocket PING events received by the server. + - Errors from Support Packet generation are now shown in the **System Console**. + - Added a client-side ping to the websocket to detect broken connections more quickly. + - Removed the feature flag and added a ``EnableCrossTeamSearch`` configuration option for cross-team search feature. + +### Bug Fixes + - Fixed ``GET /groups endpoint`` documentation. + - Fixed an issue with group mentions overlay and details after an update. + - Fixed an issue with showing local hours on bot users. + - Fixed an issue where replies appeared as part of the wrong thread when Collapsed Reply Threads were disabled. + - Fixed an issue with keyboard input not working on new menus when the menu was opened using the mouse. + - Fixed an issue with keyboard navigation with the channel switcher. + - Fixed an issue with link previews when using angle brackets for autolinking. + - Fixed an issue where **Recent Mentions** showed incorrect results for custom notification keywords containing hyphens. + - Fixed an issue where there were invalid restrictions on local mode administration (e.g. via mmctl). + - Fixed an issue where users were not able to escape emoticon formatting by prefixing with a backslash. + - Fixed an issue with post links trapping focus when hovered or focused using the keyboard. + - Fixed an issue where plugins were disabled when Mattermost was embedded. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Enterprise plans: + - Under ``AccessControlSettings`` in ``config.json``: + - Added ``EnableAttributeBasedAccessControl`` and ``EnableChannelScopeAccessControl`` configuration settings. + - Under ``ServiceSettings`` in ``config.json``: + - Added a ``EnableCrossTeamSearch`` configuration option for cross-team search feature. + - Under ``ElasticsearchSettings`` in ``config.json``: + - Added a new configuration setting ``GlobalSearchPrefix`` which can be used to search across multiple indices having a common prefix. This is useful in a scenario with multiple Elasticsearch instances, where multiple instances are writing to different indices with different prefixes using the ``ElasticsearchSettings.IndexPrefix`` setting. + +### API Changes + - Added a new API endpoint to retrieve the Custom Profile Attributes group data. + +### Open Source Components + - Added ``bep/imagemeta`` and removed ``rwcarlsen/goexif`` from https://github.com/mattermost/mattermost. + +### Go Version + - v10.8 is built with Go ``v1.23.7``. + +### Known Issues + - The ``icon_emoji`` property does not work for webhook posts. + - Setting the license file location through an environment variable still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the environment variable. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + +### Contributors + - [aboukhal](https://github.com/aboukhal), [acc0mplish-note](https://translate.mattermost.com/user/acc0mplish-note), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Arusekk](https://translate.mattermost.com/user/Arusekk), [Aryakoste](https://github.com/Aryakoste), [AshiishKarhade](https://github.com/AshiishKarhade), [AulakhHarsh](https://github.com/AulakhHarsh), [BenCookie95](https://github.com/BenCookie95), [bndn](https://github.com/bndn), [bshumylo](https://github.com/bshumylo), [burakcakirel](https://github.com/burakcakirel), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [DSchalla](https://github.com/DSchalla), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [errotu](https://github.com/errotu), [esarafianou](https://github.com/esarafianou), [evituzas](https://translate.mattermost.com/user/evituzas), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jadrales](https://github.com/jadrales), [JahleelT](https://github.com/JahleelT), [jasonblais](https://github.com/jasonblais), [jeoooo](https://github.com/jeoooo), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kasyap1234](https://github.com/kasyap1234), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lil5](https://github.com/lil5), [lucasvbeek](https://github.com/lucasvbeek), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [mariuskarotkis](https://translate.mattermost.com/user/mariuskarotkis), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [melroy89](https://github.com/melroy89), [mgdelacroix](https://github.com/mgdelacroix), [mlcuchlu](https://translate.mattermost.com/user/mlcuchlu), [nickmisasi](https://github.com/nickmisasi), [panoramix360](https://github.com/panoramix360), [polinapianina](https://github.com/polinapianina), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [Ricky-Tigg](https://github.com/Ricky-Tigg), [Roy-Orbison](https://github.com/Roy-Orbison), [sadohert](https://github.com/sadohert), [saket-dev01](https://github.com/saket-dev01), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [spirosoik](https://github.com/spirosoik), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [surya2611](https://github.com/surya2611), [ThrRip](https://github.com/ThrRip), [timstott](https://github.com/timstott), [tnir](https://translate.mattermost.com/user/tnir), [toninis](https://github.com/toninis), [vasilybels](https://translate.mattermost.com/user/vasilybels), [ViKriuVK](https://translate.mattermost.com/user/ViKriuVK), [vish9812](https://github.com/vish9812), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.7-feature-release)= +## Release v10.7 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.7.4, released 2025-06-18** + - Mattermost v10.7.4 contains high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin [v2.2.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.1). + - Pre-packaged Playbooks plugin [v1.41.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.1). + - Pre-packaged Boards plugin version [v9.1.3](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.3). + - Added support for SSO while Mattermost is embedded in an iframe. + - Mattermost v10.7.4 contains no database or functional changes. +- **10.7.3, released 2025-05-21** + - Mattermost v10.7.3 contains a Critical severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v2.2.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.2.0). + - Fixed an issue where Team Admin permissions couldn't be changed if they were missing in **All members** section. + - Mattermost v10.7.3 contains no database or functional changes. +- **10.7.2, released 2025-05-12** + - Mattermost v10.7.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.7.2 contains no database or functional changes. +- **10.7.1, released 2025-04-29** + - Mattermost v10.7.1 contains a low severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where plugins were disabled when Mattermost was embedded. + - Fixed an issue with post links trapping focus when hovered or focused using the keyboard. + - Stopped logging websocket PING events received by the server. + - Mattermost v10.7.1 contains no database or functional changes. +- **10.7.0, released 2025-04-16** + - Original 10.7.0 release. + +### Compatibility + - Updated minimum Edge and Chrome versions to 132+. + +### Important Upgrade Notes + - Added a new column ``BannerInfo`` in the ``Channels`` table for storing metadata for an upcoming licensed feature. + - Added support for cursor-based pagination on the property architecture tables, including SQL migration to create indices. + +```{Important} +If you upgrade from a release earlier than v10.6, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin version [v1.6.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.6.0). + - Webapp plugin loading and footer are now disabled if ``MMEMBED`` cookie is set. + - Updated the ``marked`` package which includes full-width punctuation intervals for Unicode characters fix. + - Added a minor change in the message priority checkbox menu item; the description width is now smaller than in previous versions. + - Updated the library used for controlling and positioning the emoji picker. + - Added a browser window title to the **Scheduled Posts** tab. The title is **Scheduled - <team name>**, using the same pattern as the **Drafts** tab. + +#### Administration + - Added a new System Console page called **Embedding** which allows frame ancestor domains to be specified when embedding Mattermost in other web sites. Note, ``teams.microsoft.com`` is no longer added automatically to the frame ancestors list. + - The Channel Export plugin is removed from the transitional package list as it is now pre-packaged. + - Removed unnecessary log messages by checking the license before calling to retrieve groups. + - Made configuration location in the Support Packet human-readable. + - Added advanced audit and notifications logs to the Support Packet. + - Added log information to LDAP sync about ``include_removed_members`` option. + - Upgraded ``react-select`` from v3.0.3 to v5.9.0. + +### Bug Fixes + - Fixed an issue with the alignment of the draft list when scheduled posts are disabled. + - Fixed an issue where threads created by users were auto-followed on reply by the creator when they left the channel. + - Fixed an issue where muted channels in other teams would show their mentions in the title bar. + - Fixed an issue where messages from new channels in other teams wouldn't show up until a refresh. + - Fixed an issue with the scrolling behavior when navigating the Direct Message list using UP/DOWN arrow keys. + - Fixed a few minor bugs with websocket reconnection logic in the webapp. + - Fixed an issue where DND statuses did not expire at the expiry time displayed in the app. + - Fixed an issue where the group mentions permission was missing. + - Fixed an issue where a system bot reply to a command entered in a thread was also posted in the channel. + - Fixed an issue where the channel member menu could open in the wrong direction. + - Fixed an issue where the edit post textbox sized incorrectly with the Grammarly browser extension installed. + - Fixed an issue where onclick was missing in the channel header text, thus enabling hashtag, link, and mention clicks. + - Fixed an issue with jobs in a High Availability environment, where two job servers would take the same job. + - Fixed an issue where there was inconsistent behaviour on removing non-group members from group synced teams and channels. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``MetricsSettings`` in ``config.json``: + - Added ``ClientSideUserIds`` where users can set the user IDs that they want to track for client-side webapp metrics. The total number of userIDs have been capped to 5 for performance reasons, otherwise Prometheus gets overwhelmed with high label cardinality. We recommend modifying this list infrequently to ensure Prometheus performance. + - Under ``CacheSettings`` in ``config.json``: + - Added ``RedisCachePrefix`` has been added which can be used to add a prefix to all Redis cache keys. + - Under ``ServiceSettings`` in ``config.json``: + - Added a new configuration setting ``FrameAncestors`` to allow frame ancestor domains to be specified when embedding Mattermost in other web sites. + +#### Changes to Enterprise plans: + - Under ``NativeAppSettings`` in ``config.json``: + - Added new settings to enable mobile biometric authentication prompt, jailbreak / root detection and to prevent screen captures. The settings are: ``MobileEnableBiometrics`` (default: false), ``MobilePreventScreenCapture`` (default: false), ``MobileJailbreakProtection`` (default: false). + - Added a new configuration setting ``LdapSettingsDefaultMaximumLoginAttempts``. + +### API Changes + - Added new ``pluginapi`` methods for managing groups, a new group source type called GroupSourcePluginPrefix and added a new URL parameter called include_syncable_sources to GET /api/v4/groups. + - Added ``Client4.createPostEphemeral`` method. + +### Websocket Event Changes + - Added Custom Profile Attributes websocket support. + - Added websocket messages to the Custom Profile Attributes operations. + +### Go Version + - v10.7 is built with Go ``v1.22.6``. + +### Known Issues + - Tooltip and highlight of icon for sidebar expansion appear after pressing **Enter** on a search. + - Shortcut keys to open the right-hand side from the last post in a channel are causing blue borders to be shown in the right-hand side header. + - Setting the license file location through an environment variable still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the environment variable. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [AlexKalopsia](https://github.com/AlexKalopsia), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anlerandy](https://github.com/anlerandy), [Aryakoste](https://github.com/Aryakoste), [AulakhHarsh](https://github.com/AulakhHarsh), [ayush-chauhan233](https://github.com/ayush-chauhan233), [BenCookie95](https://github.com/BenCookie95), [bndn](https://github.com/bndn), [Boruus](https://github.com/Boruus), [bshumylo](https://github.com/bshumylo), [calebroseland](https://github.com/calebroseland), [capricorni](https://translate.mattermost.com/user/capricorni), [Carloswaldo](https://github.com/Carloswaldo), [CBID2](https://github.com/CBID2), [cfarrell987](https://github.com/cfarrell987), [cinlloc](https://github.com/cinlloc), [Combs7th](https://github.com/Combs7th), [cpoile](https://github.com/cpoile), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), +[cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [DeathCamel58](https://github.com/DeathCamel58), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [Dschoordsch](https://github.com/Dschoordsch), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [equalsgibson](https://github.com/equalsgibson), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [felixerdy](https://github.com/felixerdy), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henrique](https://translate.mattermost.com/user/henrique), [hmhealey](https://github.com/hmhealey), [hpflatorre](https://github.com/hpflatorre), [isacikgoz](https://github.com/isacikgoz), [iyampaul](https://github.com/iyampaul), [j0794](https://github.com/j0794), [jachewz](https://github.com/jachewz), [jaehyun-ko](https://github.com/jaehyun-ko), [jasonblais](https://github.com/jasonblais), [jesperordrup](https://translate.mattermost.com/user/jesperordrup), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kondo97](https://github.com/kondo97), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lathiat](https://github.com/lathiat), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [Michal](https://translate.mattermost.com/user/Michal), [moeenio](https://translate.mattermost.com/user/moeenio), [Morgansvk](https://github.com/Morgansvk), [Movion](https://github.com/Movion), [nickmisasi](https://github.com/nickmisasi), [Nityanand13](https://github.com/Nityanand13), [omerfsen](https://github.com/omerfsen), [pineoak-audio](https://github.com/pineoak-audio), [potatogim](https://translate.mattermost.com/user/potatogim), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Reinkard](https://github.com/Reinkard), [ricardogalvao](https://translate.mattermost.com/user/ricardogalvao), [Ricky-Tigg](https://github.com/Ricky-Tigg), [robregonm](https://github.com/robregonm), [Saturate](https://github.com/Saturate), [SaurabhSharma-884](https://github.com/SaurabhSharma-884), [sbishel](https://github.com/sbishel), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [sumitbhanushali](https://github.com/sumitbhanushali), [svelle](https://github.com/svelle), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [trokar](https://translate.mattermost.com/user/trokar), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.6-feature-release)= +## Release v10.6 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.6.6, released 2025-05-21** + - Mattermost v10.6.6 contains a Critical severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v2.2.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.2.0). + - Mattermost v10.6.6 contains no database or functional changes. +- **10.6.5, released 2025-05-15** + - Added support for AES-256-GCM encryption in SAML. + - Fixed an issue where Team Admin permissions couldn't be changed if they were missing in "All members" section. + - Mattermost v10.6.5 contains no database or functional changes. +- **10.6.4, released 2025-05-12** + - Mattermost v10.6.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.6.4 contains no database or functional changes. +- **10.6.3, released 2025-04-29** + - Mattermost v10.6.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.6.3 contains no database or functional changes. +- **10.6.2, released 2025-04-15** + - Mattermost v10.6.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Stopped logging websocket PING events received by the server. + - Fixed an issue with post links trapping focus when hovered or focused using the keyboard. + - Mattermost v10.6.2 contains no database or functional changes. +- **10.6.1, released 2025-03-17** + - Fixed an issue with jobs in an High Availability environment, where two job servers would take the same job. + - Pre-packaged Calls plugin version [v1.5.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.5.2). + - Mattermost v10.6.1 contains the following functional changes: + - Added a new System Console page called ``Embedding`` which allows frame ancestor domains to be specified when embedding Mattermost in other web sites. Note, ``teams.microsoft.com`` is no longer added automatically to the frame ancestors list. Added a new configuration setting ``FrameAncestors``. +- **10.6.0, released 2025-03-14** + - Original 10.6.0 release. + +### Important Upgrade Notes + - Support for PostgreSQL v11 and v12 have been removed. The new minimum PostgreSQL version is v13+. See the [minimum supported PostgreSQL version policy](https://docs.mattermost.com/deploy/software-hardware-requirements.html#minimum-postgresql-database-support-policy) documentation for details. + - System Console statistics now perform faster on PostgreSQL. The ``MaxUsersForStatistics`` configuration setting now only disables the **User counts with posts** chart, while all other stats remain unaffected. The other stats remain unaffected because that configuration value is no longer needed to disable the other queries since they are always fast now. Post and file counts update daily, so they may not always reflect real-time data. Advanced stats, such as line charts and plugin data, are now hidden until clicked, reducing load time. No performance improvements apply to MySQL since it's scheduled for full deprecation in v11. We recommend migrating to PostgreSQL for better performance and long-term support. Migration times: On a system with 12M posts, and 1M fileinfo entries, the migration takes 15s, but could take several minutes depending on the server's table sizes and database specs. This migration is non-locking. Note that there is no migration for MySQL deployments because this optimization is only applicable for PostgreSQL. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +```{Important} +If you upgrade from a release earlier than v10.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Boards plugin version [v9.1.1](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.1). + - Pre-packaged Playbooks plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.1.1). + - Pre-packaged Copilot plugin version [v1.1.1](https://github.com/mattermost/mattermost-plugin-ai/releases/tag/v1.1.1). + - Pre-packaged MS Teams plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.1.1). + - Pre-packaged Jira plugin version [v4.2.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.2.1). + - Upgraded Ukrainian language to official. + +#### Administration + - Unlicensed server limits have been updated: a soft limit of 2500 users now results in a banner notification visible by admins, and a 5K hard limit that prevents the creation or activation of users until the user count is reduced below the hard limit. + - Removed the automatic Elasticsearch/OpenSearch channel index schema check. As a result, admins will no longer receive Direct Message alerts to notify that their ``elasticsearch`` channel index is out of date. + +### Bug Fixes + - Fixed an issue where the email address in Mattermost would not get updated if the one in SAML changed. + - Fixed an issue where deleted messages would still show thread replies in the channel. + - Fixed an error that could occur when navigating away from the threads screen. + - Fixed an issue where INFO level logging for ``DoActionRequest POST`` requests was missing. + - Fixed an issue where users did not have the ability to toggle the switcher menu in the global header using the **SPACE** and **ENTER** keys while the product branding was in focus. + - Fixed "An error has occurred" bar being shown with developer mode disabled. + - Fixed an issue where deleted threads would get stuck in the thread viewer. + - Fixed an issue where the channel file count was incorrect due to files not actually being submitted as part of a post. + - Fixed a crash issue in the integration action system. + - Fixed an issue where a currently selected thread was shown in the **Unreads** pane. + - Fixed an issue with mmctl preventing the logging of a harmless debug-level "error". + - Fixed an issue where the unread count in your team sidebar may be out of sync when following/unfollowing threads. + - Fixed an issue with Bulk Export: Exports will no longer stop when they encounter a missing file. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: +- Under ``ServiceSettings`` in ``conig.json``: + - A new configuration setting ``EnableWebHubChannelIteration`` was added, which allows a user to control the performance of websocket broadcasting. By default, this setting is turned off. If it is turned on, it improves the websocket broadcasting performance at the expense of poor performance when users join/leave a channel. We don't recommended turning this on unless you have at least 200,000 concurrent users actively using Mattermost. +- Removed ``EnableOpenTracing`` to remove the unused ``opentracing`` support. + +### API Changes + - Added audit logging to the ``SearchPosts`` API. + - Added a ``metrics`` tag to ``client_perf`` endpoint. + +### Open Source Components + - Added and removed several components. + +### Go Version + - v10.6 is built with Go ``v1.22.6``. + +### Known Issues + - Setting the license file location through an environment variable still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the environment variable. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [ayush-chauhan233](https://github.com/ayush-chauhan233), [BenCookie95](https://github.com/BenCookie95), [bshumylo](https://github.com/bshumylo), [calebroseland](https://github.com/calebroseland), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkcircle](https://translate.mattermost.com/user/darkcircle), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [dgwhited](https://github.com/dgwhited), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [equalsgibson](https://github.com/equalsgibson), [esarafianou](https://github.com/esarafianou), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henrique](https://translate.mattermost.com/user/henrique), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [hpflatorre](https://github.com/hpflatorre), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [liul8258](https://github.com/liul8258), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [mvitale1989](https://github.com/mvitale1989), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [NCPSNetworks](https://github.com/NCPSNetworks), [nickmisasi](https://github.com/nickmisasi), [panoramix360](https://github.com/panoramix360), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [Ricky-Tigg](https://github.com/Ricky-Tigg), [robregonm](https://github.com/robregonm), [SaurabhSharma-884](https://github.com/SaurabhSharma-884), [sbishel](https://github.com/sbishel), [SorenHolm](https://translate.mattermost.com/user/SorenHolm), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [ThrRip](https://github.com/ThrRip), [tnir](https://translate.mattermost.com/user/tnir), [toninis](https://github.com/toninis), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [willypuzzle](https://github.com/willypuzzle), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.5-extended-support-release)= +## Release v10.5 - [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.5.14, released 2025-10-30** + - Fixed Go v1.23 incompatibility issues with plugins. + - Mattermost v10.5.14 contains no database or functional changes. +- **10.5.13, released 2025-10-28** + ```{Attention} + **Critical Fixes** + - Mattermost v10.5.13 contains Critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Boards plugin [v9.1.7](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.7). + - Mattermost v10.5.13 contains no database or functional changes. +- **10.5.12, released 2025-10-15** + - Mattermost v10.5.12 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin [v2.2.2](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.2). + - Upgraded to go version 1.23.12. + - Mattermost v10.5.12 contains no database or functional changes. +- **10.5.11, released 2025-09-10** + - Mattermost v10.5.11 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where the content of webhook posts did not display. + - Fixed an issue where unread messages from muted channels were shown in the favicon/desktop app. + - Mattermost v10.5.11 contains no database or functional changes. +- **10.5.10, released 2025-08-15** + - Mattermost v10.5.10 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.5.10 contains no database or functional changes. +- **10.5.9, released 2025-07-22** + - Mattermost v10.5.9 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Pre-packaged Agents plugin [v1.2.4](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.2.4). + - Pre-packaged Calls plugin [v1.9.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.9.2). + - Fixed an issue where overridden webhook usernames did not appear in replies when Threaded Discussions were disabled. + - Removed redux selector's telemetry. + - Mattermost v10.5.9 contains no database or functional changes. +- **10.5.8, released 2025-06-18** + - Mattermost v10.5.8 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where unreads from deleted teams would display in the titlebar/Desktop App. + - Pre-packaged Playbooks plugin [v1.41.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.1). + - Pre-packaged Boards plugin version [v9.1.3](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.3). + - Mattermost v10.5.8 contains no database or functional changes. +- **10.5.7, released 2025-05-27** + - Mattermost v10.5.7 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed possible deadlocks when updating ``SidebarCategories`` and ``SidebarChannels`` tables. + - Pre-packaged MS Teams plugin [v2.2.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.1). + - Mattermost v10.5.7 contains no database or functional changes. +- **10.5.6, released 2025-05-21** + - Mattermost v10.5.6 contains a Critical severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v2.2.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.2.0). + - Pre-packaged Calls plugin [v1.7.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.7.1). + - Fixed an issue where Team Admin permissions couldn't be changed if they were missing in **All members** section. + - Mattermost v10.5.6 contains no database or functional changes. +- **10.5.5, released 2025-05-09** + - Mattermost v10.5.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.5.5 contains the following database changes: + - A new index to the ``CategoryId`` column in ``SidebarChannels`` table was added to improve query performance. No database downtime is expected for this upgrade. It takes around 2s to add the index on a table with 1.2M rows for PostgreSQL, and it takes around 5s on MySQL on a table with 300K rows. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are ``CREATE INDEX idx_sidebarchannels_categoryid ON SidebarChannels(CategoryId);`` for MYSQL and ``CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_sidebarchannels_categoryid ON sidebarchannels(categoryid);`` for PostgreSQL. +- **10.5.4, released 2025-04-29** + - Mattermost v10.5.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where **Recent Mentions** showed incorrect results for custom notification keywords containing hyphens. + - Fixed an issue with post links trapping focus when hovered or focused using the keyboard. + - Mattermost v10.5.4 contains no database or functional changes. +- **10.5.3, released 2025-04-15** + - Mattermost v10.5.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Metrics plugin version [v0.6.0](https://github.com/mattermost/mattermost-plugin-metrics/releases/tag/v0.6.0). + - Stopped logging websocket PING events received by the server. + - Mattermost v10.5.3 contains no database or functional changes. +- **10.5.2, released 2025-03-17** + - Mattermost v10.5.2 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.1.1). + - Pre-packaged Jira plugin version [v4.2.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.2.1). + - Pre-packaged Calls plugin version [v1.5.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.5.2). + - Mattermost v10.5.2 contains no database or functional changes. +- **10.5.1, released 2025-02-19** + - Mattermost v10.5.1 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.1](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.1). + - Pre-packaged Playbooks plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.1.1). + - Fixed an issue in Compliance Exports whereby a missing file attachment in S3 could prevent the export run from completing. + - Mattermost v10.5.1 contains the following functional changes: + - A new configuration setting ``ServiceSettings.EnableWebHubChannelIteration`` was added which allows a user to control the performance of websocket broadcasting. By default, this setting is turned off. If it is turned on, it improves the websocket broadcasting performance at the expense of poor performance when users join/leave a channel. It is not recommended to turn it on unless you have atleast 200,000 concurrent users actively using Mattermost. +- **10.5.0, released 2025-02-14** + - Original 10.5.0 release. + +### Compatibility + - Updated minimum Safari version to 17.4+ and minimum Firefox version to 119+. + +### Important Upgrade Notes + - Mattermost versions v10.5.0 and v10.5.1 include a bundled Jira plugin (v4.2.0) that contains a bug which may cause plugin configuration settings to disappear. We strongly advise against upgrading to these versions to avoid potential disruption. +If you have already upgraded to v10.5.0 or v10.5.1, we recommend updating the Jira plugin to version v4.2.1, or preferably, upgrading both Mattermost and the Jira plugin to their latest available versions. + - v10.5 introduces Property System Architecture schema migration. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for details. + - The Compliance Export system has been overhauled. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for details. + - The Mattermost server has stopped supporting manual plugin deployment. Plugins were deployed manually when an administrator or some deployment automation copies the contents of a plugin bundle into the server's working directory. If a manual or automated deployment workflow is still required, administrators can instead prepackage the plugin bundles. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192). + - Mattermost has stopped official Mattermost server builds for the Microsoft Windows operating system. Administrators should migrate existing Mattermost server installations to use the official Linux builds. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-server-builds-for-microsoft-windows/21498). + +### Breaking Changes +- The internal workings of the `PluginLinkComponent` in the web app have been changed to unmount link tooltips from the DOM by default, significantly improving performance. Plugins that register link tooltips using `registerLinkTooltipComponent` will experience changes in how tooltip components are managed—they are now only mounted when a link is hovered over or focused. As a result, plugins may need to update their components to properly handle mounting and unmounting scenarios. For example, changes were made in [mattermost-plugin-jira](https://github.com/mattermost/mattermost-plugin-jira/pull/1145), where componentDidUpdate lifecycle hook was replaced with componentDidMount. If your plugin’s tooltip component is a functional React component, there is a high chance that this behavior will be handled automatically, as it would be managed by useEffect with an empty dependency array. + +```{Important} +If you upgrade from a release earlier than v10.3, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Boards plugin [v9.1.0](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.0). + - Pre-packaged Calls plugin [v1.5.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.5.1). + - Pre-packaged MS Teams plugin [v2.1.0](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.1.0). + - Pre-packaged Channel Export plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.2.1). + - Pre-packaged Jira plugin [v4.2.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.2.0). + - Added the ability to modify post attachments during edit. + - The [channel bookmarks bar](https://docs.mattermost.com/end-user-guide/collaborate/manage-channel-bookmarks.html) is now hidden when there are no bookmarks in the channel. Bookmarks can now be added from the channel menu. + - Removed the video from the onboarding checklist. + - Improved accessibility throughout the webapp by fixing several issues around keyboard navigation and screen reader focused on modals, right-hand side and core chat functionality. + +#### Administration + - Added the migrations, store layer and service for the Property System Architecture. + - Added Custom Profile Attributes, an experimental Enterprise-only feature. This feature is disabled by default. To enable this feature, set the feature flag `CustomProfileAttributes`. Once enabled, administrators can access the System Properties section in the System Console to create and manage custom user profile fields. The initial release supports text fields only. + - Added the Custom Profile Attribute fields store, app and API endpoints. + - Introduced V2 of the Support Packet, containing improvement diagnosis information for high-availability deployments. + - Added a new ``Fallback`` field to ``PluginSettingsSection`` that controls whether the settings defined under the section should still render as fallback when the plugin is disabled. + - Updated the library used for tooltips throughout the app to fix a memory leak. + - Reduced the volume of unnecessary debug logs generated during scheduled post job execution. + - Removed ``form-data`` from @mattermost/client. + +### Bug Fixes + - Fixed archived filter behavior in System Console > User Management > Channels to restore the ability to exclude archived channels. + - Fixed an issue where DMs/GMs with a `DeleteAt` non-zero value in the database might cause issues with several APIs. + - Fixed an issue where the team sidebar's mention count could be out of sync with the thread count. + - Fixed an issue where replies with props could not be imported. + - Fixed an issue where ``pluginapi.store.GetReplicaDB`` returned nil if masterDB was not initialized. + - Fixed an issue in ``SqlPostStore.PermanentDeletebyUser`` where no error was returned when 10K posts were exceeded. + - Fixed an issue where a channel would no longer be exported for Bulk Export workflow if any of the users of a Direct or Group Message channel were permanently deleted. + - Fixed an issue where the scroll position reset when custom emojis were requested. + - Fixed a panic during LDAP synchronization. + - Fixed an issue where the bulk export retention job would accidentally delete non-bulk export files and directories. + - Fixed an issue where archived channels were not searchable with Elasticsearch/OpenSearch if ``TeamSettings.ExperimentalViewArchivedChannels`` was enabled. If there are old channels which were archived before a bulk index was run, users would need to purge indexes, and do bulk index again. Because those old archived channels are removed from the index when a bulk index is run. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Enterprise plans: + - Under ``essageExportSettings`` in ``config.json``: + - Added ``ComplianceExportDirectoryFormat``, ``ComplianceExportPath``, ``ComplianceExportPathCLI``, ``ComplianceExportChannelBatchSizeDefault``, and ``ComplianceExportChannelHistoryBatchSizeDefault`` for compliance export overhaul. + +### API Changes + - ``GetUsersInChannelDuring`` now accepts a slice; added ``GetChannelsWithActivityDuring``. + - Two new boolean query parameters were added to the ``api/v4/config`` endpoint: + - ``remove_defaults`` (filters out default values). + - ``remove_masked`` (removes masked fields). + +### Go Version + - v10.5 is built with Go ``v1.23.12``. + +### Known Issues + - Setting the license file location through an envvar still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the envvar. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agardelein](https://github.com/agardelein), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AulakhHarsh](https://github.com/AulakhHarsh), [ayush-chauhan233](https://github.com/ayush-chauhan233), [BenCookie95](https://github.com/BenCookie95), [bshumylo](https://translate.mattermost.com/user/bshumylo), [calebroseland](https://github.com/calebroseland), [code1492](https://github.com/code1492), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [dmanpearl](https://github.com/dmanpearl), [Dschoordsch](https://github.com/Dschoordsch), [ebuildy](https://github.com/ebuildy), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emmapeel2](https://github.com/emmapeel2), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [fume4mattermost](https://github.com/fume4mattermost), [gabrieljackson](https://github.com/gabrieljackson), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henrique](https://translate.mattermost.com/user/henrique), [hmhealey](https://github.com/hmhealey), [Honsei901](https://github.com/Honsei901), [hpflatorre](https://github.com/hpflatorre), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [juliemanalo](https://github.com/juliemanalo), [JulienTant](https://github.com/JulienTant), [jure](https://translate.mattermost.com/user/jure), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kasyap1234](https://github.com/kasyap1234), [kayazeren](https://translate.mattermost.com/user/kayazeren), [kondo97](https://github.com/kondo97), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [MattSilvaa](https://github.com/MattSilvaa), [mgdelacroix](https://github.com/mgdelacroix), [Morgansvk](https://github.com/Morgansvk), [mvitale1989](https://github.com/mvitale1989), [NadavTasher](https://github.com/NadavTasher), [narutoxboy](https://translate.mattermost.com/user/narutoxboy), [NCPSNetworks](https://github.com/NCPSNetworks), [nickmisasi](https://github.com/nickmisasi), [otbutz](https://github.com/otbutz), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [robregonm](https://github.com/robregonm), [sarthak0714](https://github.com/sarthak0714), [saturninoabril](https://github.com/saturninoabril), [SaurabhSharma-884](https://github.com/SaurabhSharma-884), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [svelle](https://github.com/svelle), [ThrRip](https://github.com/ThrRip), [toninis](https://github.com/toninis), [tormi](https://translate.mattermost.com/user/tormi), [uday-rana](https://github.com/uday-rana), [unode](https://github.com/unode), [varghesejose2020](https://github.com/varghesejose2020), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [wetneb](https://github.com/wetneb), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [willypuzzle](https://github.com/willypuzzle), [X1Vi](https://github.com/X1Vi), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v10.4-feature-release)= +## Release v10.4 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.4.5, released 2025-04-15** + - Mattermost v10.4.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Stopped logging websocket PING events received by the server. + - Mattermost v10.4.5 contains no database or functional changes. +- **10.4.4, released 2025-03-17** + - Mattermost v10.4.4 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin version [v1.5.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.5.2). + - Mattermost v10.4.4 contains no database or functional changes. +- **10.4.3, released 2025-02-19** + - Mattermost v10.4.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.1](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.1). + - Pre-packaged Playbooks plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.1.1). + - Fixed an issue in Compliance Exports whereby a missing file attachment in S3 could prevent the export run from completing. + - Fixed an issue where the bulk export retention job could accidentally delete non-bulk export files and directories. + - Mattermost v10.4.3 contains the following functional changes: + - A new configuration setting ``ServiceSettings.EnableWebHubChannelIteration`` was added which allows a user to control the performance of websocket broadcasting. By default, this setting is turned off. If it is turned on, it improves the websocket broadcasting performance at the expense of poor performance when users join/leave a channel. It is not recommended to turn it on unless you have atleast 200,000 concurrent users actively using Mattermost. +- **10.4.2, released 2025-01-22** + - Mattermost v10.4.2 contains critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.5). + - Pre-packaged Channel Export plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.2.1). + - Fixed a panic during LDAP synchronization. + - Fixed an issue with webhook attachment button styles. + - Mattermost v10.4.2 contains no database or functional changes. +- **10.4.1, released 2025-01-16** + - Fixed errors logged by performance telemetry due to certain browser extensions. + - Fixed an issue with insertion errors to ``LinkMetadata`` table. + - Mattermost v10.4.1 contains no database or functional changes. +- **10.4.0, released 2025-01-16** + - Original 10.4.0 release. + +```{Important} +If you upgrade from a release earlier than v10.3, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.4.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.4.0). + - Pre-packaged Boards plugin [v9.0.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.2). + - Improved the handling of Thai script in search terms. + - Added tooltips to the buttons shown in the channel info in the right pane. + - Downgraded Spanish language to Alpha. + - Removed the feature to import themes from Slack. + +#### Administration + - Redis is now available as an alternative cache backend for all Enterprise customers. It can be leveraged to run Mattermost at a very high scale. + - Plugins are now allowed to add Support Packet data without user interface elements. + - Improved the detection of the mobile app operating system as stored in the **Sessions** table. + +### Bug Fixes + - Fixed an issue where imported replies were missing their reactions. + - Fixed an issue with how links in Markdown headings are displayed in the Threads list. + - Fixed an issue where marking a channel as read wouldn't persist through a refresh. + - Fixed a warning in the Support Packet about an unreadable LDAP server even if LDAP was disabled. + - Fixed an issue where multiple timezones were highlighted when selecting certain timezones. + - Fixed an issue where unread messages on other teams would not appear after the application reconnected to the server. + - Fixed an issue where the scrollbar was not clickable when there was a toaster. + - Fixed an issue when pressing **Page Up** or **Page Down** on a long message (scrollable) with the right sidebar open. + - Fixed an issue with incorrect reporting in the **Server Updates** section in **System Console > Workspace Optimizations**. + - Fixed an issue where EXIF rotated image previews did not have the correct size. + - Fixed an issue where the search input field in the emoji picker did not accept uppercase letters. + - Fixed an issue where imported replies were missing their reactions. + - Fixed an issue where System Administrators could not pull posts from Direct Message channels that they were not in. + - Fixed an issue by restoring System Administrator access to Direct and Group Messages without being a member. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: +- Under ``LocalizationSettings`` in ``config.json``: + - Added a new ``EnableExperimentalLocales`` configuration setting that controls whether to allow the selection of experimental (e.g., in progress) languages. + +#### Changes to Enterprise plans: + - Under ``CacheSettings`` in ``config.json``: + - Added ``CacheType``: This can be either ``lru`` or ``redis``. ``lru`` is the default choice which will use the in-memory cache store that we use currently. + - Added ``RedisAddress``: The hostname of the Redis host. + - Added ``RedisPassword``: The password of the Redis host (can be left blank if there is no password). + - Added ``RedisDB``: The database of the Redis host. Typically ``0``. + - Added ``DisableClientCache``: This can be set to ``true`` if you decide to disable the client-side cache of Redis. Typically there is no need to do this in production, and this is mainly used as a test option. + - Under ``FileSettings`` in ``config.json``: + - Added new ``AmazonS3StorageClass`` and ``ExportAmazonS3StorageClass``, both default to ``""`` to preserve the current behavior. Administrators may configure this storage class to the storage class required by their S3 solution. + +### API Changes + - Added a new query string to exclude threads that are not part of the team ``GET api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}/threads``. + +### Websocket Event Changes + - Added a new ``server_hostname`` field to the websocket ``HELLO`` event. + +### Go Version + - v10.4 is built with Go ``v1.22.6``. + +### Known Issues + - Setting the license file location through an envvar still gives the option to upload a new license through the System Console, resulting in the license being overwritten by the one set through the envvar. See this [knowledge base article](https://support.mattermost.com/hc/en-us/articles/33911983851284-System-console-still-displays-old-license-after-uploading-a-new-one) on how to resolve this issue. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akbarkz](https://translate.mattermost.com/user/akbarkz), [amyblais](https://github.com/amyblais), [and-ri](https://github.com/and-ri), [andreabia](https://translate.mattermost.com/user/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [AulakhHarsh](https://github.com/AulakhHarsh), [ayush-chauhan233](https://github.com/ayush-chauhan233), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [callmeott](https://github.com/callmeott), [catalintomai](https://github.com/catalintomai), [creeper-0910](https://github.com/creeper-0910), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [Destrosvet](https://translate.mattermost.com/user/Destrosvet), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [fume4mattermost](https://github.com/fume4mattermost), [fxnm](https://github.com/fxnm), [gabrielctn](https://github.com/gabrielctn), [gabrieljackson](https://github.com/gabrieljackson), [gabsfrancis](https://translate.mattermost.com/user/gabsfrancis), [Gesare5](https://github.com/Gesare5), [Haliax](https://translate.mattermost.com/user/Haliax), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henrique](https://translate.mattermost.com/user/henrique), [hmhealey](https://github.com/hmhealey), [Honsei901](https://github.com/Honsei901), [hpflatorre](https://github.com/hpflatorre), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [jessiekahn](https://github.com/jessiekahn), [joakim.rivera](https://translate.mattermost.com/user/joakim.rivera), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://translate.mattermost.com/user/jprusch), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [Kuruyia](https://github.com/Kuruyia), [kyrillosisaac2](https://github.com/kyrillosisaac2), [lani009](https://translate.mattermost.com/user/lani009), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lorumic](https://github.com/lorumic), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [massimo](https://translate.mattermost.com/user/massimo), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mh4ckt3mh4ckt1c4s](https://translate.mattermost.com/user/mh4ckt3mh4ckt1c4s), [minchae.lee](https://translate.mattermost.com/user/minchae.lee), [morgancz](https://translate.mattermost.com/user/morgancz), [Morgansvk](https://github.com/Morgansvk), [muratbayan](https://translate.mattermost.com/user/muratbayan), [mvitale1989](https://github.com/mvitale1989), [nbruneau71250](https://translate.mattermost.com/user/nbruneau71250), [nickmisasi](https://github.com/nickmisasi), [nikolaiz](https://translate.mattermost.com/user/nikolaiz), [Nityanand13](https://github.com/Nityanand13), [pmokeev](https://github.com/pmokeev), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [renaudk](https://github.com/renaudk), [ricardogalvao](https://translate.mattermost.com/user/ricardogalvao), [RS-labhub](https://github.com/RS-labhub), [Rutam21](https://github.com/Rutam21), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [sypianski](https://translate.mattermost.com/user/sypianski), [TenGentoppa](https://translate.mattermost.com/user/TenGentoppa), [TheInvincibleRalph](https://github.com/TheInvincibleRalph), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [tokipulan](https://translate.mattermost.com/user/tokipulan), [tomdereub](https://translate.mattermost.com/user/tomdereub), [toninis](https://github.com/toninis), [wetneb](https://github.com/wetneb), [wiggin77](https://github.com/wiggin77), [YahyaHaq](https://github.com/YahyaHaq), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yesbhautik](https://github.com/yesbhautik), [zenocode-org](https://translate.mattermost.com/user/zenocode-org) + +(release-v10.3-feature-release)= +## Release v10.3 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.3.4, released 2025-02-19** + - Mattermost v10.3.4 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.1](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.1). + - Pre-packaged Playbooks plugin version [v2.1.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.1.1). + - Fixed an issue in Compliance Exports whereby a missing file attachment in S3 could prevent the export run from completing. + - Mattermost v10.3.4 contains the following functional changes: + - A new configuration setting ``ServiceSettings.EnableWebHubChannelIteration`` was added which allows a user to control the performance of websocket broadcasting. By default, this setting is turned off. If it is turned on, it improves the websocket broadcasting performance at the expense of poor performance when users join/leave a channel. It is not recommended to turn it on unless you have atleast 200,000 concurrent users actively using Mattermost. +- **10.3.3, released 2025-01-22** + - Mattermost v10.3.3 contains critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.5). + - Pre-packaged Channel Export plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.2.1). + - Fixed a panic during LDAP synchronization. + - Fixed an issue where the bulk export retention job would accidentally delete non-bulk export files and directories. + - Mattermost v10.3.3 contains no database or functional changes. +- **10.3.2, released 2025-01-15** + - Mattermost v10.3.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.2). + - Fixed an issue with the webhook attachment button style. + - Mattermost v10.3.2 contains no database or functional changes. +- **10.3.1, released 2024-12-16** + - Fixed an issue where user statuses weren't synced properly between servers. + - Fixed an accessibility problem in the new search input. + - Mattermost v10.3.1 contains no database or functional changes. +- **10.3.0, released 2024-12-16** + - Original 10.3.0 release. + +### Important Upgrade Notes + + - The Classic Mobile App has been phased out. Please download the new v2 Mobile App from the [Apple App Store](https://apps.apple.com/us/app/mattermost/id1257222717) or [Google Play Store](https://play.google.com/store/apps/details?id=com.mattermost.rn). See more details in the [classic mobile app deprecation](https://forum.mattermost.com/t/classic-mobile-app-deprecation/18703) Mattermost forum post. + +### Compatibility + + - Updated minimum Edge and Chrome versions to 130+. + +```{Important} +If you upgrade from a release earlier than v10.2, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.3.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.3.0). + - Downgraded Traditional Chinese language to Beta. + - Added a feature to schedule a message at a future date (Professional and Enterprise plans). + - Copilot plugin is now installed and enabled by default. + - Added an option to test notifications. + - Added a new [search interface](https://docs.mattermost.com/end-user-guide/collaborate/search-for-messages.html). + - Updated product string for clarity. + - Removed most places where deprecated translation code is used in the web app. + - Removed some duplicate CSS from the web app bundle. + +#### Administration + - A 200 response is now returned for HEAD requests to a sub-path rather than responding with a 302. This fixes mobile devices trying to connect to a server hosted on a sub-path. + - Added the ``fetchMissingUsers`` option to ``PostUtils.messageHtmlToComponent`` for use by plugins. + - Added support for exporting and importing bot users via mmctl. + - Added a warning to mmctl for cases where a user specifies a per-page parameter that's larger than the maximum value supported. + +#### Performance + - Added Desktop App performance metrics. + +### Bug Fixes + - Fixed an issue with post drafts being unnecessarily saved when changing channels. + - Fixed an issue where the Web App would feel slower to load than the Desktop App. + - Fixed an issue where new messages from new channels wouldn't appear in the sidebar after reconnecting the websocket. + - Fixed an issue with a link in the Compliance Monitoring page banner in the System Console. + - Fixed an issue that no longer allowed managing user tokens via the System Console. + - Fixed a SVG image rendering issue by setting conditional width and height attributes in ``ImagePreview`` and ``SizeAwareImage`` components. + - Fixed an issue with the web app status not being updated correctly for the current user. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings `` in ``config.json``: + - Added ``ScheduledPosts`` to enable the feature to schedule and send message in the future. + +### Go Version + - v10.3 is built with Go ``v1.22.6``. + +### Open Source Components + - Added ``opensearch-project/opensearch-go`` to https://github.com/mattermost/mattermost. + +### Known Issues + - The bottom padding is missing in the edit state of a scheduled messages. + - An incorrect count is displayed in channels for scheduled messages. + - The scheduled post channel indicator sometimes ends up in a bad state. + - Scheduled messages are not removed from queued list when sent while being disconnected. + - Scheduled message date displayed for Direct Message users is sometimes incorrect. + - The new search modal doesn't autocomplete after a space. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [7+7](https://translate.mattermost.com/user/7+7), [abdellani](https://github.com/abdellani), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akbarkz](https://translate.mattermost.com/user/akbarkz), [Alenoda](https://github.com/Alenoda), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [and-ri](https://translate.mattermost.com/user/and-ri), [andr-sokolov](https://github.com/andr-sokolov), [andreabia](https://github.com/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AulakhHarsh](https://github.com/AulakhHarsh), [ayusht2810](https://github.com/ayusht2810), [azadDsync](https://github.com/azadDsync), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [callmeott](https://github.com/callmeott), [carlosGuimaraesTc](https://github.com/carlosGuimaraesTc), [catalintomai](https://github.com/catalintomai), [cedric.lamalle](https://translate.mattermost.com/user/cedric.lamalle), [creeper-0910](https://translate.mattermost.com/user/creeper-0910), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyberm8](https://github.com/cyberm8), [cyrusjc](https://github.com/cyrusjc), [decke](https://github.com/decke), [devinbinnie](https://github.com/devinbinnie), [Dishika18](https://github.com/Dishika18), [Dzenan](https://translate.mattermost.com/user/Dzenan), [edlerd](https://github.com/edlerd), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabsfrancis](https://translate.mattermost.com/user/gabsfrancis), [Gesare5](https://github.com/Gesare5), [guruprasath-v](https://github.com/guruprasath-v), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [HarshitVashisht11](https://github.com/HarshitVashisht11), [henrique](https://translate.mattermost.com/user/henrique), [hmhealey](https://github.com/hmhealey), [Honsei901](https://github.com/Honsei901), [hpflatorre](https://github.com/hpflatorre), [hun-a](https://github.com/hun-a), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [Jelmerovereem](https://github.com/Jelmerovereem), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jonathan-dove](https://github.com/jonathan-dove), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kczpl](https://github.com/kczpl), [Killer2OP](https://github.com/Killer2OP), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [Kuruyia](https://github.com/Kuruyia), [KuSh](https://github.com/KuSh), [kyrillosisaac2](https://github.com/kyrillosisaac2), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mas-who](https://github.com/mas-who), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mentz](https://translate.mattermost.com/user/mentz), [minkyngkm](https://github.com/minkyngkm), [molejnik88](https://github.com/molejnik88), [morgancz](https://translate.mattermost.com/user/morgancz), [Morgansvk](https://github.com/Morgansvk), [mvitale1989](https://github.com/mvitale1989), [NadavTasher](https://github.com/NadavTasher), [nickmisasi](https://github.com/nickmisasi), [Niharika0104](https://github.com/Niharika0104), [nikolaiz](https://translate.mattermost.com/user/nikolaiz), [NilsArnlund](https://github.com/NilsArnlund), [potatogim](https://translate.mattermost.com/user/potatogim), [pranay-0512](https://github.com/pranay-0512), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [ricardogalvao](https://translate.mattermost.com/user/ricardogalvao), [RS-labhub](https://github.com/RS-labhub), [Rutam21](https://github.com/Rutam21), [s1Sharp](https://github.com/s1Sharp), [samarth29jc](https://github.com/samarth29jc), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Seyifunmi](https://github.com/Seyifunmi), [Sharuru](https://github.com/Sharuru), [sohzm](https://github.com/sohzm), [sparr](https://github.com/sparr), [srisri332](https://github.com/srisri332), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sumedhakoranga](https://github.com/sumedhakoranga), [TheInvincibleRalph](https://github.com/TheInvincibleRalph), [thelizardreborn](https://github.com/thelizardreborn), [theoforger](https://github.com/theoforger), [ThrRip](https://translate.mattermost.com/user/ThrRip), [tokipulan](https://translate.mattermost.com/user/tokipulan), [toninis](https://github.com/toninis), [verdel](https://github.com/verdel), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [wetneb](https://github.com/wetneb), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [willypuzzle](https://github.com/willypuzzle), [yanyiyi](https://github.com/yanyiyi), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yesbhautik](https://github.com/yesbhautik) + +(release-v10.2-feature-release)= +## Release v10.2 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.2.3, released 2025-01-22** + - Mattermost v10.2.3 contains critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.5). + - Pre-packaged Channel Export plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.2.1). + - Fixed a panic during LDAP synchronization. + - Fixed an issue where the bulk export retention job would accidentally delete non-bulk export files and directories. + - Mattermost v10.2.3 contains no database or functional changes. +- **10.2.2, released 2025-01-15** + - Mattermost v10.2.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.2). + - Mattermost v10.2.2 contains no database or functional changes. +- **10.2.1, released 2024-12-10** + - Mattermost v10.2.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where plugin settings got wiped if the plugin declared some of its fields as secrets. + - Pre-packaged Calls plugin [v1.3.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.3.2). + - Mattermost v10.2.1 contains no database or functional changes. +- **10.2.0, released 2024-11-15** + - Original 10.2.0 release. + +### Important Upgrade Notes + + - Docker Content Trust (DCT) for signing Docker image artifacts has been replaced by Sigstore Cosign in v10.2 (November, 2024). If you rely on artifact verification using DCT, please [transition to using Cosign](https://edu.chainguard.dev/open-source/sigstore/cosign/how-to-install-cosign/). See the [DCT deprecation Mattermost forum post](https://forum.mattermost.com/t/upcoming-dct-deprecation/19275) for more details. + +```{Important} +If you upgrade from a release earlier than v10.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.2.1). + - Changed the logic of ``useMilitaryTime`` to ``false`` to default to 12-hour time format unless the user's preference from ``data.Value`` is ``true``. When a notification email is sent to a user, the time should now default to the 12-hour format unless otherwise stated by the user. + - A warning is now shown when deleting a post or comment from a remote/shared channel. + - Bot messages will now properly mention both users when they happen on non-bot Group Messages. + - Updated the channel header to hide pinned posts when there aren't any in the channel. + - Added full support for @mentions in the values of fields in [message attachments](https://developers.mattermost.com/integrate/reference/message-attachments/). + +#### Administration + - Added a new URL parameter called ``permanent`` to ``DELETE /api/v4/posts/<post-id>``, and set ``permanent`` to ``true`` in order to permanently delete a post and its attachments. + - Added Connected Workspaces (Beta) administration page to the System Console when Connected Workspaces are [enabled](https://docs.mattermost.com/onboard/connected-workspaces.html#enable-connected-workflows) for the server. + - Added a team selector to accept connection invite flow in Connected Workspaces. + - Restricted activation and deactivation of LDAP-managed users through both the System Console UI and Mattermost API. + - Export/import improvements: added the ability to export all user preferences and flagged posts. + - Increased timeouts to fetch cluster logs. + - Improved log messages for cluster communication. + - Information about deleted rows from the Data Retention job are now logged. + - License details to logs are now emitted when added or removed. + - Added a new mmctl command, ``mmctl post delete <post-id>``, in order to permanently delete a post and its attachments. + +#### Performance + - Added metrics to prometheus to check the mobile versions for each session daily. + - Improved the performance of LDAP sync jobs when group-contained teams and channels are used. + - Added minor improvements to notification metrics. + - Added minor improvements to mobile push notifications. + +### Bug Fixes + - Fixed an issue with email notifications using 24-hour timestamps by default. + - Fixed an issue where bots were not ignored when counting deactivated accounts for statistics. + - Fixed an issue where drafts didn’t allow scrolling if the user had many drafts. + - Fixed an issue that caused Javascript errors in the System Console. + - Fixed racy use of session in ``NewWebConn``. + - Fixed a race condition that would happen after a server start if ``EnableTesting`` was enabled. + - Fixed an issue where no error message was shown when replying to a deleted post from the draft screen. + - Fixed an issue where the check icons were missing from the Sort and Show options in the Direct Messages tab, and the Sort tab of the Channels tab. + - Fixed desyncing issues with unreads between the team sidebar and the title bar. + - Fixed an issue with message export file attachments with dedicated filestore: when the dedicated filestore is set, file attachments will be found and exported correctly. + - Reverted a change enforcing usernames to start with alpha characters on the server. + - Reverted a breaking change in ``registerSlashCommandWillBePostedHook`` that caused errors to surface in case an expected empty object was returned. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added a new configuration setting ``EnableAPIPostDeletion`` in order to enable/disable post deletion. This configuration setting does not need to be enabled when running mmctl in local mode. + - Added ``EnableDesktopLandingPage`` to allow the desktop app landing page to be disabled. + - Under ``NativeAppSettings`` in ``config.json``: + - Added a configuration setting ``MobileExternalBrowser`` that tells the Mobile app to perform SSO Authentication using the external default browser. + +### Go Version + - v10.2 is built with Go ``v1.22.6``. + +### Known Issues + - The scrollbar is not clickable when there is a "Jump to recents" toaster. + - Shared Channels: Direct Messages are not supported. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [047pegasus](https://github.com/047pegasus), [1510janu](https://github.com/1510janu), [aamfahim](https://github.com/aamfahim), [aditipatelpro](https://github.com/aditipatelpro), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andreabia](https://translate.mattermost.com/user/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anudhyan](https://github.com/anudhyan), [Arch130](https://github.com/Arch130), [arilloid](https://github.com/arilloid), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [azadDsync](https://github.com/azadDsync), [azigler](https://github.com/azigler), [belkhoujaons](https://github.com/belkhoujaons), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [Camillarhi](https://github.com/Camillarhi), [CarlssonFilip](https://github.com/CarlssonFilip), [catalintomai](https://github.com/catalintomai), [CBID2](https://github.com/CBID2), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [diamant3](https://github.com/diamant3), [Dishika18](https://github.com/Dishika18), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [fume4mattermost](https://github.com/fume4mattermost), [gabrieljackson](https://github.com/gabrieljackson), [Gesare5](https://github.com/Gesare5), [Good-Soma](https://github.com/Good-Soma), [grubbins](https://github.com/grubbins), [gvarma28](https://github.com/gvarma28), [hamzawritescode](https://github.com/hamzawritescode), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [HarshitVashisht11](https://github.com/HarshitVashisht11), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [ja49619](https://translate.mattermost.com/user/ja49619), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jopaleti](https://github.com/jopaleti), [jprusch](https://github.com/jprusch), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Killer2OP](https://github.com/Killer2OP), [kom-senapati](https://github.com/kom-senapati), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [KvngMikey](https://github.com/KvngMikey), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [Malay-dev](https://github.com/Malay-dev), [master7](https://translate.mattermost.com/user/master7), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [mm-prodsec-bot](https://github.com/mm-prodsec-bot), [moda-l10n](https://translate.mattermost.com/user/moda-l10n), [Morgan_svk](https://translate.mattermost.com/user/Morgan_svk), [Movion](https://github.com/Movion), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [Niharika0104](https://github.com/Niharika0104), [nikolaiz](https://translate.mattermost.com/user/nikolaiz), [NilsArnlund](https://github.com/NilsArnlund), [panoramix360](https://github.com/panoramix360), [pradeepmurugesan](https://github.com/pradeepmurugesan), [pvev](https://github.com/pvev), [qfrigolac](https://github.com/qfrigolac), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Ranjana761](https://github.com/Ranjana761), [raremax](https://translate.mattermost.com/user/raremax), [Reinkard](https://github.com/Reinkard), [RS-labhub](https://github.com/RS-labhub), [Ruhi14](https://github.com/Ruhi14), [Rutam21](https://github.com/Rutam21), [s4kh](https://github.com/s4kh), [sahariardev](https://github.com/sahariardev), [samarth29jc](https://github.com/samarth29jc), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sedivst](https://translate.mattermost.com/user/sedivst), [Sharuru](https://translate.mattermost.com/user/Sharuru), [shraddha761](https://github.com/shraddha761), [space-w-alker](https://github.com/space-w-alker), [srisri332](https://github.com/srisri332), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [swills](https://github.com/swills), [tanmaythole](https://github.com/tanmaythole), [TealWater](https://github.com/TealWater), [TheInvincibleRalph](https://github.com/TheInvincibleRalph), [theoforger](https://github.com/theoforger), [ThrRip](https://github.com/ThrRip), [TomerPacific](https://github.com/TomerPacific), [toninis](https://github.com/toninis), [varghesejose2020](https://github.com/varghesejose2020), [vawaver](https://translate.mattermost.com/user/vawaver), [vhaska](https://translate.mattermost.com/user/vhaska), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [WeBjAnJaN](https://translate.mattermost.com/user/WeBjAnJaN), [wetneb](https://github.com/wetneb), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yanyiyi](https://github.com/yanyiyi), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [z44440000z](https://github.com/z44440000z), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) + +(release-v10.1-feature-release)= +## Release v10.1 - [Feature Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.1.7, released 2025-01-15** + - Mattermost v10.1.7 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.2). + - Mattermost v10.1.7 contains no database or functional changes. +- **10.1.6, released 2024-12-20** + - Fixed an issue by restoring System Administrator access to Direct and Group Messages without being a member. + - Mattermost v10.1.6 contains no database or functional changes. +- **10.1.5, released 2024-12-18** + - Fixed an issue where System Administrators could not pull posts in from Direct Message channels they were not in. + - Mattermost v10.1.5 contains no database or functional changes. +- **10.1.4, released 2024-12-10** + - Mattermost v10.1.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin [v1.3.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.3.2). + - Mattermost v10.1.4 contains no database or functional changes. +- **10.1.3, released 2024-11-14** + - Mattermost v10.1.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Reverted a change enforcing usernames to start with alpha characters on the server. + - Reverted a breaking change in ``registerSlashCommandWillBePostedHook`` that caused errors to surface in case an expected empty object was returned. + - Mattermost v10.1.3 contains no database or functional changes. +- **10.1.2, released 2024-10-28** + - Mattermost v10.1.2 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with message export file attachments with a dedicated filestore. + - Mattermost v10.1.2 contains the following functional change: + - Added a configuration setting **NativeAppSettings > MobileExternalBrowser** that tells the Mobile app to perform SSO Authentication using the external default browser. +- **10.1.1, released 2024-10-16** + - Fixed an issue where a shared indicator was shown in all Direct Messages, regardless of the user coming from a shared server. + - Mattermost v10.1.1 contains no database or functional changes. +- **10.1.0, released 2024-10-16** + - Original 10.1.0 release. + +```{Important} +If you upgrade from a release earlier than v10.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Added Metrics plugin to the prepackaged plugins, [v0.5.3](https://github.com/mattermost/mattermost-plugin-metrics/releases/tag/v0.5.3). + - Pre-packaged Calls plugin [v1.1.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.1.0). + - Enabled [Channel Bookmarks](https://docs.mattermost.com/end-user-guide/collaborate/manage-channel-bookmarks.html), added re-ordering, and fixed URL validity checking. + - Added a more descriptive error message, "Uploaded plugin size exceeds limit." for plugin uploads that are too large. + - Added channel specific message notification sounds configuration. + +#### Administration + - Added ``DeleteAt`` field for ``SharedChannelRemotes`` and ``RemoteClusters``. + - Added support for sending channel invites to offline remotes in Shared Channels. + - Changed server-side logic to return a ``413: Request Entity Too Large`` HTTP status code for a plugin upload that is too large. + - Direct and Group Message unread/read state over export and import will now be carried over. + - CRT memberships are now importable for import. + - CRT memberships are now exportable for bulk export. + - Added ``--local mode`` support in MMCTL to handle user preferences. + - Plugins are now allowed to mark setting fields as secret, obfuscating them in the System Console and the Support Packet. + +#### Performance + - Improved metrics related to push proxy errors. + - Improved metrics around notifications. + +### Bug Fixes + - Fixed an issue where threads would be marked as read if they were open in the background. + - Fixed an issue where Direct and Group Messages didn't load correctly in the sidebar when refreshing the app from Drafts. + - Fixed an issue attempting to bind to Apps plugin when the plugin was not enabled. + - Fixed an issue where the Unreads tab would not update correctly after the websocket reconnected. + - Fixed an issue with focusing on the main box when loading the app. + - Fixed an issue where Team and Channel Admins could lose the ability to create posts in a moderated channel. + - Fixed an issue where marking a channel as unread did not show immediately in other clients. + - Fixed an issue with not allowing to use ``@`` and ``~`` in the ``in:`` search modifier without affecting search results. + - Fixed an issue with YouTube previews no longer being displayed. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``YoutubeReferrerPolicy`` to fix an issue where YouTube previews showed an “Video Unavailable” error instead of the video. + +#### Changes to the Enterprise plan: + - Under ``ConnectedWorkspacesSettings`` in ``config.json``: + - Added ``DisableSharedChannelsStatusSync`` to add status sync support to Shared Channels. + - Under ``ConnectedWorkspacesSettings`` in ``config.json``: + - Moved the Shared Channel related configuration properties out of the Experimental section. + - Added the ``MaxPostsPerSync`` configuration property. + +### API Changes + - Added new API endpoints to manage shared channels. + - Added proper response to ``/api/v4/client_perf`` endpoint. + +### Go Version + - v10.1 is built with Go ``v1.22.6``. + +### Known Issues + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [adityasoni2019](https://github.com/adityasoni2019), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [algeorgiadis](https://github.com/algeorgiadis), [amyblais](https://github.com/amyblais), [andreabia](https://translate.mattermost.com/user/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [armmanvaillancourt](https://github.com/armmanvaillancourt), [Aryakoste](https://github.com/Aryakoste), [ayusht2810](https://github.com/ayusht2810), [azistellar](https://translate.mattermost.com/user/azistellar), [azizthegit](https://github.com/azizthegit), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [ChinoUkaegbu](https://github.com/ChinoUkaegbu), [Chlbek](https://translate.mattermost.com/user/Chlbek), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [daveseo901](https://github.com/daveseo901), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [Gesare5](https://github.com/Gesare5), [Glandos](https://github.com/Glandos), [grundleborg](https://github.com/grundleborg), [gvarma28](https://github.com/gvarma28), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [ja49619](https://translate.mattermost.com/user/ja49619), [johnsonbrothers](https://github.com/johnsonbrothers), [jones](https://translate.mattermost.com/user/jones), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kaoski](https://github.com/kaoski), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [L3o-pold](https://github.com/L3o-pold), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lukasMega](https://github.com/lukasMega), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [manujgrover71](https://github.com/manujgrover71), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [milotype](https://translate.mattermost.com/user/milotype), [Morgan_svk](https://translate.mattermost.com/user/Morgan_svk), [Movion](https://github.com/Movion), [mvitale1989](https://github.com/mvitale1989), [nekodayo2222](https://translate.mattermost.com/user/nekodayo2222), [nickmisasi](https://github.com/nickmisasi), [nikhilskul7](https://github.com/nikhilskul7), [Porma120](https://github.com/Porma120), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Rishiii7](https://github.com/Rishiii7), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [testtomato1230](https://translate.mattermost.com/user/testtomato1230), [TheInvincibleRalph](https://github.com/TheInvincibleRalph), [ThrRip](https://translate.mattermost.com/user/ThrRip), [toninis](https://github.com/toninis), [tsabi](https://github.com/tsabi), [vish9812](https://github.com/vish9812), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yaz](https://translate.mattermost.com/user/yaz), [yuney-worx4you](https://github.com/yuney-worx4you) + +(release-v10.0-major-release)= +## Release v10.0 - [Major Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **10.0.4, released 2024-12-10** + - Mattermost v10.0.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin [v1.3.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.3.2). + - Mattermost v10.0.4 contains no database or functional changes. +- **10.0.3, released 2024-11-14** + - Mattermost v10.0.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v10.0.3 contains no database or functional changes. +- **10.0.2, released 2024-10-28** + - Mattermost v10.0.2 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Reverted a change enforcing usernames to start with alpha characters on the server. + - Reverted a breaking change in ``registerSlashCommandWillBePostedHook`` that caused errors to surface in case an expected empty object was returned. + - Mattermost v10.0.2 contains no database or functional changes. +- **10.0.1, released 2024-10-10** + - Mattermost v10.0.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue enabling Professional customers and Team Edition users to upgrade to Playbooks v2 via the in-product marketplace, which fails to start without an Enterprise License. Additional details and discussion can be found on the [forums here](https://forum.mattermost.com/t/clarification-on-playbooks-in-mattermost-v10/20563). + - Mattermost v10.0.1 contains no database or functional changes. +- **10.0.0, released 2024-09-16** + - Original 10.0.0 release. + +### Important Upgrade Notes + - We no longer support new installations using MySQL starting in v10. All new customers and/or deployments will only be supported with the minimum supported version of the PostgreSQL database. End of support for MySQL is targeted for Mattermost v11. + - Apps Framework is deprecated for new installs. Please extend Mattermost using webhooks, slash commands, OAuth2 apps, and plugins. + - Mattermost v10 introduces Playbooks v2 for all Enterprise licensed customers. Professional SKU customers may continue to use Playbooks v1 uninterrupted which will be maintained and supported until September 2025, followed by an appropriate grandfathering strategy. More detailed information and the discussion are available on the [Mattermost discussion forum](https://forum.mattermost.com/t/clarification-on-playbooks-in-mattermost-v10/20563). + - Renamed ``Channel Moderation`` to ``Advanced Access Control`` in the channel management section in the **System Console**. + - Renamed announcement banner feature to “system-wide notifications”. + - Renamed “Collapsed Reply Threads” to “Threaded Discussions” in the System Console. + - Renamed “System Roles” to “Delegated Granular Administration” in the System Console. + - Renamed "Office 365" to "Entra ID" for SSO logins. + - Fully deprecated the ``/api/v4/image`` endpoint when the image proxy is disabled. + - Pre-packaged Calls plugin [v1.0.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.0.1). This includes breaking changes including removal of group calls from unlicensed servers in order to focus supportability and quality on licensed servers. Unlicensed servers can continue to use Calls in direct message channels, which represent the majority of activity. + - Removed deprecated ``Config.ProductSettings``, ``LdapSettings.Trace``, and ``AdvancedLoggingConfig`` configuration fields. + - Removed deprecated ``pageSize`` query parameter from most API endpoints. + - Deprecated the experimental Strict CSRF token enforcement. This feature will be fully removed in Mattermost v11. + +```{Important} +If you upgrade from a release earlier than v9.11, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Mattermost Microsoft Teams Plugin + - Pre-packaged the Microsoft Teams plugin for Mattermost, [v2.0.3](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.0.3). + +#### Mattermost Microsoft Calendar and Microsoft Teams Meetings Plugins + - Pre-packaged Microsoft Calendar Integration [v1.3.4](https://github.com/mattermost/mattermost-plugin-mscalendar/releases/tag/v1.3.4) and Microsoft Teams Meetings [v2.2.0](https://github.com/mattermost-community/mattermost-plugin-msteams-meetings/releases/tag/v2.2.0) plugins. + +#### Mattermost Copilot GA + - Pre-packaged Mattermost Copilot plugin version [v1.0.0](https://github.com/mattermost/mattermost-plugin-ai/releases/tag/v1.0.0). + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls plugin [v1.0.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.0.1). + - Added Playbooks [v2.0.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.0.1) to the prepackaged plugins. + - Added Mattermost user survey plugin to pre-packaged plugins, [v1.1.1](https://github.com/mattermost/mattermost-plugin-user-survey/releases). + - Changed the right-hand side scroll direction and fixed the advanced text editor to the bottom. + - Added [Do not disturb and late timezone warnings](https://docs.mattermost.com/end-user-guide/collaborate/channel-types.html#direct-message-channels) to Direct Message posts. + - Added user statuses to the Group Members modal. + - Added labels for channel header and purpose in the right-hand side channel info view. + - Added pagination support to the **Integrations > Incoming WebHooks** page to be able to navigate through all configured incoming webhooks. + - Made various improvements to code involving user preferences. + - Promoted GIF picker, custom groups and message priority out of Beta. + - Removed the **Pre-release features** section from **Settings > Advanced** due to lack of usage. + +#### Administration + - Made payload size limit error more clearly visible and recognisable in API responses and server error logs. + - Extended the plugin schema to support defining sections for **System Console** settings. + - Added support for a default team on secure connections for incoming channel invites. + - Remote clusters can now be created without explicitly providing a password. + - Files are now fetched from all nodes in a cluster when generating a Support Packet. + - Docker images are now based on Ubuntu Noble. + +#### Performance + - Removed a re-render on channel change. + - Batched requests made by certain components for loading users and their statuses from the server. + - Cleaned up some unused post handling logic. + +### Bug Fixes + - Fixed an issue with web app notifications not being shown in the **Notification Center** on Windows or Mac. + - Fixed an issue with ``mmctl webhooks list`` to paginate past 200 results. + - Fixed an issue where scrolling capability and a visible scrollbar were missing in post textboxes. + - Fixed an issue where false warnings about Channel indexes being incorrect were sent to system admins. + - Fixed an issue where indexing would always be done async even after setting ``LiveIndexingBatchSize`` to ``1``. Now we respect the config and index synchronously if the value is set to ``1``. + - Fixed an issue where the **Edit Post Time Limit** button was not being displayed in the System Console. + - Fixed another issue where users would not see channels they were added to/messages from those channels in clustered environments. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added a new setting ``MaximumURLLength`` to remove the hardcoded URL length limit. + - Removed deprecated ``Config.ProductSettings``. + - Removed ``EnablePreviewFeatures`` setting. + +#### Changes to the Enterprise plan: + - Removed deprecated ``LdapSettings.Trace`` setting. + - Removed deprecated ``AdvancedLoggingConfig`` setting. + +### API Changes + - Reduced the number of API requests made to fetch user information for Group Messages on page load. + - User APIs now enforce username beginning with alphabetic character, matching client-side validation. + - Added a new request parameter ``include_total_count`` to API endpoint ``GET /api/v4/hooks/incoming``. + +### Go Version + - v10.0 is built with Go ``v1.21.8``. + +### Open Source Components + - Added ``redis/rueidis`` to https://github.com/mattermost/mattermost. + +### Known Issues + - The cursor is not placed in the "Write to" field on login. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [abhijit-singh](https://github.com/abhijit-singh), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [alexcekay](https://github.com/alexcekay), [amyblais](https://github.com/amyblais), [andreabia](https://github.com/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [axu-trex](https://github.com/axu-trex), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [Boruus](https://github.com/Boruus), [BrandonS09](https://github.com/BrandonS09), [bruno-keiko](https://github.com/bruno-keiko), [Camillarhi](https://github.com/Camillarhi), [catalintomai](https://github.com/catalintomai), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [DemoYeti](https://github.com/DemoYeti), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [Eleferen](https://translate.mattermost.com/user/Eleferen), [elewis787](https://github.com/elewis787), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esethna](https://github.com/esethna), [ezekielchow](https://github.com/ezekielchow), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [gabrieljackson](https://github.com/gabrieljackson), [Gesare5](https://github.com/Gesare5), [gvarma28](https://github.com/gvarma28), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [imanmagomedov.said](https://translate.mattermost.com/user/imanmagomedov.said), [isacikgoz](https://github.com/isacikgoz), [ja49619](https://translate.mattermost.com/user/ja49619), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://translate.mattermost.com/user/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KvngMikey](https://github.com/KvngMikey), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [MattSilvaa](https://github.com/MattSilvaa), [mgdelacroix](https://github.com/mgdelacroix), [movion](https://github.com/movion), [mvitale1989](https://github.com/mvitale1989), [NCPSNetworks](https://translate.mattermost.com/user/NCPSNetworks), [nickmisasi](https://github.com/nickmisasi), [ovrheat](https://github.com/ovrheat), [petersauvignon](https://translate.mattermost.com/user/petersauvignon), [phoinixgrr](https://github.com/phoinixgrr), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [RS-labhub](https://github.com/RS-labhub), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sblaisot](https://github.com/sblaisot), [Sn-Kinos](https://github.com/Sn-Kinos), [spirosoik](https://github.com/spirosoik), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [tasnim0tantawi](https://github.com/tasnim0tantawi), [TealWater](https://github.com/TealWater), [theaino](https://github.com/theaino), [ThrRip](https://translate.mattermost.com/user/ThrRip), [Tihomir-N](https://github.com/Tihomir-N), [tnir](https://translate.mattermost.com/user/tnir), [toninis](https://github.com/toninis), [vish9812](https://github.com/vish9812), [wiggin77](https://github.com/wiggin77), [willypuzzle](https://github.com/willypuzzle), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) diff --git a/docs/main/product-overview/mattermost-v11-changelog.mdx b/docs/main/product-overview/mattermost-v11-changelog.mdx new file mode 100644 index 000000000000..9bf15b7c35d2 --- /dev/null +++ b/docs/main/product-overview/mattermost-v11-changelog.mdx @@ -0,0 +1,883 @@ +--- +title: "v11 Changelog" +--- +import Inc0_common_esr_support_upgrade from './common-esr-support-upgrade.mdx'; + +{/* TODO: eval-rst block left verbatim, port manually */} +``` +.. meta:: + :page_title: Mattermost Server v11 Release Notes +``` + +```{Important} + + + +Platform and OS scope reflects reported and tested environments and may not represent all affected configurations. + + + +(release-v11.6-feature-release)= +## Release v11.6 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.6.1, released 2026-04-22** + - Mattermost v11.6.1 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.13.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.13.0). + - Pre-packaged GitHub plugin version [v2.7.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.7.0). + - Pre-packaged Boards plugin [v9.2.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.4). + - Added a new API endpoint ``PUT /api/v4/channels/{channel_id}/members`` that sets the complete membership of a channel in a single call. The endpoint accepts a JSON object with ``members`` (desired user IDs) and an optional ``channel_admins`` (user IDs to designate as channel admins). The server computes the diff against current membership, adds or removes users as needed, and reconciles admin roles. Results are streamed back as NDJSON for progress tracking. Requires system admin permissions. + - Updated URL validation in integration actions to make them more secure. + - Improved response handling for outgoing webhook requests. + - Upgraded Go to 1.25.8. + - Mattermost v11.6.1 contains no database or functional changes. +- **11.6.0, released 2026-04-16** + - Original 11.6.0 release. + +### Upgrade Impact + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to all plans:** + - Under ``ServiceSettings`` in ``config.json``, added a configuration setting ``MinimumDesktopAppVersion`` to enforce a minimum Desktop App version that shows a warning screen when a user is on an older version. + - **Changes to Professional and Enterprise plans:** + - Under ``SSOSettings`` in ``config.json``, added a configuration setting ``UsePreferredUsername`` to add support for OpenID Connect (OIDC) [``preferred_username`` profile field](https://docs.mattermost.com/administration-guide/onboard/sso-openidconnect.html#step-2-configure-mattermost-for-an-openid-connect-sso) as the mapped Mattermost username for GitLab, OpenID and EntraID/M365. This feature can be enabled in the **OpenID Connect** tab in the System Console. + - **Changes to Enterprise plans:** + - Under ``ElasticsearchSettings`` in ``config.json``, added a configuration setting ``EnableCJKAnalyzers`` to enable using CJK analysis plugins when installed. + - Under ``ElasticsearchSettings`` in ``config.json``, added a configuration setting ``EnableSearchPublicChannelsWithoutMembership`` to allow searching public channel messages without channel membership. + - Under ``PrivacySettings`` in ``config.json``, added ``UseAnonymousURLs`` to support creating teams and channels using anonymous URLs. + - Removed redundant ``EnableChannelScopeAccessControl`` configuration setting; [channel-level ABAC](https://docs.mattermost.com/administration-guide/manage/admin/abac-channel-access-rules.html#troubleshooting-and-faqs) is now controlled by main toggle and permissions only. + - Removed unused configuration settings ``ExperimentalAuditSettings.FileMaxSizeMB``, ``FileMaxAgeDays``, ``FileMaxBackups``, ``FileCompress``, and ``FileMaxQueueSize``. These settings were never applied to the audit log file target. Use ``AdvancedLoggingJSON`` for fine-grained audit log configuration. + +#### Compatibility + - Updated minimum supported macOS version to 14+ and minimum Safari version to 26.2+. + +```{Important} +If you upgrade from a release earlier than v11.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-6-is-now-available/) on the highlights in our latest release. + +#### UI Changes + - Pre-packaged Calls plugin version [v1.11.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.4). + - Pre-packaged Playbooks plugin version [v2.8.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.8.0). + - Pre-packaged MS Calendar plugin version [v1.6.0](https://github.com/mattermost/mattermost-plugin-mscalendar/releases/tag/v1.6.0). + - Pre-packaged MS Teams Meetings plugin version [v2.4.1](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.4.1). + - Pre-packaged GitLab plugin version [v1.12.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.12.1). + - Added support for Default Agent in suggestions and integrated Agents into the App Bar. + - Improved the reliability of AI recap summarization by using structured JSON output from the LLM. + - Added a new feature of creating teams and channels using [anonymous URLs](https://docs.mattermost.com/end-user-guide/collaborate/rename-channels.html) so the channel and team name are not revealed in the URL. Requires Enterprise Advanced license. + - Added [popouts](https://docs.mattermost.com/end-user-guide/collaborate/search-for-messages.html#search-for-message) for Recent Mentions, Saved Messages, and Search Results via the right-hand side. + - The emoji picker on web and Desktop now inserts unicode emoji characters into the message composer instead of shortcode text. + - Renamed Enterprise Advanced feature Content Flagging to Data Spillage. + - Added [a contextual note](https://docs.mattermost.com/administration-guide/onboard/sso-google.html#step-3-configure-mattermost-for-google-apps-sso) in Security Settings that explains how Google SSO can synchronize usernames and emails, shown alongside the Sign-in Method details. + - Renamed ``SlackAttachment`` and ``SlackAttachmentField`` types to ``MessageAttachment`` and ``MessageAttachmentField``. Old names are maintained as deprecated aliases for backward compatibility with plugins. + - Posts created by integrations using Slack-compatible attachments (webhooks, bots, plugins) are now fully searchable in Elasticsearch. Previously, only the attachment text field was indexed. Now title, pretext, fallback, and field content are also indexed. A bulk re-index is required after upgrade to apply this to existing posts. + - Added timezone support and manual time entry for Interactive Dialog ``datetime`` fields. + - Added sub-day relative date patterns (H/M/S) for datetime dialog fields, enabling min/max constraints with hour, minute, and second precision. + +#### Administration + - Added "Guests in single channel" and "Guests in multiple channels" [role filters](https://docs.mattermost.com/administration-guide/onboard/guest-accounts.html) and a "Channel count" column to the System Console Users report. + - Added reporting and soft-limit tracking for single-channel guests. Single-channel guests are no longer counted toward the primary licensed seat count and are permitted free up to a 1:1 ratio with licensed seats. A new stat card, license row, and admin banner provide visibility into single-channel guest usage and overage warnings. + - Introduced authentication token generation for Hosted Push Notification Service. + - Users assigned the Shared Channel Manager role can now share and unshare channels and browse available connections without needing the Secure Connection Manager role. + - System Admins are now allowed [to view and update](https://docs.mattermost.com/administration-guide/configure/user-management-configuration-settings.html#users) User **AuthData** and **Username** in the System Console. + - Added single-channel guest count to the support packet stats for improved licensing visibility. + +#### Performance + - Added Prometheus metrics support for plugin webapp performance measurements, enabling monitoring and load testing of plugin client-side operations. + - Data spillage reports are now cached in the Redux store to reduce unnecessary API calls and to improve performance. + +#### Plugins + - Added support for using CJK analysis plugins if installed for Elasticsearch (also Opensearch) to improve search results for Korean, Japanese and Chinese languages. + - Added the ability for plugins to programmatically open their right-hand side panel in a pop-out window. + - Plugins can now display times in specific timezones and allow text input for exact times. + +### Bug Fixes + - Fixed an issue where OAuth and SAML login failed when a ``redirect_to`` URL parameter was provided. + - Fixed Interactive Dialog datetime fields to respect user's 12-hour/24-hour time display preference. Also fixed inconsistent date formatting between date and datetime fields. + - Fixed an issue with Shared Channels where channel memberships would not sync after remote reconnect. + - Fixed an issue where Shared Channels related slash commands were failing in High Availability cluster environments. + - Fixed an issue with incorrectly displaying **Channel Mentions** as **Channel Links**. + - Fixed an issue with the right-hand side panel snapping to minimum width on resize. + - Fixed an issue where encoded special characters present in post attachment titles would be displayed as-is instead of decoding the characters. + - Fixed an issue with the results header disappearing in the **Find Channels** dialog. + - Fixed an issue where the "Last login" field in System Console **Users** table was empty. + - Fixed an issue where old scheduled posts with a ``NULL`` value in the ``Type`` column caused a SQL error when fetching the team's scheduled posts. + - Fixed an issue where Intune settings had incorrect configuration access tags, causing warning logs and preventing delegated admins from configuring Intune settings. + - Fixed a cache issue for ``Channels.GetMany`` and ``Channels.getByNames``. + - Fixed an issue with AI rewrites where pressing **Enter** during IME composition would trigger the submit action. + - Fixed an issue where the configuration wasn’t kept when the plugin system was re-enabled. + - Fixed a critical timezone preservation bug. + - Fixed an issue where Elasticsearch server version and plugins were not included in the Support Packet diagnostics. + - Fixed an issue in the job progress estimation that caused progress percentages to be larger than 100. + - Fixed an issue with system bot Direct Messages failing when direct message restrictions were enabled. + - Fixed an issue where clicking a channel checkbox in the **Create Recap** modal did not select the channel. + - Fixed incorrect "Copilot" copy shown in the **Create Recap** modal for the "Recap all my unreads" option. + - Fixed an issue where opening Recaps could leave the previously selected channel highlighted in the left-hand sidebar. + - Fixed a visual issue where the Recaps sidebar icon was vertically misaligned with its label. + - Fixed an issue where permalink previews did not show important or urgent post badges. + - Fixed an issue with multiselect dialog fields with dynamic data sources not splitting comma-separated default values into individual selections. + - Fixed post rendering errors when certain invalid links were part of message attachments. + - Added security validation to prevent plugin uploads when the plugin directory conflicted with the import directory, and vice versa. + - Fixed an issue where remote cluster invite confirmations could accept a ``RefreshedToken`` that matched the original invite token, preventing proper token rotation. + - Fixed an issue where membership changes from remote clusters could operate on a different channel than the one validated in the sync message. + - Fixed a regression where the ``system_admin`` role on new installations or after certain updates was missing the ``manage_oauth`` permission, preventing access to OAuth application management API endpoints. This change restores the permission to the default ``system_admin`` role and includes a migration to backfill it on affected existing servers. + - Fixed an issue where popouts changing state did not update the title on Desktop App. + - Fixed an issue with angle brackets displaying as HTML entities in inline code blocks within dialog markdown text. + - Fixed an issue where image proxies did not detect content-types accurately in certain cases. + - Fixed an issue with edit post permissions. + - Fixed text contrast issues with the marketplace modal when using dark themes. + - Fixed an issue with custom slash command response URL construction. + - Fixed an issue with [file attachment processing](https://docs.mattermost.com/end-user-guide/collaborate/search-for-messages.html#search-for-files) for certain archive types. + - Fixed a server-side validation that was incorrectly rejecting valid datetime and relative patterns in ``MinDate``/``MaxDate`` fields. + - Fixed an issue with the PostgreSQL query parameter overflow and added transactional atomicity for bulk inserts of channel members, team members, thread memberships, posts, statuses, and group members. + - Fixed an issue with source language detection for auto-translations. + - Fixed typing issues in the **Find Channels** modal caused by interference with IMEs. + - Fixed an issue where thread context for message rewrites could be assembled without applying the same channel read validation used for other post reads. + +### API Changes + - Updated shared channel API endpoints to use the new Shared Channel Manager role's permission. Users assigned the Shared Channel Manager role can now share and unshare channels and browse available connections without needing the Secure Connection Manager role. + - Added ``operationId`` annotations to ``content_flagging`` endpoints. + - Implemented ``filewillbedownloaded`` and ``sendtoastmessage`` plugin API calls. + +### Audit Log Event Changes + - Added authentication status tracking to logout audit log entries. + +### Go Version + - v11.6 is built with Go ``v1.24.13``. + +### Contributors + - [135yshr](https://github.com/135yshr), [Adam-Schildkraut](https://github.com/Adam-Schildkraut), [adityadav1987](https://github.com/adityadav1987), [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [AulakhHarsh](https://github.com/AulakhHarsh), [avasconcelos114](https://github.com/avasconcelos114), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [calebroseland](https://github.com/calebroseland), [carlisgg](https://github.com/carlisgg), [cheba](https://translate.mattermost.com/user/cheba), [claude](https://github.com/claude), [coltoneshaw](https://github.com/coltoneshaw), [Combs7th](https://github.com/Combs7th), [cpoile](https://github.com/cpoile), [crazylogic03](https://github.com/crazylogic03), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [DannyDaemonic](https://github.com/DannyDaemonic), [davidkrauser](https://github.com/davidkrauser), [davidpaquin](https://github.com/davidpaquin), [devinbinnie](https://github.com/devinbinnie), [DSchalla](https://github.com/DSchalla), [edgarbellot](https://github.com/edgarbellot), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [eshamir3](https://github.com/eshamir3), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [IndushaS](https://github.com/IndushaS), [isacikgoz](https://github.com/isacikgoz), [jgheithcock](https://github.com/jgheithcock), [jprusch](https://translate.mattermost.com/user/jprusch), [JulienTant](https://github.com/JulienTant), [kevrl](https://translate.mattermost.com/user/kevrl), [krotesk](https://translate.mattermost.com/user/krotesk), [larkox](https://github.com/larkox), [LeoVie](https://translate.mattermost.com/user/LeoVie), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://translate.mattermost.com/user/mansil), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://translate.mattermost.com/user/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [mgdelacroix](https://github.com/mgdelacroix), [NARSimoes](https://github.com/NARSimoes), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [Parth10P](https://github.com/Parth10P), [pavelzeman](https://github.com/pavelzeman), [pvev](https://github.com/pvev), [quirkoglass-debug](https://translate.mattermost.com/user/quirkoglass-debug), [Rajat-Dabade](https://github.com/Rajat-Dabade), [roberson-io](https://github.com/roberson-io), [Roy-Orbison](https://github.com/Roy-Orbison), [ruturaj-rathod](https://github.com/ruturaj-rathod), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sudip-kumar-prasad](https://github.com/sudip-kumar-prasad), [svelle](https://github.com/svelle), [Umeaboy](https://translate.mattermost.com/user/Umeaboy), [unode](https://github.com/unode), [VertexToEdge](https://github.com/VertexToEdge), [vetash](https://translate.mattermost.com/user/vetash), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [willypuzzle](https://github.com/willypuzzle), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v11.5-feature-release)= +## Release v11.5 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.5.4, released 2026-04-22** + - Mattermost v11.5.4 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.13.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.13.0). + - Pre-packaged GitHub plugin version [v2.7.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.7.0). + - Pre-packaged Boards plugin [v9.2.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.4). + - Updated URL validation in integration actions to make them more secure. + - Improved response handling for outgoing webhook requests. + - Upgraded Go to 1.25.8. + - Mattermost v11.5.4 contains no database or functional changes. +- **11.5.3, released 2026-04-16** + - Added a new API endpoint ``PUT /api/v4/channels/{channel_id}/members`` that sets the complete membership of a channel in a single call. The endpoint accepts a JSON object with ``members`` (desired user IDs) and an optional ``channel_admins`` (user IDs to designate as channel admins). The server computes the diff against current membership, adds or removes users as needed, and reconciles admin roles. Results are streamed back as NDJSON for progress tracking. Requires system admin permissions. + - Mattermost v11.5.3 contains no database or functional changes. +- **11.5.2, released 2026-04-15** + - Mattermost v11.5.2 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin version [v1.11.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.4). + - Pre-packaged Playbooks plugin version [v2.8.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.8.0). + - Pre-packaged MS Teams Meetings plugin version [v2.4.1](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.4.1). + - Pre-packaged GitLab plugin version [v1.12.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.12.1). + - Fixed an issue where membership changes from remote clusters could operate on a different channel than the one validated in the sync message. + - Fixed an issue where image proxies did not detect content-types accurately in certain cases. + - Fixed an issue with edit post permissions. + - Fixed an issue with file attachment processing for certain archive types. + - Fixed an issue where remote cluster invite confirmations could accept a ``RefreshedToken`` that matched the original invite token, preventing proper token rotation. + - Fixed an issue with custom slash command response URL construction. + - Fixed a regression where the ``system_admin`` role on new installations or after certain updates was missing the ``manage_oauth`` permission, preventing access to OAuth application management API endpoints. This change restores the permission to the default ``system_admin`` role and includes a migration to backfill it on affected existing servers. + - Fixed an issue with bulk imports failing on PostgreSQL when channel, team, or thread membership batches exceeded the 65,535 query parameter limit by automatically chunking large INSERT statements. + - Fixed an issue where thread context for message rewrites could be assembled without applying the same channel read validation used for other post reads. + - Mattermost v11.5.2 contains no database or functional changes. +- **11.5.1, released 2026-03-16** + - Mattermost v11.5.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved security hardening for the user authentication update API endpoint. + - Improved token handling in the guest magic link authentication flow. + - Increased maximum number of ``autotranslations`` workers per node to 64. + - Fixed an issue with the import process looking for the main json import file in subfolders of the export zip file. + - Mattermost v11.5.1 contains no database or functional changes. +- **11.5.0, released 2026-03-16** + - Original 11.5.0 release. + +### Upgrade Impact + +#### Database Schema Changes + - The following schema changes are included in the v11.5 release. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Added a new column ``translations.state`` and a new index ``idx_translations_state`` to the ``translations`` table. + - Added a new column ``channelmembers.autotranslationdisabled`` to the ``channelmembers`` table. + - Modified the column ``translations.objectType`` and changed the primary key ``(objectId, dstLang)`` to ``(objectId, objectType, dstLang)`` in the ``translations`` table. + - Added a new column ``translations.channelid`` to the ``translations`` table. + - Added a new index ``idx_translations_channel_updateat`` to the ``translations`` table. + - Dropped the index ``idx_translations_updateat`` from the ``translations`` table. + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to Enterprise Advanced plan:** + - Added ``Autotranslation`` settings ``Enable``, ``RestrictDMAndGM``, ``Provider``, ``TargetLanguages``, ``Workers``, ``TimeoutMs``, ``LibreTranslate``, and ``Agents`` to support auto-translations. + - **Changes to Enterprise plan:** + - Added ``DCRRedirectURIAllowlist`` under ``ServiceSettings`` to restrict OAuth Dynamic Client Registration redirect URIs with glob patterns and to return ``invalid_redirect_uri`` when any redirect URI is not allowlisted. + +#### Compatibility + - Updated minimum Edge and Chrome versions to 144+. + +```{Important} +If you upgrade from a release earlier than v11.4, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-5-is-now-available/) on the highlights in our latest release. + +#### UI Changes + - Pre-packaged GitLab plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.12.0). + - Pre-packaged MS Teams Meetings plugin version [v2.4.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.4.0). + - Pre-packaged Zoom plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.12.0). + - Pre-packaged Playbooks plugin version [v2.7.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.7.0). + - Pre-packaged GitHub plugin version [v2.6.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.6.0). + - Pre-packaged Calls plugin version [v1.11.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.1). + - Added support for [auto-translations](https://docs.mattermost.com/end-user-guide/collaborate/autotranslate-messages.html). Initial Beta release. Requires Enterprise Advanced license. + - Added the ability for web app plugin code to be loaded asynchronously. + - [AI Rewrites](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html#rewrite-messages-with-ai) now includes some context from the most recent messages in the thread to help provide better rewrites. + - Available AI Agents are now shown in the @-mention autocomplete menu, regardless of channel membership. + - Added the ability to access channel settings and rename a channel from the channel info right-hand sidebar. + - Added tooltips to action buttons, and action errors are now displayed. + - Updated the signup flow to replace the newsletter opt-in with a checkbox to agree to the **Acceptable Use Policy** and **Privacy Policy**. + - Added back [offline **Help** documentation](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html) accessible from the message composer. + - Added [new icons](https://docs.mattermost.com/end-user-guide/collaborate/channel-types.html#archived-channels) for archived and private channels. + +#### Administration + - Added a [``mmctl license get`` command](https://docs.mattermost.com/administration-guide/manage/mmctl-command-line-tool.html#mmctl-license-get) to retrieve and display current server license information. + - Introduced ``protected`` attribute on property fields to restrict write access to the managing plugin. + - Introduced ``access_mode`` attribute on property fields to manage read access. + - Configured the build system to natively build the server on FreeBSD. + - Upgraded to node 24 and main dependencies with ``babel``, ``webpack@5.103`` and ``jest@30``. + - Renamed **Self-Deleting Messages** to **Burn on Read** in the **System Console**. + - Added [CJK Post search support for PostgreSQL](https://docs.mattermost.com/administration-guide/configure/enabling-chinese-japanese-korean-search.html), which sits behind the new feature flag ``MM_FEATUREFLAGS_CJKSEARCH``. + +#### Performance + - Benchmarking test results showed no significant difference: a 4.28% increase in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.5). + +### Bug Fixes + - Fixed an issue with popout windows in subpath deployments. + - Fixed an issue where additional error details were missing from ``ElasticSearch`` test connection failures. + - Fixed an issue where several Shared Channels operations recorded failure into the audit log even when successful. + - Fixed an issue where the check-cws-connection endpoint returned 500 errors in self-hosted enterprise environments. + - Fixed a performance regression that caused the requests to populate the **Recent mentions** right-hand side (RHS) to timeout. This, in turn, re-introduces a known bug in searches with quoted strings, that may include results not exactly matching the quoted string. + - Fixed an issue where an un-needed **Cancel** button was shown for **User Attributes** in the **System Console**. + - Fixed an issue where plugin settings marked as ``secret: true`` inside ``settings_schema.sections[]`` were not sanitized, potentially exposing secret values through the API. + - Fixed an issue with link preview metadata processing and image validation. + - Fixed an issue with the usage of ``WebSocketClient`` from ``@mattermost/shared`` package being broken in Node.js environments. + - Fixed an issue where rate limiting was missing from the login endpoint (5 requests/second, 10 burst). + - Fixed an issue where the profile status menu disappeared at higher zoom levels or at resized window on mobile view. + - Fixed an issue where importing a guest user without team or channel memberships would cause the bulk import to fail with an error. + +### Audit Log Event Changes + - Updated audit/activity logging for Desktop App external authentication. + - Added [audit logs](https://docs.mattermost.com/administration-guide/comply/embedded-json-audit-log-schema.html) for when admins access posts on channels they are not a member of. + - Added new [audit events](https://docs.mattermost.com/administration-guide/comply/embedded-json-audit-log-schema.html#ai-recap-events) ``AuditEventCreateRecap``, ``AuditEventGetRecap``, ``AuditEventGetRecaps``, ``AuditEventMarkRecapAsRead``, ``AuditEventRegenerateRecap``, and ``AuditEventDeleteRecap``. + - Added a new audit event ``AuditEventUpdateChannelMemberAutotranslation``. + - Added a new audit event ``AuditEventLoginWithDesktopToken``. + - Added new audit events ``AuditEventListChannelBookmarksForChannel``, ``AuditEventGetPinnedPosts``, ``AuditEventGetFileThumbnail``, ``AuditEventGetFileInfosForPost``, ``AuditEventGetFileInfo``, ``AuditEventGetFilePreview``, ``AuditEventSearchFiles``, ``AuditEventCreateEphemeralPost``, ``AuditEventGetEditHistoryForPost``, ``AuditEventGetFlaggedPosts``, ``AuditEventGetPostsForChannel``, ``AuditEventGetPostsForChannelAroundLastUnread``, ``AuditEventGetPost``, ``AuditEventGetPostThread``, ``AuditEventGetPostsByIds``, ``AuditEventGetThreadForUser``, ``AuditEventNotificationAck``, and ``AuditEventWebsocketPost``. + +### Go Version + - v11.5 is built with Go ``v1.24.13``. + +### Open Source Components + - Added ``react-intl`` and ``x/sys``, and replaced ``avct/uasurfer`` with ``LumenResearch/uasurfer`` in https://github.com/mattermost/mattermost. + +### Contributors + - [adityadav1987](https://github.com/adityadav1987), [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [bshumylo](https://translate.mattermost.com/user/bshumylo), [calebroseland](https://github.com/calebroseland), [carlisgg](https://github.com/carlisgg), [catalintomai](https://github.com/catalintomai), [Combs7th](https://github.com/Combs7th), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [guenjun](https://translate.mattermost.com/user/guenjun), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jgheithcock](https://github.com/jgheithcock), [JOAO-Ethan](https://github.com/JOAO-Ethan), [jprusch](https://translate.mattermost.com/user/jprusch), [JulienTant](https://github.com/JulienTant), [kondo97](https://github.com/kondo97), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [locnnil](https://github.com/locnnil), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [milotype](https://translate.mattermost.com/user/milotype), [NARSimoes](https://github.com/NARSimoes), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [ogi-m](https://github.com/ogi-m), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://translate.mattermost.com/user/Reinkard), [roman.belda](https://translate.mattermost.com/user/roman.belda), [Roy-Orbison](https://translate.mattermost.com/user/Roy-Orbison), [sadohert](https://github.com/sadohert), [salvatorearianna](https://translate.mattermost.com/user/salvatorearianna), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [SharpGoldHawk](https://translate.mattermost.com/user/SharpGoldHawk), [Sharuru](https://translate.mattermost.com/user/Sharuru), [svelle](https://github.com/svelle), [thePanz](https://translate.mattermost.com/user/thePanz), [ThrRip](https://translate.mattermost.com/user/ThrRip), [Umeaboy](https://translate.mattermost.com/user/Umeaboy), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [ZeWaren](https://github.com/ZeWaren) + +(release-v11.4-feature-release)= +## Release v11.4 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.4.5, released 2026-04-22** + - Mattermost v11.4.5 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.13.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.13.0). + - Pre-packaged GitHub plugin version [v2.7.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.7.0). + - Pre-packaged Boards plugin [v9.2.4](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.4). + - Updated URL validation in integration actions to make them more secure. + - Improved response handling for outgoing webhook requests. + - Upgraded Go to 1.25.8. + - Mattermost v11.4.5 contains no database or functional changes. +- **11.4.4, released 2026-04-15** + - Mattermost v11.4.4 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin version [v1.11.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.4). + - Pre-packaged Playbooks plugin version [v2.8.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.8.0). + - Pre-packaged MS Teams Meetings plugin version [v2.4.1](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.4.1). + - Pre-packaged GitLab plugin version [v1.12.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.12.1). + - Fixed an issue where membership changes from remote clusters could operate on a different channel than the one validated in the sync message. + - Fixed an issue where image proxies did not detect content-types accurately in certain cases. + - Fixed an issue with edit post permissions. + - Fixed an issue with file attachment processing for certain archive types. + - Fixed an issue where remote cluster invite confirmations could accept a ``RefreshedToken`` that matched the original invite token, preventing proper token rotation. + - Fixed an issue with custom slash command response URL construction. + - Mattermost v11.4.4 contains no database or functional changes. +- **11.4.3, released 2026-03-16** + - Mattermost v11.4.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved security hardening for the user authentication update API endpoint. + - Improved token handling in the guest magic link authentication flow. + - Fixed a regression where the ``system_admin`` role on new installations or after certain updates was missing the ``manage_oauth`` permission, preventing access to OAuth application management API endpoints. This change restores the permission to the default ``system_admin`` role and includes a migration to backfill it on affected existing servers. + - Mattermost v11.4.3 contains no database or functional changes. +- **11.4.2, released 2026-02-26** + - Mattermost v11.4.2 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v11.4.2 contains no database or functional changes. +- **11.4.1, released 2026-02-23** + - Mattermost v11.4.1 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.12.0). + - Fixed an issue with link preview metadata processing and image validation. + - Fixed an issue where rate limiting was missing from the login endpoint (5 requests/second, 10 burst). + - Mattermost v11.4.1 contains no database or functional changes. +- **11.4.0, released 2026-02-16** + - Original 11.4.0 release. + +### Upgrade Impact + +```{Attention} +**Breaking Changes** + - Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments. +``` + +#### Database Schema Changes + - Added two new tables, ``Recaps`` and ``RecapChannels``. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +#### Compatibility + - Updated minimum Edge and Chrome versions to 142+. + +```{Important} +If you upgrade from a release earlier than v11.3, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-4-is-now-available/) on the highlights in our latest release. + +#### User Interface + - Pre-packaged Boards plugin version [v9.2.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.2). + - Pre-packaged Jira plugin version [v4.5.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.5.1). + - Pre-packaged Playbooks plugin version [v2.6.2](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.6.2). + - Updated illustrations and visual design for the initial loading screen, preparing workspace flow, IP filtering empty state, and admin console feature discovery panels. + - Added adjustments to thread and right-hand side plugin pop-out titles. + - MS Teams and Outlook on mobile no longer display a "Your browser does not support notifications" warning banner when running Mattermost embedded in those apps. + +#### Administration + - Added [debug logs](https://docs.mattermost.com/administration-guide/manage/logging.html#cluster-job-execution-debug-messages) to indicate if the scheduled post job, Do Not Disturb status reset job, or the post reminder job is not running with the current node not being a leader node. + - Added CPU cores and total memory to the Support Packet. + - Added a new ``MM_LOG_PATH`` environment variable to [restrict log file locations](https://docs.mattermost.com/administration-guide/manage/logging.html#log-path-restrictions). Log files must now be within a configured root directory. + +#### Performance + - Benchmarking test results showed no significant difference: a 0.28% decrease in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.4). + +### Bug Fixes + - Fixed an issue with the behavior of the right‑hand sidebar (RHS) when navigating to global threads. The application now checks the current RHS state and suppresses the sidebar only if it is not showing mentions, search results, or flagged posts. + - Fixed an issue where the post list automatically scrolled to the bottom when a user edited a message. + - Fixed the misaligned design in posts in the thread view on mobile view. + - Fixed **Add channels** menu getting cut off when the **Direct Messages** category was collapsed. + - Fixed an issue with the user's theme applying when it shouldn't, such as when creating a new team. + - Fixed an issue where the channel info right sidebar was not scrollable. + - Fixed an issue with PSD file previews. + - Fixed an issue where users removed from a private team could still enumerate public channels in that team via the channel search API. + - Fixed an issue with permalink embeds arriving from websocket messages. + - Fixed an issue with memory use during integration actions. + - Fixed an issue with permalink preview information after losing channel or team permissions. + - Fixed a permission validation issue when attaching files to posts. + - Fixed a memory allocation issue by updating ``mscfb`` and ``msoleps`` dependencies. + - User's actual authentication method is now validated before processing authentication type switch. + - Fixed an issue where the ``/mute`` slash command could be used to enumerate private channels. + +### API Changes + - Updated the POST `/api/v4/teams` team creation API to omit the `invite_id` value in the response when the requesting user does not have permission to invite members to the new team. + - ``ImportSettings.Directory`` can no longer be modified through the REST API. Infrastructure operators can still modify this setting via configuration file, environment variables, or mmctl in local mode. + - ``/api/v4/access_control_policies/{policy_id}/activate`` has been deprecated. + +### Audit Log Event Changes + - Added a new audit event ``AuditEventGenerateSupportPacket``. + +### Go Version + - v11.4 is built with Go ``v1.24.11``. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [akshat-khosya](https://github.com/akshat-khosya), [Alesia](https://translate.mattermost.com/user/Alesia), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [Boruus](https://github.com/Boruus), [brandon1024](https://github.com/brandon1024), [bshumylo](https://translate.mattermost.com/user/bshumylo), [calebroseland](https://github.com/calebroseland), [carlisgg](https://github.com/carlisgg), [CIOSAI](https://translate.mattermost.com/user/CIOSAI), [Combs7th](https://github.com/Combs7th), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danilvalov](https://github.com/danilvalov), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jgheithcock](https://github.com/jgheithcock), [jprusch](https://translate.mattermost.com/user/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [Kuruyia](https://github.com/Kuruyia), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lifeisafractal](https://github.com/lifeisafractal), [lindalumitchell](https://github.com/lindalumitchell), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marko-matusovic](https://translate.mattermost.com/user/marko-matusovic), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [merlynadena](https://github.com/merlynadena), [mikhail10](https://translate.mattermost.com/user/mikhail10), [milotype](https://translate.mattermost.com/user/milotype), [Morgan_svk](https://translate.mattermost.com/user/Morgan_svk), [NARSimoes](https://github.com/NARSimoes), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://translate.mattermost.com/user/Reinkard), [Ricky-Tigg](https://translate.mattermost.com/user/Ricky-Tigg), [roberson-io](https://github.com/roberson-io), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shawnaym](https://github.com/shawnaym), [svelle](https://github.com/svelle), [ThrRip](https://translate.mattermost.com/user/ThrRip), [tnir](https://github.com/tnir), [tsabi](https://translate.mattermost.com/user/tsabi), [Umeaboy](https://translate.mattermost.com/user/Umeaboy), [vadim.asadchi](https://translate.mattermost.com/user/vadim.asadchi), [varghesejose2020](https://github.com/varghesejose2020), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wooki-00](https://translate.mattermost.com/user/wooki-00), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v11.3-feature-release)= +## Release v11.3 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.3.3, released 2026-03-16** + - Mattermost v11.3.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved security hardening for the user authentication update API endpoint. + - Improved token handling in the guest magic link authentication flow. + - Fixed a regression where the ``system_admin`` role on new installations or after certain updates was missing the ``manage_oauth`` permission, preventing access to OAuth application management API endpoints. This change restores the permission to the default ``system_admin`` role and includes a migration to backfill it on affected existing servers. + - Mattermost v11.3.3 contains no database or functional changes. +- **11.3.2, released 2026-02-23** + - Mattermost v11.3.2 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.12.0). + - Fixed an issue with link preview metadata processing and image validation. + - Fixed an issue where rate limiting was missing from the login endpoint (5 requests/second, 10 burst). + - Mattermost v11.3.2 contains no database or functional changes. +- **11.3.1, released 2026-02-13** +```{Attention} +**Breaking Changes** + - Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments. +``` + - Mattermost v11.3.1 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.2.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.2). + - Pre-packaged Playbooks plugin version [v2.6.2](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.6.2). + - Fixed an issue with PSD file previews. + - Added a new ``MM_LOG_PATH`` environment variable to restrict log file locations. Log files must now be within a configured root directory. + - Fixed an issue where the ``/mute`` slash command could be used to enumerate private channels. + - Fixed an issue where users removed from a private team could still enumerate public channels in that team via the channel search API. + - Fixed an issue with permalink embeds arriving from websocket messages. + - Fixed a memory allocation issue by updating ``mscfb`` and ``msoleps`` dependencies. + - Fixed an issue with memory use during integration actions. + - ``/api/v4/access_control_policies/{policy_id}/activate`` has been deprecated. + - Updated the POST `/api/v4/teams` team creation API to omit the `invite_id` value in the response when the requesting user does not have permission to invite members to the new team. + - ``ImportSettings.Directory`` can no longer be modified through the REST API. Infrastructure operators can still modify this setting via configuration file, environment variables, or mmctl in local mode. + - Fixed a permission validation issue when attaching files to posts. + - Mattermost v11.3.1 contains no database or functional changes. +- **11.3.0, released 2026-01-16** + - Original 11.3.0 release. + +**Release Day: January 16, 2026** + +### Upgrade Impact + +#### Database Schema Changes + - Added schema changes in the form of a new tables (``ReadReceipts`` and ``TemporaryPosts``) that aggregate user attributes into a separate table. Added ``Type`` field for both ``Drafts`` and ``ScheduledPosts``. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - Added a new ``translations`` table and two new columns (``channels.autotranslation``, ``channelmembers.autotranslation)``. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to Enterprise Advanced plan:** + - Under ``ServiceSettings`` in ``config.json``, added ``EnableBurnOnRead``, ``BurnOnReadDurationSeconds``, ``BurnOnReadMaximumTimeToLiveSeconds`` and ``BurnOnReadSchedulerFrequencySeconds``. + - **Changes to Enterprise plans:** + - Under ``GuestAccountsSettings`` in ``config.json``, added ``EnableGuestMagicLink``. + - Under ``ServiceSettings`` in ``config.json``, added ``AWSMeteringTimeoutSeconds``. This configuration value can be used to set the timeout in seconds when connecting to the AWS marketplace metering service. + - Under ``NativeAppSettings`` in ``config.json``, added ``EnableIntuneMAM``, which can be edited in the **System Console**. + +#### Important Upgrade Notes + - Beginning in Mattermost v11.3, some plugins that register a Right Hand Sidebar (RHS) component using ``registerRightHandSidebarComponent`` will need to implement additional code to support RHS popouts if their RHS component relies on plugin-specific state. See [this forum post](https://forum.mattermost.com/t/rhs-popout-support-for-plugins/25626) for full details. + +```{Important} +If you upgrade from a release earlier than v11.2, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-3-is-now-available/) on the highlights in our latest release. + +#### User Interface + - Pre-packaged Microsoft Calendar plugin version [v1.5.0](https://github.com/mattermost/mattermost-plugin-mscalendar/releases/tag/v1.5.0). + - Pre-packaged Agents plugin version [v1.7.2](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.7.2). + - Pre-packaged Zoom plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.11.0). + - Pre-packaged Jira plugin version [v4.5.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.5.0). + - Added Korean language support and upgraded Korean translations from Alpha to Official. + - Added pop-outs for right-hand-side (RHS) plugins. + - Removed outdated system notices. + - Removed the Collapsed Reply Threads tutorial. + - Added support for triggering user mentions using the full-width at-sign (@) in addition to the standard half-width at-sign (@), improving the experience for users of Japanese input methods. + - Added the ability to schedule posts in 15-minutes interval. + - Updated Giphy SDK from 8.1.0 to 10.1.0. + - Custom Profile Attributes now always return a set of [default attributes](https://docs.mattermost.com/administration-guide/manage/admin/user-attributes.html#add-attributes) if they're not set. + - Added a new webapp plugin component ``registerSidebarBrowseOrAddChannelMenuComponent``, which allows users to add options to the ``BrowseOrCreateChannel`` menu. + +#### Administration + - Added [Microsoft Intune MAM authentication support](https://docs.mattermost.com/deployment-guide/mobile/mobile-security-features.html#microsoft-intune-mobile-application-management-mam) (requires Enterprise Advanced license). + - Added a [Burn-on-Read feature](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html#send-burn-on-read-messages) (requires Enterprise Advanced license). + - Added support for passwordless authentication with [Magic Link for guest users](https://docs.mattermost.com/end-user-guide/access/access-your-workspace.html#magic-link-login-for-guests) (requires Enterprise license). + - The channel ABAC auto-sync setting is now individually configurable through the **System Console**. + - Validated [log levels in ``AdvancedLoggingJSON``](https://docs.mattermost.com/administration-guide/manage/logging.html). + - Changes to HTML templates now require a server restart to take effect. + - Updated the AWS SDK dependency. + +#### Performance + - Benchmarking test results showed no significant difference: a 1.61% decrease in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.3). + - Improved the performance of the post textbox and fixed typing bugs in the thread popout. + +### Bug Fixes + - Fixed a translation issue for invalid slash commands to ensure all locales display the correct message. + - Fixed a desktop token infinite redirect when the wrong app was opened. + - Fixed the session expired notification not showing the server name on Desktop App. + - Fixed development Docker Compose files to work on SELinux-enabled hosts. + - Fixed discrepancies with ``control_access_policies/search`` endpoint and its documentation. + - Fixed an issue where channel memberships from exports were not properly validated. + - Fixed an issue where pressing **Back** in the Desktop App after an external login would cause a weird state. + - Fixed a server panic that occurred when a bot created a post with persistent notifications enabled. + - Fixed an issue where the Chrome/Desktop App spell check on Windows often couldn't correct typos. + - Fixed an issue where pressing ``Shift+Up`` in the channel textbox to reply to a thread could cause the right‑hand sidebar (RHS) reply textbox to not focus. + - Fixed an issue where the guest group mentions permission setting was not available in the **System Console** for Professional licenses. + - Fixed a minor UX issue in **Set custom status** modal after visiting the **System Console**. + - Fixed an issue where the ``TelemetryID`` could be temporarily missing on brand new High Availability clusters due to replica lag. + - Fixed an issue where scheduling a post in the thread popout did not work. + +### API Changes + - Added a new ``LoginByEntraIdToken`` API endpoint for MSAL ``id_token`` authentication. + - Added a new ``report/posts`` API for retrieving posts for reporting. + +### Audit Log Event Changes + - Added new audit events ``AuditEventRevealPost`` and ``AuditEventBurnPost``. + - Added a new audit event ``AuditEventSetActiveStatus``. + +### Go Version + - v11.3 is built with Go ``v1.24.6``. + +### Open Source Components + - Replaced ``aws/aws-sdk-go`` with ``aws/aws-sdk-go-v2``, and replaced ``go-yaml/yaml`` with ``goccy/go-yaml``. Added ``mattermost/mattermost-plugin-agents`` and removed ``fsnotify/fsnotify`` and ``html-to-markdown`` from https://github.com/mattermost/mattermost. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [avasconcelos114](https://github.com/avasconcelos114), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [calebroseland](https://github.com/calebroseland), [carlisgg](https://github.com/carlisgg), [Combs7th](https://github.com/Combs7th), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jgheithcock](https://github.com/jgheithcock), [jprusch](https://translate.mattermost.com/user/jprusch), [jwilander](https://github.com/jwilander), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://translate.mattermost.com/user/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mental-space1532](https://github.com/mental-space1532), [minhthanhonly](https://translate.mattermost.com/user/minhthanhonly), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [roberson-io](https://github.com/roberson-io), [RyanisyydsTT](https://translate.mattermost.com/user/RyanisyydsTT), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [Sharuru](https://translate.mattermost.com/user/Sharuru), [Student-coder-web](https://github.com/Student-coder-web), [svelle](https://github.com/svelle), [Taofik01](https://github.com/Taofik01), [tnir](https://github.com/tnir), [Umeaboy](https://translate.mattermost.com/user/Umeaboy), [varghesejose2020](https://github.com/varghesejose2020), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vimobe](https://translate.mattermost.com/user/vimobe), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [zlv](https://github.com/zlv) + +(release-v11.2-feature-release)= +## Release v11.2 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.2.4, released 2026-02-23** + - Mattermost v11.2.4 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.12.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.12.0). + - Fixed an issue with link preview metadata processing and image validation. + - Fixed an issue where rate limiting was missing from the login endpoint (5 requests/second, 10 burst). + - Mattermost v11.2.4 contains no database or functional changes. +- **11.2.3, released 2026-02-13** +```{Attention} +**Breaking Changes** + - Photoshop Document (PSD) files are now no longer inline previewed, they are treated as regular file attachments. +``` + - Mattermost v11.2.3 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.2.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.2.2). + - Pre-packaged Playbooks plugin version [v2.6.2](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.6.2). + - Fixed an issue with PSD file previews. + - Added a new ``MM_LOG_PATH`` environment variable to restrict log file locations. Log files must now be within a configured root directory. + - Fixed an issue where the ``/mute`` slash command could be used to enumerate private channels. + - Fixed an issue where users removed from a private team could still enumerate public channels in that team via the channel search API. + - Fixed an issue with permalink embeds arriving from websocket messages. + - Fixed a memory allocation issue by updating ``mscfb`` and ``msoleps`` dependencies. + - ``/api/v4/access_control_policies/{policy_id}/activate`` has been deprecated. + - Fixed an issue with memory use during integration actions. + - Updated the POST `/api/v4/teams` team creation API to omit the `invite_id` value in the response when the requesting user does not have permission to invite members to the new team. + - ``ImportSettings.Directory`` can no longer be modified through the REST API. Infrastructure operators can still modify this setting via configuration file, environment variables, or mmctl in local mode. + - Fixed a permission validation issue when attaching files to posts. + - Mattermost v11.2.3 contains no database or functional changes. +- **11.2.2, released 2026-01-15** + - Mattermost v11.2.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.11.0). + - Pre-packaged Jira plugin version [v4.5.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.5.0). + - Mattermost v11.2.2 contains no database or functional changes. +- **11.2.1, released 2025-12-16** + - Improved the performance of the post textbox and fixed typing bugs in the thread popout. + - Fixed an issue where Chrome/Desktop App spell check on Windows often couldn't correct typos. + - Fixed an issue where some plugin configurations were deleted when another plugin saved its configuration. + - Pre-packaged Agents plugin [v1.6.3](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.6.3). + - Mattermost v11.2.1 contains no database or functional changes. +- **11.2.0, released 2025-12-16** + - Original 11.2.0 release. + +### Upgrade Impact + +#### Database Schema Changes + - Added a new column to the ``OAuthApps`` table called ``isdynamicallyregistered``. It has a default value of ``false``. Also added three new columns to the ``OAuthAuthData`` table called ``resource``, ``codechallenge`` and ``codechallengemethod``. All columns default to ``‘’``. Also added a new column to the ``OAuthAccessData`` table called ``audience``. It has a default value of ``‘’``. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to Enterprise plans:** + - Under ``ServiceSettings`` in ``config.json``, added ``EnableDynamicClientRegistration`` configuration setting to control whether Dynamic Client Registration is enabled in your Mattermost instance. The default value is ``false``. + +```{Important} +If you upgrade from a release earlier than v11.1, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-2-is-now-available/) on the highlights in our latest release. + +#### User Interface (UI) + - Pre-packaged Playbooks plugin [v2.6.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.6.1). + - Pre-packaged Zoom plugin [v1.10.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.10.0). + - Pre-packaged Agents plugin [v1.6.2](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.6.2). + - Pre-packaged ServiceNow plugin [v2.4.0](https://github.com/mattermost/mattermost-plugin-servicenow/releases/tag/v2.4.0). + - Pre-packaged MS Calendar plugin [v1.4.0](https://github.com/mattermost/mattermost-plugin-mscalendar/releases/tag/v1.4.0). + - Pre-packaged Channel Export plugin [v1.3.0](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.3.0). + - Pre-packaged Boards plugin version [v9.2.1](https://github.com/mattermost/mattermost-plugin-boards/releases). + - Pre-packaged Jira plugin version [v4.4.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.1). + - Enabled [thread popouts](https://docs.mattermost.com/end-user-guide/collaborate/organize-conversations.html#start-or-reply-to-threads) in the browser. + - Reduced the channel banner height. + - Improved license and plan name clarity throughout the user interface. License settings and the **About** modal now display specific plan names (Professional, Enterprise, Entry) instead of the generic "Enterprise Edition" label, reducing confusion between edition and plan terminology. + +#### Administration + - Added search backend type to the Support Packet. + - Added SAML provider type to the Support Packet. + +#### Integrations + - Permission schemes now fully expose controls for managing other users' integrations (Webhooks, Slash Commands, OAuth Apps) in the **System Console** for greater administrative clarity. Additionally, permissions for managing your own integrations have been renamed for consistency, and a new configuration option allows administrators to enforce Incoming Webhook channel locking. + - Added AI-enabled rewriting of messages for servers with the Agents plugin. + - Applicable posts are now marked as AI-generated. + - Added an authorization metadata endpoint and [Dynamic Client Registration of Confidential OAuth Apps](https://docs.mattermost.com/administration-guide/configure/integrations-configuration-settings.html#enable-dynamic-client-registration). + - Added OAuth public client support through DCR and PKCE for public/confidential clients. + - Added support for a resource parameter with OAuth. + - Added ability to create OAuth public clients through the **Integrations** page. + - Added ``http.Flusher`` support to the plugin RPC layer. + +#### Performance + - Benchmarking test results showed no significant difference: a 2.62% decrease in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.2). + +### Bug Fixes + - Fixed a server panic that could occur when patching channel moderations with restricted permissions. + - Fixed the justification of sidebar icons for plugins. + - Fixed an issue with the translation of "Until <time>" text for custom statuses. + - Fixed an issue where guest users could not log in via SAML when "Ignore Guest Users when Synchronizing with AD/LDAP" was enabled. + - Fixed an issue where length validation was missing for LDAP user fields. + - Fixed an issue where some modals would appear when editing messages. + - Fixed an issue where the slash command autocomplete did not preserve user input case when forwarding pretext to backend. + - Fixed an issue where some text on the signup page was not translatable. + - Fixed an issue where thread popouts did not show the current user's status. + - Fixed an issue where clicking on a permalink to a reply in another thread would not navigate the main window. + - Fixed an issue where focusing on the thread popout would not mark the thread as read. + - Fixed an issue where a content reviewer could not download file attachments from a flagged post. + - Fixed an issue where users could not add bots without an error message popping up. + - Fixed an issue displaying custom emojis in thread popouts. + +### API Changes + - Added a new ``api/v4/posts/rewrite`` endpoint to enable AI-powered message rewriting. It accepts a message, an AI agent ID, and a rewrite action, and returns a JSON object with a ``rewritten_text`` field containing the rewritten text. The endpoint supports six predefined actions: ``shorten``, ``elaborate``, ``improve_writing``, ``fix_spelling``, ``simplify``, and ``summarize``. A custom action is also available, which requires a ``custom_prompt`` parameter to specify the desired transformation. + - Updated the ``GetFile`` ``GET`` ``api/v4/files/file_id`` endpoint to include two new query params: ``as_content_reviewer`` and ``flagged_post_id``. These are used for the Data Spillage feature to allow content reviewers to download files from flagged posts. + - Added two new fields to the ``/oauth/authorize`` endpoints called ``code_challenge`` and ``code_challenge_method`` in order to support PKCE with our OAuth authorization flow. + - Added ``/.well-known/oauth-authorization-server`` so that OAuth clients can check what Mattermost supports. The endpoint returns a 501 error if ``ServiceSettings.EnableOAuthServiceProvider`` is disabled. + - Added ``/api/v4/oauth/apps/register`` in order to support Dynamic Client Registration for OAuth. This allows **any** external OAuth client to automatically register an OAuth App within Mattermost without requiring authentication. The endpoint requires ``ServiceSettings.EnableOAuthServiceProvider`` and ``ServiceSettings.EnableDynamicClientRegistration`` to be enabled. + - Introduced ``GET /api/v4/agents`` and ``GET /api/v4/llmservices`` to allow authenticated clients to fetch available agents and LLM services. + +### Audit Log Event Changes + - Added new ``AuditEventRegisterOAuthClient``. + +### Go Version + - v11.2 is built with Go ``v1.24.6``. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [Arusekk](https://github.com/Arusekk), [asaadmahmood](https://github.com/asaadmahmood), [AurelienS](https://github.com/AurelienS), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [calebroseland](https://github.com/calebroseland), [carlisgg](https://github.com/carlisgg), [catenacyber](https://github.com/catenacyber), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [David](https://translate.mattermost.com/user/David), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [domibarton](https://github.com/domibarton), [efemonge](https://translate.mattermost.com/user/efemonge), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [evituzas](https://translate.mattermost.com/user/evituzas), [ferdymercury](https://github.com/ferdymercury), [feyzaozcann](https://github.com/feyzaozcann), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [guenjun](https://translate.mattermost.com/user/guenjun), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [helloinah](https://translate.mattermost.com/user/helloinah), [hmhealey](https://github.com/hmhealey), [iamleson98](https://translate.mattermost.com/user/iamleson98), [isacikgoz](https://github.com/isacikgoz), [itz-Me-Pj](https://github.com/itz-Me-Pj), [j0taD](https://translate.mattermost.com/user/j0taD), [jgheithcock](https://github.com/jgheithcock), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://translate.mattermost.com/user/kaakaa), [kayazeren](https://translate.mattermost.com/user/kayazeren), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://translate.mattermost.com/user/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [Morgan_svk](https://translate.mattermost.com/user/Morgan_svk), [mrckndt](https://github.com/mrckndt), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [oberleg](https://translate.mattermost.com/user/oberleg), [pvev](https://github.com/pvev), [quarac](https://translate.mattermost.com/user/quarac), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [RS-labhub](https://github.com/RS-labhub), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [svelle](https://github.com/svelle), [TimTin](https://translate.mattermost.com/user/TimTin), [tsakmas](https://translate.mattermost.com/user/tsakmas), [tuladhar](https://github.com/tuladhar), [uright](https://github.com/uright), [vpecinka](https://github.com/vpecinka), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [willypuzzle](https://github.com/willypuzzle), [wooki-00](https://translate.mattermost.com/user/wooki-00), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [zlv](https://github.com/zlv) + +(release-v11.1-feature-release)= +## Release v11.1 - [Feature Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.1.3, released 2026-01-15** + - Mattermost v11.1.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Zoom plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.11.0). + - Pre-packaged Jira plugin version [v4.5.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.5.0). + - Mattermost v11.1.3 contains no database or functional changes. +- **11.1.2, released 2025-12-17** + - Mattermost v11.1.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved the performance of the post textbox and fixed typing bugs in the thread popout. + - Fixed an issue where Chrome/Desktop App spell check on Windows often couldn't correct typos. + - Mattermost v11.1.2 contains no database or functional changes. +- **11.1.1, released 2025-11-21** + ```{Attention} + **Critical Fixes** + - Mattermost v11.1.1 contains a Critical severity level security fix in the Jira plugin. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Jira plugin version [v4.4.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.1). + - Fixed an issue where thread popouts did not show the current user's status. + - Fixed an issue where clicking on a permalink to a reply in another thread would not navigate the main window. + - Fixed an issue where users could not add bots without an error message popping up. + - Mattermost v11.1.1 contains no database or functional changes. +- **11.1.0, released 2025-11-14** + - Original 11.1.0 release. + +```{Attention} +**Breaking Changes** + - The version of React used by the Mattermost web app has been updated from React 17 to React 18. See more details in [this forum post](https://forum.mattermost.com/t/upgrading-the-mattermost-web-app-to-react-18-v11/25000). +``` + +### Upgrade Impact + +#### Database Schema Changes + - Added three new tables, ``ContentFlaggingCommonReviewers``, ``ContentFlaggingTeamSettings``, and ``ContentFlaggingTeamReviewers`` for storing Data Spillage settings. Added an index on ``ContentFlaggingTeamReviewers`` table to optimize fetching the team settings. No database downtime is expected for this upgrade. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to Enterprise Advanced plan:** + - Added a new ``AutoTranslationSettings`` configuration settings section. The auto-translation feature will be available in a future release. + +### Compatibility + - Updated minimum required Edge, Firefox and Chrome versions to v140+ and updated minimum supported Windows version to v11+. + +```{Important} +If you upgrade from a release earlier than v11.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-1-is-now-available/) on the highlights in our latest release. + +#### User Interface (UI) + - Pre-packaged Agents plugin version [v1.4.0](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.4.0). + - Pre-packaged Playbooks plugin version [v2.5.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.5.1). + - Pre-packaged GitLab plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.11.0). + - Pre-packaged Jira plugin version [v4.4.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.0). + - Pre-packaged GitHub plugin version [v2.5.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.5.0). + - Pre-packaged Boards plugin version [v9.1.7](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.7). + - Pre-packaged MS Teams Meetings plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.3.0). + - Pre-packaged Calls plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.0). + - Removed Mattermost MS Teams Sync plugin from pre-packaged plugins. + - Added support for standalone windows pop-out. Threads can now be popped out to its own window in Desktop. + - The desktop app version is now shown on the **About** modal, allowing clicking to copy both the server and desktop app versions. + - Downgraded French language support from Beta to Alpha. + +#### Administration + - Added the ability to edit User Attributes in **System Console > Users > User Configuration**. + +#### Integrations + - Added ``Date`` and ``DateTime`` types for interactive dialogs. + - Added ``MultiForm`` and ``Element`` refresh support for interactive dialogs. + +#### Performance + - Benchmarking test results showed no significant difference: a 3.64% decrease in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.1). + +### Bug Fixes + - Fixed an issue where email address verification for SAML/LDAP users was required when a user’s email address changed. + - Fixed an issue where users could still message each other when not sharing a team, despite the configuration setting stating otherwise. + - Fixed an issue with the mmctl system status to return non-zero exit codes when health checks fail, ensuring proper integration with container orchestration health check systems. + - Fixed a configuration retention issue where even active configuration got deleted. + - Fixed an issue where plugins could not receive 3rd-party authorization headers. + +### API Changes + - Added a new API endpoint ``POST /api/v4/groups/names``. + - Added a ``since`` parameter to the property value search method of the ``PluginApi``. + +### Audit Log Event Changes + - Added ``AuditEventFlagPost``, ``AuditEventGetFlaggedPost``, ``AuditEventPermanentlyRemoveFlaggedPost``, ``AuditEventKeepFlaggedPost``, ``AuditEventUpdateContentFlaggingConfig``, and ``AuditEventSetReviewer``. + +### Go Version + - v11.1 is built with Go ``v1.24.6``. + +### Open Source Components + - Added ``@redux-devtools/extension`` and ``@types/react-is``, and removed ``react-intl`` from https://github.com/mattermost/mattermost/. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [abhijit-singh](https://github.com/abhijit-singh), [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [Arusekk](https://translate.mattermost.com/user/Arusekk), [asaadmahmood](https://github.com/asaadmahmood), [BenCookie95](https://github.com/BenCookie95), [bgardner8008](https://github.com/bgardner8008), [buzzyboy](https://github.com/buzzyboy), [calebroseland](https://github.com/calebroseland), [codiphile](https://github.com/codiphile), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [franklinferre](https://translate.mattermost.com/user/franklinferre), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [grubbins](https://github.com/grubbins), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [homerCOD](https://github.com/homerCOD), [isacikgoz](https://github.com/isacikgoz), [itz-Me-Pj](https://github.com/itz-Me-Pj), [iyampaul](https://github.com/iyampaul), [jgheithcock](https://github.com/jgheithcock), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [jsedy7](https://translate.mattermost.com/user/jsedy7), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [KohheiAdachi](https://github.com/KohheiAdachi), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [l-ra](https://github.com/l-ra), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lynn915](https://github.com/lynn915), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mental-space1532](https://translate.mattermost.com/user/mental-space1532), [mgdelacroix](https://github.com/mgdelacroix), [moi90](https://github.com/moi90), [neflyte](https://github.com/neflyte), [nickmisasi](https://github.com/nickmisasi), [Omar8345](https://github.com/Omar8345), [pavelzeman](https://github.com/pavelzeman), [pnaskardev](https://github.com/pnaskardev), [polyacedev](https://translate.mattermost.com/user/polyacedev), [pvev](https://github.com/pvev), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Reinkard](https://github.com/Reinkard), [roberson-io](https://github.com/roberson-io), [roskee](https://github.com/roskee), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [shawnaym](https://github.com/shawnaym), [svelle](https://github.com/svelle), [thejoeejoee](https://translate.mattermost.com/user/thejoeejoee), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vpecinka](https://translate.mattermost.com/user/vpecinka), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yairsz](https://github.com/yairsz), [Yash-Chakerverti](https://github.com/Yash-Chakerverti), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +(release-v11.0-major-release)= +## Release v11.0 - [Major Release](https://docs.mattermost.com/product-overview/release-policy.html#release-types) + +- **11.0.7, released 2025-12-17** + - Mattermost v11.0.7 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v11.0.7 contains no database or functional changes. +- **11.0.6, released 2025-11-21** + ```{Attention} + **Critical Fixes** + - Mattermost v11.0.6 contains a Critical severity level security fix in the Jira plugin. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Pre-packaged Jira plugin version [v4.4.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.4.1). + - Mattermost v11.0.6 contains no database or functional changes. +- **11.0.5, released 2025-11-17** + - Mattermost v11.0.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged MS Teams Meetings plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-msteams-meetings/releases/tag/v2.3.0). + - Pre-packaged Calls plugin version [v1.11.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v1.11.0). + - Fixed a configuration retention issue where even active configuration got deleted. + - Fixed an issue where plugins could not receive 3rd-party authorization headers. + - Mattermost v11.0.5 contains no database or functional changes. +- **11.0.4, released 2025-10-28** + ```{Attention} + **Critical Fixes** + - Mattermost v11.0.4 contains Critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + ``` + - Fixed an issue where plugin configuration settings were incorrectly sanitized, causing API endpoints and plugins to receive masked values instead of actual configuration values. + - Pre-packaged Boards plugin [v9.1.7](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.7). + - Mattermost v11.0.4 contains no database or functional changes. +- **11.0.3, released 2025-10-27** + - Mattermost v11.0.3 contains no database or functional changes. +- **11.0.2, released 2025-10-16** + - Reverted a breaking change related to ``ServiceSettings.ExperimentalStrictCSRFEnforcement`` setting. +- **11.0.1, released 2025-10-16** + - Original 11.0.1 release. + +```{Attention} +**Breaking Changes** + - GitLab SSO has been deprecated from Team Edition. Deployments using GitLab SSO can remain on v10.11 ESR (with 12 months of security updates), transition to our new free offering Mattermost Entry, or can explore commercial/nonprofit options. See more details in [this forum post](https://forum.mattermost.com/t/mattermost-v11-changes-in-free-offerings/25126). + - The ``TeamSettings.ExperimentalViewArchivedChannels`` setting has been deprecated. Archived channels will always be accessible, subject to normal channel membership. The server will fail to start if this setting is set to ``false``. To deny access to archived channels, mark them as private and remove affected channel members. See more details in [this forum post](https://forum.mattermost.com/t/viewing-accessing-archived-channels-v11/22626). + - Playbooks has been deprecated from Team Edition. Entry, Professional, Enterprise, and Enterprise Advanced plans are automatically upgraded to Playbooks v2 with no expected downtime. See more details in [this forum post](https://forum.mattermost.com/t/clarification-and-update-on-the-playbooks-plugin-v11/25192). + - Experimental Bleve Search functionality has been retired. If Bleve is enabled, search will not work until ``DisableDatabaseSearch`` is set to ``false``. See more details in [this forum post](https://forum.mattermost.com/t/transitioning-from-bleve-search-in-mattermost-v11/22982). + - Support for MySQL has ended. Our [Migration Guide](https://docs.mattermost.com/deployment-guide/postgres-migration.html) outlines the steps, tools and support available for migrating to PostgreSQL. See more details in [this forum post](https://forum.mattermost.com/t/transition-to-postgresql/19551). + - The ``registerPostDropdownMenuComponent`` hook in the web app’s plugin API has been removed in favour of ``registerPostDropdownMenuAction``. See more details in [this forum post](https://forum.mattermost.com/t/deprecating-a-post-dropdown-menu-component-plugin-api-v11/25001). + - The web app is no longer exposing the [Styled Components](https://styled-components.com/) dependency for use by web app plugins. See more details in [this forum post](https://forum.mattermost.com/t/removing-styled-components-export-for-web-app-plugins-v11/25002). + - Omnibus support has been deprecated. The last ``mattermost-omnibus`` release was v10.12. See more details in [this forum post](https://forum.mattermost.com/t/mattermost-omnibus-to-reach-end-of-life-v11/25175). + - Deprecated ``include_removed_members`` option in ``api/v4/ldap/sync`` has been removed. Admins can use the LDAP setting ``ReAddRemovedMembers``. + - Customers that have the NPS plugin enabled can remove it as it no longer sends the feedback over through telemetry. + - Format query parameter requirement in the ``/api/v4/config/client`` endpoint has been deprecated. + - Removed deprecated mmctl commands and flags: + - ``channel add`` - use ``channel users add`` + - ``channel remove`` - use ``channel users remove`` + - ``channel restore`` - use ``channel unarchive`` + - ``channel make-private`` - use ``channel modify --private`` + - ``command delete`` - use ``command archive`` + - ``permissions show`` - use ``permissions role show`` + - ``mmctl user email`` - use ``mmctl user edit email`` + - ``mmctl user username`` - use ``mmctl user edit username`` + - Experimental certificate-based authentication feature has been removed. ``ExperimentalSettings.ClientSideCertEnable`` must be ``false`` to start the server. + - Added logic to migrate the password hashing method from bcrypt to PBKDF2. The migration will happen progressively, migrating the password of a user as soon as they enter it; e.g. when logging in or when double-checking their password for any sensitive action. There is an edge case where users might get locked out of their account: if a server upgrades to v11 and user A logs in (i.e., they need to enter their password), and then the server downgrades to v10.12 or previous, user A will no longer be able to log in. In this case, admins will need to manually reset the password of such users, through the system console or through the [mmctl user reset-password [users]](https://docs.mattermost.com/administration-guide/manage/mmctl-command-line-tool.html#mmctl-user-reset-password) command. The new password hashing method is more CPU-intensive. Admins of servers with password-based login should monitor the performance on periods where many users log in at the same time. + - ``/api/v4/teams/{team_id}/channels/search_archived`` has been deprecated in favour of ``/api/v4/channels/search`` with the deleted parameter. + - Changed default database connection pool settings: changed ``MaxOpenConns`` from 300 to 100 and ``MaxIdleConns`` from 20 to 50, establishing a healthier 2:1 ratio for better database connection management. + - Separate notification log file has been deprecated. If admins want to continue using a separate log file for notification logs, they can use the ``AdvancedLoggingJSON`` configuration. See the [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html) for an example configuration. + - Stopped supporting manually installed plugins as per https://forum.mattermost.com/t/deprecation-notice-manual-plugin-deployment/21192 + - Support for PostgreSQL v13 has been removed. The new minimum PostgreSQL version is v14+. See the [minimum supported PostgreSQL version policy](https://docs.mattermost.com/deployment-guide/software-hardware-requirements.html#minimum-postgresql-database-support-policy) documentation for details. +``` + +### Upgrade Impact + +#### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + - **Changes to all plans:** + - Under ``CloudSettings`` in ``config.json``, added ``PreviewModalBucketURL``. + - Removed ``VerboseDiagnostics`` configuration setting as part of removing all telemetry support from Mattermost. + - Removed ``BleveSettings`` configuration setting as part of removing Bleve. + - Removed ``NotificationLogSettings`` as part of deprecating the separate notification log file. + - **Changes to Enterprise and Enterprise Advanced plans:** + - Removed ``ClientSideCertCheck`` as part of removing the experimental certificate-based authentication feature. + +```{Important} +If you upgrade from a release earlier than v10.10, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes.html). In case of an upgrade failure, please check the [Downgrade Guide](https://docs.mattermost.com/administration-guide/upgrade/downgrading-mattermost-server.html) and the [Recovery Guide](https://docs.mattermost.com/deployment-guide/backup-disaster-recovery.html) for rollback steps and interim mitigation strategy. +``` + +### Improvements + +See [this blog post](https://mattermost.com/blog/mattermost-v11-powering-more-mission-critical-collaboration/) on the highlights in our latest release. + +#### User Interface (UI) + - Pre-packaged Agents plugin [v1.3.1](https://github.com/mattermost/mattermost-plugin-agents/releases/tag/v1.3.1). + - Pre-packaged Boards plugin [v9.1.6](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.6). + - Pre-packaged MS Teams plugin [v2.2.2](https://github.com/mattermost/mattermost-plugin-msteams/releases/tag/v2.2.2). + - Pre-packaged Playbooks plugin [v2.4.2](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v2.4.2), allowing Professional licenses to use playbooks v2. + - Removed Playbooks v1 from pre-packaged plugins. + - Updated the library used for customizing scrollbars. + - Increased page size when retrieving posts in channels with high number of hidden messages. + +#### Administration + - Introduced support for Mattermost Entry, a commercial evaluation environment to explore Enterprise Advanced with usage limits. See more details in [this forum post](https://forum.mattermost.com/t/mattermost-v11-changes-in-free-offerings/25126). + - User limits were lowered to final threshold of 250 for Mattermost Team Edition (MIT-Compiled License). + - Added support for a [FIPS-compliant Mattermost image](https://docs.mattermost.com/deployment-guide/server/deploy-containers.html). + - PBKDF2 is now used as the new key derivation algorithm for remote cluster invitations. We do this in a backward compatible way such that invitations generated from new/old clusters work in all clusters. + - Updated the default SAML signature algorithm from SHA1 to SHA256 for improved security. + - Added admin-managed property fields to Custom Profile Attributes. + - Admin managed Custom Profile Attribute fields can now be used as part of Attribute Based Access Control policies. + - System Admins can now mark Custom Profile Attribute fields as “admin managed” from the System Console. + - Added Channel-Level Attribute-Based Access Control (Available only in Enterprise Advanced). Channel Admins can now configure attribute-based access rules directly in Channel Settings through a new Access Control tab when the ``EnableChannelScopeAccessControl`` setting is enabled. + - Channel access control policies now support multiple parent inheritances. + - Updated interactive dialogs to use the apps form framework. Implemented dynamic select and multi-select for interactive dialogs. Also, ``UserId`` and ``TeamId`` are now passed in interactive dialog submissions. + - Mattermost profile image is now deleted when LDAP profile picture is deleted. + - User ``auth_data`` is now shown in the System Console user details page. + - Added Elasticsearch test to Support Packet diagnostics. + - Added support for a new ``EmailNotificationWillBeSent`` plugin hook. + - Added a console warning when a plugin uses the now-deprecated ``registerPostDropdownMenuComponent`` API. + +#### mmctl + - Added ``mmctl user edit`` command. + - Updated mmctl shell completion to fully support zsh, powershell, and fish. Check out ``mmctl completion`` for a guide on how to set it up for your shell. + - Added the ``mmctl cpa`` set of commands to manage Custom Profile Attributes. + +#### Performance + - Benchmarking test results showed no significant difference: a 1.34% decrease in the number of supported users for the new release, which lies within the ``[-5%, +5%]`` prediction interval. View the full raw data and methodology in our [Performance Reports repository](https://github.com/mattermost/performance-reports/tree/main/performance-comparisons/v11.0). + +### Bug Fixes + - Fixed an issue where extra date separators were added in search results, pinned posts and saved messages. + - Fixed an issue where MFA warning was thrown in the logs for unauthenticated plugin requests. + - Fixed an issue that prevented new users from searching channels right after joining a team when Elasticsearch was enabled. + - Fixed some crashes in the threads screen. + +### API Changes + - Added a counting plugin API for properties. + - Added a new API endpoint to update Custom Profile Attribute values for a given user. + +### Go Version + - v11.0 is built with Go ``v1.24.6``. + +### Open Source Components + - Added ``simplebar-react``, and removed ``go-sql-driver/mysql``, ``blevesearch/bleve`` and ``axios`` from https://github.com/mattermost/mattermost. + +### Contributors + - [abbas-dependable-naqvi](https://github.com/abbas-dependable-naqvi), [adityadav1987](https://github.com/adityadav1987), [agarciamontoro](https://github.com/agarciamontoro), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [arush-vashishtha](https://github.com/arush-vashishtha), [AulakhHarsh](https://github.com/AulakhHarsh), [AurelienS](https://github.com/AurelienS), [avasconcelos114](https://github.com/avasconcelos114), [azistellar](https://translate.mattermost.com/user/azistellar), [azizthegit](https://github.com/azizthegit), [BenCookie95](https://github.com/BenCookie95), [bndn](https://github.com/bndn), [Boruus](https://translate.mattermost.com/user/Boruus), [bshumylo](https://translate.mattermost.com/user/bshumylo), [buzzyboy](https://github.com/buzzyboy), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danilvalov](https://github.com/danilvalov), [David](https://translate.mattermost.com/user/David), [davidkrauser](https://github.com/davidkrauser), [devinbinnie](https://github.com/devinbinnie), [eagerid](https://github.com/eagerid), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [flyply](https://translate.mattermost.com/user/flyply), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [fsilye](https://github.com/fsilye), [gabrieljackson](https://github.com/gabrieljackson), [grubbins](https://github.com/grubbins), [guenjun](https://github.com/guenjun), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [isacikgoz](https://github.com/isacikgoz), [jabi27](https://translate.mattermost.com/user/jabi27), [jgheithcock](https://github.com/jgheithcock), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [ladudu](https://github.com/ladudu), [lani009](https://github.com/lani009), [lani009217f4195555e46f1](https://translate.mattermost.com/user/lani009217f4195555e46f1), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [mansil](https://github.com/mansil), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [minchae.lee](https://translate.mattermost.com/user/minchae.lee), [mrckndt](https://github.com/mrckndt), [neflyte](https://github.com/neflyte), [nickmisasi](https://github.com/nickmisasi), [onovy](https://translate.mattermost.com/user/onovy), [polnetwork](https://translate.mattermost.com/user/polnetwork), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [saturninoabril](https://github.com/saturninoabril), [sayzard](https://github.com/sayzard), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [stafot](https://github.com/stafot), [thejoeejoee](https://github.com/thejoeejoee), [ThrRip](https://translate.mattermost.com/user/ThrRip), [tnir](https://github.com/tnir), [Victor-Nyagudi](https://github.com/Victor-Nyagudi), [vish9812](https://github.com/vish9812), [vpecinka](https://github.com/vpecinka), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [Yash-Chakerverti](https://github.com/Yash-Chakerverti), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) diff --git a/docs/main/product-overview/mobile-app-changelog.mdx b/docs/main/product-overview/mobile-app-changelog.mdx new file mode 100644 index 000000000000..519a71e4b82e --- /dev/null +++ b/docs/main/product-overview/mobile-app-changelog.mdx @@ -0,0 +1,4707 @@ +--- +title: "Mobile App Changelog" +--- +import Inc0_common_esr_support from './common-esr-support.mdx'; + +This changelog summarizes updates to Mattermost mobile apps releases for [Mattermost](https://mattermost.com). + +```{Important} + +(release-v2-39-0)= +## 2.39.0 Release + - Release Date: April 16, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Improvements + - Added support for [AI rewrites](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html#rewrite-messages-with-ai) when Agents is enabled on the server. + - Permalink previews are now properly automatically translated. + - Added support for ``filewillbedownloaded`` and ``sendtoastmessage`` plugin APIs. + +### Bug Fixes + - Fixed an issue where option descriptions were not readable due to spacing. + - Fixed an issue where profile popovers did not show message/mention actions in Direct Message contexts when viewing someone other than the current Direct Message teammate (e.g., from an at-mention). + - Fixed an issue where updates in the roles would not be reflected in the mobile app. + - Fixed an issue where the connection banner did not disappear if the user had no connection to the internet. + - Fixed an error where changes in the channel level roles permissions were not visible in the mobile app. + - Fixed an issue where collapsing the **Sources** citations panel in Agent responses could briefly overlap the content below it. + - Fixed an issue with inconsistent permalink error messages between desktop and mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-38-3)= +## 2.38.3 Release + - Release Date: April 10, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Added Intune Conditional Access support. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-38-2)= +## 2.38.2 Release + - Release Date: April 1, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Fixed an issue where Calls did not support TLS 1.3 on iOS. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-38-1)= +## 2.38.1 Release + - Release Date: March 25, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Fixed an issue where users were not able to attach the app's logs into a conversation to help troubleshoot issues. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-38-0)= +## 2.38.0 Release + - Release Date: March 16, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Improvements + - Added auto-translation support. Initial Beta release. Requires Enterprise Advanced license. + - Added ability to send [Burn on Read posts](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html#send-burn-on-read-messages) from mobile app. + - Updated the splash screen background graphic. + - Added ability to edit Playbook runs and Checklist summaries. + - Allowed task item [renaming and editing](https://docs.mattermost.com/end-user-guide/workflow-automation/work-with-tasks.html#update-tasks) descriptions. + - Updated the Interactive Dialog to use Apps Form Framework. + +### Bug Fixes + - Fixed an issue where the playbook menu item was not hidden when there were no runs. + - Fixed an issue where the pre-auth secret was removed on logout. + - Fixed an issue where Playbooks view didn’t only show the playbooks for the current team. + - Fixed an issue where the "invite to team" menu did not appear in all cases it should. + +### Open Source Components + - Added ``@formatjs/intl-displaynames`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-37-2)= +## 2.37.2 Release + - Release Date: February 26, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Added various bug fixes. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-37-1)= +## 2.37.1 Release + - Release Date: February 23, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +**Note:** Mattermost Mobile App v2.37.1 contains a medium level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-37-0)= +## 2.37.0 Release + - Release Date: February 16, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Improvements + - Added support for [emoji picker](https://docs.mattermost.com/end-user-guide/collaborate/react-with-emojis-gifs.html#manage-emojis) on mobile. + - Added an option to rename playbook runs/checklists on mobile. + - Added support for [viewing and editing playbook run attributes](https://docs.mattermost.com/end-user-guide/workflow-automation/work-with-playbooks.html#playbook-attributes). + - Added support for [deleting Playbook tasks](https://docs.mattermost.com/end-user-guide/workflow-automation/work-with-tasks.html#mobile-playbooks-task-management) from mobile. + +### Bug Fixes + - Fixed an issue with the notification settings screen sometimes not showing updates when changing the email notifications. + - Fixed an issue where the server was pinged on edit even if the pre-auth secret didn't change. + +### Open Source Components + - Added ``@gorhom/portal``, ``grapheme-splitter``, and ``react-native-keyboard-controller`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-36-4)= +## 2.36.4 Release + - Release Date: January 22, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Re-enabled Intune for Mobile v2.36.4. + - Updated iOS minimum version back to v16. See more details in [this forum post](https://forum.mattermost.com/t/mobile-app-ios-version-support-update-v2-36-1-and-v2-36-2/25664). + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-36-3)= +## 2.36.3 Release + - Release Date: January 21, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6+ devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Disabled Intune for Mobile v2.36.3 to fix a crash. + - Temporarily updated minimum iOS version to 15.1+. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-36-2)= +## 2.36.2 Release + - Release Date: January 20, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 8+ devices and later with iOS 16.0+ are [required](https://support.apple.com/en-il/guide/iphone/iphe3fa5df43/16.0/ios/16.0). + +### Bug Fixes + - Re-enabled Intune for Mobile v2.36.2. + - Updated iOS minimum version to v16. See more details in [this forum post](https://forum.mattermost.com/t/mobile-app-ios-version-support-update-v2-36-1-and-v2-36-2/25664). + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-36-1)= +## 2.36.1 Release + - Release Date: January 20, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Disabled Intune for Mobile v2.36.1 so that it does not crash on iOS v15 and v16. + - Fixed an access issue to gallery tools. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-36-0)= +## 2.36.0 Release + - Release Date: January 16, 2026 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Added [Microsoft Intune MAM integration](https://docs.mattermost.com/deployment-guide/mobile/mobile-security-features.html#microsoft-intune-mobile-application-management-mam) for iOS with multi-server support (requires Enterprise Advanced license). + - Added the ability to [invite guests to a team](https://docs.mattermost.com/end-user-guide/collaborate/invite-people.html) from mobile. + - Added support for servers with passwordless authentication with [Magic Link for guest users](https://docs.mattermost.com/end-user-guide/access/access-your-workspace.html#magic-link-login-for-guests) (requires Enterprise license). + - Added a new [Burn-on-Read message feature](https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html#send-burn-on-read-messages) (requires Enterprise Advanced license). + - Added AI agent streaming support with real-time message updates, reasoning summaries, tool call approval UI, citations display, and generation controls (stop/regenerate). + - Added an authentication secret field to the **Edit server** screen with validation and a show/hide toggle. + - Updated illustrations and background styles for onboarding and authentication flows. + - Reduced channel banner height to provide a more compact interface and to optimize screen space usage. + - Added a minor visual tweak to the **Start a new run** button. + +### Bug Fixes + - Fixed an issue where a message stated that there are zero pending tasks when completing a Playbook run. + - Fixed an issue where users could not manage their own roles and memberships on the **Manage channel members** screen. + - Fixed an issue with a WebSocket event when a user burns a Burn-on-Read message for themselves. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-35-0)= +## 2.35.0 Release + - Release Date: December 16, 2025 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Added support for playbook checklists. + +### Bug Fixes + - Fixed multiple critical crashes in iOS push notification handling that could cause notification extension termination or incorrect retry behavior. + - Fixed an issue where small portrait and landscape images in the gallery could overflow the canvas, appearing larger than the viewport. Images now properly scale to fit within viewport bounds while maintaining their aspect ratio. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-34-0)= +## 2.34.0 Release + - Release Date: November 14, 2025 + - Server Versions Supported: Server v10.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#extended-support-releases) (ESR) v10.5.0 has ended and upgrading to server ESR v10.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Added the ability to finish a playbook run. + - Added post update functionality to playbooks. + - Added a unified playbook runs view. + - Added functionality to create playbook runs. + - Added support for playbook conditionals. + - Improved the visuals for selectors. + - Added a descriptive error message for the pre-auth secret when the ping fails with an authentication error. + - Improved the advanced options animation and layout in the server form. + - Temporarily opted out of Android ``EdgeToEdge`` and iOS 26 Liquid Glass for compatibility. + - Added a notice to the user on the **Notification Settings** modal to show that notifications are disabled. + +### Bug Fixes + - Fixed an issue with the Slack attachment button color. + - Fixed an issue with Android system bars taking too much space or overlapping content. + +### Open Source Components + - Added ``js-sha256`` to https://github.com/mattermost/mattermost-mobile/. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-33-1)= +## 2.33.1 Release + - Release Date: October 21, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#esr-life-cycle-changes) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Fixed an issue where links would change colors when navigating to a channel with a channel banner. + +(release-v2-33-0)= +## 2.33.0 Release + - Release Date: October 16, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#esr-life-cycle-changes) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +**Note:** Mattermost Mobile App v2.33.0 contains a medium level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Improvements + - Added checklist item options for playbooks. + - Added the ability to edit slash commands on playbooks tasks. + - Added the ability to update the due date on playbook tasks. + - Added the ability to edit the owner and the task assignee on playbooks. + - Added support for permalink previews on mobile. + +### Bug Fixes + - Fixed an issue where the playbooks option was not omitted in Direct/Group Messages. + - Fixed a screenshot share problem for iOS 26 devices. + - Fixed an issue with the **Edited** message line height. + - Fixed an issue with the file upload function when CSRF protection was enabled. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-32-0)= +## 2.32.0 Release + - Release Date: September 16, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#esr-life-cycle-changes) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Updated the app to target Android 15 (API level 35). + - Added a new pre-authentication secret configuration to the server connection. This secret will be sent as a header in every request made to the Mattermost instance. + +### Bug Fixes + - Fixed an issue where channel links were not enabled on the title of message attachments. + - Fixed a sorting problem when moving a field from custom profile attributes to the first position. + - Fixed an issue where playbooks did not update in some cases. + +### Open Source Components + - Added ``@formatjs/intl-relativetimeformat`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-31-0)= +## 2.31.0 Release + - Release Date: August 15, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/product-overview/release-policy.html#esr-life-cycle-changes) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Enhanced Secure Previews: Introduced a more secure way to preview supported images, videos, and PDF files while restricting other file types, downloads, and sharing. Requires an Enterprise Advanced license. + - Added the ability to delete/edit file attachments on existing posts. + - Playbooks Support: Initial version integrating with Playbooks with the ability to view runs and check/uncheck tasks in checklists. + - Added an accessibility check to disable animations when required. + - Added support for multi/select types and text subtypes for Custom Profile Attributes. + +### Bug Fixes + - Fixed the hashtag rendering to work with the minimum hashtag length configuration. + - Fixed an error when saving non-editable Custom Profile Attributes. + +### Open Source Components + - Added ``@mattermost/secure-pdf-viewer`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-30-0)= +## 2.30.0 Release + - Release Date: July 16, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - A default header was added to requests as ``application/json``. + +### Bug Fixes + - Fixed an issue of custom emojis not being updated with the new image when created with the same name on the web application. + - Fixed an issue where the error message displayed while editing a message pushed part of the input out of view. + - Fixed an issue where actions on ephemeral messages caused the messages to be hidden. + - Fixed an issue preventing users from reaching the second team on the team selection screen in the search functionality. + - Calls: fixed an issue that prevented the call screen from correctly handling landscape mode after locking the device while in a call. + - Fixed an issue with sending Custom Profile Attributes info if the feature is not enabled. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-29-1)= +## 2.29.1 Release + - Release Date: June 18, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Fixed an issue where an unread thread on a Direct/Group Message would mark all teams as unread. + - Fixed an issue with the **Report a Problem** screen not showing all the buttons on small screens. + +(release-v2-29-0)= +## 2.29.0 Release + - Release Date: June 16, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Added a license load metric to the **About** screen to show current license usage. + - Improved the behavior around reporting a problem. + - Updated the copy action label to **Copy Email Address** for Markdown-rendered email links. + +### Bug Fixes + - Fixed an issue with the hardware keyboard on iPad overlapping the input in threads. + - Fixed an issue where deactivated accounts would appear in the **Create direct message** screen. + - Fixed an issue with the license check where the license could be undefined. + - Fixed a UX issue where the call bar did not render correctly when displaying exceptionally long user or channel names. + - Fixed an issue where videos did not show images even if public links were disabled. + - Fixed an issue where the app could crash when viewing malformed LaTeX code. + - Fixed inconsistencies between web and mobile category sorting (may require logging out and logging back in to fix). + - Fixed an issue where message attachments (e.g. from a webhook) would not appear if received while the app was in the background. + - Calls: fixed an issue with scrolling the participants list. + - Fixed an issue with some flickering on the tooltip in the **Drafts** screen. + +### Open Source Components + - Added ``prismjs`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - "Report a problem" page sometimes gets cut off at the bottom. + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-28-1)= +## 2.28.1 Release + - Release Date: June 4, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Fixed an issue with some flickering on the tooltip in the drafts screen. + +(release-v2-28-0)= +## 2.28.0 Release + - Release Date: May 16, 2025 + - Server Versions Supported: Server v10.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v10.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.11.0 has ended and upgrading to server ESR v10.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - Added a feature to support scheduled posts on mobile. + - Added the ability to display channel banners in the mobile app. This is available for Enterprise Advanced servers that have the Channel Banners feature available. + - Added autofill on the email/password fields on the login screen. + - Upgraded forked ``commonmark`` to v0.31.2-0. + +### Bug Fixes + - Fixed an issue with some threads not getting marked as read when read from a different device. + - Fixed an issue where the team sidebar did not show the unread indicator if the user had unread threads. + - Fixed an issue where message attachments (e.g. from a webhook) would not appear if received while the app was in the background. + +### Open Source Components + - Added ``@shopify/flash-list`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Animation delay when clearing textbox after post is sent. + - iOS: Inline images with size specified fail to post. + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-27-1)= +## 2.27.1 Release + - Release Date: April 30, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Calls: fixed a regression that caused unmuting to fail when running the latest app against an older plugin version (earlier than v1.7.0). + +(release-v2-27-0)= +## 2.27.0 Release + - Release Date: April 16, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Improvements + - (Enterprise) Added the ability to configure per-server prompting for biometric authentication, to prevent the use of the app if the device is jailbroken / rooted, and to prevent screen captures. + - Updated empty state images to align with new branding style. + - Added the ability to play and download audios on the chat. + - Added custom profile attributes to the edit profile screen. Requires server v10.5+ with an Enterprise license and feature flag enabled. + - Added improvements to the emoji picker. + - Added a client-side ping to the websocket to detect broken connections more quickly. + +### Bug Fixes + - Fixed an issue with scrolling lists inside the bottom menu. + +### Known Issues + - (Android) Autocomplete suggestions are not available for at-mentions for out of channel members (as well as in-channel members). + - (Android) Autocomplete does not show up when typing ``+:taco`` in "write to" input box. + - Custom themes cannot be applied on mobile. + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-26-2)= +## 2.26.2 Release + - Release Date: March 25, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Fixed an issue where the autocomplete area was too small on Android devices. + +(release-v2-26-1)= +## 2.26.1 Release + - Release Date: March 21, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Bug Fixes + - Fixed issues where app bindings and message attachments would not show properly. + +(release-v2-26-0)= +## 2.26.0 Release + - Release Date: March 14, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +Note: Mattermost Mobile App v2.26.0 contains a low level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Improvements + - Added a "component library" debug menu for servers that have developer settings enabled. + - Native logs will now appear on iOS. + +### Bug Fixes + - Fixed an issue with image resize when the Tablet screen was resized. + - Fixed an issue with the share feedback screen layout. + - Fixed a layout issue when there was an error with the playback of a video. + - Fixed the style of ephemeral messages that prompted the user to add mentioned people to a channel. + - Fixed an issue where the keyboard blocked the text input. + - Fixed a blank space between the content and the keyboard on Android. + +### Known Issues + - Samsung S22 might not display custom profile attributes correctly. + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-25-1)= +## 2.25.1 Release + - Release Date: February 21, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +Note: Mattermost Mobile App v2.25.1 contains a medium level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +(release-v2-25-0)= +## 2.25.0 Release + - Release Date: February 14, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 15.1+ are required. + +### Breaking Changes + - In the Mattermost Mobile App v2.25 release, Mattermost has stopped supporting iOS versions 13 and 14. Users should update their iOS version to v15.1 or newer before February 14, 2025. See more details in [this forum post](https://forum.mattermost.com/t/deprecation-notice-ios-13-and-14-versions/21845). + +### Improvements + - Added a feature for having a separate tab for **Drafts** on mobile. The Drafts screen currently only supports local drafts on the device and not drafts synchronized with the server. + - Android: App logs now includes enhanced logging for events that happen on the native (device-side) of the app which can be useful for troubleshooting issues related to Mattermost push notifications. + - Added visualization of custom profile attributes. Requires server v10.5 and feature flag enabled. + +### Bug Fixes + - Fixed reliability issues with threads. + - Fixed certain scenarios where the keyboard area in the channel and thread screen took more space than it should. + +### Open Source Components + - Added ``@react-native-community/cli``, ``@react-native-community/cli-platform-android``, and ``@react-native-community/cli-platform-ios`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Samsung S22 might not display custom profile attributes correctly. + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-24-1)= +## 2.24.1 Release + - Release Date: January 17, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ are required. + +### Bug Fixes + - Fixed a crash when using certain timezones. + +(release-v2-24-0)= +## 2.24.0 Release + - Release Date: January 16, 2025 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ are required. + +### Improvements + - End users will no longer receive messages about being on unsupported servers. + +### Bug Fixes + - Fixed an issue with the user interface for editing custom statuses. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-23-1)= +## 2.23.1 Release + - Release Date: December 19, 2024 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ are required. + +### Bug Fixes + - Fixed an issue with the number field validation on interactive dialogs. + - Fixed an issue with interactive dialogs not showing all the elements. + +(release-v2-23-0)= +## 2.23.0 Release + - Release Date: December 16, 2024 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ are required. + +Note: Mattermost Mobile App v2.23.0 contains medium level security fixes. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Improvements + - Added the test notification tool for servers above v10.3.0. + - Added performance improvements when logging in to a server. + - Added a **Copy** button in the code view screen. + - The thread overview is now hidden until there are replies. + - Reworked the date format to respect language and region specificities. + - Improved load performance measures. + - Improved connection behavior when switching network types (cell, wifi, vpn...). + - Added a new index to the type column in the ``Post`` table. Bumped up server database schema version to 6. + - Added a new column ``update_at`` to the Drafts table. + +### Bug Fixes + - Fixed an issue with the sort order of channel bookmarks when sorted on a different client. + - Fixed an issue where posts in archived channels showed emoji reactions with a count “0” instead of the actual count. + - Fixed an issue with the sorting of teams in the team sidebar by following the user preferences if set. + - Fixed an issue where ephemeral posts didn't go away after a refresh or an app relaunch. + - Fixed an issue where the **Only visible to you** text was missing from ephemeral posts. + - Fixed a layout issue on iPad with split screen and stage manager. + - Fixed a crash caused by incorrect Markdown handling. + - Fixed an issue with image overflow when using message attachments. + +### Open Source Components + - Added ``react-native-url-polyfill`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-22-0)= +## 2.22.0 Release + - Release Date: November 15, 2024 + - Server Versions Supported: Server v9.11.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.11.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v9.5.0 has ended and upgrading to server ESR v9.11.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +Note: Mattermost Mobile App v2.22.0 contains a medium level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Improvements + - Calls: added experimental support for signaling media tracks using data channels. + +### Bug Fixes + - Fixed an issue where the Threads list didn't show channel links. + - Fixed an issue with the split view on iPad as the layout was not changing in certain scenarios. + - Fixed an issue where images inside links within markdown were not tappable for link navigation. + +### Open Source Components + - Added ``fflate`` and removed ``pako`` from https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-21-0)= +## 2.21.0 Release + - Release Date: October 16, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Improvements + - Removed unneeded permissions on Android. + - Improved metrics around notifications. + +### Bug Fixes + - Fixed an issue with handling of malformed Markdown tables. + - Fixed an issue where Calls buttons and actions were not hidden if the plugin was disabled. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-20-1)= +## 2.20.1 Release + - Release Date: October 9, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Improvements + - Added a configuration setting ``NativeAppSettings > MobileExternalBrowser`` that tells the Mobile app to perform SSO Authentication using the external default browser. + +(release-v2-20-0)= +## 2.20.0 Release + - Release Date: September 16, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Breaking Changes + - Calls: starting in Mattermost v10 and Calls plugin v1.0, calls functionality will be available in Direct Message channels only if running an unlicensed server. + +### Improvements + - Calls: added experimental support for receiving AV1 encoded screen sharing tracks. + - Calls: implemented client-side ICE candidate pairs metrics. + - Added support for SSL Pinning certificates on build your own. + - Added channel bookmarks (default off behind a feature flag). + +### Bug Fixes + - Fixed an issue with deep links that did not match the patterns of channel or permalink and were crashing the app. + +### Open Source Components + - Added ``node-html-parser`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-19-2)= +## 2.19.2 Release + - Release Date: August 29, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Bug Fixes + - Added a new message to the SSO login screen when the login is successful. + - Fixed an issue that prevented live captions for Calls to show. + +(release-v2-19-1)= +## 2.19.1 Release + - Release Date: August 27, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Bug Fixes + - Fixed an issue where the iPad hardware keyboard did not work as intended. + - Fixed an issue where the Android keyboard did not autocapitalize the first letter of a sentence by default when writing a post. + +(release-v2-19-0)= +## 2.19.0 Release + - Release Date: August 16, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +**Note:** Mattermost Mobile App v2.19.0 contains a medium level security fix. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Improvements + - Added significant dependency upgrades and replacements to the underlying project structure to support upgrading React version, and to establish a foundation for future architecture improvements ([pull request](https://github.com/mattermost/mattermost-mobile/pull/8011)). + - Calls: Incoming calls on Direct Messages and Group Messages ring; ringtone is selectable in the settings menu. + - Calls: Added stop recording confirmation; redesigned the header of the call screen to better display recording badge. + - Calls: Added an end call confirmation and an “End call for everyone” option for the call host. + - Improved how UUIDs are generated. + - Restored "Out of Channel" section in the user autocomplete. + - Improved load time performance metrics. + +### Open Source Components + - Added ``@rneui/base, expo``, ``expo-application``, ``expo-crypto``, ``expo-device``, ``expo-image``, ``expo-linear-gradient``, ``expo-store-review`` and ``expo-video-thumbnails``, ``expo-web-browser``, and removed ``react-native-create-thumbnail``, ``react-native-fast-image`` and ``react-native-hw-keyboard-event`` from https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-18-1)= +## 2.18.1 Release + - Release Date: July 17, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Bug Fixes + - Fixed an issue with the server list modal displayed on tablet devices. + +(release-v2-18-0)= +## 2.18.0 Release + - Release Date: July 16, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Improvements + - The app will now send performance metrics to servers v9.10+ that have metrics enabled. + - Improved websocket behavior. + - Calls: Updated call post user interface. + - Calls: Added channel name to the call header. + - Calls: Feedback is now provided after user taps **Start call**. + +### Bug Fixes + - Fixed an issue with the apply button not appearing on iPads when trying to set post priority. + - Fixed a crash that occured when sharing a file. + +### Open Source Components + - Added ``react-native-performance`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +(release-v2-17-1)= +## 2.17.1 Release + - Release Date: June 25, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +### Bug Fixes + - Fixed a crash when receiving a push notification on Android when the app was not running. + +## 2.17.0 Release + - Release Date: June 14, 2024 + - Server Versions Supported: Server v9.5.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v9.5.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v8.1.0 has ended and upgrading to server ESR v9.5.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 6s devices and later with iOS 13.4+ is required. + +Note: Mattermost Mobile App v2.17.0 contains low to medium level security fixes. Updating is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the Mattermost Responsible Disclosure Policy. + +### Breaking Changes + - **IMPORTANT:** The iPhone Deployment Target was updated to 13.4. Old devices may not be able to update the app (<1GB RAM and Authentication > Guest Access > Show Guest Tag**. + - Improved behavior of multi-request environments (such as HTTP/1.1). + - Added search result highlight that matches the words being searched. + - Added a new feature for remembering the last viewed channel or thread that takes returning users to the last channel or thread they visited. + - Improved the appearance of the search results. + - User’s current status is now shown at the bottom tab bar profile image. + - Added a **Copy info** button to the **About** page. + +### Bug Fixes + - Fixed issues with timeouts when uploading files. + - Fixed hashtag search to match the hashtag and not the word. + - Fixed search results to match the webapp. + - Fixed an issue with selecting the custom theme from the display setting. + - Fixed an issue where the keyboard overlapped with recent search items in the search tab. + - Fixed an issue with notifications showing a session expired message when it shouldn't. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +---- + +(release-v2-6-0)= +## 2.6.0 Release +- Release Date: July 14, 2023 +- Server Versions Supported: Server v7.8.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.8.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v7.1.0 has ended and upgrading to server ESR v7.8.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Calls: ``/call start`` will now start calls within an existing thread. + - Improved logging for mobile apps. + - Added localization support to iOS share extension. + - Improved the user interface of the **Edit Post** screen. + +### Bug Fixes + - Fixed a rare issue when changing the role of the current user in a channel. + - Calls: Fixed an issue for blank screen after ending a call and exiting its thread. + - Fixed an issue where the Global Threads screens didn't show a badge if the user had mentions in other channels / servers. + - Removed unneeded fetch posts for unread archived channels that were appearing in the logs. + - Removed unneeded group calls that were appearing in the logs. + - Fixed an issue with the progress indicator when uploading files on Android. + - Fixed a few issues with app initialization. + - Fixed an issue where notifications would show "Session expired" instead of the message. + - Fixed a crash when users that reacted with a certain emoji were listed and a user was missing. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +---- + +(release-v2-5-1)= +## 2.5.1 Release +- Release Date: June 23, 2023 +- Server Versions Supported: Server v7.8.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.8.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v7.1.0 has ended and upgrading to server ESR v7.8.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +```{Note} Mattermost Mobile App v2.5.1 contains a high level security fix. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Bug Fixes + - Fixed an issue where reading a thread could lead to the phone and server to overwork. + - Fixed the overlap between image attachments and the post footer with Collapsed Reply Threads enabled. + +---- + +(release-v2-5-0)= +## 2.5.0 Release +- Release Date: June 16, 2023 +- Server Versions Supported: Server v7.8.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.8.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v7.1.0 has ended and upgrading to server ESR v7.8.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Calls: Added call quality degradation logic and a banner to alert users when they are on unstable connections. + - Improved client error handling. + - Post editing now respects the ``message_source`` field. + - Improved reaction time for the **Copy Text** option. + - Improved behavior around "Maximum call stack size exceeded" errors. + - Android: removed unneeded space after the list in the **Find Channels** screen. + +### Bug Fixes + - Fixed an issue where **Search** and **Recent Mentions** did not highlight saved posts. + - Fixed the interactive dialog radio buttons style when using the light theme. + - Fixed a small issue when marking threads as read. + - Fixed an issue where the **Save** button sometimes did not show on the Edit Post screen. + - Fixed theming issues in the login screen. + - Fixed an issue where replies sometimes seemed to be attributed to the wrong person or the wrong thread. + - Ensured users mentioned in message attachments are loaded by the app. + - Fixed issues with user status synchronization. + - Fixed duplicated text for SSO login method when only SSO was available. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +---- + +(release-v2-4-0)= +## 2.4.0 Release +- Release Date: May 17, 2023 +- Server Versions Supported: Server v7.8.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.8.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v7.1.0 has ended and upgrading to server ESR v7.8.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added mobile support for message acknowledgements and persistent notifications. + - Added the ability to add members to channels. + - Increased the character limit for the user's nickname from 22 to 64 characters. + - Added localization support for iOS usage description strings in permission dialogs. + - Users can now follow or unfollow a thread and undo the action if needed. + - Added the ability to search for files posted in a channel. + - Added support for ``ExperimentalSettings.DelayChannelAutocomplete`` to make the channel autocomplete only appear after typing a couple letters instead of immediately after a tilde. + - Calls: Redesigned the Calls user interface. + - Calls: Call threads are now auto-followed when joining from mobile. + - Calls (Android): Fixed an issue with Bluetooth, and added audio device selection menu. + - Added support for self-hosted Sentry URL parameters in build scripts. + +### Bug Fixes + - Fixed an issue where the app did not now show an error when adding servers without a diagnostic ID. + - Fixed an issue where users were unable to select several files when attaching files to a message. + - Fixed an issue where some channels would appear as if no messages were there. + - Fixed an issue with using the camera to capture photos/videos on Android versions 9 and below. + - Fixed a crash on iOS when attempting to open a Thread by tapping on the notification. + - Fixed an incomplete setup of ``sentry-cli`` node package. + - Fixed an issue with out of order websocket event handling for posts. + - Fixed a crash when opening a push notification for a thread when the Thread screen was already opened in the background. + - Fixed a crash issue and error ``Cannot read property "id" of undefined``. + - RN Image is now used on local images to avoid cache problems. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +---- + +(release-v2-3-0)= +## 2.3.0 Release +- Release Date: April 14, 2023 +- Server Versions Supported: Server v7.1.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.1.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 6.3.0 has ended and upgrading to server ESR v7.1.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Calls: Raising a hand will now take precedence when ordering participants in the call screen. + - Calls: Optimized screensharing in landscape mode for Android and iOS and unlocked landscape mode for iOS phone devices. + - Channel names are now tappable in threads and in recent mentions, search, and saved message screens. + - The ``ExperimentalGroupUnreadChannels`` server config is now respected. + - Added more information to the logs for better debugging. + +### Bug Fixes + - Calls: Fixed an issue with emoji rendering. + - Calls: Fixed an issue that caused a crash when the current presenter left the call without stopping the screenshare. + - Fixed an issue with guest badges not appearing on the channel member list. + - Added minor performance fixes to the channel member list screen. + - Fixed an issue where some notifications did not show when a channel sidebar category was collapsed. + - Fixed an issue where tapping on a custom status in the message list did not open the user's profile card. + - Fixed an issue where the channel members count did not get updated after removing users. + - Fixed a crash on markdown table images and prevented image-related crashes on other parts of the app. + - Fixed websocket not connecting during rare scenarios. + - Fixed the sort order of the search results. Search results now display from newest to oldest. + +### Open Source Components + - Added ``mattermost/calls-common`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Some Google Pixel phones on Android 12+ might not continue past the login screen. This is a known issue with the OS, and the current workaround is to restart the device. + +---- + +(release-v2-2-0)= +## 2.2.0 Release +- Release Date: March 17, 2023 +- Server Versions Supported: Server v7.1.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.1.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 6.3.0 has ended and upgrading to server ESR v7.1.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added the ability to set mobile notifications preferences per channel. + - Added support for connecting the WebSocket over TLS1.3. + - Calls: Added slash commands to start/stop call recordings (``/call recording [start|stop]``). + - Calls: Implemented glare free negotiation. This fix prevents potential negotiation problems when two clients try to connect simultaneously. + - The Help link now is not converted to lowercase. + - Added minor performance improvements on sending a message. + - Archived channels show a more detailed warning. + +### Bug Fixes + - Calls: Fixed a rare case where the Join Call banner showed that a call started "53 years ago". + - Calls: Fixed a crash on joining calls. + - Fixed an issue where tapping **Send Message** in a user’s profile pop-over did not open a Direct Message channel. + - Fixed an issue where an incorrect skin tone was applied to emojis selected in the emoji picker. + - Fixed an issue where the channel list displayed Direct Messages with user accounts that had been deactivated. + - Fixed an issue with searching for channels and users that contain non-Latin characters. + - Fixed an issue where selecting an item from the autocomplete doubled tilde and slash characters. + - Fixed an "Unable to reset your password" issue. + - Fixed an issue where the Group Message member count showed as 0 on GraphQL enabled instances. + - Fixed an issue with missing posts in a thread when a post gets deleted. + - Fixed an issue with saving a draft when navigating away from a thread or channel screens. + - Fixed an issue with running the app in a Stage Manager on iPad. + - Fixed an issue with the timing of showing the tutorial for the skin tone selector in the emoji picker. + - Fixed a crash when toggling Collapsed Reply Thread on/off. + - Fixed an issue with the push notification display when push notifications were set as a generic message with sender only. + +### Known Issues + - Users are unable to adjust the font size via the OS font size setting. + - Moving posts with the Wrangler plugin causes database "Unique key" errors. + - Some pixel phones on Android 12+ might not go past the login screen. This is a known issue with the OS and the current workaround is to restart the device. + +---- + +(release-v2-1-0)= +## 2.1.0 Release +- Release Date: February 16, 2023 +- Server Versions Supported: Server v7.1.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.1.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 6.3.0 has ended and upgrading to server ESR v7.1.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added the ability to manage channel members. + - Added the option in **Profile > Settings > Display** settings to enable/disable Collapsed Reply Threads. + - Added functionality to invite users by email and to invite users from other teams on the server. + - Calls: Calls now start in speaker mode by default. + - Calls: Calls now show the call thread in root calls posts. + - Implemented Data Retention for mobile. + +### Bug Fixes + - Calls: fixed an issue with displaying recording messages. + - Fixed an issue where a long team name wasn’t wrapped and pushed the "+ icon " next to it. + - Fixed an issue on Android where user avatars instead of webhook avatars were shown in notifications. + - Fixed an issue where the file menu remained open after the option to "open in channel" was selected. + - Fixed the ability to mark a post as unread if the post was created from a webhook. + - Fixed a crash on iOS versions lower than 16.x when opening an item in the gallery. + - Fixed an issue where ``enableMobileUploadFiles`` setting was not working correctly. + +### Open Source Components + - Added ``@gorhom/bottom-sheet`` and ``react-native-walkthrough-tooltip`` https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Selecting an item from autocomplete doubles tilde and slash characters. + - Users are unable to adjust the font size via the OS font size setting. + - Drafts are lost when following a notification. + - Moving posts with the Wrangler plugin causes database "Unique key" errors. + - Some pixel phones on Android 12+ might not go past the login screen. This is a known issue with the OS and the current workaround is to restart the device. + +---- + +(release-v2-0-1)= +## 2.0.1 Release +- Release Date: February 7, 2023 +- Server Versions Supported: Server v7.1.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v7.1.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 6.3.0 has ended and upgrading to server ESR v7.1.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added support for Android tablets and foldables. + - Added support to rotate iPads in all orientations. + - Improved the mobile emoji picker user interface and interaction. + +### Bug Fixes + - Fixed a crash when dismissing a notification on Android. + - Fixed a potential crash when trying access non existent database records. + - Fixed opening a link when the server is hosted on a subpath. + - Fixed an issue with uploading certain files. + - Fixed an issue with downloading certain files from the search results. + - Disabled top domain level verification. + - Fixed some potential crashes in the iOS Share Extension and Notification Service. + - Fixed some screens in the login flow not showing the content when animations are turned off in the device settings. + - Fixed an issue where new Direct and Group Messages sometimes did not appear in the channel list until reopening the app. + - The permissions required to receive push notifications is now always requested if needed. + - Fixed ANRs found with some Android devices. + - Fixed an issue where the keyboard changed on iOS when a code block was started. + - Fixed an issue where the EMM configuration for VPN timeouts were in ``seconds`` instead of in ``ms``. + - Fixed an issue with markdown bolded strings. + - Fixed an issue where the markdown for mentions did not inherit heading fonts. + - Fixed an issue where a crash occurred when attempting to download a profile image. + +### Known Issues + - Selecting an item from autocomplete doubles tilde and slash characters. + - Users are unable to adjust the font size via the OS font size setting. + - **Manage Members** modal is not yet added. + - Posts may remain in the local device database after data retention job has been run. + - Drafts are lost when following a notification. + - Moving posts with the Wrangler plugin causes database "Unique key" errors. + - Some pixel phones on Android 12+ might not go past the login screen. This is a known issue with the OS and the current workaround is to restart the device. + +---- + +(release-v2-0-0)= +## 2.0.0 Release +- Release Date: January 16, 2023 +- Server Versions Supported: Server v7.1.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - Please [see here](https://mattermost.com/blog/preparing-for-mobile-v2-0/) for more details on preparing for the mobile v2 release. + - **Upgrade to server version v7.1.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 6.3.0 has ended and upgrading to server ESR v7.1.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Highlights + +Mattermost mobile v2.0 is a major update to the iOS and Android apps bringing support for multiple workspaces and a more stable and performant user experience that includes: + + - Support for collaborating in multiple workspaces with a redesigned channel and team sidebar for easier navigation. + - Improved app responsiveness to user input, faster launch, and less memory consumed when running. + - Improved app stability so users encounter fewer crashes and bugs, as well as reduced app hang and errors if internet connectivity becomes unstable. + +Users now gain a more reliable and feature-rich application, improving their experience for collaborating with their teams on the go. + +### Known Issues + - Landscape mode doesn't work on Android tablets. + - Users are unable to adjust the font size via the OS font size setting. + - **Add Members** and **Manage Members** modals are not yet added. + - Posts may remain in the local device database after data retention job has been run. + - Drafts are lost when following a notification. + - Moving posts with the Wrangler plugin causes database "Unique key" errors. + - Some pixel phones on Android 12+ might not go past the login screen. This is a known issue with the OS and the current workaround is to restart the device. + - The app crashes when uploading a PDF file. + - The ``timeoutVPN`` values are not converted from milliseconds to seconds in v2. + +---- + +(release-v1-55-1)= +## 1.55.1 Release +- Release Date: September 15, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - Mobile App v1.55.1 is our first extended support release (ESR). We are very excited about the upcoming general availability of the v2.0 mobile app in December. We recognize that some customers may have a custom build of Mattermost mobile and need more time to test or implement their custom changes on mobile v2.0. The mobile ESR will be supported until July 2023. v1.55.1 will receive critical security fixes only and will be released as needed via unsigned builds to our mobile GitHub repository. + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + - Fixed an issue where users were unable to convert public channels to private. + - Fixed an issue where selected boxes in app forms and interactive dialogs could not be cleared. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-55-0)= +## 1.55.0 Release +- Release Date: August 16, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Calls: Implemented WebSocket reconnection support. + +### Bug Fixes + - Calls: Fixed a crash on "cannot replaceTrack after peer is destroyed" error. + - Fixed an issue with sharing of text alongside an image on Android. + - Fixed an issue on Android where clicking on a hashtag from the Saved Posts modal returned the user to the channel instead of taking the user to the search results. + - Fixed an issue where the select modal value was not getting populated. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-54-0)= +## 1.54.0 Release +- Release Date: July 15, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Calls: Added support for accepting advanced ICE server configurations through the config. + - Calls: Added support for using Calls when the Mattermost installation is served under a subpath. + - Calls: Added support for generating short-lived TURN credentials. + +### Bug Fixes + - Fixed an issue where Latex in root posts crashed the global Threads screen. + +### Known Issues + - The app crashes when the session length for mobile is changed via webapp. + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-53-0)= +## 1.53.0 Release +- Release Date: June 15, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added Calls Cloud Freemium limits. + - Added a handler for a new ``call_end`` event. + - Added support for a new ``MaxCallParticipants`` config setting. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-52-0)= +## 1.52.0 Release +- Release Date: May 16, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added .m4a audio file preview support via the video player. + - Added the ability to render latex code blocks. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-51-2)= +## 1.51.2 Release +- Release Date: May 5, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue with Calls where multiple "Access to route for non-existent plugin" errors got logged in the server logs. + +---- + +(release-v1-51-1)= +## 1.51.1 Release +- Release Date: April 22, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue with logging in when multiple SSO methods are enabled while email/password is disabled. + +---- + +(release-v1-51-0)= +## 1.51.0 Release +- Release Date: April 16, 2022 +- Server Versions Supported: Server v6.3.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v6.3.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.37 has ended and upgrading to server ESR v6.3.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Breaking Changes + - The Apps Framework protocol for binding/form submissions has changed, by separating the single `call` into separate `submit`, `form`, `refresh` and `lookup` calls. If any users have created their own Apps, they have to be updated to the new system. + +### Improvements + - Users are now taken directly to the SSO login if only one SSO login method is enabled. + - Calls are now enabled on mobile if the server has Calls enabled. + - For Calls, added "raise hand" functionality and a screensharing icon. + - "Default Enabled Calls" and "Allow Enable Calls" server settings are now respected by Calls on mobile. + - Added a speakerphone button to the Calls interface. + - Added support for link highlighting for capitalized link schemes, such as ``Https://`` instead of ``https://``. + - Changed the search bar in manual timezone selection view to be consistent with the rest of the app. + - The mobile app no longer attempts to fetch thread bindings when the ``AppsEnabled`` feature flag is ``false``. + - The mobile app will now only fetch App bindings if the Apps plugin is enabled. + - Added support for allowing 1-character channel names. + +### Bug Fixes + +#### All apps + - Fixed an issue with Calls banner locations for earlier iPhone models. + - Fixed an issue where users were not able to scroll down to view custom themes. + - Fixed a bug that resulted in dropping the Call state when switching to another app and returning. + - Fixed an issue where some messages could have been cut off if the markdown used had two or more links with an ``=`` sign. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + +---- + +(release-v1-50-1)= +## 1.50.1 Release +- Release Date: March 21, 2022 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrading to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) v5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue where Latex-formatted text caused the mobile app to crash. + +---- + +(release-v1-50-0)= +## 1.50.0 Release +- Release Date: March 16, 2022 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added support for markdown inline image custom sizes. + +### Bug Fixes + +#### All apps + - Fixed an issue where setting a custom status failed silently. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-49-1)= +## 1.49.1 Release +- Release Date: February 23, 2022. +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### Android specific + - Fixed an issue on Android where document files did not open. + +---- + +(release-v1-49-0)= +## 1.49.0 Release +- Release Date: February 16, 2022 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Improvements + - Added SVG support for markdown inline images. + +### Bug Fixes + +#### All apps + - Fixed an issue where the date picker jumped back to the current month after the past date selection. + - Fixed a crash issue on markdown table images. + - Fixed an issue with Collapsed Reply Threads where clicking on a permalink added the thread replies in the channel view. + - Fixed an issue with Collapsed Reply Threads where link previews disappeared when a thread was created. + +### Known Issues + - Some files (such as PDFs) fail to open/download on v1.49.0. + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-48-2)= +## 1.48.2 Release +- Release Date: January 6, 2022 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue with custom status updates with no expiry. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Clicking on a permalink adds the thread replies in the channel view. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-48-1)= +## 1.48.1 Release +- Release Date: December 15, 2021 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed a crash on collapsed reply threads when opening the Gallery view from within a Thread. + - Fixed an issue with clearing and grouping of push notifications when Collapsed Reply Threads is enabled. + - Fixed an issue with opening the YouTube app from within Mattermost. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Clicking on a permalink adds the thread replies in the channel view. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-48-0)= +## 1.48.0 Release +- Release Date: November 16, 2021 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Highlights + +#### Cross-team Recent Mentions + - Recent mentions and saved posts now show across all teams. + +### Improvements + - Adjusted channel override mobile notification preferences for Threads. + - Added long-press options to the Global Threads screen. + - Added a new messages line to the Threads screen. + - Added "pull to refresh" to load threads in the Global Threads screen. + - Added OAuth support for plugins and apps. + - Added multiselect support for apps forms. + - Added a "Rest" field app command to filter empty options on static and dynamic selects and to prohibit executing non-leaf commands. + - App bindings now recognize the post menu options for each channel they live in. + - Added ``@here`` mention to the ``EnableConfirmNotificationsToChannel`` config setting to show a warning modal when over 5 members might be alerted with ``@here``. + - Updated "Jump to..." to match webapp equivalent user interface string. + +### Bug Fixes + +#### All apps + - Fixed an issue where image previews could only be viewed once while on the Thread view. + +### Known Issues + - Channel sidebar disappears sometimes when the channel categories are not fetched from the server. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Clicking on a permalink adds the thread replies in the channel view. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-47-2)= +## 1.47.2 Release +- Release Date: October 25, 2021 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### iOS specific + - Fixed an issue copying and pasting files on iOS. + +#### Android specific + - Fixed a crash when switching channels or focusing the text input area on Android. + - Fixed a crash while opening notifications on Android. + +---- + +(release-v1-47-1)= +## 1.47.1 Release +- Release Date: October 19, 2021 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue where navigating to Global Threads crashed the app. + - Fixed Text input font scaling to follow the OS setting to fix an issue where iOS Dynamic Type size was not correct in the message box. + +#### iOS specific + - Updated the iOS app icon to a flattened version. + - Fixed a gesture conflict between the drawers and the post input on iOS. + +---- + +(release-v1-47-0)= +## 1.47.0 Release +- Release Date: October 13, 2021 +- Server Versions Supported: Server v5.37.0+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.37.0 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.31 has ended and upgrading to server ESR v5.37.0 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 12.1+ is required. + +### Highlights + +#### Branding Changes + - Updated the Splash Screen, app icons, and Threads illustration to align with new branding. + - Added a new default brand theme named "Denim". + - The existing theme names and colors, including "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" have been updated to the new "Denim", "Sapphire", "Indigo", and "Onyx" theme names and colors, respectively. Anyone using the existing themes will see slightly modified theme colors after their server or workspace is upgraded. The theme variables for the existing "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" themes will still be accessible in [our documentation](https://docs.mattermost.com/messaging/customizing-theme-colors.html#custom-theme-examples), so a custom theme can be created with these theme variables if desired. Custom themes are unaffected by this change. + - Added a new light theme named "Quartz" to the default available list of themes. + +#### Deprecations + - Stopped evaluating deprecated config settings starting with server version 6.0. + +#### Custom, Collapsible Channel Categories + - App now displays custom categories in the sidebar. + +### Improvements + - Added mobile push notifications for followed Threads. + - Increased the limit of uploaded file attachments per post from 5 to 10. + - Removed deprecated ``Posts.ParentId`` in favor of the semantically equivalent ``Posts.RootId``. + - Added better support for channel and user selection from within Apps commands. + - Added better binding filtering for Apps. + +### Bug Fixes + +#### All apps + - Added an option to download a video in the gallery view if it failed to playback. + - Fixed an issue where the emojis were cutoff when editing a message with jumbo emojis. + - Fixed an issue where some mentions were highlighted when the mention key partially matched the mention in the message. + - Fixed an issue with in-app notifications that caused the keyboard to blur when the notifications were automatically dismissed. + - Fixed an issue where the autocomplete options were still visible when the keyboard was dismissed. + - Fixed an issue where the “Loading messages…” text was upside down. + - Fixed an issue where tapping on the push notification for a new reply did not open the thread with the post. + - Fixed an issue where opening a push notification while in the Thread screen did not take the user to the channel screen. + - Fixed an issue where a System message was missing when a guest user was added to a channel or when a guest joined a channel. + - Fixed an error where the submit button on interactive dialogs was not shown when the dialog did not specify ``submit_label``. + - Fixed an issue where pressing **Jump to** on mobile showed a different highlighted channels list than the sidebar highlighted channels list. + - Removed Date and Time label from recently used custom statuses. + - Fixed an error with locations and binding filtering. + +#### iOS specific + - Fixed a crash when attempting to share content into Mattermost on iOS when Biometric authentication was required. + +#### Android specific + - Fixed the ability to snooze push notifications on Android. + - Fixed an issue with uploading of animated gif files on Android. + +### Known Issues + - An error may occur when archiving a channel or when attempting to post to an archived channel. + - The "+" to add a reaction is still visible in archived channels. + - Close Preview X and Close Settings X are themed incorrectly in Quartz theme. + - Channel sidebar disappears sometimes in Airplane mode. + - Posts sometimes get stuck behind the post textbox on iPad. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - New messages banner should only count root posts. + - Turning the feature on and off does not push an update to the Mobile client. + - Clicking on a permalink adds the thread replies in the channel view. + - Threads item unread state (bolding) does not persist when deleting documents and data. + +---- + +(release-v1-46-0)= +## 1.46.0 Release +- Release Date: August 16, 2021 +- Server Versions Supported: Server v5.31.3+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Collapsed Reply Threads (Beta) + - Added support for [Collapsed Reply Threads](https://mattermost.com/blog/collapsed-reply-threads-beta/) for the mobile apps. + +#### Custom Status Expiry + - Added a feature to choose expiry time when setting a custom status. Requires server version 5.37 or later. Also added new screens such as **Clear** and new components such as ``DateTime`` picker. + +#### Granular Data Retention Policies + - Added support for Granular Data Retention Policies for the mobile apps. Requires server version 5.37 or later. + +### Improvements + - Added the custom statuses to the mention autocomplete. + - Changed the default behavior of autocomplete user interface for cases of long display names. Long display names will be truncated to show the username. + - Added support for showing plugin slash command icons. + - Added support for apps to add arbitrary markdown in between fields on forms. + - Implemented a new style for app submit buttons. + - Added markdown support for app fields descriptions and errors. + +### Bug Fixes + +#### All apps + - Fixed an issue where boolean fields did not get disabled on dialogs when they should have. + - Fixed an issue with displaying the current user when multiple users were part of the System join / leave messages. + - Fixed a race condition when bringing the app to the foreground by tapping in a notification that belongs to a channel other than the current channel that caused the current channel to miss any mentions if it had any. + - Fixed an issue with attaching files to the correct post. + +#### Android specific + - Fixed a silent crash that could happen for some users when receiving a push notification on Android. + +### Known Issues + - Posts sometimes get stuck behind the post textbox on iPad. + - User may need to log out and back in from the app to see data retention results on the app. + - Various known issues with Collapsed Reply Threads (Beta) feature: + - Mobile app top bar disappears after resuming app from screen lock. + - New messages banner should only count root posts. + - Clicking Jump to on mobile shows a different highlighted channel list than the sidebar highlighted channel list. + - Only the last six threads are visible in the Threads view. + - Some unread channels with leave/join system messages are doubled in search results. + - Tapping on the push notification for new reply should open the thread with the post. + - Turning the feature on and off does not push an update to the Mobile client. + - Clicking on a permalink adds the thread replies in the channel view. + - Threads item is lost when clearing search in the channel sideabar. + - Previously viewed Thread is auto-followed after new replies come in. + - Threads item unread state (bolding) does not persist when deleting documents and data. + - Clicking Jump to on mobile shows different highlighted channels list than the sidebar unread channels list. + +### Contributors + - [anurag6713](https://github.com/anurag6713), [ashishbhate](https://github.com/ashishbhate), [enahum](https://github.com/enahum), [larkox](https://github.com/larkox), [manojmalik20](https://github.com/manojmalik20) + +---- + +(release-v1-45-1)= +## 1.45.1 Release +- Release Date: July 20, 2021 +- Server Versions Supported: Server v5.31.3+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue where the app crashed when a message with only emojis included a hard break. + +#### Android specific + - Fixed Android push notifications so that they are now grouped by channel. + +---- + +(release-v1-45-0)= +## 1.45.0 Release +- Release Date: July 16, 2021 +- Server Versions Supported: Server v5.31.3+ is required. Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device. + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Emoji Enhancements with Skin Tone Selection + - Added support for emoji standard v13.0 with Mattermost server v5.37. + +```{Note} +Due to the upgrade to Emoji 13.0, some emojis may be missing on Android older than 11 and iOS older than 14.2. +``` + +#### English-Australian Language Support + - Mattermost is now available in English-Australian. + +### Improvements + - Added the ability to reply to individual messages from push notifications on Android. + - Included message sender's user icon in push notifications. + - Removed the nickname from the user autocomplete when the item is the current user. + - The "swipe up to refresh" functionality was added back. + +### Bug Fixes + +#### All apps + - Fixed an issue where the progress indicator did not display for all attachments in the post draft when adding multiple images at once. + - Fixed an issue where tapping a channel link from a reply thread did not open the channel. + - Fixed an issue that caused the reply from a push notification to fail when the message belonged to a thread. + - Fixed an issue where the at-sign ``@`` was not ignored when searching for users. + - Fixed the post draft to correctly detect if the channel being viewed is read only, including when the thread view is from a different channel than the current channel. + - Fixed the render of auto-responder posts. + - Fixed an issue where the option to join another team was not present after deleting cache & data. + +#### Android specific + - Fixed Android not being hidden when going back in the thread screen when the keyboard was opened. + +#### iOS specific + - Fixed an animation transition when displaying the options menu on iOS. + +### Known Issues + - Android app doesn't group notifications properly. + +---- + +(release-v1-44-1)= +## 1.44.1 Release +- Release Date: June 28, 2021 +- Server Versions Supported: Server v5.31.3+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + +#### All apps + - Added a fix to prevent a crash when message attachments or app bindings were ``null``. + - Fixed an issue where the app crashed when bringing the app from the background after tapping on a deep link. + - Added back the permalink view from search, recent mentions, pinned and saved posts. + - Fixed an issue where the custom status did not get reflected on the Mobile App until closing and reopening the app when changing the custom status from the webapp while the Mobile App was in the background. + +#### iOS specific + - Fixed an issue where the keyboard covered the messages on the channel screen. + - Fixed an issue where a YouTube playback error could appear when clicking the thumbnail of a linked YouTube video. + - Fixed an issue where the badge count on the app icon for iOS was incorrect. + +---- + +(release-v1-44-0)= +## 1.44.0 Release +- Release Date: June 16, 2021 +- Server Versions Supported: Server v5.31.3+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +```{Note} +Mattermost Mobile App v1.44.0 contains low to high level security fixes. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Highlights + +#### Custom Statuses + - Added the custom status feature support for mobile apps. Mattermost server v5.36+ is required to access custom statuses on mobile. + +#### Shared Channels + - Added support for Shared Channels feature (Experimental, Enterprise Edition E20) by displaying information and icons for the shared channels and remote users. Also added shared channel filter for browser channels. This feature is available in Mattermost server versions v5.35.0+. + +#### Hungarian Language (Beta) + - Added a new language, Hungarian (beta). + +### Improvements + - Added support for localization with country variants. + - The "swipe up to refresh" functionality was removed to fix an issue where the app performed slowly on Android devices. + +### Bug Fixes + +#### Android specific + - Fixed an issue where the app performed slowly on Android devices that ran at 120fps instead of the normal 60fps. + +### Known Issues + - When changing the custom status from the webapp while the Mobile App is in the background, the custom status does not get reflected on the Mobile App until you close and re-open the Mobile App. + - Users will need to be on v5.31.3 for the "Unsupported server version" in-app notice to go away as [5.31.3 fixes an issue](https://docs.mattermost.com/install/self-managed-changelog.html#release-v5-31-esr) where the server version was reported as v5.30.0. + - On iOS, a YouTube playback error may appear when clicking the thumbnail of a linked YouTube video. A workaround is to tap on the link to open the video in YouTube. + +---- + +(release-v1-43-0)= +## 1.43.0 Release +- Release Date: May 16, 2021 +- Server Versions Supported: Server v5.31.3+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Support for Apps Framework (Developer Preview) + - Apps Framework is now supported on the mobile client and allows developers to create Apps which have interactivity and buttons on mobile. + +### Improvements + - Added avatars to the sidebar Direct Messages and channel info. + - On Websocket reconnect, instead of getting all the groups, only the updated groups are now fetched. + - Team channels including archived channels are now fetched since the last known timestamp. + +### Bug Fixes + +#### All apps + - Fixed an issue where appended skin tone emoji didn't render on the app. + - Fixed an issue where users were unable to get to the last line when editing a very long post. + - Fixed the user autocomplete by adding the current user to the list. + +#### Android specific + - Fixed an issue where archived teams were accessible and functional. + - Fixed an issue where uploading files failed when uploading multiple files. + +#### iOS specific + - Fixed an issue on iPad where the last message rendered behind the input box. + - Fixed an issue that caused the draft to be saved for a different channel when running the app on tablet devices. + - Fixed an issue where the **Automatic replies** setting's **Done** button on the keyboard added a new line. + +### Known Issues + - Users will need to be on v5.31.3 for the "Unsupported server version" in-app notice to go away as [5.31.3 fixes an issue](https://docs.mattermost.com/install/self-managed-changelog.html#release-v5-31-esr) where the server version was reported as v5.30.0. + - On iOS, a YouTube playback error may appear when clicking the thumbnail of a linked YouTube video. A workaround is to tap on the link to open the video in YouTube. + - The app has been reported to perform slowly on Android devices that run at 120fps instead of the normal 60fps. + +---- + +(release-v1-42-1)= +## 1.42.1 Release +- Release Date: April 19, 2021 +- Server Versions Supported: Server v5.31.3+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + +#### All apps + - Set the minimum server version to 5.31.3 instead of 5.31.0 for the "Unsupported server version" in-app notice. Servers will need to be on v5.31.3 for the in-app notice to go away as [5.31.3 fixes an issue](https://docs.mattermost.com/install/self-managed-changelog.html#release-v5-31-esr) where the server version was reported as v5.30.0. + +#### iOS specific + - Fixed an issue where the app crashed on launch. + +---- + +(release-v1-42-0)= +## 1.42.0 Release +- Release Date: April 16, 2021 +- Server Versions Supported: Server v5.31.3+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.31.3 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.25 has ended and upgrading to server ESR v5.31.3 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Support for Apps Framework (Developer Preview) + - This feature is available on Mobile Apps when Apps Framework becomes available on Mattermost v5.35.0 and the proxy plugin is loaded on an instance. The launch for the Developer Preview of the Apps Framework is scheduled for April 29th. + +### Bug Fixes + +#### All apps + - Fixed an issue where the parser of images did not accept URL escaped string, contrary to what happens in the webapp. + - Fixed an issue where images with a transparent background showed as black in the gallery. + - Fixed an issue where the Mention Highlight Link Color was not being used properly. + - Fixed an issue where sliding did not work when five images were uploaded. + - Fixed a minor typo in the search **in:** modifier label. + - Fixed an issue where OpenGraph without images did not show the image placeholder. + +#### Android specific + - Fixed an issue with frequent logouts on the latest Android OS. + - Fixed an issue where the app crashed when pressing the back button while sharing an image. + - Fixed an issue where uploading and sharing PDFs crashed the app. + - Fixed an issue where the image gallery view had a weird behaviour and did not close smoothly. + +### Known Issues + - Users will need to be on v5.31.3 for the "Unsupported server version" in-app notice to go away as [5.31.3 fixes an issue](https://docs.mattermost.com/install/self-managed-changelog.html#release-v5-31-esr) where the server version was reported as v5.30.0. + - The app has been reported to perform slowly on Android devices that run at 120fps instead of the normal 60fps. + - The last message in a channel is sometimes rendered behind the message box on iPad devices. + +---- + +(release-v1-41-1)= +## 1.41.1 Release +- Release Date: April 7, 2021 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where authenticating with any SAML provider opened the default browser, breaking the app VPN tunnel. + +---- + +(release-v1-41-0)= +## 1.41.0 Release +- Release Date: March 16, 2021 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +``` {Note} +Mattermost Mobile App v1.41.0 contains a high level security fix. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Improvements + - Refined animations for the new image gallery. + - System Admins are now prompted before joining a private channel via a permalink. + - The ``filteredEmojis`` is now calculated on first change. + +### Bug Fixes + +#### All apps + - Fixed an issue where the status and reminder time did not get updated in "Update Status" screen in the Incident Collaboration plugin on the mobile apps. + - Fixed an issue where a handler was missing for permalinks with ``_redirect``. + +### Known Issues + - Frequent logouts from the app have been experienced on the latest Android OS. Some ways to recover include logging out from the app and then uninstalling and installing the app, as well as restarting the device. + - On Pixel 4a, uploading PDFs crashes the app and sharing files does not work. + - The app has been reported to perform slowly on Android devices that run at 120fps instead of the normal 60fps. + - The last message in a channel is sometimes rendered behind the message box on iPad devices. + +---- + +(release-v1-40-0)= +## 1.40.0 Release +- Release Date: February 25, 2021 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +``` {Note} +Mattermost Mobile App v1.40.0 contains a low level security fix. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Improvements + - Added support for OpenID Connect (E20 Edition) - **This feature is available in Mattermost Cloud and will be available in upcoming server v5.33.0 (March 16th) release.** + - Changed the OAuth / SAML login flow to utilize an external browser instead of the WebView in the Mobile App. + - Added new languages, Bulgarian and Swedish. + +### Bug Fixes + +#### All apps + - Fixed an issue where deeply nested asterisks caused the app to crash. + - Fixed an issue where the app crashed when attempting to render a post whose attachment value was null. + - Fixed an issue where in-app notification banner locked user interaction until the notification banner was dismissed. + - Fixed an issue where posts with at-mentions were double posting if the user hit the **Send** button quickly multiple times in a thread. + - Fixed an issue where users were unable to add more than 40 emoji reactions on a post. + - Fixed an issue where unexpected emoji picker sometimes appeared in search results. + - Fixed an issue where "(you)" did not appear after the current username when using ``@yourself`` autocomplete in a channel. + +#### iOS specific + - Fixed an issue where users were unable to scroll horizontally to view multiple file attachments. + +### Known Issues + - Frequent logouts from the app have been experienced on the latest Android OS. Some ways to recover include logging out from the app and then uninstalling and installing the app, as well as restarting the device. + - On Pixel 4a, uploading PDFs crashes the app and sharing files does not work. + - The app has been reported to perform slowly on Android devices that run at 120fps instead of the normal 60fps. + - The last message in a channel is sometimes rendered behind the message box on iPad devices. + +---- + +(release-v1-39-0)= +## 1.39.0 Release +- Release Date: January 16, 2021 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Improvements + - Teams in the sidebar are now ordered by user preference. + - Typing an emoji in a post now adds the emoji to the list of recently used emojis. + +### Bug Fixes + +#### All apps + - Fixed an issue where users were unable to open files with file names that contained multiple dots. + - Fixed an issue where ``/mscalendar settings`` did not redirect a user to the bot Direct Message channel. + - Fixed an issue where tapping on an archived channel link from the app did not redirect the user to the archived channel. + +#### Android specific + - Fixed an issue where in some cases the deviceID used to receive push notifications wasn't being attached to the session as the registration completed. + +#### iOS specific + - Fixed an issue where custom URL schemes didn't work. + +### Known Issues + - Frequent logouts from the app have been experienced on the latest Android OS. Some ways to recover include logging out from the app and then uninstalling and installing the app, as well as restarting the device. + - The app has been reported to perform slowly on Android devices that run at 120fps instead of the normal 60fps. + - In-app notification banner locks user interaction until the notification banner is dismissed. + - The last message in a channel is sometimes rendered behind the message box on iPad devices. + +---- + +(release-v1-38-1)= +## 1.38.1 Release +- Release Date: December 18, 2020 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where the v1.38.0 app crashed on iPadOS 14 when reopened from the app switcher. + - Fixed an issue where the at-mention and slash command suggestion autocomplete modals blocked the post draft. + +---- + +(release-v1-38-0)= +## 1.38.0 Release +- Release Date: December 16, 2020 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +```{Note} +Support for landscape orientation was removed for non-tablet devices. +``` + +### Improvements + - Added gallery user interface improvements. + - Images now load progressively as the image comes into view-port instead of loading all the images on mount. + - Mattermost is now resizeable on Android Desktops such as Samsung DeX. + - "Something went wrong" message block is now vertically centered. + +### Bug Fixes + +#### All apps + - Fixed an issue where the apps frequently failed to load channels for initial team. + - Fixed an issue where all channel push notifications were cleared when opening one channel's push notification. + - Fixed an issue where post edits and deletes propagated inconsistently. + +#### Android specific + - Fixed an issue where the list of Group Mentions was not updated when Groups were added or removed in an LDAP Group Synced Team. + - Fixed an issue where a group mention was highlighted by default before it was posted. + +#### iOS specific + - Fixed an issue where the header area overlapped notch on launch on iPhone 12. + +### Known Issues + - At-mention and slash command suggestion autocomplete modals block post draft. + +---- + +(release-v1-37-0)= +## 1.37.0 Release +- Release Date: November 16, 2020 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Improvements + - Icons have been updated across the app to be more consistent and adhere to new design standards. + - The user autocomplete now allows matching on terms with spaces (For example: @firstname lastName) the same way as in the WebApp. + +### Bug Fixes + +#### All apps + - Fixed an issue where the app crashed when a user received a notification while dismissing a modal. + - Fixed an issue where users were still able to paste files in the message box even when mobile file uploads were disabled in the System Console. + - Fixed an issue where tapping on an invalid permalink showed an error. + - Fixed an issue where Global Default notification channel setting displayed incorrect notification defaults. + - Fixed an issue where the channel info count for Group Messages did not match the total number of users when both active and deactivated users were present. + - Fixed an issue where the hamburger icon width had changed and notification badges were misaligned. + - Fixed an issue where the redux-persist serializer did not return a value based on the type of the argument. + +#### Android specific + - Fixed an issue where the Android app added autofill data in the chat box. + - Fixed an issue where the Android app defaulted to Town Square after sharing a file outside of the app. + +---- + +(release-v1-36-0)= +## 1.36.0 Release +- Release Date: October 16, 2020 +- Server Versions Supported: Server v5.25+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.25 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.19 has ended and upgrading to server ESR v5.25 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Improvements + - Added **Channel Info > Notification Preferences** to add the ability to edit mobile push notification settings at the channel level. + - Server URL now autofills when opening the app from a mobile browser landing page. + - Added support for accessibility to the channel header buttons. + - Refactored the post draft component, including writing and posting messages, attaching images, using the autocomplete functionality, showing alerts from group mentions and channel wide mentions, and executing slash commands. + - Improved the empty state screen for Recent Mentions. + - Improved ``in:@user`` search to return Direct and Group Message search results. + - Improved styling of Read Only channels. + - Removed the filename from an error message when an image/video was too large. + - Improved unread badge styling of the hamburger menu and team icons. + - Improved styling of autocomplete modals. + - Improved the validation error message of the Enter Server URL screen when entering an invalid server URL. + +### Bug Fixes + +#### All apps + - Fixed an issue where a hashtag (#) character added to an announcement banner caused the app to display a blank screen. + - Fixed an issue where users were still able to upload files via the share extension when ``EnableMobileFileUpload`` was disabled on the server. + - Fixed an issue where a draft message on the reply thread was not retained if the user navigated away from the thread. + - Fixed an issue where a thumbnail of a file attachment posted in a reply thread displayed in the center channel. + - Fixed an issue where users were unable to join public channels via channel links. + +#### iOS specific + - Fixed an issue where user received an error when opening links on iOS 14 when Safari was not set as the default browser. + +---- + +(release-v1-35-1)= +## 1.35.1 Release +- Release Date: September 21, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where the app crashed when tapping on "Show More" on a long post and then tapping on the post to go to the thread. + +---- + +(release-v1-35-0)= +## 1.35.0 Release +- Release Date: September 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Upgrade to React Native 0.63.2 + - React Native 0.63.2 introduces performance and stability improvements to the core app platform. + +### Improvements + - Addded a default empty search state for the emoji picker screen. + - Added an alert box to let users know what happened when removed from a channel they were viewing. + +### Bug Fixes + +#### All apps + - Fixed an issue where the app crashed on a channel that had lot of images and attachments. + - Fixed an issue where YouTube videos rendered as OpenGraph objects but also displayed play buttons when posted using bit.ly links. + - Fixed an issue where at-mention notifications followed by a period were not highlighted. + - Fixed an issue where the permission to delete other users' posts did not function independently of deleting own posts. + - Fixed an issue where archiving a channel while in the permalink view cleared the permalink view content. + - Fixed an issue where edits to “Full Name” in Mattermost profile got overwritten by the setting from the GitLab / Google / Office365 Single Sign-On providers. + - Fixed an issue where an AD/LDAP group mention of an outsider group was highlighted on a Group Synced channel. + +#### Android specific + - Fixed an issue where users were unable to upload files with spaces in the file name. + +#### iOS specific + - Fixed an issue where using keyboard dictation sent a blank message. + - Fixed an issue where users were unable to swipe to close the left-hand side after closing the keyboard. + - Fixed an issue where the channel info screen ``This channel has guests`` text was out of safe area. + +### Known Issues + - Some Android devices running Android 11 may notice some choppiness in certain animations. + +---- + +(release-v1-34-1)= +## 1.34.1 Release +- Release Date: August 27, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where GitLab SSO was appending a # sign causing the app to fail on further requests. + - Fixed an issue where an "Hair on fire" emoji caused the app to crash. + - Fixed an issue where the app crashed when receiving a push notification when having special characters in the Nickname field. + +---- + +(release-v1-34-0)= +## 1.34.0 Release +- Release Date: August 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + - End users will now receive an in-app notification to contact their System Admin to upgrade the server version if they are running versions v5.18 and below. + - Added support for [LDAP group mentions (E20 feature)](https://docs.mattermost.com/onboard/ad-ldap-groups-synchronization.html) for mobile apps. + - Added support for non-cached slash command autocomplete for mobile apps. + +### Improvements + - Removed auto-scrolling to the new message line on channel load and added a "More Messages" button when there are unread posts. + - Improved screen styling for iOS Settings, Profile, Channel Info, "+" button for DMs and channels, Create Channel, and other user profile pages. + - Added the ability to view users' first and last name in the profile view. + - Added support on Android for showing a toast to exit when pressing the back button on channel screen. + - Added the ability for editing others' posts to function independently of Edit Own Posts. + +### Bug Fixes + +#### All apps + - Fixed an issue where an endless spinner instead of an error message was displayed when SSO login action failed. + - Fixed an issue where users were unable to create channels when first joining a team. + - Fixed an issue where an extra separator line appeared above the message box in landscape view after using mentions autocomplete. + - Fixed an issue where the at-symbol was shown twice when clicking on the at-icon. + +#### Android specific + - Fixed an issue with keyboard glitches after using an invalid slash command. + - Fixed an issue where the keyboard did not disappear when closing the channel sidebar **More** screen. + - Fixed an issue where typing right after clicking the send button didn't clear the old message. + +#### iOS specific + - Fixed an issue where users were unable to edit a message that contained a bullet list. + - Fixed an issue where user was unable to scroll or tap on emoji autocomplete in post **Edit** screen. + - Fixed an issue where the channel list was not scrolled to the bottom when a new message was received while the keyboard was open. + +---- + +(release-v1-33-1)= +## 1.33.1 Release +- Release Date: July 15, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where the apps crashed when a malformed YouTube link was posted in a channel. + +---- + +(release-v1-33-0)= +## 1.33.0 Release +- Release Date: July 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Breaking Changes + - Starting with mobile app v1.33.0, users on server versions below v5.19 may experience issues with how attachments, link previews, reactions and embed data are displayed. Updating your server to v5.19 or later is required. + +```{Note} +Mattermost Mobile App v1.33.0 contains a low level security fix. Upgrading is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +``` + +### Highlights + - System admins will now receive an in-app notification to upgrade their server version if they are running versions v5.18 and below. + +### Improvements + - Removed **Select Team** title in cases where teams aren't loading. + - The at-mention and search autocompletes now render even if there is a server request or a network outage. + +### Bug Fixes + +#### All apps + - Fixed an issue where push notifications did not redirect to the correct channel when the app was not running in the background. + - Fixed an issue where Enterprise mobility management (EMM) filled username field was not accepted as a valid username. + - Fixed an issue where the app did not open on server url screen with previous server url filled in after logging out. + - Fixed an issue where leaving a team in a browser while the mobile app was open caused the app to be stuck in the team. + - Fixed an issue where, when hitting the **Delete Documents & Data** button, the button to join the team disappeared. + - Fixed an issue where the channel header transition to landscape mode was slow. + - Fixed an issue where teams were not listed alphabetically on the **Select Team** screen. + - Fixed an issue where a currently active unread channel was not bolded. + - Fixed an issue where a team icon was not visible on the left-hand side. + - Fixed an issue where user was unable to create channels directly after joining a team. + - Fixed an issue where the **:** search date picker on edit replaced the date and left old date info. + - Fixed an issue where a confusing **Invalid Message** banner was present on Edit Message modal when typing a message that was over the character limit. + - Fixed an issue with an unhandled error when logging out from the **Select Team** screen. + - Fixed an issue where an error message on Server URL screen moved strangely when the keyboard slid on. + - Fixed an issue with an uneven horizontal margins around **Jump to** box. + - Fixed an issue where the OneLogin button had a blue outline, but a green fill. + +#### Android specific + - Fixed an issue where hitting edit multiple times opened the edit window without a save button. + +#### iOS specific + - Fixed an issue where ``switchKeyboardForCodeBlocks`` crashed the app on iOS 11. + - Fixed an issue where the Enter key did not work in search when using an iPad with an external keyboard. + - Fixed an issue where OAuth and SAML single sign-on (SSO) no longer required re-entering credentials after logging out and logging back in. + +---- + +(release-v1-32-2)= +## 1.32.2 Release +- Release Date: June 26, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where some users on the v1.32.0 or v1.32.1 mobile apps authenticating with GitLab or Office365 Single Sign-On (SSO) to a Mattermost server using a subpath were unable to login to the app. Some users authenticating to Mattermost using SAML SSO with two-factor authentication or authenticating to Mattermost with an SSO provider that utilizes query strings as part of the authentication URLs were also impacted. + - Fixed an issue where opening the app was causing an "Unexpected Error" due to a failed migration. + +---- + +(release-v1-32-1)= +## 1.32.1 Release +- Release Date: June 25, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where Android app cold start and channel switching were slow. + +---- + +(release-v1-32-0)= +## 1.32.0 Release +- Release Date: June 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Breaking Changes + - On mobile apps, users will not be able to see group mentions (E20 feature) in the autocomplete dropdown. Users will still receive notifications if they are part of an LDAP group. However, the group mention keyword will not be highlighted. + - **Upcoming breaking change** Starting with mobile app v1.33.0 (to be released on July 16th), users on server versions below v5.19 may experience issues with how attachments, link previews, reactions and embed data are displayed. Updating your server to v5.19 or later is required. + +### Highlights + +#### Quick access to emoji reactions + - Long press on a post and add recently used reactions in a single tap. + +#### Upgrade to React Native 0.62 + - React Native 0.62 introduces performance and stability improvements to the core app platform. + +### Improvements + - Automatic retry when id-loaded push notification fails to fetch on receipt. + - An appropriate error message is now shown when connecting to the server on the mobile app with an invalid SSL certificate. + - Added the ability to find users by nickname when searching using ``@``. + - Added the ability to view first and last name in profile view. + - Improved the search bar to have smoother animations. + +### Bug Fixes + +#### All apps + - Fixed an issue with an infinite skeleton channel screen on app relaunch when ``ExperimentalPrimaryTeam setting`` was enabled. + - Fixed an issue where users were scrolled to old messages when switching to a channel with unread messages. + - Fixed an issue where a logout message for session expiration was missing. + - Fixed an issue where the app did not properly handle server URL and SSO redirects. + - Fixed an issue where Direct and Group Messages disappeared from the left-hand side after opening them on webapp. + - Fixed an issue where a crash occurred instead of showing proper error on entering invalid MFA token. + - Fixed an issue where a user could not interact with the app until in-app notifications were dismissed. + - Fixed an issue where using emoji on an instance with the custom emoji feature disabled triggered a "Custom emoji have been disabled by the system admin" error in the server logs. + - Fixed an issue where the replay icon was cut off on full screen video preview. + +#### Android specific + - Fixed an issue where dropdowns in the channel modal were hard to read. + +#### Known issues + - Signing in with supported SSO methods (OKTA, OneLogin, GitLab and Office365) may fail to redirect on iOS 12. It is recommended to use iOS 13 if any issues are encountered. + +---- + +(release-v1-31-2)= +## 1.31.2 Release +- Release Date: May 27, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +Mattermost Mobile App v1.31.2 contains a high level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Bug Fixes + - Fixed an issue where file uploads failed due to a time out when the [Antivirus plugin](https://github.com/mattermost/mattermost-plugin-antivirus) was enabled. + +---- + +(release-v1-31-1)= +## 1.31.1 Release +- Release Date: May 22, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed a crash issue on Android when preloading images. + +---- + +(release-v1-31-0)= +## 1.31.0 Release +- Release Date: May 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - **Upgrade to server version v5.19 or later is required.** Support for server [Extended Support Release](https://docs.mattermost.com/upgrade/extended-support-release.html) (ESR) 5.9 has ended and upgrading to server ESR v5.19 or later is required. As we innovate and offer newer versions of our mobile apps, we maintain backwards compatibility only with supported server versions. Users who upgrade to the newest mobile apps while being connected to an unsupported server version can be exposed to compatibility issues, which can cause crashes or severe bugs that break core functionality of the app. See [this blog post](https://mattermost.com/blog/support-for-esr-5-9-has-ended/) for more details. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Improvements + - Improved network reliability and channel switching time for unread channels by fetching new posts as soon as the app reconnects. + +### Bug Fixes + +#### All apps + - Fixed an issue where slash commands with long descriptions had their description text truncated in the slash command autocomplete. + - Fixed an issue where users could not swipe up to dismiss in-app push notifications. + - Fixed an issue where the username that created the webhook was shown on webhook posts instead of the name of the bot. + - Fixed an issue where posts on the same thread appeared to be from different threads since the "...commented on [Thread Title]" was shown on all posts in the thread. + - Fixed an issue where the system message for "Edit Channel Purpose" rendered markdown. + +#### iOS specific + - Fixed an issue where code block numbering was obstructed by the iPhone's notch. + - Fixed an issue where the search text box was partially obstructed in landscape mode. + - Fixed an issue where using `Share...` option to post highlighted text to the app threw an error. + - Fixed an issue where the "back" button color was incorrect when transitioning from Thread screen to Channel screen. + - Fixed an issue where the keyboard flashed a darker color when opening Keywords from **Settings > Notifications > Mentions and replies**. + +#### Android specific + - Fixed an issue where the keyboard did not close after editing a message. + +---- + +(release-v1-30-1)= +## 1.30.1 Release +- Release Date: April 24, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + +#### All apps + - Fixed an issue with repeated forced logouts. + - Fixed an issue where channels appeared as read-only when opening the app. + - Fixed an issue where users were unable to log in if ``ExperimentalStrictCSRFEnforcement`` setting was enabled. + - A clean install may be required for the fix to take effect by uninstalling v1.30.0 (Build 285) and then installing v1.30.1 (Build 287). + - Fixed an issue where a "No internet connection" error occurred when deleting documents and data. + +#### iOS specific + - Fixed an issue where Mattermost app crashed when Enterprise mobility management (EMM) was enabled. + +#### Android specific + - Fixed an issue where using backspace out of a conversation thread or a channel caused a forced logout. + - Fixed an issue where a video upload attempt failed with an error. + +---- + +(release-v1-30-0)= +## 1.30.0 Release +- Release Date: April 16, 2020 +- Server Versions Supported: Server v5.19+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +Mattermost Mobile App v1.30.0 contains a high level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +``` {Note} +- v5.9.0 as our Extended Support Release (ESR) is coming to the end of its life cycle and upgrading to 5.19.0 ESR or a later version is highly recommended. v5.19.0 will continue to be our current ESR until October 15, 2020. +- [The Channel Moderation Settings feature](/manage/team-channel-members.html#channel-moderation-e20) released in v5.22.0 is supported on mobile app versions v1.30 and later. In earlier versions of the mobile app, users who attempt to post or react to posts without proper permissions will see an error. +``` + +### Improvements + - Significantly improved Android performance, including how quickly posts in the center screen are displayed. + - Added support for different interactive message button styles on mobile. + - Enter key on hardware Android keyboard now posts a message. + - The statuses of those users that are in the Direct Message list are now fetched when opening the app and on login. + - Added "Unarchive Channel" option to the channel info screen. + +### Bug Fixes + +#### All apps + - Fixed an issue where the modal popped down when attempting to scroll down to see if there are more emoji. + - Fixed a few crash issues. + - Fixed an issue where the navigation bar tucked under status bar when using photo or camera post icons in landscape. + - Removed mark as unread option from post menus for archived channels. + - Fixed an issue where the "Refreshing message failed" error was shown when starting a Direct Message with a new user without a verified email. + - Fixed an issue where Markdown tables was rendering in full in the center channel on larger screen sizes. + - Made the name displayed consistent with teammate display name setting. + - Fixed some selected emojis in autocomplete from rendering properly when posted. + +#### iOS specific + - Fixed an issue on iOS where the navigation bar tucked under status bar when using photo or camera post icons in landscape. + - Fixed an issue on iOS where Automatic Replies custom message text box was obstructed by the iPhone's notch. + - Fixed an issue on iOS where double dashes in mobile inside a code block got converted to emdash. + +#### Android specific + - Fixed an issue on Android where downloading a file or video was not reporting progress. + - Fixed an issue on Android that was preventing to share content through the share extension. + +---- + +(release-v1-29-0)= +## 1.29.0 Release +- Release Date: March 16, 2020 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +``` {Note} +- The persisted sidebar on Android tablets was removed in order to significantly improve the mobile app performance. +- An issue was fixed where a user's status was set as online when replying to a message from a push notification. This fix only works in combination with server v5.20.0+. +``` + +### Improvements + - Significantly improved how quickly channels load when you open the app and when you switch between them. + - Set all requests timeouts to a maximum of five seconds to improve reliability on bad networks. + - Changed "Copy Permalink" to "Copy Link" for readability. + +### Bug Fixes + - Fixed an issue where downloaded files on Android had the words `download successful` appended to their filenames, preventing the file from being opened until it was renamed in the file manager. + - Fixed a silent crash on Android when receiving a push notification. + - Fixed an issue on Android where users could not swipe to close sidebar unless the gesture was initiated outside of the sidebar. + - Fixed an issue where channels drawers were partially shown with orientation change on iOS RN61. + - Fixed an issue on iOS where the message box obstructed the bottom part of the message when opened from the notification banner. + - Fixed an issue where switching teams showed the center channel from the old team until the new team's channel data got loaded. + - Fixed an issue where users could not post messages after returning from an archived channel. + - Fixed an issue where user experienced infinite scrolling when viewing all public joinable/archived channels. + - Fixed an issue where archived channels membership was lost on the client. + - Fixed an issue on iOS where the channel intro scrolled past the top of the channel. + - Fixed an issue on Android where inline custom emojis did not display in portrait mode. + - Fixed an issue where markdown tables did not display all rows in a post when it had multiple heights. + - Fixed an issue where deleting documents and data caused a flash of the background when the app reloaded. + - Fixed an issue where tall and thin image attachments got pushed to the left instead of appearing centered. + +### Known Issues + - Some gender neutral emojis don't render as jumbo emojis. + +---- + +(release-v1-28-0)= +## 1.28.0 Release +- Release Date: February 16, 2020 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### UI/UX Improvements to the Post Draft Area + - Links added to facilitate easier access to common functions: + - finding channel members for @mentioning; + - finding and referencing slash commands; + - attaching photos and videos; + - accessing the camera + +#### Deep Linking + - Links to posts in email notifications now launch to a browser landing page with option to open in the Mobile app. + +### Improvements + - Removed markdown rendering from Channel Purpose in channel info screen. + - Improved channel info transition so that it opens up as a modal rather than as a drawer from the right. + - Clicking on the time in the iOS status bar now scrolls up the center channel. + - Improved the sliding behaviour of the left-hand sidebar on iOS. + - Added more responsiveness to markdown tables. + - User's own username with a suffix 'you' is now shown in the username autocomplete. + - Improved sorting of emojis in the emoji picker so that thumbsup is sorted first, then thumbsdown, and then custom emoji. + +### Bug Fixes + - Fixed an issue on Android where the app displayed an incorrect timestamp when the experimental Timezone setting was disabled. + - Fixed an issue where combined system messages with many users listed hid posts above them. + - Fixed an issue on iOS where the app crashed when pasting a GIF via the keyboard. + - Fixed an issue where explicit links to teams and channels on the same server currently logged in to didn't switch to that team and channel. + - Fixed an issue where the keyboard glitched when returning to the main channel view after viewing a code block in the right-hand side. + - Fixed an issue with default boolean values in interactive dialogs. + +### Known Issues + - Markdown tables are missing a header colour. + +---- + +(release-v1-27-1)= +## 1.27.1 Release +- Release Date: January 21, 2020 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where all previously auto-closed Direct Message channels were listed in the channel sidebar. + - Fixed a regression affecting webapp and mobile apps where some users were experiencing client-side performance issues. This was mainly affecting users with more than 100 channels listed in the channel sidebar and with channels sorted alphabetically. + +---- + +(release-v1-27-0)= +## 1.27.0 Release +- Release Date: January 16, 2020 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where flaky networks caused users to miss messages when at the top of the channel. + - Fixed an issue where uploading image attachments in the mobile app was not working in some cases. + - Fixed an issue where joining a user's first team from the mobile apps failed. + - Fixed an issue where an unexpected `More New Messages Above` line appeared when marking a first post as unread in a Direct Message or Group Message channel. + - Fixed an issue where disagreeing with custom Terms of Service gives users a glimpse of the app. + - Fixed an issue on Android where the Back button did not dismiss the modal before dismissing the sidebar. + - Fixed an issue where a message draft was lost after attempting to post an invalid slash command. + - Fixed an issue where timestamps on 12-hour format had a leading zero. + - Fixed an issue where the display name of a post was truncated even when there was enough space to render it on landscape. + - Fixed an issue where the post input field icon was mis-aligned. + - Fixed an issue where system message mentions were not at 100% opacity compared to non-system messages. + +### Known Issues + - Text box obstructs bottom part of messages in Direct Message channels when opened from a notification banner. + +---- + +(release-v1-26-2)= +## 1.26.2 Release +- Release Date: January 7, 2020 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue on iOS where the mobile app was not usable if ``inAppPincode`` was enabled. + +---- + +(release-v1-26-1)= +## 1.26.1 Release +- Release Date: December 20, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed a crash issue on Android and iOS on server versions prior to the v5.9.0 Extended Support Release (ESR). + - Fixed a crash when connecting the WebSocket to a server with Cert Based Auth (CBA) enabled. + +---- + +(release-v1-26-0)= +## 1.26.0 Release +- Release Date: December 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +Mattermost Mobile App v1.26.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Highlights + +#### Improved Styling for File, Image and Video Attachments, Including In-line Image Thumbnails + +#### Mark as Unread + - With server v5.18 and above, users can stay on top of important messages with a new feature that allows marking posts as unread. After doing so, users will automatically land on the unread post the next time they click on the relevant channel. + +#### Push Notification Message Contents Fetched from the Server on Receipt (E20) + - Allows push notifications to be delivered showing the full message contents that are fetched from the server once the notification is delivered to the device. This means that Apple Push Notification Service (APNS) or Google Firebase Cloud Messaging (FCM) cannot read the message contents since only a unique message ID is sent in the notification payload. + +#### Upgraded RN to v0.61 + +### Improvements +- Added support for pasting other file types such as videos, PDFs and documents. +- Added the option to convert public channels to private in the channel info screen. +- Added support for reading the channel drawer button with voice-over. +- Made usernames in system messages tappable. +- Added an autocomplete to edit post screen. +- Added a count for pinned posts icon. +- Updated the channel name length character limit to 64 to match server. +- Added an expand button to truncated markdown tables to improve discoverability of opening them in full screen. +- Added an error message when trying to share too long text from share extension. +- Improved behaviour where posts from different authors in the same thread appeared to be from different threads if separated by new message line. +- Added support for native emojis in the emoji picker and autocomplete. +- Removed reactions and file attachments from the long post view. +- Large number of emoji reactions now wrap instead of introducing horizontal scroll. +- Added support for a generic error message in interactive dialog responses. +- Added the ability to disable attachment buttons and fields. + +### Bug Fixes +- Fixed an issue on Android where the app slowed down when opening a channel with large number of animated emoji. +- Fixed an issue where the app crashed when pasting a large file to the text box from the clipboard. +- Fixed an issue where the app crashed when previewing large GIF files. +- Fixed an issue where the app crashed when using the emoji category selector. +- Fixed an issue where the app was not able to play YouTube videos. +- Fixed an issue where images/videos could not be saved. +- Fixed an issue where channels archived via the command line interface were still visible on the left-hand side and accessible on mobile apps. +- Fixed an issue where the thread header in landscape view was wider than the main channel view header. +- Fixed an issue where sidebar separator line was misaligned between Teams and Channel view. +- Fixed an issue on iOS where the channel spinner appeared black on a dark theme. +- Fixed an issue where an asterisk appeared on the "Nickname" and "Position" fields in Edit Profile screen even though nickname is not handled through the login provider. +- Fixed an issue where the filtered list for emojis opened above the edit box and behind the channel header when adding an emoji to channel header using ``:emoji:``. + +---- + +(release-v1-25-1)= +## 1.25.1 Release +- Release Date: November 22, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed a crash issue on iOS when SSO cookies did not contain an expiration date during login. + - Fixed a crash issue on Android caused by notification channels being unavailable in Android 7. + - Fixed an issue on Android where Enterprise Mobility Management (EMM) blur app screen did not work. + - Fixed an issue where changing team/channel when sharing several files closed the share dialog. + +---- + +(release-v1-25-0)= +## 1.25.0 Release +- Release Date: November 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where Mattermost monokai theme no longer worked properly on mobile apps. + - Fixed an issue on Android where the notification badge count didn't update when using multiple channels. + - Fixed an issue on Android where test notifications did not work properly. + - Fixed an issue where "In-app" notifications caused the app badge count to get out of sync. + - Fixed an issue on Android where email notification setting displayed was not updated when the setting was changed. + - Fixed an issue where Favorite channels list didn't update if the app was running in the background. + - Fixed an issue where the timezone setting did not update when changing it back to set automatically. + - Fixed an issue on iOS where clicking on a hashtag from "recent mentions" (or flagged posts) returned the user to the channel instead of displaying hashtag search results. + - Fixed an issue where tapping on a hashtag engaged a keyboard for a moment before displaying search results. + - Fixed an issue where posts of the same thread appeared to be from different threads if separated by a new message line. + - Fixed styling issues on iOS for Name, Purpose and Header information on the channel info screen. + - Fixed styling issues with bot posts timestamps in search results and pinned posts. + - Fixed styling issues on single sign-on screen in landscape view on iOS iPhone X and later. + - Fixed styling issues on iOS for the Helper text on Settings screens. + - Fixed an issue where the thread view header theme was inconsistent during transition back to main channel view. + - Fixed an issue on iOS where the navigation bar tucked under the phone's status bar when switching orientation. + - Fixed an issue on iOS where the keyboard flashed darker when Automatic Replies had been previously enabled. + - Fixed an issue on Android where uploading pictures from storage or camera required unwanted permissions. + - Fixed an issue where ``mobile.message_length.message`` did not match webapp's ``create_post.error_message``. + +### Known Issues + - App slows down when opening a channel with large number of animated emoji. + +---- + +(release-v1-24-0)= +## 1.24.0 Release +- Release Date: October 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Sidebar UI/UX improvements + - Improved usability and styling of the channel drawer. + +### Improvements + - Added the ability to paste images on input text box. + - Added copy and paste protection managed configuration support for Android. + - Added a confirmation dialog when posting a message with `@channel` and `@all`. + - Added support for safe area in landscape view on iOS. + - Changed recent date separators to read Today/Yesterday. + - Added an autocomplete to the edit channel screen. + - Emoji picker search now ignores the leading colon. + - Added support for emoji not requiring a whitespace to render. + - Added support for footer and footer_icon in message attachments. + - Added a password type for interactive dialogs. + - Added support for introductory markdown paragraph in interactive dialogs. + - Added support for boolean elements in interactive dialogs. + - Improved the permissions prompt if Mattermost doesn't have permission to the photo library. + +### Bug Fixes + - Fixed an issue where the notification badge could get out of sync when reading messages in another client. + - Fixed an issue where the notification badge number did not reset when opening a push notification. + - Fixed an issue where SafeArea insets were not working properly on new iPhone 11 models. + - Fixed an issue where long press on a system message in an archived channel locked up the app. + - Fixed an issue where tapping on a hashtag while replying to search results didn't open search correctly. + - Fixed an issue where the channel list panel was missing for a user when they were added to a new team by another user. + - Fixed an issue where once in a thread, pressing a channel link appeared to do nothing. + - Fixed an issue where file previews could scroll to the left until all files were out of view. + - Fixed an issue on iOS where user was unable to select an emoji from two rows on the bottom of the emoji picker. + - Fixed an issue where duplicate pinned posts displayed after editing pinned post from Pinned Posts screen. + - Fixed an issue where the reply arrow overlapped a posts's timestamp in some cases. + - Fixed an issue where post textbox did not clear after using a slash command. + - Fixed an issue where users were are not immediately removed from the mention auto-complete when those users were deactivated. + - Fixed an issue where returning to a channel from a thread view could trigger a long-press menu that couldn't be dismissed. + - Fixed an issue with a missing "(you)" suffix in the channel header of a self Direct Message. + - Fixed an issue where the Connected banner got stuck open after the WebSocket was connected. + - Fixed an issue where the text input area in Android Share extension did not use available space. + - Fixed an issue where Windows dark theme was not consistent when viewing an archived channel. + - Fixed an issue where interactive dialogs rendered out of safe area view on landscape orientation. + - Fixed an issue where a themed "Delete Documents & Data" action flashed a white screen. + +### Known Issues + - App slows down when opening a channel with large number of animated emoji. + +---- + +(release-v1-23-1)= +## 1.23.1 Release +- Release Date: September 27, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed issues causing the app to crash on some devices. + +---- + +(release-v1-23-0)= +## 1.23.0 Release +- Release Date: September 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where some Giphy actions were not working in ephemeral posts on mobile. + - Fixed an issue where users were unable to create new channels when "Combine all channel types" was selected. + - Fixed an issue on Android EMM where a crash occurred when tapping **Go to Settings**. + - Fixed an issue on iOS where the in-app "Date" localization persisted after server and user changed. + - Fixed an issue where the download step was showing when previewing a video right after posting it. + - Fixed an issue on Android where cancelling a video download twice in a row showed an error. + - Fixed an issue where file attachment thumbnail/preview could fail to load and not be able to be reloaded. + - Fixed an issue on Android where **Channel > Add Members > ADD** text changed to black. + - Fixed an issue on iOS where the **Cancel** label text didn't fit in one line in German language. + - Fixed an issue where longer than allowed reply posts kept showing a warning with every backspace. + - Fixed an issue where there was a delay in search box and emoji content width change when switching to/from portrait/landscape view. + - Fixed an issue where deactivated users did not appear in the "Jump to..." screen. + - Fixed an issue where "@undefined has joined the channel" was shown instead of "Someone has joined the channel" when a user joined a channel that another user was viewing. + - Fixed an issue on Android where the reply arrow was cut off in search results. + - Fixed an issue where changing display theme from webapp didn't work properly on mobile. + - Fixed an issue on iOS where a bot account icon style was broken. + - Fixed an issue with an incorrect UI text for location of touch ID setting. + +### Known Issues + - App slows down when opening a channel with large number of animated emoji. + - When users are deactivated, they are not immediately removed from the mention auto-complete. + +---- + +(release-v1-22-1)= +## 1.22.1 Release +- Release Date: August 23, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where the apps crashed when setting the language to Chinese Traditional. + - Fixed an issue on Android where push notification receipt delivery failed due to invalid server URL. + - Fixed an issue where the apps crashed when launched via a notification. + - Fixed an issue where posts made while the app was closed did not appear until refresh. + +---- + +(release-v1-22-0)= +## 1.22.0 Release +- Release Date: August 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Support for iOS13 and Android Q + - Added support for iOS13 and Android Q which are to be released later this year. + +### Improvements + - Added support for Interactive Dialog with no elements. + - Added a setting for tablets to enable or disable fixed sidebar. + - Changed "about" section references to use the site name when it is configured in **System Console > Custom Branding > Site Name**. + - Added support for plus-sign and period/dot in custom URL schemes. + - Added "Edit profile" button to right-hand side menu and to users' own profile pop-over. + - Message draft is now saved when closing the app. + - Removing a link preview on webapp now also removes it on the mobile app. + - Added ability to select and copy channel header text and purpose. + +### Bug Fixes + - Fixed a few mobile app crash / fatal error issues. + - Fixed an issue where timestamps were off on Android. + - Fixed an issue where contents of ephemeral posts from /giphy were not being displayed on mobile. + - Fixed an issue where team/channel page dots at the bottom of left-hand side overlapped with the last Direct Message channel. + - Fixed an issue where network reconnection incorrectly showed refreshing messages failed. + - Fixed an issue with the channel sidebar theme colors not being respected on iPhone X. + - Fixed an issue where "Message failed to send" had incorrect app badge behaviour. + - Fixed an issue where a white screen was briefly shown after pressing "Send Message" when viewing a user's profile. + - Fixed an issue on Android where using "Https" instead of "https" in the url of an image didn't show the preview. + - Fixed an issue where the client ``setCSRFFromCookie`` did not look for subpaths when accessing cookies. + - Fixed an issue where archived teams reappeared in selector. + - Fixed an issue where users' profile picture and name did not get updated after websocket disconnect. + +### Known Issues + - App slows down when opening a channel with large number of animated emoji. + - Some Giphy actions do not work in ephemeral posts. + +---- + +(release-v1-21-2)= +## 1.21.2 Release +- Release Date: August 1, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where the mobile apps logged out without a session expiry notification. + +---- + +(release-v1-21-1)= +## 1.21.1 Release +- Release Date: July 22, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue on Android where logging in using SSO failed when the Mattermost server was running on a subpath. + +---- + +(release-v1-21-0)= +## 1.21.0 Release +- Release Date: July 16, 2019 +- Server Versions Supported: Server v5.9+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed a few mobile app crash / fatal error issues. + - Fixed an issue where having the sidebar open at all times on tablets did not work for split view. + - Fixed an issue where new messages were often hidden behind a keyboard or text field. + - Fixed an issue on Android where channel sorting didn't match the web app. + - Fixed an issue where sharing a GIF via keyboard resulted in an error screen. + - Fixed an issue where long-press menu could not be dragged up when rotating the device to landscape view while the menu was open. + - Fixed an issue on Android where push notification settings were only saved after closing the settings page. + - Fixed an issue where users on View Members list had an icon that appeared to be selectable but was not. + - Fixed an issue where "Jump To" showed archived channels the user did not belong to instead of the ones the user was a member of. + - Fixed an issue where changing the timezone setting manually to "Set automatically" did not work on the mobile app. + - Fixed an issue where setting a position field for AD/LDAP sync or SAML in the System Console did not block the user from changing it in account settings. + - Fixed an issue where **Channel Info > Manage/View Members** screen didn't load channel users. + - Fixed an issue where enabling large fonts on iOS caused the left-hand side text to be cut off. + - Fixed an issue on Android where users could not reply to a push notification if the mention was in a thread message. + +### Known Issues + - (Android) On subpath server, logging in using GitLab or OneLogin fails to display Mattermost. + - Buttons inside ephemeral posts are not clickable / functional on the mobile app. + - Android apps slow down when opening a channel with large number of animated emoji. + +---- + +(release-v1-20-2)= +## 1.20.2 Release +- Release Date: July 10, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where Moto G7 devices were detected as tablets and showed a fixed width sidebar. + - Fixed an issue where having the sidebar open at all times on tablets did not work on split view. + +---- + +(release-v1-20-1)= +## 1.20.1 Release +- Release Date: June 21, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where some Android devices were crashing. + - Fixed an issue where messages were missing after reconnecting the network. + +---- + +(release-v1-20-0)= +## 1.20.0 Release +- Release Date: June 16, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + +#### Tablet Improvements + - Channel sidebar now remains open at a fixed width on tablet devices. + +#### iOS Keyboard Dismissal + - If the keyboard is open, swiping down past it now closes it. + +#### Profile Telemetry for Android Beta Builds + - To improve Android app performance, we are collecting trace events and device information, collectively known as metrics, to identify slow performing key areas. Those metrics will be sent only from users using Android app beta build starting in version v1.20, who are logged in to servers that allow sending [diagnostic information](https://docs.mattermost.com/configure/configuration-settings.html#enable-diagnostics-and-error-reporting). + +### Improvements + - Increased the double tap delay for post action buttons. + - Implemented assets for Adaptive icons. + - Users are now brought to the bottom of the channel when posting a message. + - Users can now execute actions while the keyboard is open. + - Added support on iOS for IPv6 on LTE networks. + - Added support for LDAP Group constrained feature with v5.12 servers. + +### Bug Fixes + - Fixed an issue where a post wasn't immediately removed when deleting another user's post. + - Fixed an issue where the cursor jumped back when typing after auto-completing a slash command. + - Fixed an issue where the iOS app didn’t properly restore its connection after disconnect. + - Fixed an issue where the long press menu persisted after returning from a thread. + - Fixed an issue on Android where the "Write to [channel name]" was cut off for group messages with several users. + - Fixed an issue where users were not able to flag or unflag posts in a read-only channel. + - Fixed an issue where the progress indicator was negative while downloading a video. + - Fixed an issue where the edit post modal didn’t have an autocorrect. + - Fixed an issue where the 'I forgot my password' option was available on the mobile client even with Email Authentication disabled on the server. + - Fixed an issue with large separation between placeholders on iPad when a channel was loading. + - Fixed an issue where "Show More" was not removed after the post was edited to a single line. + +### Known Issues + - Buttons inside ephemeral posts are not clickable / functional on the mobile app. + - App slows down when opening a channel with large number of animated emoji. + + ---- + +(release-v1-19-0)= +## 1.19.0 Release +- Release Date: May 16, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed an issue where Android managed config was lost on the thread view. + - Fixed an issue where contents of ephemeral posts did not display on the mobile app. + - Fixed a few mobile app crash / fatal error issues. + - Fixed an issue with an expanding animation when tapping on Jump to Channel in the channel list. + - Fixed an issue on iOS where animated custom emoji weren't animated. + - Fixed an issue on iOS where users were unable to create channel name of two characters. + - Fixed an issue on iOS where emoji appeared too close, with uneven spacing, and too small in the info modal. + - Added an error handler when sharing text that was over server's maximum post size with the iOS Share Extension. + - Fixed an issue where users could upload a GIF as a profile image. + +### Known Issues + - Buttons inside ephemeral posts are not clickable / functional on the mobile app. + +---- + +(release-v1-18-1)= +## 1.18.1 Release +- Release Date: April 18, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Bug Fixes + - Fixed a crash issue caused by a malformed post textbox localize string. + - Fixed an issue where iOS crashed when trying to log in using SSO and the SSO provider set a cookie without an expiration date. + +---- + +(release-v1-18-0)= +## 1.18.0 Release +- Release Date: April 16, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + - ``Bot`` tags were added for bot accounts feature in server v5.10 and mobile v1.18, meaning that mobile v1.17 and earlier don't support the tags. + +### Highlights + - Added support for Office365 single sign-on (SSO). + - Added support for Integrated Windows Authentication (IWA). + +### Improvements + - Added the ability for channel links to open inside the app. + - Added ability for emojis and hyperlinks to render in the message attachment title. + - Added Chinese support for words that trigger mentions. + - Added a setting to the system console to change the minimum length of hashtags. + - Added a reply option to long press context menu. + +### Bug Fixes + - Fixed an issue where blank spaces broke markdown tables. + - Fixed an issue where deactivated users appeared on "Add Members" modal but not on the search results. + - Fixed an issue on Android where extra text in the search box appeared after using the autocomplete drop-down. + - Fixed an issue with multiple text entries when typing with Shift+Letter on Android. + - Fixed an issue where push notifications badges did not always clear when read on another device. + - Fixed an issue where opening a single or group notification did not take the user into the channel where the notification came from. + - Fixed an issue where timezone did not automatically update on Android when travelling to another timezone. + - Fixed an issue where the user mention autocomplete drop-down was case sensitive. + - Fixed an issue where system administrators were able to see the full long press menu when long pressing a system message. + - Fixed an issue where users were not able to unflag posts from "Flagged Posts" when opened from a read-only channel. + - Fixed an issue where users were unable to create channel names of two byte characters. + +### Known Issues + - Content for ephemeral messages is not displayed on Mattermost Mobile Apps. + +---- + +(release-v1-17-0)= +## 1.17.0 Release +- Release Date: March 20, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - If **DisableLegacyMfa** setting in ``config.json`` is set to ``true`` and [multi-factor authentication](https://docs.mattermost.com/onboard/multi-factor-authentication.html) is enabled, ensure your users have upgraded to mobile app version 1.17 or later. See [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. + - If you are using an EMM provider via AppConfig, make sure to add two new settings, `useVPN` and `timeoutVPN`, to your AppConfig file. The settings were added for EMM connections using VPN on-demand - one to indicate if every request should wait for the VPN connection to be established, and another to set the timeout in seconds. See docs for more details on [setting AppConfig values](https://docs.mattermost.com/deploy/mobile/deploy-mobile-apps-using-emm-provider.html#mattermost-appconfig-values) for VPN support. + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + - iPhone 5s devices and later with iOS 11+ is required. + +### Highlights + - iOS Share Extension now supports large file sizes and improved performance + +### Bug Fixes + - Fixed support for EMM connections using VPN on-demand. See docs for more details on [setting AppConfig values](https://docs.mattermost.com/deploy/mobile/deploy-mobile-apps-using-emm-provider.html#mattermost-appconfig-values) for VPN support. + - Fixed several Android app crash / fatal error issues. + - Fixed an issue on Android where the app crashed intermittently when selecting a link. + - Fixed an issue where email notifications setting was out of sync with the webapp until the setting was edited. + - Fixed an issue where notification badges were not cleared from other clients when clicking on a push notification after opening the mobile app. + - Fixed an issue where the app did not show local notification when session expired. + - Fixed an issue where the profile picture for webhooks was showing the hook owner picture. + - Fixed an issue where some emoji were not rendered as jumbo. + - Fixed an issue where jumbo emoji posted as a reply sometimes appeared with large space beneath. + - Fixed an issue where the "No Internet Connection" banner did not always display when internet connectivity was lost. + - Fixed an issue where the "No Internet Connection" banner did not always disappear when connection was re-estabilished. + - Fixed an issue where opening channels with unreads had loading indicator placed above unread messages line. + +---- + +(release-v1-16-1)= +## 1.16.1 Release +- Release Date: February 21, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + +### Bug Fixes + - Fixed an issue where link previews and reactions weren't displayed when post metadata was disabled. + - Fixed an issue on Android where the app crashed when sharing multiple files. + +---- + +(release-v1-16-0)= +## 1.16.0 Release +- Release Date: February 16, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + +### Improvements + - Added the ability to remove own profile picture. + - Changed "X" to "Cancel" on Edit Profile page. + - Added support for relative permalinks. + +### Bug Fixes + - Fixed an issue where the iOS app did not wait until the on-demand VPN connection was established. (EMM Providers) + - Fixed an issue with a white screen caused by missing Russian translations. + - Fixed an issue where the iOS badge notification did not always clear. + - Fixed an issue where the thread view displayed a new message indicator. + - Fixed an issue where quick multiple taps on the file icon opened multiple file previews. + - Fixed an issue where the settings page did not show an option to join other teams. + - Fixed an issue where image previews didn't work after using Delete File Cache. + - Fixed an issue on Android where the notification trigger word modal title was "Send email notifications" instead of "Keywords". + - Fixed an issue where the Webhook icon was misaligned and bottom edges were cut off. + - Fixed an issue on Android where the user was not asked to authenticate to the app first when trying to share a photo, resulting in a white "Share modal" screen with a never-ending loading indicator. + - Fixed an issue on iOS where push notifications were not preserved when opening the app via the Mattermost icon. + +---- + +(release-v1-15-2)= +## 1.15.2 Release +- Release Date: January 16, 2019 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + +### Bug Fixes + + - Fixed an issue where the status changes for other users did not always stay current in the mobile app. + - Fixed an issue where a post did not fail properly when the user attempted to send the post while there was no network access. + - Fixed an issue where date separators did not update when changing timezones. + - Fixed an issue where the Favorites section did not clear from a users's channel drawer. + - Removed an extra divider below "Edit Channel" of Direct Message Channel Info. + - Fixed an issue where a user was not returned to previously viewed channel after viewing and then closing an archived channel. + - Fixed an issue where a quick double tap on switch of Channel Info created and extra on/off state. + - Fixed an issue where iOS long press menu didn't have rounded corners. + +---- + +(release-v1-15-1)= +## 1.15.1 Release +- Release Date: December 28, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + +### Bug Fixes + - Fixed an issue preventing some users from logging in using OKTA. + +---- + +(release-v1-15-0)= +## 1.15.0 Release +- Release Date: December 16, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +### Compatibility + + - Mobile App v1.13+ is required for Mattermost Server v5.4+. + - Android operating system 7+ [is required by Google](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html). + +### Highlights + - Added mention and reply mention highlighting. + - Added a sliding animation for the reaction list. + - Added support for pinned posts. + - Added support for jumbo emojis. + - Added support for interactive dialogs. + - Improved UI for the long press menu and emoji reaction viewer. + +### Improvements + - Added the ability to include custom headers with requests for custom builds. + - Push Notifications that are grouped by channels are cleared once the channel is read. +- Improved auto-reconnect when unable to reach the server. + - Added support for changing the mobile client status to offline when the app loses connection. + - Added 'View Members' button to archived channels. + - Added support on iOS for keeping the postlist in place without scrolling when new content is available. + +### Bug Fixes + - Fixed an issue where clicking on a file did not show downloading progress. + - Fixed an issue on Android where on fresh install the share extension would not properly show available channels. + - Fixed an issue where recently archived channels remained in in: autocomplete when they had been archived. + - Fixed an issue where text should render when no actual custom emoji matched the named emoji pattern. + - Fixed an issue on iOS where text got cut-off after replying to a message. + - Fixed an issue where search modifier for channels was showing Direct Messages without usernames. + - Fixed an issue where "Close Channel" did not work properly when viewing two archived channels in a row. + - Fixed an issue with "Critical Error" screen when trying to upload certain file types from "+" to the left of message input box. + +---- + +(release-v1-14-0)= +## 1.14.0 Release +- Release Date: November 16, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported unless the user installs the CA certificate on their device + +**Compatibility Note: Mobile App v1.13+ is required for Mattermost Server v5.4+** + +### Bug Fixes +- Fixed an issue where the Android app did not allow establishing a network connection with any server that used a self-signed certificate that had the CA certificate user installed on the device. +- Removed "Copy Post" option on long-press message menu for posts without text. +- Fixed an issue where the "Search Results" header was not fully scrolled to top on search "from:username". +- Fixed an issue where channel names truncated at fewer characters than necessary. +- Fixed an issue where the same uploaded photo generated a different file size. +- Fixed an issue where the "(you)" was not displayed to the right of a user's name in the channel drawer when a user opened a Direct Message channel with themself. +- Fixed an issue where a dark theme set from webapp broke mobile display. +- Fixed an issue where channel drawer transition sometimes lagged. +- Fixed an issue where sending photos to Mattermost created large files. +- Fixed an issue where the apps showed "Select a Team" screen when opened. +- Fixed an issue where at-mention, emoji, and slash command autocompletes had a double top border. +- Fixed an issue where the drawer was unable to close when showing the team list. +- Fixed an issue where team sidebar showed + sign even without more teams to join. + +---- + +(release-v1-13-1)= +## 1.13.1 Release +- Release Date: October 18, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported + +**Compatibility Note: Mobile App v1.13+ is required for Mattermost Server v5.4+** + +### Bug Fixes +- Fixed an issue preventing some users from authenticating using OKTA + +---- + +(release-v1-13-0)= +## v1.13.0 Release +- Release Date: October 16, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported + +**Compatibility Note: Mobile App v1.13+ is required for Mattermost Server v5.4+** + +### Highlights + +#### View Emoji Reactions +- Hold down on any emoji reaction to see who reacted to the post. + +#### Hashtags +- Added support for searching for hashtags in posts. + +#### Dropdown menus +- Added support for dropdown menus in message attachments. + +### Improvements +- Added support for iPhone XR, XS and XS Max. +- Added support for nicknames on user profile. +- On servers 5.4+, added support for searching in direct and group message channels using the "in:" modifier. +- Channel autocomplete now gets closed if multiple tildes are typed. +- Added a draft icon in sidebar and channel switcher for channels with unsent messages. +- Users are now redirected to the archived channel view (rather than to Town Square) when a channel is archived. +- When closing an archived channel, users are now returned to the previously viewed channel. + +### Bug Fixes +- Refactored postlist to include Android Pie fixes and smoother scrolling. +- Fixed an issue where deactivated users were not marked as such in "Jump To" search. +- Fixed an issue where users got a permission error when trying to open a file from within the image preview screen. +- Fixed an issue where session expiry notifications were not being sent on Android. +- Fixed an issue where post attachments failed to upload. +- Fixed an issue where the "DM More..." list cut off user info. +- Fixed an issue where the user would briefly see a system message when loading a reply thread. +- Fixed an issue where the error message was incorrectly formatted if the login method was set to email/password and the user tried to log in with SAML. +- Fixed an issue on Android where the keyboard sometimes overlapped the bottom of the post textbox. +- Fixed an issue where there was no option to take video via "+" > "Take Photo or Video" on iOS. + +---- + +(release-v1-12-0)= +## v1.12.0 Release +- Release Date: September 16, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Search Date Filters +- Search for messages before, on, or after a specified date. + +### Improvements +- Added notification support for Android O and P. + +### Bug Fixes +- Fixed an issue where Okta was not able to login in some deployments. +- Fixed an issue where messages in Direct Message channels did not show when clicking "Jump To". +- Fixed an issue where `Show More` on a post with a message attachment displayed a blank where content should have been. +- Prevent downloading of files when disallowed in the System Console. +- Fixed an issue where users could not click on attachment filenames to open them. +- Fixed an issue where email notification settings did not save from mobile. +- Fixed an issue where the share extension allowed users to select and attempt to share content to channels that had been archived. +- Fixed an issue where reacting to an existing emoji in an archived channel was allowed. +- Fixed an issue where archived channels sometimes remained in the drawer. +- Fixed an issue where deactivated users were not marked as such in Direct Message search. + +---- + +(release-v1-11-0)= +## v1.11.0 Release +- Release Date: August 16, 2018 +- Server Versions Supported: Server v4.10+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Searching Archived Channels +- Added ability to search for archived channels. Requires Mattermost server v5.2 or later. + +#### Deep Linking +- Added the ability for custom builds to open Mattermost links directly in the app rather than the default mobile browser. Learn more in our [documentation](https://docs.mattermost.com/deploy/mobile-faq.html#how-do-i-configure-deep-linking) + +### Improvements +- Added profile pop-up to combined system messages. +- Force re-entering SSO auth credentials after logout. +- Added consecutive posts by the same user. +- Added a loading indicator when user info is still loading in the left-hand side. + +### Bug Fixes +- Fixed an issue where Android devices showed an incorrect timestamp. +- Fixed an issue on Android where the app did not get sent to the background when pressing the hardware back button in the channel screen. +- Fixed an issue with video playback when the filename had spaces. +- Fixed an issue where the app crashed when playing YouTube videos. +- Fixed an issue with session expiration notification. +- Fixed an issue with sharing files from Google Drive in Android Share Extension. +- Fixed an issue on Android where replying to a push notification sometimes went to the wrong channel. +- Fixed an issue where the previous server URL was present on the input textbox before changing the screen to Login. +- Fixed an issue where user menu was not translated correctly. +- Fixed an issue where some field lengths in Account Settings didn't match the desktop app. +- Fixed an issue where long URLs for embedded images in message attachments got cut off and didn't render. +- Fixed an issue where link preview images were not cropped properly. +- Fixed an issue where long usernames didn't wrap properly in the Account Settings menu. +- Fixed an issue where DMs would not open if users were using "Jump To". +- Fixed an issue where no message was displayed after removing a user from a channel with join/leave messages disabled. + +---- + +(release-v1-10-0)= +## v1.10.0 Release +- Release Date: July 16, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Channel drawer performance +- Android devices will notice significant performance improvements when opening and closing the channel drawer. + +#### Channel loading performance +- Improved channel loading performance as post are retrieved with every push notification + +#### Announcement banner improvements +- Markdown now renders when announcement banners are expanded +- When enabled by the System Admin, users can now dismiss announcement banners until their next session + +### Improvements + + - Combined consecutive messages from the same user. + - Added experimental support for certificate-based authentication (CBA) for iOS to identify a user or a device before granting access to Mattermost. See [documentation](https://docs.mattermost.com/onboard/certificate-based-authentication.html) to learn more. + - Added support for the experimental automatic direct message replies feature. + - Added support for the experimental timezone feature. + - Changed post textbox to not be a connected component. + - Allow connecting to mattermost instances hosted at subpaths. + - Added support for starting YouTube videos at a given time. + - Added support for keeping messages if slash command fails. + +### Bug Fixes + + - Fixed an issue where the unread badge background was always white. + - Fixed an issue where a username repeated in system message if user was added to a channel more than once. + - Fixed an issue where Android Sharing from Microsoft apps failed. + - Fixed an issue where YouTube crashed the app if link did not have a time set. + - Fixed an issue where System Admins did not see all teams available to join on mobile. + - Fixed an issue where users were unable to share from Files app. + - Fixed an issue where viewing a non-existent permalink didn't show an error message. + - Fixed an issue where jumping to a channel search did not bold unread channels. + - Fixed an issue with being able to add own user to a Group Message channel. + - Fixed an issue with not being able to reply from a push notification on iOS. + - Fixed an issue where the app did not display Brazilian language. + +---- + +(release-v1-9-3)= +## 1.9.3 Release +- Release Date: July 04, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes + +- Fixed multiple issues causing app crashes +- Fixed an issue on iOS devices with typing non-english characters in the post input box + +---- + +(release-v1-9-2)= +## 1.9.2 Release +- Release Date: June 27, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes + +- Fixed an issue where attached videos did not play for the poster +- Fixed an issue where "Jump to recent messages" from the permalink view did not direct the user to the bottom of the channel +- Fixed an issue where post comments did not identify which parent post they belonged to +- Fixed multiple issues with typing non-english characters in the post input box +- Fixed multiple issues causing random app crashes +- Fixed an issue where files from the Android Files app failed to upload +- Fixed an issue where the iOS share extension crashed when switching the team or channel +- Fixed an issue where files from the Microsoft app failed to upload +- Fixed an issue on Android devices where sharing files changed the file extension of the attachment + +---- + +(release-v1-9-1)= +## 1.9.1 Release +- Release Date: June 23, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes +- Fixed an issue with typing lag on Android devices +- Fixed an issue causing users to be logged out after upgrading to v1.9.0 +- Fixed an issue where the ``in:`` and ``from:`` modifiers were not being added to the search field + +---- + +(release-v1-9-0)= +## v1.9.0 Release +- Release Date: June 16, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Improved first load time on Android + - Significantly decreased first load time on Android devices from cold start. + +#### iOS Files app support +- Added support for attaching files from the iOS Files app from within Mattermost. + +#### Improved styling of push notification +- Improved the layout of message content, channel name and sender name in push notifications. + +### Improvements + + - Combined join/leave system messages. + - Added splash screen and channel loader improvements. + - Removed the desktop notification duration setting. + - Added cache team icon and set background to always be white if using a PNG file. + - Added whitelabel for icons and splash screen. + +### Bug Fixes + + - Fixed an issue where other user's display name did not render in combined system messages after joining the channel. + - Fixed an issue where posts incorrectly had "Commented on Someone's message" above them. + - Fixed an issue where deleting a post or its parent in permalink view left permalink view blank. + - Fixed an issue where "User is typing" message cut was off. + - Fixed an issue where `More New Messages Above` appeared at the top of new channel on joining. + - Fixed an issue where a user was not directed to Town Square when leaving a channel. + - Fixed an issue where long post were not collapsed on Android. + - Fixed an issue where a user's name was initially shown as "someone" when opening a direct message with the user. + - Fixed an issue where an error was received when trying to change the team or channel from the share extension. + - Fixed an issue where switching to a newly created channel from a push notification redirected a user to Town Square. + - Fixed an issue where a public channel made private did not disappear automatically from clients not part of the channel. + +---- + +(release-v1-8-0)= +## v1.8.0 Release +- Release Date: April 27, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Image performance +- Images are now downloaded and stored locally for better performance + +#### Flagged Posts and Recent Mentions +- Access all your flagged posts and recent mentions from the buttons in the sidebar + +#### Muted Channels +- Added support for Muted Channels released with Mattermost server v4.9 + +### Improvements +- Date separators now appear between each posts in the search view +- Deactivated users are now filtered out of the channel members lists +- Direct Messages user list is now sorted by username first +- Added the option to Direct Message yourself from your user profile screen +- Improved performance on the post list +- Improved matching and display when searching for users in the Direct Message user list + +### Bug Fixes +- Fixed an issue where emoji reactions could be added from the search view but did not appear +- Fixed an issue causing the app to crash when trying to share content from a custom keyboard +- Fixed an issue where team names were being sorted based on letter case +- Fixed an issue where username would not be inserted to the post draft when using experimental configuration settings +- Fixed an issue with nested bullet lists being cut off in the user interface +- Fixed an issue where private channels were listed in the public channels section of the channel autocomplete list +- Fixed an issue where a profile images could not be updated from the app + +---- + +(release-v1-7-1)= +## v1.7.1 Release +- Release Date: April 3, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes +- Fixed an issue where the iOS share extension sometimes crashed the Mattermost app +- Fixed an issue preventing Markdown tables from rendering with some international characters + +---- + +(release-v1-7-0)= +## v1.7.0 Release +- Release Date: March 26, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### iOS File Sharing +- Share files and images from other applications as attached files in Mattermost + +#### Markdown Tables +- Tables created using markdown formatting can now be viewed in the app + +#### Permalinks +- Permalinks now open in the app instead of launching a browser window + +### Improvements +- Increased the tappable area of various icons for improved usability +- Announcement banners now display in the app +- Added "+" button to add emoji reactions to a post +- Minor performance improvements for app launch time +- Text files can now be viewed in the app +- Support for email autolinking into the app + +### Bugs +- Fixed an issue causing some devices to hang at the splash screen on app launch +- Fixed an issue causing some letters to be hidden in the Android search input box +- Fixed an issue causing some Direct Message channels to show date stamps below the most recent message +- Fixed an issue where users weren't able to join open teams they've never been a member of +- Fixed an issue so double tapping buttons can no longer cause UI issues +- Fixed an issue where changing the channel display name wasn't being updated in the UI appropriately +- Fixed an issue where searhing for public channels sometimes showed no results +- Fixed an issue where the post menu could remain open while scrolling in the post list +- Fixed an issue where the system message to add users to a channel was missing the execution link +- Fixed an issue where bulleted lists cut off text if nested deeper than two levels +- Fixed an issue where logging into an account that is not on any team freezes the app +- Fixed an issue on iOS causing the app to crash when taking a photo then attaching it to a post + +---- + +(release-v1-6-1)= +## v1.6.1 Release +- Release Date: February 13, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes +- Fixed an issue preventing the app from going to the correct channel when opened from a push notification +- Fixed an issue on Android devices where the app could sometimes freeze on the launch screen +- Fixed an issue on Samsung devices causing extra letters to be insterted when typing to filter user lists + +---- + +(release-v1-6-0)= +## v1.6.0 Release +- Release Date: February 6, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Android File Sharing +- Share files and images from other applications as attached files in Mattermost + +### Improvements +- Added a right drawer to access settings, edit profile information, change online status and logout +- Added support for opening a Direct Message channel with yourself + +### Bugs +- Fixed a number of issues causing crashes on Android devices +- Fixed an issue with auto capitalization on Android keyboards +- Fixed an issue where the GitLab SSO login button sometimes didn't appear +- Fixed an issue with link previews not appearing on some accounts +- Fixed an issue where logging out of the app didn't clear the notification badge on the homescreen icon +- Fixed an issue where interactive message buttons would not wrap to a new line +- Fixed an issue where the keyboard would sometimes overlap the text input box +- Fixed an issue where the Direct Message channel wouldn't open from the profile page +- Fixed an issue where posts would sometimes overlap +- Fixed an issue where the app sometimes hangs on logout + +---- + +(release-v1-5-3)= +## v1.5.3 Release +- Release Date: February 1, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported +- Fixed a login issue when connecting to servers running a Data Retention policy + +---- + +(release-v1-5-2)= +## v1.5.2 Release +- Release Date: January 12, 2018 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes +- Fixed an issue causing some Android devices to crash on launch +- Fixed an issue with the app occasionally crashing when receiving push notifications in a new channel +- Channel footer area is now refreshed when switching between Group and Direct Message channels +- Fixed an issue on some Android devices so Mattermost verifies it has permissions to access ringtones +- Fixed an issue where the text box overlapped the keyboard on some iOS devices using multiple keyboard layouts +- Fixed an issue with video uploads on Android devices +- Fixed an issue with GIF uploads on iOS devices +- Fixed an issue with the mention badge flickering on the channel drawer icon when there were over 10 unread mentions +- Fixed an issue with the app occasionally freezing when requesting the RefreshToken + +---- + +(release-v1-5-1)= +## v1.5.1 Release + +- Release Date: December 7, 2017 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes +- Fixed an issue with the upgrade app screen showing with a transparent background +- Fixed an issue with clearing or replying to notifications sometimes crashing the app on Android +- Fixed an issue with the app sometimes crashing due to a missing function in the swiping control + +---- + +(release-v1-5)= +## v1.5 Release + +- Release Date: December 6, 2017 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### File Viewer +- Preview videos, RTF, PDFs, Word, Excel, and Powerpoint files + +#### iPhone X Compatibility +- Added support for iPhone X + +#### Slash Commands +- Added support for using custom slash commands +- Added support for built-in slash commands /away, /online, /offline, /dnd, /header, /purpose, /kick, /me, /shrug + +### Improvements +- In iOS, 3D touch can now be used to peek into a channel to view the contents, and quickly mark it as read +- Markdown images in posts now render +- Copy posts, URLs, and code blocks +- Opening a channel with Unread messages takes you to the "New Messages" indicator +- Support for data retention, interactive message buttons, and viewing Do Not Disturb statuses depending on the server version +- (Edited) indicator now shows up beside edited posts +- Added a "Recently Used" section for emoji reactions + +### Bug Fixes +- Android notifications now follow the default system setting for vibration +- Fixed app crashing when opening notification settings on Android +- Fixed an issue where the "Proceed" button on log in screen stopped working after pressing logout multiple times +- HEIC images posted from iPhones now get converted to JPEG before uploading + +---- + +(release-v1-4-1)= +## v1.4.1 Release + +Release Date: Nov 15, 2017 +Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Bug Fixes + +- Fixed network detection issue causing some people to be unable to access the app +- Fixed issue with lag when pressing send button +- Fixed app crash when opening notification settings +- Fixed various other bugs to reduce app crashes + +---- + +(release-v1-4)= +## v1.4 Release + +- Release Date: November 6, 2017 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Performance improvements +- Various performance improvements to decrease channel load times + +### Bug Fixes +- Fixed issue with Android app sometimes showing a white screen when re-opening the app +- Fixed an issue with orientation lock not working on Android + +---- + +(release-v1-3)= +## v1.3 Release + +- Release Date: October 5, 2017 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Tablet Support (Beta) +- Added support for landscape view, so the app may be used on tablets +- Note: Tablet support is in beta, and further improvements are planned for a later date + +#### Link Previews +- Added support for image, GIF, and youtube link previews + +#### Notifications +- Android: Added the ability to set light, vibrate, and sound settings +- Android: Improved notification stacking so most recent notification shows first +- Updated the design for Notification settings to improve usability +- Added the ability to reply from a push notification without opening the app (requires Android v7.0+, iOS 10+) +- Increased speed when opening app from a push notification + +#### Download Files +- Added the ability to download all files on Android and images on iOS + +### Improvements +- Using `+` shortcut for emoji reactions is now supported +- Improved emoji formatting (alignment and rendering of non-square aspect ratios) +- Added support for error tracking with Sentry +- Only show the "Connecting..." bar after two connection attempts + +### Bug Fixes +- Fixed link rendering not working in certain cases +- Fixed theme color issue with status bar on Android + +---- + +(release-v1-2)= +## v1.2 Release + +- Release Date: September 5, 2017 +- Server Versions Supported: Server v4.0+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### AppConfig Support for EMM solutions +- Added [AppConfig](https://www.appconfig.org/) support, to make it easier to integrate with a variety of EMM solutions + +#### Code block viewer +- Tap on a code block to open a viewer for easier reading + +### Improvements +- Updated formatting for markdown lists and code blocks +- Updated formatting for `in:` and `from:` search autocomplete + +### Emoji Picker for Emoji Reactions +- Added an emoji picker for selecting a reaction + +### Bug Fixes +- Fixed issue where if only LDAP and GitLab login were enabled, LDAP did not show up on the login page +- Fixed issue with three digit mention count UI in channel drawer + +### Known Issues +- Using `+:emoji:` to react to a message is not yet supported + +---- + +(release-v1-1)= +## v1.1 Release + +- Release Date: August 2017 +- Server Versions Supported: Server v3.10+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Search +- Search posts and tap to preview the result +- Click "Jump" to open the channel the search result is from + +#### Emoji Reactions +- View Emoji Reactions on a post + +#### Group Messages +- Start Direct and Group Messages from the same screen + +#### Improved Performance on Poor Connections +- Added auto-retry to automatically reattempt to get posts if the network connection is intermittent +- Added manual loading option if auto-retry fails to retrieve new posts + +### Improvements +- Android: Added Big Text support for Android notifications, so they expand to show more details +- Added a Reset Cache option +- Improved "Jump to conversation" filter so it matches on nickname, full name, or username +- Tapping on an @username mention opens the user's profile +- Disabled the send button while attachments upload +- Adjusted margins on icons and elsewhere to make spacing more consistent +- iOS URL scheme: mattermost:// links now open the new app +- About Mattermost page now includes a link to NOTICES.txt for platform and the mobile app +- Various UI improvements + +### Bug Fixes +- Fixed an issue where sometimes an unmounted badge caused app to crash on start up +- Group Direct Messages now show the correct member count +- Hamburger icon does not break after swiping to close sidebar +- Fixed an issue with some image thumbnails appearing out of focus +- Uploading a file and then leaving the channel no longer shows the file in a perpetual loading state +- For private channels, the last member can no longer delete the channel if the EE server permissions do not allow it +- Error messages are now shown when SSO login fails +- Android: Leaving a channel now redirects to Town Square instead of the Town Square info page +- Fixed create new public channel screen shown twice when trying to create a channel +- Tapping on a post will no longer close the keyboard + +---- + +(release-v1-0-1)= +## v1.0.1 Release + +- Release Date: July 20, 2017 +- Server Versions Supported: Server v3.8+ is required, Self-Signed SSL Certificates are not yet supported + +### Bug Fixes +- Huawei devices can now load messages +- GitLab SSO now works if there is a trailing `/` in the server URL +- Unsupported server versions now show a prompt clarifying that a server upgrade is necessary + +---- + +(release-v1-0)= +## v1.0 Release + +- Release Date: July 10, 2017 +- Server Versions Supported: Server v3.8+ is required, Self-Signed SSL Certificates are not supported + +### Highlights + +#### Authentication (Requires v3.10+ [Mattermost server](https://github.com/mattermost/platform)) +- GitLab login + +#### Offline Support +- Added offline support, so already loaded portions of the app are accessible without a connection +- Retry mechanism for posts sent while offline +- See [FAQ](https://github.com/mattermost/mattermost-mobile#frequently-asked-questions) for information on how data is handled for deactivated users + +#### Notifications (Requires v3.10+ [push proxy server](https://github.com/mattermost/mattermost-push-proxy)) +- Notifications are cleared when read on another device +- Notification sent just before session expires to let people know login is required to continue receiving notifications + +#### Channel and Team Sidebar +- Unreads section to easily access channels with new messages +- Search filter to jump to conversations quickly +- Improved team switching design for better cross-team notifications +- Added ability to join open teams on the server + +#### Posts +- Emojis now render +- Integration attachments now render +- ~channel links now render + +#### Navigation +- Updated navigation to have smoother transitions + +### Known Issues +- Android: Swipe to close in-app notifications does not work +- Apps are not yet at feature parity for desktop, so features not mentioned in the changelog are not yet supported + +### Contributors + +Many thanks to all our contributors. In alphabetical order: +- asaadmahmood, cpanato, csduarte, enahum, hmhealey, jarredwitt, JeffSchering, jasonblais, lfbrock, omar-dev, rthill + +---- + +(mobile-beta-release)= +## Beta Release + +- Release Date: March 29, 2017 +- Server Versions Supported: Server v3.7+ is required, Self-Signed SSL Certificates are not yet supported + +Note: If you need an SSL certificate, consider using Let's Encrypt instead of a self-signed one. + +### Highlights + +The Beta apps are a work in progress, supported features are listed below. + +#### Authentication +- Email login +- LDAP/AD login +- Multi-factor authentication +- Logout + +#### Messaging +- View and send posts in the center channel +- Automatically load more posts in the center channel when scrolling +- View and send replies in thread view +- "New messages" line in center channel (app does not yet scroll to the line) +- Date separators +- @mention autocomplete +- ~channel autocomplete +- "User is typing" message +- Edit and delete posts +- Flag/Unflag posts +- Basic markdown (lists, headers, bold, italics, links) + +#### Notifications +- Push notifications +- In-app notifications when you receive a message in another channel while the app is open +- Clicking on a push notification takes you to the channel + +#### User profiles +- Status indicators +- View profile information by clicking on someone's username or profile picture + +#### Files +- File thumbnails for posts with attachments +- Upload up to five images +- Image previewer to view images when clicked on + +#### Channels +- Channel drawer for selecting channels +- Bolded channel names for Unreads, and mention jewel for Mentions +- (iOS only) Unread posts above/below indicator +- Favorite channels (Section in sidebar, and ability to favorite/unfavorite from channel menu) +- Create new public or private channels +- Create new Direct Messages (Group Direct Messages are not yet supported) +- View channel info (name, header, purpose) +- Join public channels +- Leave channel +- Delete channel +- View people in a channel +- Add/remove people from a channel +- Loading screen when opening channels + +#### Settings +- Account Settings > Notifications page +- About Mattermost info dialog +- Report a problem link that opens an email for bug reports + +#### Teams +- Switch between teams using "Team Selection" in the main menu (viewing which teams have notifications is not yet supported) + +### Contributors + +Many thanks to all our contributors. In alphabetical order: +- csduarte, dmeza, enahum, hmhealey, it33, jarredwitt, jasonblais, lfbrock, mfpiccolo, saturninoabril, thomchop diff --git a/docs/main/product-overview/mobile.mdx b/docs/main/product-overview/mobile.mdx new file mode 100644 index 000000000000..346cc517048e --- /dev/null +++ b/docs/main/product-overview/mobile.mdx @@ -0,0 +1,11 @@ +--- +title: "Mattermost Mobile App" +--- +Mattermost users can take Mattermost wherever they go by installing the Mattermost mobile app on their iOS or Android mobile device. + +Learn more about: + +- [Mobile releases](/product-overview/mattermost-mobile-releases) +- [Mobile changelog](/product-overview/mobile-app-changelog) + +See the [mobile apps software requirements](/deployment-guide/software-hardware-requirements#mobile-apps) for details on supported operating systems and releases. diff --git a/docs/main/product-overview/non-profit-subscriptions.mdx b/docs/main/product-overview/non-profit-subscriptions.mdx new file mode 100644 index 000000000000..123601d4ed48 --- /dev/null +++ b/docs/main/product-overview/non-profit-subscriptions.mdx @@ -0,0 +1,40 @@ +--- +title: "Non-Profit Subscriptions" +--- +The Mattermost Nonprofit License enables nonprofit and open-source organizations who are unable to afford our commercial licenses to apply the benefits of the self-hosted [Mattermost Professional offering](/product-overview/editions-and-offerings) towards advancing their missions with special nonprofit pricing. + + + +Nonprofit and open-source organizations that meet the [eligibility requirements](#who-s-eligible) can apply for the Mattermost Nonprofit license by completing [this form](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=17664739497236). Please note that it may take up to six weeks for us to respond to your request. + + + +## What's included? + +A 3-year subscription to our Mattermost Professional Self-Hosted offering for up to 1,000 users with a subscription fee of $250 USD. If the nonprofit has over 1,000 users, the application will undergo a review on a case-by-case basis, both for Mattermost Professional Self-Hosted and Mattermost Professional Cloud offerings. Upon acceptance of these terms, Mattermost has the right to place the name and logo of the nonprofit, open-source, or charitable institution on our website and in our marketing materials. + +Following the 3-year subscription, the institution can renew the license every 3 years for an additional $250 USD subscription fee. + +## Who's eligible? + +Organizations applying for a non-profit license must meet **ALL** of the following requirements: + +- Be able to provide documentation that establishes the organization as a recognized nonprofit status. +- Have no affiliation with government, academic, commercial, religious, or political entities. +- Be unable to afford a commercial Mattermost license. +- Be willing to let Mattermost use their logo for promotional purposes. +- Be willing to pay a $250 processing fee for a 3-year, self-hosted Professional license contract for up to 1000 users. + +If your organization doesn’t fit this description, we suggest that you purchase a [commercial license](https://mattermost.com/pricing/) instead. + +If you represent an open source community or project that is not hosted under a recognized nonprofit, but would like a commercial license for Mattermost, please email [community@mattermost.com](mailto:community@mattermost.com) with your organization’s needs and requirements. + +## How to apply? + +To apply for the Mattermost Nonprofit License, please complete [this form](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=17664739497236). + + + +It may take up to 6 weeks for us to respond to your request. + + diff --git a/docs/main/product-overview/plans.mdx b/docs/main/product-overview/plans.mdx new file mode 100644 index 000000000000..b8d891468862 --- /dev/null +++ b/docs/main/product-overview/plans.mdx @@ -0,0 +1,353 @@ +--- +title: "Mattermost Plans" +--- + + + + + + + + + + + + + + + + {/* Channel-based messaging */} + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* AI-accelerated collaboration */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Operational & technical collaboration */} + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Advanced access controls & automation */} + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Multi-team collaboration */} + + + + + + + + + + + + + + + + + + + {/* Scale & high availability */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Advanced compliance & administration */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Enterprise mobility */} + + + + + + + + + + + + + + + {/* Workflow automation */} + + + + + + + + + + + {/* Federated communications */} + + + + + + + + + + + {/* Enterprise Advanced exclusive features */} + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Support */} + + + + + + + + + + + + + + + + + + + +
Feature CategoryTeam EditionEntryProfessionalEnterpriseEnterprise AdvancedAvailable From
Channel-based messaging
1-1, group messaging, public and private channels, file sharing, link and media previews across web, PC, Mac, iOS and Android devices, with 1-1 audio calls and screen share, threaded discussions, search, custom branding themes and emojis, and availability in 20+ languages.
Messaging, file sharing, and link and file previews across device platforms: Channels-based messaging including 1-1, group messaging, public and private channels, file sharing , and link and media previews across web, PC, Mac, iOS, and Android devices.*v9.11+
1:1 audio calls and screen sharing: Call another user to start a 1-1 audio discussion in web, desktop, and mobile experiences with optional screen sharing.*v9.11+
Threaded discussions: Organize discussions within channels using threaded discussions and the thread inbox to follow-up on threaded discussions in addition to channels.v9.11+
Core search: Search over messages and files in Mattermost. Core search happens in a relational database and is intended for deployments under about 2–3 million posts and file entries. Beyond that scale, Enterprise Search is recommended.*v9.11+
Custom branding, themes, and emojis: Match your organizations look, feel and brand by customizing the site name, description, login brand image and text, as well as theme colors.v9.11+
Available in 20+ languages: Support for English (U.S., Australian), Japanese, Korean, Swedish, Dutch, French, German, Italian, Spanish, Turkish, Polish, Portuguese (Brazil), Romanian, Vietnamese, Ukrainian, Bulgarian, Hungarian, Persian, Russian, and Chinese (Simplified and Traditional) languages.v9.11+
AI-accelerated collaboration
Integrate your preferred LLM in 1-1, group messaging, public and private channels, with audio calls and screen share, and threaded discussions to speed workflows, increase efficiency and unlock innovation.
Interactive AI bot support: Enable organizations to work with LLM-powered AI bots through Direct Messages, Group Messages, threads, and @mentions to bot in private and public channels with full commercial support from Mattermost, Inc.*v9.11+
Flexible bring-your-own-LLM integration: Connect Mattermost to any LLM platform compatible with OpenAI protocol across public cloud, private cloud and air gapped edge including OpenAI, Llama, Anthropic, and custom LLMs.v9.11+
Contextual summarization and composition: Enable organizational interaction with LLMs with permission-restricted access to Mattermost conversations to summarize topics, answer questions and follow-ups, note action items and open questions from meetings, and compose draft messages and responses.v9.11+
Private, air-gapped & DDIL AI operations: Run AI-accelerated operations in private cloud, air-gapped and disconnected, denied, intermittent and limited-bandwidth (DDIL) environments with open source and custom LLMs self-hosted alongside workflow, chat operations, audio calling, screen sharing, recording, transcription, analysis, workflow and summarization capabilities.v9.11+
Real-time channel briefing: Concisely summarize unread messages, action items and unanswered questions in channels to focus attention and accelerate priority responses and workflows.v9.11+
Q&A with access-controlled backend systems: Receive secure and compliant real-time answers to questions about permission-controlled backend systems connected with Mattermost channels which can optionally pass back end user credentials to work with access-controlled data. For example, asking a channel connected with an issue tracking system which code defect tickets they have access to which could expose security vulnerabilities.v9.11+
Optional full trace mode: Optional full trace mode for detailed monitoring and to verify Responsible AI/LLM assurances by recording every prompt, question, AI request and response across users, systems and LLM-backends and platform source code into specialized audit logs for analysis.v9.11+
Operational & technical collaboration
Accelerate operational and technical success with a collaboration platform integrating with mainstream and customer toolchains, with information rich visualizations of systems and processes, prioritized message broadcasting, and conversational interoperability with technical systems through platform-level Markdown support.
Integrations platform: Tailor fit and transform your mission-critical collaboration infrastructure with a broad range of configuration and extension options ranging from webhooks and custom slash commands, to bots and API integrations, to building out plug-ins and making source code customizations.v9.11+
Operational and DevOps integrations: Accelerate operational and technical workflows by integrating Mattermost's collaborative platform with data and automation from an array of systems ranging from modern, cloud-based applications and tools to legacy and on-prem infrastructure, including Jira, GitHub, GitLab, and ServiceNow among others.v9.11+
Compact view: Increase the efficiency of technical teams with compact display views of discussions and tooling notifications integrated in Mattermost channels.v9.11+
Markdown compatibility: Easily move information across Mattermost discussions and technical tooling outputs with built-in support for the Markdown technical formatting standard. Text formatting, code snippets, media embedding, tables, status indicators, and emojis render consistently across the Mattermost user experience and Markdown-compatible tools.v9.11+
Message priority: Elevate the focus of organizations with the ability for end users to specify the priority of messages as Standard (Default), Important, and Urgent.v9.11+
Persistent notifications: Replace phone-based confirmations with message-based acknowledgement requests that can persist on a recipient's Mattermost interface until acknowledged.*v9.11+
Advanced access controls & automation
Centralize and automate user identity and permissions with a range of single-sign-on (SSO), user synchronization and advanced access control capabilities.
Email authentication: Basic email-based authentication with username and password is available in Mattermost Team Edition and paid Mattermost packages. While the method includes a number of core admin features around email address verification, password complexity, maximum login attempts, and password reset, among others, it is highly recommended that this method of authentication is only used in small teams on private networks.v9.11+
Single sign-on w/SAML 2.0, Entra ID, Okta, and others: Centralize, integrate, and automate identify management and access controls by enabling Mattermost to operate as a SAML 2.0 service provider. Integrate with SAML 2.0-based providers including Entra ID (formerly Office365 SSO), Okta, OneLogin, Microsoft ADFS SAML Configuration, and Keycloak, among others.v9.11+
SSO with AD/LDAP, OpenID, and others: Simplify sign-on and user management with non-SAML-based SSO options including Open ID, Google SSO, and GitLab SSO. Moreover, Mattermost offers "same sign-on" with Active Directory/LDAP by enabling the same credentials used in on-prem AD/LDAP deployments to be reused in Mattermost, with optional multi-factor authentication (MFA).v9.11+
AD/LDAP user sync: Simplify and accelerate user administration, access control, and compliance by synchronizing Active Directory and LDAP with Mattermost, including single-sign-on with AD/LDAP credentials, synchronization of user display attributes (e.g., first name, last name, email, and username), automated account provisioning on a user's first sign-on, automated assignment of Mattermost roles based on a user's LDAP group, and compliance with administrator settings managed in AD/LDAP by having the Mattermost System Console honor LDAP filters for disabled users, guest users, and administrative users.v9.11+
MFA enforcement for email and LDAP accounts: Fulfill MFA compliance requirements by enforcing an MFA requirement for login with email and LDAP accounts.v9.11+
Advanced access controls: Empower admins to manage and moderate multi-team deployments with the ability to configure channels to be read-only, to restrict channel mentions, emoji reactions, and to lock down channels so that users can only be added or removed by selected administrators.v9.11+
Multi-team collaboration
Work across teams and organizations with real-time calling and screen share, guest accounts to integrate internal and external stakeholders, customer user groups to organize teams within teams, and system-wide notifications to share organization-wide messages.
Group calling and screen share: Streamline real-time collaboration with complete privacy by enabling group audio calling and screenshare up to approximately 50 concurrent users in any group call per self-hosted server. High-scale options for private, self-hosted group calling and screen share are available in Mattermost Enterprise with the setup of its horizontal scaling option.*v9.11+
Guest accounts: Bring external users and users who need to have restricted access into your Mattermost instance as guests who can interact with your team with limited permissions. Guests in exactly one channel are treated as single-channel guests and are free up to a 1:1 ratio with licensed seats. Guests in multiple channels continue to count as paid active users. Direct messages and group messages do not affect whether a guest is counted as a single-channel guest.v9.11+
Custom user groups: Simplify communication by creating custom user groups to mention and notify up to 256 users who work together on projects or in functions or have other ties. Examples include creating custom groups for cross-functional teams, for job types, or organization membership within an enterprise.v9.11+
System-wide notifications: Notify users across teams of upcoming system maintenance, service changes, and other announcements using system-wide announcement banners.v9.11+
Scale & high availability
Achieve scale and resilience with cluster-based deployment, horizontal system architecture, advanced performance monitoring and logging and Kubernetes-based deployment.
High availability cluster-based deployment: Enable business continuity through component failures using cluster-based deployment with multiple application servers, multiple database servers, and multiple front-end proxies and/or load balancers.v9.11+
Horizontal scalability architecture: Scale to tens of thousands of users with horizontal scale-out architectures offering a range of deployment options from on-prem data centers to cloud-based hyperscalers including AWS and Azure.v9.11+
Enterprise search (3M+ posts): Enable enterprise-scale search after exceeding 3 million posts in the Mattermost database by deploying Elasticsearch or AWS OpenSearch with dedicated indexing and usage resourcing via cluster support.v9.11+
Performance monitoring: Track system health in large deployments, including deployments on high availability clusters, using advanced performance monitoring integrated with Grafana and Prometheus.v9.11+
Advanced logging: Enable advanced logging for optimizing and troubleshooting high-scale, mission-critical deployments including error, panic, debug, trace and conditional logging to a full range of destinations including Syslog and TCP target options.v9.11+
High availability, horizontally scalable calls and screen share: Enable high-scale, high availability deployment of audio calling and screen share through dedicated servers managed on an integrated Kubernetes platform.v9.11+
Supported Kubernetes deployment: Simplify and automate IT administration through Mattermost's supported options for deploying to Kubernetes clusters running either on-prem in data centers or in managed services such as Amazon EKS, Azure Kubernetes Service, Google Kubernetes Engine, and DigitalOcean Kubernetes, among others.v9.11+
Advanced compliance & administration
Fulfill enterprise- and critical infrastructure-level compliance and administration requirements with advanced identity and access control synchronization, delegated administration, granular configuration of data retention, eDiscovery, and legal hold and information export requirements while automating disclosures and agreements with end users.
AD/LDAP group, channel, and team sync: Automate management of users, groups, access controls, and channel and team membership through synchronizing with Entra ID/AD/LDAP Groups.v9.11+
Delegated granular administration: In large deployments where administrative tasks need to be separated and delegated, Mattermost supports the creation and customization of system administrator roles with specific granular permissions in order to offer specialized administration delegated from senior administrators.v9.11+
Data retention policy: Meet data retention compliance requirements. By default Mattermost uses a "soft delete" system where messages and files deleted based on user actions are removed from the user interface, but persist in the Mattermost database.

By activating Mattermost's data retention policy capability, rules can be set to permanently delete all messages and files in a Mattermost system, or in specific teams or channels, that are beyond a specific age (e.g., 30 days, 90 days, or other options). This feature should be used carefully; once data is removed using data retention policies, the action is irreversible.

v9.11+
Legal hold: Comply with legal hold and litigation hold requests to preserve information in anticipation of legal action. The legal hold capability can be combined with eDiscovery integration and data retention policies to customize the data retained and deleted to meet compliance requirements.v9.11+
Compliance export and eDiscovery automation: Fulfill eDiscovery and compliance requirements with manual and automated export of message history to Actiance, Global Relay, and custom compliance formats.v9.11+
Channel export: Archive, backup, or submit the contents of a channel into other systems to fulfill reporting and auditability requirements as needed.v9.11+
Custom end user Terms of Service: Increase clarity on legal expectations for internal employees and guests with the ability to set custom Terms of Service ("ToS") agreements and re-acceptable periods.v9.11+
Enterprise mobility
Speed real-world workflows with enterprise-grade mobility and security through EMM, MDM, and AppConfig integration across iOS and Android mobile platforms.
Enterprise Mobility Management (AppConfig) support: Enhance mobile security by deploying with Enterprise Mobility Management (EMM) to secure mobile endpoints with management application configuration, and Mattermost AppConfig compatibility.v9.11+
Private mobility with ID-only push notifications: ID-only push notifications protect a Mattermost customer against breaches in iOS and Android notification infrastructure by enabling mobile notifications to be fully private. The standard way to send notifications to iOS and Android applications requires sending clear text messages to Apple or Google so they can be forwarded to a user's phone and displayed on iOS or Android.

While Apple and Google assure the data is not collected or stored, all standard mobile notifications on the platform could be compromised should the organizations be breached or coerced. To avoid this risk, Mattermost can be configured to replace mobile notification text with message ID numbers that pass no information to Apple of Google, and which, when received by the Mattermost mobile application on a user's phone, are used to privately communicate with their Mattermost server and use the message ID to retrieve mobile notification messages over an encrypted channel. This means at no time will the message text be visible to Apple or Google's message relay system.

Because of the extra steps to retrieve the notifications messages under Mattermost's private mobility capability with ID-only push notifications, end users may experience a slight delay before the mobile notification is fully displayed compared to sending clear text through Apple and Google's platform.

v9.11+
Microsoft Intune MAM Support: Enhanced mobile security through Microsoft Intune Mobile Application Management (MAM), enabling organizations to secure and manage Mattermost mobile deployments with Intune's enterprise mobility management capabilities.v11.3+
Workflow automation
Streamline and automate workflows to reduce errors and delays while increasing efficiency and innovation using collaborative playbooks to speed structured team processes, from incident response and software release cycle management to accelerating operational logistics, as well as workflow dashboards to assess and refine process outcomes and operations.
Collaborative playbooks: Collaborative playbooks provide structure, monitoring and automation for repeatable, team-based processes integrated with the Mattermost platform. Use cases include incident response, software release management, and logistical operations. Playbooks monitor channels for keywords or user actions to trigger structured processes, which bring up a set of individual or shared tasks, each associated with manual or automated actions.

As playbooks execute, some may have requirements for broadcasting status updates to stakeholders at regular intervals, conducting retrospectives after the core process is complete, or meeting other customer needs as exit criteria for each playbook "run." Advanced permissions are also available to delegate and manage playbook controls in larger organizations.

*v9.11+
Workflow dashboards: Unlock insights about the performance of collaborative workflows across organizations with workflow dashboards. They compare the output metrics from different runs of collaborative playbooks against targets and historical performance.

Examples of metrics-based workflow dashboards that can be set up to monitor and inform performance include time to detect and time to resolve in incident response workflows, workplan completion percentage for monthly software releases management workflows, and launch success rate for logistical workflows involving launch operations.

v9.11+
Federated communications
Connect across organizations using Mattermost and Microsoft Teams to share information and accelerate collaborative, cross-organizational workflows.
Microsoft Teams messaging integration: Increase focus and adaptability across your organization by connecting users across Microsoft Teams and Mattermost. Microsoft Teams often serves as a centralized, organization-wide standard for general collaboration and everyday productivity, which can complicate the business case for customizing workflows and integrated toolsets to meet the specialized needs of technical and operational teams.

Mattermost is often deployed to supplement a centralized, general purpose Microsoft Teams deployment with a dedicated environment for developers, security professionals, and operators. Integrated direct messaging and group messaging across Microsoft Teams and Mattermost deployments connects an organization to the best of both worlds, helping teams unlock their full potential.

v9.11+
Connected Workspaces: Communicate across organizations using Mattermost by synchronizing messages, emoji reactions, and file sharing in real time through Mattermost Connected Workspaces.v9.11+
Enterprise Advanced exclusive features
Advanced security, compliance, and deployment capabilities designed for the most demanding cyber defense and mission-critical environments.
Classified and Sensitive Information Controls: Display channel banners to indicate classification levels and sensitive information handling requirements, ensuring compliance with security protocols for classified environments.v10.9+
Zero Trust Security: Implement dynamic attribute-based policy controls with environmental attributes and User Authoritative Source integration for comprehensive zero trust security architecture.v10.9+
Mobile security controls: Advanced mobile security features and controls designed for high-security environments and mission-critical mobile deployments.v10.9+
Air-gapped deployment workflows: Specialized deployment workflows and procedures for completely disconnected and air-gapped environments with no external network connectivity.v10.9+
Data Spillage Prevention: Advanced content flagging and review system enabling designated reviewers to identify, review, and manage potentially sensitive information that may have been inappropriately shared in channels. Supports team-specific reviewer assignments and common reviewers across teams.v11.1+
Burn-on-Read Messages: Time-limited message viewing functionality where messages automatically delete after being read for a configured duration, ensuring sensitive information has controlled exposure. Administrators can configure read durations and maximum time-to-live settings.v11.3+
Support
A range of support options are available across Mattermost Free, Professional, and Enterprise offerings.
Community Support: Community support for all Mattermost offerings is available on peer-to-peer trouble shooting forums. Organizations using Mattermost Free to evaluate a future purchase of Mattermost Enterprise can contact sales to apply for early access to commercial support as part of the evaluation process.v9.11+
Professional Support: Professional Support includes business hours support from 8am to 8pm United States Pacific Time (UTC-8 except for U.S. daylight savings time), with next business day response time via email and the Mattermost online ticketing system. See Support Terms for details.v9.11+
Enterprise Support: Enterprise Support is available 24×7 at all times on all days via email and the Mattermost online ticketing system with a 4-hour response time service-level target. For more information, please see Support Terms.v9.11+
Premier Support: Available as an additional purchase offering additional license entitlements for non-production environments, direct access to senior support team members, screen-sharing and audio calling for P1 and P2 tickets, and access to a private channel with Mattermost technical staff. See Support Terms for details.v9.11+
+ +See a [complete list of features](https://mattermost.com/pricing) on the Mattermost website. Features with an asterisk (``*``) next to the check mark indicate rate usage limitation. See the [Editions and Offerings](https://docs.mattermost.com/product-overview/editions-and-offerings.html) page for additional details. + + + +Mattermost Enterprise Advanced requires a Mattermost Server running v10.9 or later and a PostgreSQL database. Enterprise plugins must be updated to support the new license (most of which are pre-packaged from v10.9). + + + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/product-overview/release-policy.mdx b/docs/main/product-overview/release-policy.mdx new file mode 100644 index 000000000000..5c11d4259d9f --- /dev/null +++ b/docs/main/product-overview/release-policy.mdx @@ -0,0 +1,115 @@ +--- +title: "Release Policy" +--- +This page describes Mattermost’s release policy, and our recommended practices around releases, including extended support releases, so that you can allocate your IT resources effectively. + +To ensure a secure, functional, performant, and efficient Mattermost deployment, system admins managing a self-hosted deployment need to be proactive in: +- monitoring Mattermost release cycles and planning upgrades before life cycles end, +- considering the use of [extended support releases](#extended-support-releases) for longer-term stability, and +- keeping both server and client applications updated. + +(release-types)= +## Release Types + +Mattermost releases include feature, extended support, and major releases. Each release has a specified life cycle start and end date, and life cycles depend on the release type. + +- **Feature**: Feature releases contain new features and include high severity and high impact security backported to the previous 3 monthly releases. This is to ensure your organization's Mattermost deployment remains secure and stable. It's crucial to apply feature updates to maintain the security of your Mattermost deployment. +- **Extended**: Releases maintained for a longer period of time that receive backports for security fixes and major bug fixes for the length of their life cycle. Learn more about [Mattermost extended support releases](#extended-support-releases) below. +- **Major**: Annual mid-year releases that follow a release theme, and include multiple new features. + +With multiple release types, you can plan the upgrade path that best suits your organization's needs and compliance requirements. Align your plan with your organization's IT strategy and risk management policies to ensure continuous operation without exposure to security vulnerabilities. + +See the full list of all Mattermost Server and desktop app releases and life cycles. + +(extended-support-releases)= +## Extended Support Releases + +Mattermost Extended Support Releases (ESRs) are a strategic choice for organizations looking for stability and reduced frequency of updates. Using ESRs can minimize disruptions associated with frequent upgrades, making them an attractive option for environments where stability is paramount. + +Starting with the August 2025 Mattermost server and desktop app releases (server v10.11 and desktop app v5.13), Mattermost has adjusted the ESR life cycle as follows: + - **Extended Cadence**: The ESR release cycle has changed from every 6 months to every 9 months. + - **Prolonged Support**: The support window has increased from 9 months to 12 months. + +We strongly recommend planning ahead for upgrades before the end of an ESR's life cycle to ensure continuity in receiving security updates. + +ESRs don’t include changes to product functionality or new features. ESRs are intended for organizations who value stability over having the newest features and improvements, or who have a long internal testing and certification process to undergo when upgrading. Consider using ESRs for more stable and long-term deployments, especially in environments where frequent updates are challenging. If your organization prefers to have the newest features and improvements, Extended Support Releases may not be the best fit for you. + +To install extended support releases, follow our [install and upgrade](/administration-guide/upgrade/enterprise-install-upgrade) documentation. To restore a previous ESR, restore the database and previous version if you need to revert an upgrade. Previous ESR versions continue remain subject to a [life cycle end date](/product-overview/mattermost-server-releases). + +```{Important} +- We strongly recommend reviewing [upgrade best practices](https://docs.mattermost.com/administration-guide/upgrade/prepare-to-upgrade-mattermost.html#upgrade-best-practices) for upgrading, and [important upgrade notes](/upgrade/important-upgrade-notes) for all the versions beyond the current ESR version you have currently installed. See the [Mattermost v9 changelog](https://docs.mattermost.com/product-overview/mattermost-v9-changelog.html) for a list of database, API, and `config.json` updates for all v9.x releases. +- Your license key is decoupled from the Mattermost server version, so you can upgrade to the latest ESR using a legacy license. +We highly recommend working with your Mattermost Account Team to plan for a migration to our new plans, and to access the latest features such as persistent notifications, advanced compliance features, call recordings, and more. +``` + +```{mermaid} + +gantt + dateFormat YYYY-MM-DD + axisFormat %b %y + + section Releases + v10.10 :done, 2025-07-16, 2025-10-15 + v10.11 & Desktop App v5.13 Extended Support :crit, 2025-08-16, 2026-08-15 + v10.12 :done, 2025-09-16, 2025-12-15 + v11.0 :done, 2025-10-16, 2026-01-15 + v11.1 :done, 2025-11-14, 2026-02-15 + v11.2 :done, 2025-12-16, 2026-03-15 + v11.3 :done, 2026-01-16, 2026-04-15 + v11.4 :active, 2026-02-16, 2026-05-15 + v11.5 :active, 2026-03-16, 2026-06-15 + v11.6 :active, 2026-04-16, 2026-07-15 + v11.7 & Desktop App v6.2 Extended Support :crit, 2026-05-16, 2027-05-15 +``` + +**Timeline Legend:** +The chart above shows both release dates and end-of-life dates for each version. ESRs provide longer-term stability for organizations preferring less frequent updates. +- 🔵 **Blue bars**: Regular feature releases (monthly releases with standard support lifecycle) +- 🔴 **Red bars**: Extended Support Releases (ESRs) - Released every 6-9 months with extended 9-12 month support + +(esr-notifications)= +### ESR Notifications + +When an ESR is at the end of its life cycle, there will be announcements ahead of time to provide time for people to test, certify, and deploy a newer ESR version before support ends. After a release reaches its end-of-life, no further updates will be provided for that version. + +To receive updates about Extended Support Releases, sign up for [our mailing list](https://mattermost.com/newsletter/). + +For a new upcoming ESR, an email is sent out 3 months before the end of support for an ESR version. This email includes a note about the new ESR that was just published. A second email is sent out during the month when an ESR version is reaching the end of support. + +For deprecated ESRs, an email announcement is sent 3 months in advance. We also add reminders on our release announcements, changelogs, important upgrade notes, and the [Mattermost Discussion Forums](https://forum.mattermost.com/) site. + +### Legacy Releases + +The following table lists all releases across Mattermost v7.0, v8.0, and v9.0, including ESRs. See the [unsupported legacy releases](https://docs.mattermost.com/product-overview/unsupported-legacy-releases.html) documentation for comprehensive changelog details for these legacy releases. + +```{Important} +- If you're on a legacy Mattermost release prior to v7.1, in order to take advantage of newer Mattermost releases, you must upgrade to [v7.1 ESR](https://docs.mattermost.com/product-overview/unsupported-legacy-releases.html#release-v7-1-extended-support-release) at a minimum. +- Upgrading from one Extended Support Release (ESR) to the next ESR (``major`` -> ``major_next``) is fully supported and tested. However, upgrading across multiple ESR versions (``major`` to ``major+2``) is supported, but not tested. If you plan to skip versions, we strongly recommend upgrading only between ESR releases. For example, if you're upgrading from v8.1 ESR, upgrade to the v9.5 ESR or the v9.11 ESR before attempting to upgrade to the [v10.5 ESR](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-5-extended-support-release) or the [v10.11 ESR](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-11-extended-support-release). +``` + +| **Release** | **Release Type** | **Support ended** | +|:---|:---|:---| +| v9.11 | Extended | 2025-05-15 | +| v9.10 | Feature | 2024-10-15 | +| v9.9 | Feature | 2024-09-15 | +| v9.8 | Feature | 2024-08-15 | +| v9.7 | Feature | 2024-07-15 | +| v9.6 | Feature | 2024-06-15 | +| v9.5 | Extended | 2024-11-15 | +| v9.4 | Feature | 2024-04-15 | +| v9.3 | Feature | 2024-03-15 | +| v9.2 | Feature | 2024-02-15 | +| v9.1 | Feature | 2024-01-15 | +| v9.0 | Major | 2023-12-15 | +| v8.1 | Extended | 2024-05-15 | +| v8.0 | Major | 2023-10-15 | +| v7.10 | Feature | 2023-07-15 | +| v7.9 | Feature | 2023-06-15 | +| v7.8 | Extended | 2023-11-15 | +| v7.7 | Feature | 2023-04-15 | +| v7.5 | Feature | 2023-02-15 | +| v7.4 | Feature | 2023-01-15 | +| v7.3 | Feature | 2022-12-15 | +| v7.2 | Feature | 2022-11-15 | +| v7.1 | Extended | 2023-04-15 | +| v7.0 | Major | 2022-09-15 | diff --git a/docs/main/product-overview/releases-lifecycle.mdx b/docs/main/product-overview/releases-lifecycle.mdx new file mode 100644 index 000000000000..4a1ef0a9d410 --- /dev/null +++ b/docs/main/product-overview/releases-lifecycle.mdx @@ -0,0 +1,12 @@ +--- +title: "Releases and Life Cycle" +--- +import Inc0_common_esr_support_rst from './common-esr-support-rst.mdx'; + + + +- Learn about Mattermost [release types, including extended support releases](/product-overview/release-policy) +- Learn about [Server releases, frequency, and latest releases](/product-overview/server) +- Learn about [Desktop app releases and server compatibility](/product-overview/desktop) +- Learn about [Mobile apps releases and server compatibility](/product-overview/mobile) +- Review [removed and deprecated features that are no longer supported](/product-overview/deprecated-features) diff --git a/docs/main/product-overview/self-hosted-subscriptions.mdx b/docs/main/product-overview/self-hosted-subscriptions.mdx new file mode 100644 index 000000000000..34f74a83f56e --- /dev/null +++ b/docs/main/product-overview/self-hosted-subscriptions.mdx @@ -0,0 +1,122 @@ +--- +title: "Self-Hosted" +--- +## Buy a subscription + +To purchase a commercial subscription for Mattermost Enterprise or Mattermost Professional, please visit our pricing page online: [https://mattermost.com/pricing/](https://mattermost.com/pricing/) + +## Apply your license + +Once downloaded, your Mattermost license is ready to use and is applied via the Mattermost System Console. + +![Apply the Mattermost Enterprise license using the System Console.](/images/mattermost_enterprise_license.png) + +System admin access is required in order to apply the license. If you're not a Mattermost system admin, contact your organization's Mattermost system admin for assistance. + +### Mattermost installed + +Check your email for a purchase confirmation from Mattermost. Download the attached license. In Mattermost, follow the steps provided in **System Console \> About \> Edition and License** to apply your license key. + +You can also use the [mmctl](/administration-guide/manage/mmctl-command-line-tool#mmctl-license) to apply the license. + +### Mattermost not yet installed + +If you haven't yet installed and deployed a Mattermost instance, visit the [Deployment Guide](/deployment-guide/deployment-guide-index) to get started. For information on creating a system admin account, visit our [Administrator Tasks](/administration-guide/upgrade/admin-onboarding-tasks) documentation. + +## Add more users to your subscription + +If at any time you'd like to add more users to your Mattermost subscription, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) + +## Quarterly true-up reports + +When you buy an annual Mattermost subscription, you agree to provide Mattermost with quarterly reports of the actual number of activated users within your system. An activated user is a user who has a Mattermost account and doesn't show as **Deactivated** in **System Console \> User Management \> Users**. + +Single-channel guests are tracked separately from activated users. Guests in exactly one channel are free up to a 1:1 ratio with licensed seats, while guests in multiple channels continue to count as activated users. Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. + +We'll send you an email notice around the end of the quarter reminding you to send us your report. + +![The timeframes followed for the true-up notifications.](/images/true-up-schedule.png) + +If you have more total activated users than you purchased in your annual subscription, your Customer Success Manager will provide you with a true-up quote for the new users added. The additional invoice will be pro-rated based on the number of months left in your subscription term, including the months for the calendar quarter for the time you pull the report. Mattermost won't provide downward adjustments. Mattermost will invoice based on Mattermost’s [current list prices](https://mattermost.com/pricing/). + +A system admin must take a screenshot of the **System Console \> Reporting \> Site Statistics** page and send it to Mattermost in an email. + +- Please ensure your screenshot is taken from the top of the page and includes **Total Activated Users**, **Single-channel Guests**, and **Monthly Active Users**. +- Please include the date of the screenshot in the file name. +- We don't need your server address, so if it appears on your screenshot, you can redact it from the image. + + + +Not sure where to take the screenshot? Please reach out to your account executive, your Customer Success Manager, [orders@mattermost.com](mailto:orders@mattermost.com), or [create a support ticket](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=11184911962004) for assistance. + + + +## Renew your subscription + +System admins will be alerted 60 days prior to license expiry via a banner in Mattermost. You can also dismiss the banner and renew your license at a later date via **System Console \> Edition and License**. To renew your license, talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) + +## Frequently asked questions + +### What is the minimum number of users I can purchase on a subscription? + +The minimum purchase for a Mattermost license subscription is **more than 10 users** (i.e., at least 11). There is no set maximum — you can buy as many user seats as your organization requires. + +### What is a true-up report and why is the true-up notice necessary? + +A true-up report is our quarterly request for you to provide us with the actual number of activated users within your system to determine if you have more activated users now than when you bought your subscription. + +As your organization grows, you may need to add additional users during your subscription period. Mattermost needs to have insight into changes in your activated user count so that we can charge you appropriately for your self-hosted license usage. Additionally, we don’t want to over estimate/charge activated users at your renewal time. + +Single-channel guests are visible separately in reporting and on the **Edition and License** page. They don't count toward the primary paid seat count up to a 1:1 ratio with licensed seats, and exceeding that allowance generates system-admin warnings rather than hard limits. + +When you receive the quarterly true-up notice from Mattermost, please share your activated user count with us. + +### How do I renew my subscription if I don't have internet access? + +If you don't have access to the internet, please [create a support ticket](https://support.mattermost.com/hc/en-us/requests/new?ticket_form_id=11184911962004) for assistance. + +### Can I use my Mattermost license on more than one server? + +Each license covers one deployment — either a single server, or multiple nodes in a High Availability configuration that share a single database. If you need to run a second independent server, that requires its own license. Contact your account team for assistance. + +### Can I use my license in a non-production environment? + +Non-production environments are provisioned with a dedicated license key separate from the production license. Customers with Premier Support are eligible for up to four non-production license keys. Customers without Premier Support should contact their account team for assistance. + +### Where can I find my new license key? + +Once your payment is successfully processed, your license key will be provided via email. + +### How will I know when to renew my subscription? + +You'll be notified 60 days prior to your subscription expiry, via a blue banner displayed at the top of your Mattermost window. This banner is only visible to system admins. + +You can select **Renew license now** to begin the renewal process. You can also select the **x** to dismiss the notification. The notification is reactivated when your browser is refreshed or you reload the Mattermost Desktop App. + +### How long does it take to renew a subscription? + +Once you’ve started the renewal process, we'll be in contact with you to confirm your order and send you the order form. There may be additional paperwork required. Once we have the signed order form and (if applicable) the necessary paperwork from you, we're able to process the renewal and issue your license key within 24 hours. + +### What happens to my subscription if I don't renew in time? + +If you don't renew within the 60-day renewal period, a 10-day grace period is provided. During this period your Mattermost installation runs as normal, with full access to commercial features. During the grace period, the notification banner is not dismissable. + +When the grace period expires, your Mattermost Enterprise or Professional plan is downgraded to the Free plan and other plan features are disabled. + +### What happens when my subscription expires? + +If you don't renew within the 10-day grace period, your Mattermost version is automatically downgraded to Free plan so you can still access and use Mattermost. However, subscription features will no longer be available, and if you are currently using them, the functionality will no longer be accessible. + +When you renew, the subscription features will become available with the previous configuration (provided no action such as user migration has been taken). + +### Why can't I dismiss the expiry notification banner? + +If there's a red expiry announcement banner stating: "Enterprise license is expired and some features may be disabled. Please contact your system admin for details." it means your grace period has expired. This announcement banner persists until the license is renewed, and is visible to all users. + +Once a new license is applied, the banner will no longer be visible. + +If you don't plan to renew your subscription, revoke the expired license in **System Console \> Edition and License**. + +### Where can I find the license agreement for Mattermost Enterprise Edition? + +Mattermost Enterprise Edition is the name for the binary of the Mattermost self-hosted Enterprise and Professional editions. This edition can be used for free without a license key as commercial software functionally equivalent to the open source Mattermost Team Edition licensed under MIT. When a license key is purchased and applied to Mattermost Enterprise Edition, additional features unlock. The license agreement for Mattermost Enterprise Edition is included in the software and also available [here](https://mattermost.com/enterprise-edition-license/). diff --git a/docs/main/product-overview/server.mdx b/docs/main/product-overview/server.mdx new file mode 100644 index 000000000000..bb8b8a5935d7 --- /dev/null +++ b/docs/main/product-overview/server.mdx @@ -0,0 +1,13 @@ +--- +title: "Mattermost Server" +--- +Mattermost Server installs as a single compiled binary file that includes the RESTful JSON web service, authentication client, authentication provider, notification service, and data management service. The Mattermost Server can be deployed in stand-alone or high availability mode where two or more servers are clustered together using gossip protocol and a proxy server that routes traffic from client applications to healthy servers in the cluster. + +Learn more about: + +- [Server releases](/product-overview/mattermost-server-releases) +- [v11 changelog](/product-overview/mattermost-v11-changelog) +- [v10 changelog](/product-overview/mattermost-v10-changelog) +- [Unsupported legacy releases](/product-overview/unsupported-legacy-releases) +- [Version archive](/product-overview/version-archive) +- [UI and accessibility changes across releases](/product-overview/ui-ada-changelog) diff --git a/docs/main/product-overview/subscription.mdx b/docs/main/product-overview/subscription.mdx new file mode 100644 index 000000000000..d0fd8bf7f34d --- /dev/null +++ b/docs/main/product-overview/subscription.mdx @@ -0,0 +1,177 @@ +--- +title: "Subscription Overview" +--- +Mattermost offers the following types of paid subscriptions: + +- [Self-hosted subscriptions](/product-overview/self-hosted-subscriptions) for secure enterprise collaboration with full control over your data. +- [Cloud subscriptions](/product-overview/cloud-subscriptions) for secure, cloud-based collaboration that's private, scaleable, and lower maintenance. +- [Non-profit subscriptions](/product-overview/non-profit-subscriptions) for nonprofit and open-source organizations who are unable to afford commercial licenses. + +Learn more about Mattermost's commerial [editions and offerings](/product-overview/editions-and-offerings). + +## Mattermost Cloud + +Enterprises can inquire about Mattermost Cloud -- a secure, cloud-based collaboration for fast moving enterprises that’s private, scaleable, and low maintenance offered on the same Kubernetes-based platform as the self-hosted edition, and managed by Mattermost, Inc. + +Enterprises can choose between [dedicated](/product-overview/cloud-dedicated) and [shared](/product-overview/cloud-shared) infrastructure based on your organizations’ size, budget, technical requirements, and level of control and customization needed. [Private connectivity through VPC](/product-overview/cloud-vpc-private-connectivity) is also available. + +Talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) to learn more. + +## Purchase Mattermost Licenses + +Mattermost offers self-hosted capabilities through **Mattermost Enterprise** and **Mattermost Professional** subscription plans. + +Mattermost self-hosted deployments require a license subscription key to be applied to access features. Your plan subscription determines what features you have access to. Talk to a [Mattermost expert](https://mattermost.com/contact-sales/) to learn more. + +[Mattermost Enterprise and Mattermost Professional licenses](/product-overview/editions-and-offerings) are sold as prepaid annual subscriptions based on the number of seat licenses purchased, or “seats”. Each seat license purchased entitles a customer to an “activated user”, which is a user registered on a specific Mattermost server and not deactivated. + +System administrators can view user status in the System Console and activate and deactivate registered users at any time. Deactivated users have history and preferences saved. + +Talk to a [Mattermost Expert](https://mattermost.com/contact-sales/) to learn more. + +## Mattermost educational license program + +For academic licensing, please visit us online: [https://mattermost.com/education/](https://mattermost.com/education/) + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. + +## Frequently asked questions + +### Why do I need to provide my name and physical address when purchasing a subscription? + +Mattermost is a U.S. corporation and, therefore, all business we do is governed by the laws of the United States, in addition to the local laws wherever we are doing business. + +The United States has a number of export control regulations implemented to protect national security interests and to promote its foreign policy objectives. Based on these regulations, U.S. companies are prohibited from doing business with specific countries which have been embargoed by the U.S. government. They are also prohibited from exporting certain items to certain countries that have been sanctioned by the U.S. government. In addition, U.S. companies are prohibited from doing business with specific people and/or companies that have been named and listed by the U.S. government. + +In order to comply with these requirements, Mattermost must collect the name and physical address of all individuals and companies it does business with so that it can comply with the U.S. export controls regulations. + +### What does Mattermost do with this information? + +The information you provide is used for a screening process. There are two different purposes for screening: + +- One screening is to ensure against exports of certain restricted goods to countries that are embargoed. In our case, goods refer to our software that has encryption in it. +- The other screening is against people and companies. There are certain people and companies that the government has put on a list (the Denied Party List) that US companies are prohibited from doing any business with for various reasons. They could be terrorists, be on a terrorist watch list, could be helping finance terrorists, could be participating in human rights violations, etc. If they are on the Denied Party List, we are not able to do any business with them. + +### Who are the sanctioned people, companies, and entities? + +The Office of Foreign Assets Control (OFAC) maintains a list of sanctioned entities. Some examples include: + +- Terrorists +- Banks or other financial institutions that are involved in financing terrorism +- Companies or people that have been involved in human or drug trafficking +- Organizations that have been sanctioned for human rights violations + +This will also include people in violation of government contracts because of our business with the U.S. government. Individuals and Companies do not end up on the Denied Party List based on the country they live in but by their actions and conduct. + +### What does “physical address” mean for software that will be used in many places? + +In this case, the "physical address" is the location where the individual, who will be receiving the license key, is physically located and will be able to access the software for installation. + +### How is a user defined for subscriptions? + +For the purpose of billing, an activated user is any account created in Mattermost that does not show as **Deactivated** in **System Console \> User Management \> Users**. + +Guests are billed based on channel access: + +- Guests in exactly one channel are treated as single-channel guests. They don't count toward the primary paid seat count and are free up to a 1:1 ratio with licensed seats. +- Guests in multiple channels continue to count as activated users for billing purposes. +- Direct messages and group messages don't affect whether a guest is counted as a single-channel guest. + +Bots, deactivated users, and synthetic users in [Microsoft Teams integrations](/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams) and [connected workspace](/administration-guide/onboard/connected-workspaces) users aren't counted towards the total number of activated users. + +You can review your activated user count in **System Console \> Site Statistics** under **Total Activated Users**. Review single-channel guest usage separately under **Single-channel Guests**. + +### Do I need to pay for deactivated users? + +No. If you deactivate a user, that user is not counted as an activated user during your annual renewal process. You can deactivate users manually via the System Console, and also via Active Directory/LDAP synchronization, the mmctl tool, and the server APIs. + +If you choose to pull SQL reports from the database to monitor individual activity to make deactivation decisions, and you are running under high user load, we recommend the reports are pulled from a read replica of the database. + +### Which features are affected when my subscription expires? + +The affected features include, but are not limited to, the following: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureHow it's affectedWhat steps do I need to take?
ElasticsearchElasticsearch is automatically disabled and will start using the default database for indexing posts.None needed.
AD/LDAP, SAML SSO, Entra ID SSO, and Google SSO

Login options are no longer provided on the sign-in page. Users who previously signed in with one of these methods are no longer able to.

+

Users who were already signed in can continue to use Mattermost until their session expires or until they log out.

Users must be migrated to email authentication via System Console > Users. Select the drop-down menu for the relevant member, choose Switch to Email/Password, enter a new password, and choose Reset.
AD/LDAP

Groups in the database are retained but cannot be used. Memberships are frozen in state for group synced teams/channels.

+

Mentions for AD/LDAP groups are not shown in the autocomplete menu.

+

Group mentions are no longer highlighted in text and do not trigger new notifications.

Use mmctl to modify group sync settings for the team/channel.
High availabilityHigh availability is disabled. If all nodes in a cluster continue running, the nodes will stop communicating and caches will get out of sync. This is likely to cause delays in messages, notifications, etc.None needed.
Performance monitoringMonitoring is disabled and Grafana will no longer update with new data.None needed.
Compliance exportsJobs are no longer scheduled in the job server. Data is not exported.None needed.
Data retentionJobs are no longer scheduled in the job server. Data is not deleted.None needed.
Custom termsCustom terms no longer displayed to end users on login. Data is retained in the Terms of Service database table.None needed.
Custom announcement bannersNo longer visible and is replaced by the default announcement banner.None needed.
Multi-factor authentication (MFA)MFA is no longer enforced/required for new accounts but remains enabled for those who configured it.None needed.
PermissionsPermissions are retained in the database in a frozen state and cannot be modified in the System Console.Use mmctl to reset permissions to default.
Guest accountsGuests that are not actively logged in are prevented from logging in. Guests who are actively logged in are able to use Mattermost until their session expires or they log out.None needed.
+ +### Is there a maximum number of users per subscription? + +No, there is no limit to the subscription value or number of users you can purchase per plan. + +### What happens if my department buys a Mattermost subscription and then central IT buys a high volume subscription that also covers my department? + +Mattermost subscriptions and support benefits are per production instance. + +When the subscription for your department's production instance expires, you can either discontinue your department's production instance and move to the instance hosted by central IT (which can optionally provision one or more teams for your department to control), or you can renew your subscription to maintain control of your department's instance (e.g., to configure or customize the system in a manner highly specific to your line-of-business) in addition to using the instance from central IT. diff --git a/docs/main/product-overview/ui-ada-changelog.mdx b/docs/main/product-overview/ui-ada-changelog.mdx new file mode 100644 index 000000000000..630527b7471d --- /dev/null +++ b/docs/main/product-overview/ui-ada-changelog.mdx @@ -0,0 +1,193 @@ +--- +title: "UI & ADA Changelog" +--- +This changelog tracks User Interface (UI) and Accessibility (ADA) changes across Mattermost releases. Administrators can use this page to easily see what changed in the UI from their current version to the one they're upgrading to, and track ADA improvements release to release. + +## Changelog + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VersionChange Description
v11.6(UI) Added support for Default Agent in suggestions and integrated Agents into the App Bar.
v11.6(UI) Improved the reliability of AI recap summarization by using structured JSON output from the LLM.
v11.6(UI) Added a new feature of creating teams and channels using anonymous URLs so the channel and team name are not revealed in the URL. Requires Enterprise Advanced license.
v11.6(UI) Added popouts for Recent Mentions, Saved Messages, and Search Results via the right-hand side.
v11.6(UI) The emoji picker on web and Desktop now inserts unicode emoji characters into the message composer instead of shortcode text.
v11.6(UI) Renamed Enterprise Advanced feature Content Flagging to Data Spillage.
v11.6(UI) Added a contextual note in Security Settings that explains how Google SSO can synchronize usernames and emails, shown alongside the Sign-in Method details.
v11.6(UI) Renamed SlackAttachment and SlackAttachmentField types to MessageAttachment and MessageAttachmentField. Old names are maintained as deprecated aliases for backward compatibility with plugins.
v11.6(UI) Posts created by integrations using Slack-compatible attachments (webhooks, bots, plugins) are now fully searchable in Elasticsearch. Previously, only the attachment text field was indexed. Now title, pretext, fallback, and field content are also indexed. A bulk re-index is required after upgrade to apply this to existing posts.
v11.6(UI) Added timezone support and manual time entry for Interactive Dialog datetime fields.
v11.6(UI) Added sub-day relative date patterns (H/M/S) for datetime dialog fields, enabling min/max constraints with hour, minute, and second precision.
v11.5(UI) Added support for auto-translations. Initial Beta release. Requires Enterprise Advanced license.
v11.5(UI) Added the ability for web app plugin code to be loaded asynchronously.
v11.5(UI) AI Rewrites now includes some context from the most recent messages in the thread to help provide better rewrites.
v11.5(UI) Available AI Agents are now shown in the @-mention autocomplete menu, regardless of channel membership.
v11.5(UI) Added the ability to access channel settings and rename a channel from the channel info right-hand sidebar.
v11.5(UI) Added tooltips to action buttons, and action errors are now displayed.
v11.5(UI) Updated the signup flow to replace the newsletter opt-in with a checkbox to agree to the Acceptable Use Policy and Privacy Policy.
v11.5(UI) Added back offline Help documentation accessible from the message composer.
v11.5(UI) Added new icons for archived and private channels.
v11.5(Accessibility) Fixed an issue where the profile status menu disappeared at higher zoom levels or at resized window on mobile view.
v11.4(UI) Updated illustrations and visual design for the initial loading screen, preparing workspace flow, IP filtering empty state, and admin console feature discovery panels.
v11.4(UI) Added adjustments to thread and right-hand side plugin pop-out titles.
v11.4(UI) MS Teams and Outlook on mobile no longer display a "Your browser does not support notifications" warning banner when running Mattermost embedded in those apps.
v11.3(UI) Added Korean language support and upgraded Korean translations from Alpha to Official.
v11.3(UI) Added pop-outs for right-hand-side (RHS) plugins.
v11.3(UI) Removed outdated system notices.
v11.3(UI) Removed the Collapsed Reply Threads tutorial.
v11.3(UI) Added support for triggering user mentions using the full-width at-sign (@) in addition to the standard half-width at-sign (@), improving the experience for users of Japanese input methods.
v11.3(UI) Added the ability to schedule posts in 15-minutes interval.
v11.3(UI) Updated Giphy SDK from 8.1.0 to 10.1.0.
v11.3(UI) Custom Profile Attributes now always return a set of default attributes if they're not set.
v11.3(UI) Added a new webapp plugin component registerSidebarBrowseOrAddChannelMenuComponent, which allows users to add options to the BrowseOrCreateChannel menu.
v11.2(UI) Enabled thread popouts in the browser.
v11.2(UI) Reduced the channel banner height.
v11.2(UI) Improved license and plan name clarity throughout the user interface. License settings and the About modal now display specific plan names (Professional, Enterprise, Entry) instead of the generic "Enterprise Edition" label, reducing confusion between edition and plan terminology.
v11.1(UI) Added support for standalone windows pop-out. Threads can now be popped out to its own window in Desktop.
v11.1(UI) The desktop app version is now shown on the About modal, allowing clicking to copy both the server and desktop app versions.
v11.1(UI) Removed Mattermost MS Teams Sync plugin from pre-packaged plugins.
v11.1(UI) Downgraded French language support from Beta to Alpha.
v11.0(UI) Removed Playbooks v1 from pre-packaged plugins.
v11.0(UI) Updated the library used for customizing scrollbars.
v11.0(UI) Increased page size when retrieving posts in channels with high number of hidden messages.
diff --git a/docs/main/product-overview/unsupported-legacy-releases.mdx b/docs/main/product-overview/unsupported-legacy-releases.mdx new file mode 100644 index 000000000000..3225eefb73be --- /dev/null +++ b/docs/main/product-overview/unsupported-legacy-releases.mdx @@ -0,0 +1,15500 @@ +--- +title: "Unsupported Legacy Releases" +--- +import Inc0_common_esr_support_upgrade from './common-esr-support-upgrade.mdx'; +import Inc1_common_esr_support_upgrade from './common-esr-support-upgrade.mdx'; + +This documentation contains comprehensive changelog details for all legacy Mattermost releases including v9.x, v8.x, and v7.x versions that have reached their end of support lifecycle. + +```{Important} + +(release-v9-11-extended-support-release)= +## Release v9.11 - [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#release-types) + +- **9.11.18, released 2025-07-22** + - Mattermost v9.11.18 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.5). + - Mattermost v9.11.18 contains no database or functional changes. +- **9.11.17, released 2025-06-18** + - Mattermost v9.11.17 contains high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin version [v9.1.3](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.3). + - Pre-packaged Playbooks plugin [v1.41.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.1). + - Mattermost v9.11.17 contains no database or functional changes. +- **9.11.16, released 2025-05-21** + - Mattermost v9.11.16 contains a Critical severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release as soon as possible is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.11.16 contains no database or functional changes. +- **9.11.15, released 2025-05-09** + - Mattermost v9.11.15 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Brought back the bug fix for [MM-61361](https://mattermost.atlassian.net/browse/MM-61361), since the performance regression has been fixed by tweaking the offending SQL query. + - Mattermost v9.11.15 contains the following database changes: + - A new index was added to the ``CategoryId`` column in ``SidebarChannels`` table to improve query performance. No database downtime is expected for this upgrade. It takes around 2s to add the index on a table with 1.2M rows for PostgreSQL, and it takes around 5s on MySQL on a table with 300K rows. The migrations are fully backwards-compatible and no table locks or existing operations on the table are impacted by this upgrade. Zero downtime is expected when upgrading to this release. The SQL queries included are ``CREATE INDEX idx_sidebarchannels_categoryid ON SidebarChannels(CategoryId);`` for MYSQL and ``CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_sidebarchannels_categoryid ON sidebarchannels(categoryid);`` for PostgreSQL. +- **9.11.14, released 2025-05-05** + - Mattermost v9.11.14 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Reverted a bug fix for [MM-61361](https://mattermost.atlassian.net/browse/MM-61361) that likely introduced a performance regression. + - Mattermost v9.11.14 contains no database or functional changes. +- **9.11.13, released 2025-04-29** + - Mattermost v9.11.13 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.11.13 contains no database or functional changes. +- **9.11.12, released 2025-04-15** + - Mattermost v9.11.12 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Stopped logging websocket PING events received by the server [MM-63693](https://mattermost.atlassian.net/browse/MM-63693). + - Mattermost v9.11.12 contains no database or functional changes. +- **9.11.11, released 2025-03-24** + - Mattermost v9.11.11 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v1.41.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.41.0). + - Mattermost v9.11.11 contains no database or functional changes. +- **9.11.10, released 2025-03-17** + - Mattermost v9.11.10 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed errors logged by performance telemetry due to certain browser extensions [MM-62371](https://mattermost.atlassian.net/browse/MM-62371). + - Pre-packaged Calls plugin version [v0.29.8](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.8). + - Mattermost v9.11.10 contains no database or functional changes. +- **9.11.9, released 2025-02-19** + - Mattermost v9.11.9 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.1.1](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.1.1). + - Fixed an issue in Compliance Exports whereby a missing file attachment in S3 could prevent the export run from completing [MM-62527](https://mattermost.atlassian.net/browse/MM-62527). + - Mattermost v9.11.9 contains no database or functional changes. +- **9.11.8, released 2025-01-22** + - Mattermost v9.11.8 contains critical severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Boards plugin [v9.0.5](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.5). + - Pre-packaged Channel Export plugin [v1.2.1](https://github.com/mattermost/mattermost-plugin-channel-export/releases/tag/v1.2.1). + - Pre-packaged Calls plugin [v0.29.7](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.7). + - Fixed a panic during LDAP synchronization [MM-61239](https://mattermost.atlassian.net/browse/MM-61239). + - Fixed an issue where the bulk export retention job would accidentally delete non-bulk export files and directories [MM-60888](https://mattermost.atlassian.net/browse/MM-60888). + - Fixed an issue where new messages from new channels wouldn't appear in the sidebar after reconnecting the websocket [MM-61361](https://mattermost.atlassian.net/browse/MM-61361). + - Mattermost v9.11.8 contains no database or functional changes. +- **9.11.7, released 2025-01-15** + - Mattermost v9.11.7 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with the web app status not being updated correctly for the current user [MM-59952](https://mattermost.atlassian.net/browse/MM-59952). + - Pre-packaged Boards plugin [v9.0.2](https://github.com/mattermost/mattermost-plugin-boards/releases/tag/v9.0.2). + - Fixed an issue with insertion errors to ``LinkMetadata`` table. + - Fixed an issue where the scroll position reset when custom emojis were requested [MM-62102](https://mattermost.atlassian.net/browse/MM-62102). + - Mattermost v9.11.7 contains the following database changes: + - Fixed an issue where Direct and Group Messages with a ``DeleteAt`` flag in the database could cause issues with some APIs. +- **9.11.6, released 2024-12-10** + - Mattermost v9.11.6 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - A 200 response is now returned for HEAD requests to a sub-path rather than responding with a 302. This fixes mobile devices trying to connect to a server hosted on a sub-path [MM-58042](https://mattermost.atlassian.net/browse/MM-58042). + - Pre-packaged Calls plugin [v0.29.6](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.6). + - Fixed an issue with incorrect reporting in the **Server Updates** section in **System Console > Workspace Optimizations** [MM-62030](https://mattermost.atlassian.net/browse/MM-62030). + - Mattermost v9.11.6 contains no database or functional changes. +- **9.11.5, released 2024-11-14** + - Mattermost v9.11.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin [v0.29.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.4). + - Mattermost v9.11.5 contains no database or functional changes. +- **9.11.4, released 2024-10-28** + - Mattermost v9.11.4 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where users would not see channels they were added to/messages from those channels in clustered environments [MM-59911](https://mattermost.atlassian.net/browse/MM-59911). + - Mattermost v9.11.4 contains no database or functional changes. +- **9.11.3, released 2024-10-10** + - Mattermost v9.11.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with YouTube previews no longer being displayed [MM-60351](https://mattermost.atlassian.net/browse/MM-60351). + - Improved the performance of LDAP sync jobs when group-contained teams and channels are used [MM-60253](https://mattermost.atlassian.net/browse/MM-60253). + - Mattermost v9.11.3 contains no database or functional changes. +- **9.11.2, released 2024-09-26** + - Mattermost v9.11.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added Mattermost user survey plugin to pre-packaged plugins, [v1.1.1](https://github.com/mattermost/mattermost-plugin-user-survey/releases). + - Pre-packaged Calls plugin [v0.29.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.2). + - Pre-packaged Playbooks plugin [v1.40.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.40.0). + - Fixed an issue where the **Edit Post Time Limit** button was not being displayed in the System Console ([MM-58529](https://mattermost.atlassian.net/browse/MM-58529), [MM-58824](https://mattermost.atlassian.net/browse/MM-58824)). + - Fixed racy use of session in ``NewWebConn`` [MM-60307](https://mattermost.atlassian.net/browse/MM-60307). + - Mattermost v9.11.2 contains the following functional change: + - Added a configuration setting **NativeAppSettings > MobileExternalBrowser** that tells the Mobile app to perform SSO Authentication using the external default browser [MM-60332](https://mattermost.atlassian.net/browse/MM-60332). +- **9.11.1, released 2024-08-27** + - Mattermost v9.11.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.11.1 contains no database or functional changes. +- **9.11.0, released 2024-08-16** + - Original 9.11.0 release. + +### Important Upgrade Notes + + - Added support for Elasticsearch v8. Also added Beta support for [OpenSearch v1.x and v2.x](https://opensearch.org/). A new config setting ``ElasticsearchSettings.Backend`` has been added to differentiate between Elasticsearch and OpenSearch. The default value is `elasticsearch`, which breaks support for AWS Elasticsearch v7.10.x since the official v8 client only works from Elasticsearch v7.11 and higher versions. See the important note below for details. + - Mattermost supports Elasticsearch v7.17+. However, we recommend upgrading your Elasticsearch v7 instance to v8.x. See the [Elasticsearch upgrade](https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html) documentation for details. + - When using Elasticsearch v8, ensure you set ``action.destructive_requires_name`` to ``false`` in ``elasticsearch.yml`` to allow for wildcard operations to work. + +```{Important} +**AWS Elasticsearch** + +If you're using AWS Elasticsearch, you must: +1. Upgrade to AWS OpenSearch. Refer to the [OpenSearch upgrade](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/version-migration.html) documentation for details. +2. Disable "compatibility mode" in OpenSearch. +3. Upgrade Mattermost server. +4. Update the Mattermost `ElasticsearchSettings.Backend` configuration setting value from `elasticsearch` to `opensearch` manually or using [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html#mmctl-config-set). This value cannot be changed using the System Console. See the Mattermost [Elasticsearch backend type](https://docs.mattermost.com/configure/environment-configuration-settings.html#elastic-backendtype) documentation for additional details. +5. Restart the Mattermost server. +``` + +### Compatibility + - Updated minimum Edge and Chrome versions to 126+. + - Added Ubuntu Noble support. + +```{Important} +If you upgrade from a release earlier than v9.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/mattermost-v9-11-changelog/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged Calls version [v0.29.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.1). + - Pre-packaged GitHub plugin version [v2.3.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.3.0). + - Added user interface improvements to the keyboard shortcuts modal. + - Added a message "Editing this message with an ``@mention`` will not notify the recipient" in the post edit dialog. + - Made the appearance of several tooltips more consistent. + - Updated the help text in the **Direct Messages** modal. + - Emojis are now placed at cursor position while editing messages. + - Made keyboard shortcuts modal content DIV-accessible via the keyboard. + - Added Channel Bookmarks user interface (disabled by default and behind a feature flag). + +#### Administration + - Added a new feature where an admin with user management permission can now edit a user's settings in **System Console > Users**. + - Added download functionality for admins to download server logs from **Server Logs** page in the **System Console**. + - LDAP vendor errors are now included in the Support Packet. + - Added [metadata](https://docs.mattermost.com/manage/admin/generating-support-packet.html#contents-of-a-support-packet) to the Support Packet. + - We are now adding the user's ID and session ID to the audit log's Actor field for the login event, to match what we provide for the logout event. + - Added support for custom status in bulk export/import. + - Marked the ``RemoteTeamId`` field of the ``RemoteCluster`` entity as deprecated. + - Added log ``Name`` and ``DisplayName`` of groups. + - Logged fields of users are now updated. + +#### Performance + - Added platform related information to the notification metrics. + - Added additional information to INP and LCP client metrics. + - Added minor performance improvements to webapp initialization. + +#### mmctl + - Added two new commands to mmctl, ``mmctl job list`` and ``mmctl job update``. + - Panic message is now printed when mmctl panics. + - Setting ``AdvancedLoggingJSON`` via mmctl is now supported. + +### Bug Fixes + - Fixed an issue that displayed a wrong count for custom group members on the notification warning. + - Fixed a panic when the password was too long. + - Fixed an issue where configuration patches through mmctl did not correctly merge plugin configuration values. + - Fixed issues with the OpenID local development. + - Fixed an issue where Latex was not rendered in a code block as code when Latex rendering was disabled. + - Fixed an issue with saving custom roles. + - Fixed an issue with the left-hand side scrollbar auto-hide functionality for Chrome and Safari. + - Fixed Group Message to private channel conversion edge cases. + - Fixed an issue where users with the user management permission were unable to view the list of users in the **System Console > Users** page. + - Fixed more web app performance reports being marked as outdated after a user's computer woke up from sleep. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``TerminateSessionsOnPasswordChange`` to configure the sessions revocation during password resets. + +#### Changes to the Enterprise plan: + - Under ``ElasticsearchSettings`` in ``config.json``: + - Added ``Backend`` to differentiate between Elasticsearch and OpenSearch. The default value is ``elasticsearch``. + +### API Changes + - Added new API endpoints to manage remote clusters. + - Added two new query parameters to ``GET /api/v4/jobs, job_type`` and status. + - Added a new endpoint ``PATCH /api/v4/jobs/{job_id}/status``. + - Updated ``AddChannelMember`` to accept a list of userIds. + - Added six new permissions to manage the status of particular jobs: + - ``PermissionManagePostBleveIndexesJob`` + - ``PermissionManageDataRetentionJob`` + - ``PermissionManageComplianceExportJob`` + - ``PermissionManageElasticsearchPostIndexingJob`` + - ``PermissionManageElasticsearchPostAggregationJob`` + - ``PermissionManageLdapSyncJob`` + +### Go Version + - v9.11 is built with Go ``v1.21.8``. + +### Open Source Components + - Removed ``stylelint``, and added ``elastic/go-elasticsearch`` to https://github.com/mattermost/mattermost/. + +### Known Issues + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andreabia](https://translate.mattermost.com/user/andreabia), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [ayusht2810](https://github.com/ayusht2810), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [BrandonS09](https://github.com/BrandonS09), [calebroseland](https://github.com/calebroseland), [Camillarhi](https://github.com/Camillarhi), [catalintomai](https://github.com/catalintomai), [Celeo](https://github.com/Celeo), [chessmadridista](https://github.com/chessmadridista), [ckaznable](https://github.com/ckaznable), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [devinbinnie](https://github.com/devinbinnie), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [gabrieljackson](https://github.com/gabrieljackson), [Gesare5](https://github.com/Gesare5), [grinapo](https://github.com/grinapo), [hanzei](https://github.com/hanzei), [harmeet01singh](https://github.com/harmeet01singh), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [imanmagomedov.said](https://translate.mattermost.com/user/imanmagomedov.said), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://translate.mattermost.com/user/kaakaa), [kalil0321](https://github.com/kalil0321), [KellieSue](https://github.com/KellieSue), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [matthew-w](https://translate.mattermost.com/user/matthew-w), [MeHow25](https://github.com/MeHow25), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://translate.mattermost.com/user/milotype), [Mohamed-sobhi95](https://translate.mattermost.com/user/Mohamed-sobhi95), [mvitale1989](https://github.com/mvitale1989), [natalie-hub](https://github.com/natalie-hub), [nickmisasi](https://github.com/nickmisasi), [ningthoujamSwamikumar](https://github.com/ningthoujamSwamikumar), [Pawel1894](https://github.com/Pawel1894), [phoinixgrr](https://github.com/phoinixgrr), [poppfredslund](https://translate.mattermost.com/user/poppfredslund), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [Rajat-Dabade](https://github.com/Rajat-Dabade), [recontech404](https://github.com/recontech404), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shaon72](https://github.com/shaon72), [Sharuru](https://translate.mattermost.com/user/Sharuru), [shieldsjared](https://github.com/shieldsjared), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [suraj-anthwal](https://github.com/suraj-anthwal), [svelle](https://github.com/svelle), [ThrRip](https://translate.mattermost.com/user/ThrRip), [tnir](https://github.com/tnir), [toninis](https://github.com/toninis), [varghesejose2020](https://github.com/varghesejose2020), [vhaska](https://translate.mattermost.com/user/vhaska), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [ythosa](https://github.com/ythosa), [zenocode-org](https://translate.mattermost.com/user/zenocode-org), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) + +(release-v9-10-feature-release)= +## Release v9.10 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.10.3, released 2024-09-26** + - Mattermost v9.10.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin [v1.40.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.40.0). + - Mattermost v9.10.3 contains no database or functional changes. +- **9.10.2, released 2024-08-27** + - Mattermost v9.10.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.10.2 contains no database or functional changes. +- **9.10.1, released 2024-07-22** + - Mattermost v9.10.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Mattermost Copilot plugin version [v0.8.3](https://github.com/mattermost/mattermost-plugin-ai/releases/tag/v0.8.3). + - Ensured that the web app only requests notification permissions when needed. Fixed an issue with desktop notifications not being sent on Safari [MM-59416](https://mattermost.atlassian.net/browse/MM-59416). + - Fixed an issue where the app crashed on iOS Safari [MM-59296](https://mattermost.atlassian.net/browse/MM-59296). + - Mattermost v9.10.1 contains no database or functional changes. +- **9.10.0, released 2024-07-16** + - Original 9.10.0 release. + +```{Important} +If you upgrade from a release earlier than v9.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/mattermost-v9-10-changelog/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged GitLab plugin version [v1.9.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.9.1). + - Pre-packaged Mattermost Copilot plugin version [v0.8.1](https://github.com/mattermost/mattermost-plugin-ai/releases/tag/v0.8.1). + - Pre-packaged Calls plugin version [v0.28.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.28.2). + - Re-designed the user profile popover and improved its performance. + - Added banner to prompt users to allow notification permissions when opening the app in web browsers. + - Increased the width of the profile picture setting to match other user settings. + - Improved screen reader support for the emoji picker. + - Improved the accessibility of plugin buttons in the channel header. + +#### Administration + - Extended ``PluginSiteStatsHandler`` to support more advanced visualization types. + - Stopped broadcasting ``channel_deleted/channel_restored`` messages from private channels to non-members. + +#### Performance + - Added page load time to client performance metrics. + - Added a metric to track time it takes for the Threads view to load. + - Added support for mobile client metrics. + - Increased the range of LCP metrics that can be measured. + - Added polling of ``getStatusesByIds`` and ``getProfilesByIds`` network calls. The interval of which is configurable with the ``UsersStatusAndProfileFetchingPollIntervalMilliseconds`` configuration variable. + - Added defer loading plugins scripts. + +### Bug Fixes + - Fixed an issue where the ``RefreshPostStats`` job could fail. + - Fixed an issue where attempting to create a team with the URL of an existing team showed the wrong error message. + - Fixed an issue where ``visibilitychange`` JavaScript browser event had not been added for updating the user's current timezone. + - Fixed an issue where the last admin in the system was allowed to be demoted. + - Fixed an issue where banners set by system administrators did not stack below system banners, and appeared underneath them instead. Existing system banners have remained unchanged. + - Fixed an issue with an incorrect wrapping of long words in numbered lists. + - Fixed an incorrect behavior of the image proxy when site URL is changed. + - Fixed an issue where cache invalidation messages for websocket connections were not being sent across the cluster, causing missed websocket events. + - Fixed ``EnableClientMetrics`` setting not being available in the System Console. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``UsersStatusAndProfileFetchingPollIntervalMilliseconds`` to configure the interval of ``getStatusesByIds`` and ``getProfilesByIds`` network calls. + +### API Changes + - Added a new plugin API endpoint ``GetUsersByIds`` to retrieve a list of users by their ids. + +### Go Version + - v9.10 is built with Go ``v1.21.8``. + +### Known Issues + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [abhijit-singh](https://github.com/abhijit-singh), [aeomin](https://translate.mattermost.com/user/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [ahmadJT](https://github.com/ahmadJT), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [apshada](https://github.com/apshada), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [BenCookie95](https://github.com/BenCookie95), [BillAnderson304](https://github.com/BillAnderson304), [Boruus](https://translate.mattermost.com/user/Boruus), [BrandonS09](https://github.com/BrandonS09), [bruno-keiko](https://github.com/bruno-keiko), [calebroseland](https://github.com/calebroseland), [Camillarhi](https://github.com/Camillarhi), [catalintomai](https://github.com/catalintomai), [chessmadridista](https://github.com/chessmadridista), [ckaznable](https://github.com/ckaznable), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [esarafianou](https://github.com/esarafianou), [EyeCantCU](https://github.com/EyeCantCU), [ezekielchow](https://github.com/ezekielchow), [fmartingr](https://github.com/fmartingr), [frankps](https://translate.mattermost.com/user/frankps), [gabrieljackson](https://github.com/gabrieljackson), [Gesare5](https://github.com/Gesare5), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [homerCOD](https://translate.mattermost.com/user/homerCOD), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://translate.mattermost.com/user/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [MattSilvaa](https://github.com/MattSilvaa), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [mojahani](https://translate.mattermost.com/user/mojahani), [mvitale1989](https://github.com/mvitale1989), [nbruneau71250](https://github.com/nbruneau71250), [nickmisasi](https://github.com/nickmisasi), [phoinixgrr](https://github.com/phoinixgrr), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [Rajat-Dabade](https://github.com/Rajat-Dabade), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [toninis](https://github.com/toninis), [varghesejose2020](https://github.com/varghesejose2020), [wiggin77](https://github.com/wiggin77), [willypuzzle](https://github.com/willypuzzle), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [zenocode-org](https://github.com/zenocode-org) + +(release-v9-9-feature-release)= +## Release v9.9 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.9.3, released 2024-08-27** + - Mattermost v9.9.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.9.3 contains no database or functional changes. +- **9.9.2, released 2024-07-22** + - Mattermost v9.9.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.9.2 contains no database or functional changes. +- **9.9.1, released 2024-07-02** + - Mattermost v9.9.1 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where banners set by system administrators did not stack below system banners, but rather appeared underneath them. Existing system banners have remained unchanged. + - Removed feature flag which prevented enabling ``MetricsSettings.EnableClientMetrics`` [MM-58823](https://mattermost.atlassian.net/browse/MM-58823). + - Added a page load time to the client performance metrics [MM-58359](https://mattermost.atlassian.net/browse/MM-58359). + - Fixed web app performance reports being marked as outdated after the user's computer woke up from sleep [MM-58772](https://mattermost.atlassian.net/browse/MM-58772). + - Increased range of LCP metrics and Load Event End metrics that can be measured [MM-59033](https://mattermost.atlassian.net/browse/MM-59033). + - Fixed an error caused by performance telemetry when using Firefox with ``beacon.enabled`` set to ``false`` [MM-58777](https://mattermost.atlassian.net/browse/MM-58777). + - Mattermost v9.9.1 contains no database or functional changes. +- **9.9.0, released 2024-06-14** + - Original 9.9.0 release. + +### Compatibility + - Updated minimum macOS version to 12+ and minimum Safari version to 17+. + +```{Important} +If you upgrade from a release earlier than v9.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/video-mattermost-v9-9-changelog/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged Calls plugin version [v0.27.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.27.0). + - Pre-packaged Jira plugin version [v4.1.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.1). + - Pre-packaged GitLab plugin version [v1.9.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.9.0). + - Pre-packaged Zoom plugin version [v1.8.0](https://github.com/mattermost/mattermost-plugin-zoom/releases/tag/v1.8.0). + - Updated the default themes to reduce eye strain (particularly on the dark themes). + - Added UI improvements to the core layout. + - Improved error text when inviting guests to a team. + - Increased the visibility Mattermost edition in-product when using the free edition. + - Added an **Unsupported** label to the Team/E0 editions in the product menu. + - Improved the look and feel of the **True/False** selector in the System Console. + - Updated the channel header layout to reduce height and simplify the UI. + +#### Administration + - Removed safety limit error message in compiled Team Edition and unlicensed Enterprise Edition deployments when message count exceeds 5 million posts. + - Adjusted safety limit error message to show when users exceed 5,000 in compiled Team Edition and Enterprise Edition deployments when enterprise scale and access control automation features are unavailable. ``ERROR_SAFE_LIMITS_EXCEEDED``. + - Improved the message length validation step in the ``mmctl import validate`` command. + - Added shell completion to ``mmctl user active`` and ``mmctl user deactivate``. + - Removed support for self-serve purchases of Mattermost Subscriptions in various flows, throughout Cloud and Self Hosted environments. + - Removed support for self-serve true up review submission in the **System Console**. + - Added streaming support to the file attachments import process. + - Added LDAP job command to mmctl. + - Made LDAP sync jobs more resilient against errors. + - Removed the ``PostPriority`` feature flag. + - Improved the error message of ``NotFound`` errors in store. + - Added support for post priority to incoming webhooks and outgoing webhook responses. + - Added a validation that the payload for an open Interactive Dialog request is valid according to the rules at https://developers.mattermost.com/integrate/plugins/interactive-dialogs/. + - Unblocked notification calls by using usernames instead of full names in case of a missing user profile. + - Increased the maximum password limit from 64 to 72 characters (``PasswordMaximumLength``). + +#### Performance + - Added the initial version of new client-side performance metrics to track web app performance and can be monitored in new [Grafana board](https://grafana.com/grafana/dashboards/21460-web-app-metrics/). + - Added a metric to track time it takes for the right-hand side to load. + - Improved js memory profile of status’s reducers. + - When a user receives a new post that is part of a thread from a root post in a channel they are not currently viewing, we do not fetch the complete root post and its thread posts immediately. However, we still store the newly received post. The root post and its thread posts are only fetched when the user navigates to that specific channel. + +### Bug Fixes + - Fixed an issue with ``aria-label`` for sidebar channel buttons. + - Fixed an issue where any remaining unclosed database RPC connections were not closed after a plugin shut down. + - Fixed an issue where the right-hand side stole the focus when coming back from threads or drafts. + - Fixed an issue where a proxy link was copied instead of the original image link when copying a post that included an embedded image. + - Fixed an issue where the user status would incorrectly get stuck to online after the user closed the tab. + - Fixed an issue where on some servers the user could not see the member count in the **Browse Channels** dialog. + - Fixed an issue with inline display of WebP images accessed through the public-link feature. + - Fixed an issue where it wasn’t clear that the ``mmctl import process --bypass-upload --local`` doesn't work if the server is in High Availability. + - Fixed an issue where the user status would incorrectly be set to offline without checking for connections in other nodes in an High Availability cluster. + - Fixed a longstanding issue where the @mention auto-complete could erase post text following the auto-completed @mention. + - Fixed an issue with status management to avoid missing notifications. + - Fixed an issue where audit events were not added for OAuth logins. + - Fixed an issue with the error check in the message export process. + - Fixed an issue where pasting in the post text box could not always paste without formatting. + - Fixed some plugin settings with defaults not changing value. + +### config.json +New setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``DisableWakeUpReconnectHandler`` to disable the wake up on reconnect handler. + - Removed ``SelfHostedPurchase`` setting. + +#### Changes to the Enterprise plan: + - Under ``MetricsSettings`` in ``config.json``: + - Added a feature flag and a setting ``EnableClientMetrics`` to control new client performance metrics. + - Added a setting for notification metrics ``EnableNotificationMetrics``. + - Self-hosted system administrators can now configure all ``ExperimentalAuditSettings`` through the user interface in the ``System Console``. Cloud administrators can now change the ``AdvancedLoggingJSON`` value for the ``ExperimentalAuditSettings``. This is the only configuration that Cloud administrators are able to adjust. Feature flag ``ExperimentalAuditSettingsSystemConsoleUI`` must be enabled in order to leverage this new user interface. + +### Websocket Event Changes + - Changed the semantics of the ``mattermost_http_websockets_total`` metric to track all open WebSocket connections, regardless of whether they are authenticated. + - Added a ``origin_client`` label to the ``mattermost_http_websockets_total`` Prometheus metric. + +### Go Version + - v9.9 is built with Go ``v1.21.8``. + +### Open Source Components + - Removed ``@stripe/react-stripe-js`` and ``@stripe/stripe-js``, and added ``web-vitals`` at https://github.com/mattermost/mattermost. + +### Known Issues + - Some Cloud workspaces unexpectedly received emails about license expiration. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [arush-vashishtha](https://github.com/arush-vashishtha), [asaadmahmood](https://github.com/asaadmahmood), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [bndn](https://translate.mattermost.com/user/bndn), [calebroseland](https://github.com/calebroseland), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [enzowritescode](https://github.com/enzowritescode), [fasal26](https://github.com/fasal26), [fmartingr](https://github.com/fmartingr), [gabrieljackson](https://github.com/gabrieljackson), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [joakim.rivera](https://translate.mattermost.com/user/joakim.rivera), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [marlenekoh](https://github.com/marlenekoh), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [MeHow25](https://github.com/MeHow25), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [mojahani](https://translate.mattermost.com/user/mojahani), [morgancz](https://github.com/morgancz), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [nixusUM](https://github.com/nixusUM), [orimaimon](https://github.com/orimaimon), [phoinixgrr](https://github.com/phoinixgrr), [piotr-lasota](https://github.com/piotr-lasota), [pjenicot](https://translate.mattermost.com/user/pjenicot), [pmokeev](https://github.com/pmokeev), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [tarrow](https://github.com/tarrow), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [toninis](https://github.com/toninis), [umrkhn](https://github.com/umrkhn), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [zsrv](https://github.com/zsrv) + +(release-v9-8-feature-release)= +## Release v9.8 - Feature Release + +- **9.8.3, released 2024-07-22** + - Mattermost v9.8.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.8.3 contains no database or functional changes. +- **9.8.2, released 2024-07-02** + - Mattermost v9.8.2 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where banners set by system administrators did not stack below system banners, but rather appeared underneath them. Existing system banners have remained unchanged. + - Mattermost v9.8.2 contains no database or functional changes. +- **9.8.1, released 2024-06-03** + - Mattermost v9.8.1 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Removed a safety limit error message in compiled Team Edition and unlicensed Enterprise Edition deployments when message count exceeds 5 million posts. + - Fixed an issue with some plugin settings with defaults not changing value. + - Mattermost v9.8.1 contains no database or functional changes. +- **9.8.0, released 2024-05-16** + - Original 9.8.0 release. + +### Compatibility + - Updated minimum required Edge and Chrome versions to 122+. + +```{Important} +If you upgrade from a release earlier than v9.7, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/mattermost-v9-8-changelog/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged Playbooks version [v1.39.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.3). + - Pre-packaged GitLab plugin version [v1.8.1](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.8.1). + - Pre-packaged Calls version [v0.26.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.26.2). + - Combined Desktop and Mobile notifications in the user settings modal. + - Added a **Don't Clear** option for Do Not Disturb. + - Enhanced the user interface for channel introductions. + - Added an ephemeral message for non-team member mentions in channels. + - Added emoji tooltips on hover in post message. + - Made the appearance of several tooltips more consistent. + - Updated theme colors for onboarding tour points. + - Updated the right-hand side Thread view to use relative timestamps to be more consistent with the global Threads view. + - Added a total reply count to the right-hand side thread view. + +#### Administration + - Added safety limit error message in compiled Team Edition and Enterprise Edition deployments when enterprise scale and access control automation features are unavailable, and message count exceeds 5 million posts. ERROR_SAFE_LIMITS_EXCEEDED. + - Downloading a support packet is now extensible with plugins. If a plugin can add content to the support packet, it will be displayed in the commercial support modal. Administrators will have the option to include/exclude that from the support package. + - Upgraded Nodejs to v20.11. + - Added the backend for Channel Bookmarks (disabled by default). Added Channel Bookmarks permissions to the channel user role and to the channel moderation system. + - Added Channel Bookmarks permissions to the channel user role and to the channel moderation system. + - Added progress logs for attachments in bulk exports. + - Added a **System Console** option to rebuild Elasticsearch channels indexes. + - Obfuscated ``ReplicaLagSettings`` in the Support Packet. + - Improved license loading errors. + - Updated the keycloak docker configs and added a ``make`` command. + - Removed unused ``IsOAuth`` field from ``AppError``. + - ``bool`` is now used for ``license_is_trial`` in the Support Packet. + - Bulk export: added functionality to export roles and permissions schemes. + - A new flag (``extract-content``) was added to the mmctl import process that allows the server to skip content extraction during the import phase. + +### API Changes + - Added a create channel bookmark endpoint at ``/api/v4/channels/{channel_id}/bookmarks``. + - Added additional query params to channel endpoints to include channel bookmarks. + - Added update channel bookmark endpoint at ``/api/v4/channels/{channel_id}/bookmarks/{bookmark_id}``. + - Added list channel bookmarks endpoint at ``/api/v4/channels/{channel_id}/bookmarks``. + - Added delete channel bookmark endpoint at ``/api/v4/channels/{channel_id}/bookmarks/{bookmark_id}``. + - Added update channel bookmark sort order endpoint at ``/api/v4/channels/{channel_id}/bookmarks/{bookmark_id}/sort_order``. + - Exposed a local-mode only API for reattaching plugins, primarily to facilitate mock-free unit testing. + - Exposed ``UpdateUserRoles`` in ``pluginapi``. + - Exposed ``pluginapi.ProfileImageBytes`` to simplify bot setup from a plugin. + - For ``POST /channels``, added a validation for ``display_name`` to not pass validation if the display name is empty. + +### Bug Fixes + - Fixed an issue with context cancellation for integration requests. + - Fixed an issue preventing the retrieval of SAML metadata. + - Fixed an issue causing an empty channel switcher after converting a group message to a private channel. + - Fixed an issue where System Admins were not allowed to LDAP sync SAML users when ``SamlSettings.EnableSyncWithLdap`` was set to **true**. + - Fixed an issue with markdown in the AD job status table. + - Fixed an issue with a control character in the group list modal. + - Fixed an issue where the auto-complete channels API returned archived channels in response. + - Fixed a crash issue in the **System Console**. + - Fixed an issue where links included in notifications were truncated and not clickable. + - Fixed using local requests instead of HTTP requests in the flow library. + - Fixed an issue where ``support_packet.yaml`` wasn’t generated even if an error occurred. + - Fixed an issue where outgoing webhooks did not trigger when using multiple callback URLs. + - Fixed an issue where it was not possible to clear plugin settings with a default value in the **System Console**. + - Fixed an issue where ``MaxUsersForStatistics`` wasn’t ignored when generating a Support Packet. + - Fixed an issue where the ``EnsureBot`` function did not recreate the bot if it had been manually deleted. + - Fixed an issue where users couldn't look up a user by their ID in the **System Console** anymore. + - Fixed an accessibility issue where the focus didn’t go back to the originating button when a modal was closed. + - Fixed an issue where end users were not allowed to fetch the group members list of groups that allow ``@-mentions``. + +### config.json +New setting option were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``FileSettings`` in ``config.json``: + - Added ``AmazonS3UploadPartSizeBytes`` and ``ExportAmazonS3UploadPartSizeBytes`` to control the part size used to upload files to an S3 store. + - Under ``ServiceSettings`` in ``config.json``: + - Increased the default payload size limit (``MaximumPayloadSizeBytes``) from 100 kB to 300 kB. Existing servers need to manually update this value. + - Under ``ClusterSettings`` in ``config.json``: + - Removed unused settings ``StreamingPort``, ``MaxIdleConns``, ``MaxIdleConnsPerHost`` and ``IdleConnTimeoutMilliseconds``. + + #### Changes to Professional and Enterprise plans: + - Under ``ExperimentalSettings`` in ``config.json``: + - Removed the ``UseNewSAMLLibrary`` experimental setting. + +### Go Version + - v9.8 is built with Go ``v1.21.8``. + +### Known Issues + - Status may sometimes get stuck as **Away** or **Offline** with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [Amir-Helali](https://github.com/Amir-Helali), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [annaos](https://github.com/annaos), [apshada](https://github.com/apshada), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [aszakacs](https://github.com/aszakacs), [BarbUk](https://github.com/BarbUk), [BenCookie95](https://github.com/BenCookie95), [Blaieet](https://github.com/Blaieet), [calebroseland](https://github.com/calebroseland), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyrusjc](https://github.com/cyrusjc), [daran9](https://github.com/daran9), [devharipragaz007](https://github.com/devharipragaz007), [devinbinnie](https://github.com/devinbinnie), [dsspence](https://github.com/dsspence), [Eleferen](https://translate.mattermost.com/user/Eleferen), [EltonGohJH](https://github.com/EltonGohJH), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [ezekielchow](https://github.com/ezekielchow), [fmartingr](https://github.com/fmartingr), [gabrieljackson](https://github.com/gabrieljackson), [gitairman](https://github.com/gitairman), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [hossain-sazzad](https://github.com/hossain-sazzad), [ifoukarakis](https://github.com/ifoukarakis), [inconnu1](https://github.com/inconnu1), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jones](https://translate.mattermost.com/user/jones), [josephjose](https://github.com/josephjose), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jupenur](https://github.com/jupenur), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kaoski](https://github.com/kaoski), [Karimaljandali](https://github.com/Karimaljandali), [kayazeren](https://github.com/kayazeren), [KrisSiegel](https://github.com/KrisSiegel), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lbr88](https://github.com/lbr88), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [mahdiirar](https://github.com/mahdiirar), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [MeHow25](https://github.com/MeHow25), [mentz](https://translate.mattermost.com/user/mentz), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [movion](https://github.com/movion), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [Nityanand13](https://github.com/Nityanand13), [nmnj](https://translate.mattermost.com/user/nmnj), [Obbi89](https://github.com/Obbi89), [pacop](https://github.com/pacop), [phoinixgrr](https://github.com/phoinixgrr), [Pkarle](https://github.com/Pkarle), [poppfredslund](https://translate.mattermost.com/user/poppfredslund), [potatogim](https://github.com/potatogim), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahimrahman](https://github.com/rahimrahman), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [RS-labhub](https://github.com/RS-labhub), [Rutam21](https://github.com/Rutam21), [s-krishnaraju](https://github.com/s-krishnaraju), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [tanmaythole](https://github.com/tanmaythole), [ThrRip](https://github.com/ThrRip), [tnir](https://github.com/tnir), [toninis](https://github.com/toninis), [topolovac](https://github.com/topolovac), [varghesejose2020](https://github.com/varghesejose2020), [wetneb](https://github.com/wetneb), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [zsrv](https://github.com/zsrv) + +---- + +(release-v9-7-feature-release)= +## Release v9.7 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.7.6, released 2024-07-02** + - Mattermost v9.7.6 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where banners set by system administrators did not stack below system banners, but rather appeared underneath them. Existing system banners have remained unchanged. + - Mattermost v9.7.6 contains no database or functional changes. +- **9.7.5, released 2024-06-03** + - Mattermost v9.7.5 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.7.5 contains no database or functional changes. +- **9.7.4, released 2024-05-15** + - Fixed an issue with context cancellation for integration requests [MM-58019](https://mattermost.atlassian.net/browse/MM-58019). + - Fixed some plugin settings with defaults not changing value [MM-58102](https://mattermost.atlassian.net/browse/MM-58102). + - Mattermost v9.7.4 contains no database or functional changes. +- **9.7.3, released 2024-04-30** + - Fixed an issue where creating a Direct Message channel with synthetic users failed [MM-58019](https://mattermost.atlassian.net/browse/MM-58019). + - Mattermost v9.7.3 contains no database or functional changes. +- **9.7.2, released 2024-04-25** + - Mattermost v9.7.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.7.2 contains no database or functional changes. + - Pre-packaged Playbooks version [v1.39.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.3). + - Increased the default payload size limit (``MaximumPayloadSizeBytes``) from 100 kB to 300 kB. Existing servers need to manually update this value. + - Fixed an issue where it was not possible to clear the plugin settings with a default value in the System Console. +- **9.7.1, released 2024-04-16** + - Fixed an issue with a noisy log entry for permalink post notifications. + - Mattermost v9.7.1 contains no database or functional changes. +- **9.7.0, released 2024-04-16** + - Original 9.7.0 release. + +```{Important} +If you upgrade from a release earlier than v9.6, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/mattermost-v9-7-changelog/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Added Mattermost [AI plugin](https://github.com/mattermost/mattermost-plugin-ai) to pre-packaged plugins. + - Pre-packaged Calls version [v0.25.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.25.1). + - Pre-packaged Playbooks version [v1.39.2](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.2). + - Pre-packaged GitHub plugin version [v2.2.0](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.2.0). + - The first emoji is now auto-selected in the emoji picker. + - Added Markdown support for batched email notifications. + - Users’ timezone is now used in batched email notifications. + - Removed a conflicting class (``help-text``) from the interactive dialog field description to resolve the black text color in the dark theme. + - Updated the user interface of **Team Settings** modal. + - Promoted Simplified Chinese to Beta, and downgraded Hungarian and Spanish languages to Beta. + - Improved the opening animation of the user settings modal. + +#### Administration + - Upgraded ``@mattermost/client`` and ``@mattermost/types`` to support TypeScript v5.x. + - Enforced safety limit in compiled Team Edition and Enterprise Edition deployments when enterprise scale and access control automation features are unavailable, and when the count of users who are registered, but not deactivated, exceeds 11,000. ERROR_SAFE_LIMITS_EXCEEDED. + - Dropped pre-packaged plugins for unsupported OS and architectures. + - Implemented a new **Export Settings** page in the **System Console** to allow Cloud administrators to customize their dedicated export S3 buckets. + - LDAP job details are no longer shown until the job runs. + - Added more logging to the ``NotificationsLog``. + - A message is now logged when a user tries to log in using an incorrect password. + - Posts from deactivated users are now included in **Direct Message** channel exports. Also the ``--include-archived-channels`` flag is now respected for **Direct Message** channels. + - Changed the cache headers for file endpoints to cache privately for 24 hours, instead of not caching at all. + - Improved the performance of the ElasticSearch indexing job in PostgreSQL installations. + - Moved following functions from server to public utils: + - ``ResetReadTimeout`` + - ``AppendMultipleStatementsFlag`` + - ``SetupConnection`` + - ``SanitizeDataSource`` + +#### mmctl + - mmctl can now be used to download a Support Packet using ``--local mode``. + - mmctl system ping will now return detailed server status even if the server status is unhealthy. + +### Bug Fixes + - Fixed an issue where the Desktop App login flow would erroneously show the landing page for first time users. + - Fixed an issue where a right-hand side card was not reloaded when the card body was updated. + - Fixed an issue where ``en-AU`` language selection was not allowed. + - Fixed an issue with the position of text in the default profile picture. + - Fixed an issue with the group search to parse the display name. + - Fixed an issue where items with longer text did not widen the user guide dropdown to its max-width. + - Fixed an issue where the configuration could not be updated from the **System Console** in cloud environments. + +### config.json +A new setting option was added to ``config.json``. Below is a list of the addition and its default value on install. The setting can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``CloudSettings`` in ``config.json``: + - Added a new configuration setting ``Disable`` (via config.json, or environment variable), default ``false``. When set to ``true``, all requests to the Mattermost Customer Portal from a workspace will be disabled. + +### Open Source Components + - Added ``stylelint`` to https://github.com/mattermost/mattermost/. + +### Go Version + - v9.7 is built with Go ``v1.20.7``. + +### Known Issues + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [2017Yasu](https://github.com/2017Yasu), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [andriumm](https://github.com/andriumm), [angeloskyratzakos](https://github.com/angeloskyratzakos), [annaos](https://github.com/annaos), [apshada](https://github.com/apshada), [asaadmahmood](https://github.com/asaadmahmood), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [Blaieet](https://github.com/Blaieet), [calebroseland](https://github.com/calebroseland), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [dipaksinha1](https://github.com/dipaksinha1), [doc-sheet](https://github.com/doc-sheet), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [ezekielchow](https://github.com/ezekielchow), [gabrieljackson](https://github.com/gabrieljackson), [grundleborg](https://github.com/grundleborg), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [hossain-sazzad](https://github.com/hossain-sazzad), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [iyampaul](https://github.com/iyampaul), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jones](https://translate.mattermost.com/user/jones), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [Linkinlog](https://github.com/Linkinlog), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mickmister](https://github.com/mickmister), [morgancz](https://github.com/morgancz), [mozi47](https://github.com/mozi47), [mvitale1989](https://github.com/mvitale1989), [nab-77](https://github.com/nab-77), [nachtjasmin](https://github.com/nachtjasmin), [natalie-hub](https://github.com/natalie-hub), [neflyte](https://github.com/neflyte), [nickmisasi](https://github.com/nickmisasi), [phoinixgrr](https://github.com/phoinixgrr), [poppfredslund](https://translate.mattermost.com/user/poppfredslund), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [RyoKub](https://github.com/RyoKub), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [sinansonmez](https://github.com/sinansonmez), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [tanmaythole](https://github.com/tanmaythole), [ThrRip](https://github.com/ThrRip), [toninis](https://github.com/toninis), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [vishal-rathod-07](https://github.com/vishal-rathod-07), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Wing0515](https://github.com/Wing0515), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1) + +---- + +(release-v9-6-feature-release)= +## Release v9.6 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.6.3, released 2024-06-03** + - Mattermost v9.6.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with some plugin settings with defaults not changing value. + - Mattermost v9.6.3 contains no database or functional changes. +- **9.6.2, released 2024-04-25** + - Mattermost v9.6.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.6.2 contains no database or functional changes. + - Pre-packaged Playbooks version [v1.39.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.3). + - Fixed an issue where it was not possible to clear the plugin settings with a default value in the System Console. +- **9.6.1, released 2024-03-26** + - Mattermost v9.6.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.6.1 contains no database or functional changes. + - Fixed an issue where the configuration could not be updated from the System Console in cloud environments. +- **9.6.0, released 2024-03-15** + - Original 9.6.0 release. + +### Compatibility + - Updated minimum required Edge and Chrome versions to 120+. + +```{Important} +If you upgrade from a release earlier than v9.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://mattermost.com/video/changelog-v9-6/) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged Calls version [v0.24.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.24.0). + - Pre-packaged GitLab plugin version [v1.8.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.8.0). + - Added the [Outgoing OAuth Connections](https://developers.mattermost.com/integrate/slash-commands/outgoing-oauth-connections/) integration type. + - Re-designed the **System Console > User Management** screen, and added the ability to batch export users in CSV format (Professional and Enterprise plans). On MySQL, users cannot view live results of the batch export in the user interface. + - Improved the appearance of profile/account menus. + - Added support for checkbox types in the **System Console** settings. + - Added support for WebP image previews in the web app similar to PNG and other image formats. + - Several pre-packaged plugins were removed. + +#### Administration + - Removed some unused Redux actions and reducers, including ``state.entities.posts.selectedPostId``. + - Limited the number of user preference updates to 10 per call. + - Clarified that the LDAP profile picture setting is optional. + +#### mmctl + - Extended mmctl with support for user preferences. + +### Bug Fixes + - Fixed an issue with switching to a **Direct Message** channel with a shared channel user (user from another server). + - Fixed an issue with extra space getting added to code blocks in search results. + - Fixed an issue where deactivated members were not included in a favorited **Direct Message** channel export. + - Fixed an issue where password strength settings wouldn't be disabled if they were set through environment variables. + - Fixed an issue where post mentions would grow outside the viewport on small devices. + - Fixed an issue with draft removal after deleting the post. + - Fixed a markdown issue where, on some occasions, extra space was found before a list. + - Fixed an issue where a sender to a custom group would also receive the message notification themselves. + - Fixed a web app crash when a System Admin clicked on a link to a private channel that they were not a member of. + - Fixed ``ChannelHasBeenCreated`` plugin hook not being called when a group channel was created. + - Fixed thread notifications so that if a user had **Thread Reply Notifications** disabled for your account and **Automatically follow threads in this channel** enabled for a channel, the user wouldn't receive thread notifications for that channel per global setting. + +### config.json + - Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to the Enterprise plan: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableOutgoingOAuthConnections`` configuration setting for Outgoing OAuth Connections integration type. + +### Open Source Components + - Added ``@floating-ui/react``, and removed ``@floating-ui/react-dom`` and ``@floating-ui/react-dom-interactions`` from https://github.com/mattermost/mattermost/. + +### Go Version + - v9.6 is built with Go ``v1.20.7``. + +### Known Issues + - Users' initial status is not always loaded correctly [MM-56966](https://mattermost.atlassian.net/browse/MM-56966). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [abdesslamhouioui](https://github.com/abdesslamhouioui), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [Alpha-4](https://github.com/Alpha-4), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [apshada](https://github.com/apshada), [arush-vashishtha](https://github.com/arush-vashishtha), [asaadmahmood](https://github.com/asaadmahmood), [avas27JTG](https://github.com/avas27JTG), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [bewing](https://github.com/bewing), [calebroseland](https://github.com/calebroseland), [carydrew](https://github.com/carydrew), [Chlbek](https://translate.mattermost.com/user/Chlbek), [compiledsound](https://github.com/compiledsound), [cpatulea](https://github.com/cpatulea), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [edu-ap](https://github.com/edu-ap), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [ewwollesen](https://github.com/ewwollesen), [gabrieljackson](https://github.com/gabrieljackson), [gourav-varma](https://github.com/gourav-varma), [Gregesp](https://github.com/Gregesp), [grundleborg](https://github.com/grundleborg), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [iabdousd](https://github.com/iabdousd), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johndavidlugtu](https://github.com/johndavidlugtu), [jones](https://translate.mattermost.com/user/jones), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [juliovillalvazo](https://github.com/juliovillalvazo), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lucassabreu](https://github.com/lucassabreu), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [MixeroTN](https://translate.mattermost.com/user/MixeroTN), [mjnagel](https://github.com/mjnagel), [morgancz](https://translate.mattermost.com/user/morgancz), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [nokedajunky](https://github.com/nokedajunky), [olavinto](https://github.com/olavinto), [oOoBenoitoOo](https://github.com/oOoBenoitoOo), [phoinixgrr](https://github.com/phoinixgrr), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://translate.mattermost.com/user/Sharuru), [sinansonmez](https://github.com/sinansonmez), [sohzm](https://github.com/sohzm), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [TealWater](https://github.com/TealWater), [ThrRip](https://github.com/ThrRip), [titanventura](https://github.com/titanventura), [toninis](https://github.com/toninis), [trangology](https://github.com/trangology), [trivikr](https://github.com/trivikr), [tsabi](https://github.com/tsabi), [Utsav-Ladani](https://github.com/Utsav-Ladani), [varghesejose2020](https://github.com/varghesejose2020), [vidhisaini10](https://github.com/vidhisaini10), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yeoji](https://github.com/yeoji) + +---- + +(release-v9-5-extended-support-release)= +## Release v9.5 - [Extended Support Release](https://docs.mattermost.com/upgrade/release-definitions.html#extended-support-release-esr) + +- **9.5.14, released 2025-05-09** + - Upgraded logr dependency to v2.0.22 for multiple improvements and bug fixes. + - Mattermost v9.5.14 contains no database or functional changes. +- **9.5.13, released 2024-11-14** + - Mattermost v9.5.13 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Calls plugin [v0.29.4](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.4). + - Mattermost v9.5.13 contains no database or functional changes. +- **9.5.12, released 2024-10-28** + - Mattermost v9.5.12 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed desyncing issues with unreads between the team sidebar and the title bar [MM-54021](https://mattermost.atlassian.net/browse/MM-54021). + - Mattermost v9.5.12 contains no database or functional changes. +- **9.5.11, released 2024-10-10** + - Mattermost v9.5.11 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with YouTube previews no longer being displayed [MM-60351](https://mattermost.atlassian.net/browse/MM-60351). + - Pre-packaged Calls plugin [v0.29.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.29.2). + - Improved the performance of LDAP sync jobs when group-contained teams and channels are used [MM-60253](https://mattermost.atlassian.net/browse/MM-60253). + - Mattermost v9.5.11 contains no database or functional changes. +- **9.5.10, released 2024-09-26** + - Mattermost v9.5.10 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed racy use of session in ``NewWebConn`` [MM-60307](https://mattermost.atlassian.net/browse/MM-60307). + - Pre-packaged Playbooks plugin [v1.40.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.40.0). + - Mattermost v9.5.10 contains no database or functional changes. +- **9.5.9, released 2024-08-27** + - Mattermost v9.5.9 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.9 contains no database or functional changes. +- **9.5.8, released 2024-07-22** + - Mattermost v9.5.8 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.8 contains no database or functional changes. +- **9.5.7, released 2024-07-02** + - Mattermost v9.5.7 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where banners set by system administrators did not stack below system banners, but rather appeared underneath them. Existing system banners have remained unchanged. + - Added a new configuration setting ``CloudSettings.Disable`` (via config.json, or environment variable), default ``false``. When set to ``true``, all requests to the Mattermost Customer Portal from a workspace will be disabled. + - Fixed an issue where the user status would incorrectly be set to offline without checking for connections in other nodes in an High Availability cluster [MM-57153](https://mattermost.atlassian.net/browse/MM-57153). + - Fixed an issue where users could not see the member count in the **Browse Channels** dialog on some servers [MM-56266](https://mattermost.atlassian.net/browse/MM-56266). + - Increased the maximum length of the ``Value`` column of the ``Preferences`` table [MM-57913](https://mattermost.atlassian.net/browse/MM-57913). + - Mattermost v9.5.7 contains no database or functional changes. +- **9.5.6, released 2024-06-03** + - Mattermost v9.5.6 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.6 contains no database or functional changes. +- **9.5.5, released 2024-05-15** + - Fixed an issue where the user status would incorrectly get stuck to online after the user closed their tab [MM-57885](https://mattermost.atlassian.net/browse/MM-57885). + - Mattermost v9.5.5 contains no database or functional changes. +- **9.5.4, released 2024-04-25** + - Mattermost v9.5.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.4 contains no database or functional changes. + - Pre-packaged Playbooks version [v1.39.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.3). + - Increased the default payload size limit (``MaximumPayloadSizeBytes``) from 100 kB to 300 kB. Existing servers need to manually update this value. + - Fixed an issue with context cancellation for integration requests. + - Fixed an issue where end users were not allowed to fetch the group members list of groups that allow ``@-mentions``. +- **9.5.3, released 2024-03-26** + - Mattermost v9.5.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.3 contains no database or functional changes. + - Improved the performance of the ElasticSearch indexing job in PostgreSQL installations. +- **9.5.2, released 2024-03-06** + - Mattermost v9.5.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.2 contains no database or functional changes. + - Fixed ``ChannelHasBeenCreated`` plugin hook not being called when a group channel was created. +- **9.5.1, released 2024-02-16** + - Mattermost v9.5.1 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.5.1 contains no database or functional changes. +- **9.5.0, released 2024-02-16** + - Original 9.5.0 release. + +### Important Upgrade Notes + - We have stopped supporting MySQL v5.7 since it's at the end of life. We urge customers to upgrade their MySQL instance at their earliest convenience. + +```{Important} +If you upgrade from a release earlier than v9.4, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +See [this walkthrough video](https://www.youtube.com/watch?v=b1M2BGGF578&feature=youtu.be) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Pre-packaged Calls version [v0.23.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.23.1). + - Pre-packaged Jira plugin version [v4.1.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.0). + - Improved the behavior of suggestion boxes when changing the caret position. + - Changed the time for tomorrow in the **Do Not Disturb** timer and post reminder to refer to the next day at 9:00am instead of 24hrs from the time of activation. + - Updated message timestamp tooltips to include seconds. + - Added a new Wrangler feature to be able to move threads (Experimental). Moving threads requires a Professional/Enterprise license to activate. This feature is not yet recommended for production use. A new feature flag ``MoveThreadsEnabled`` was added and is default OFF. Changing this value to ON will enable the experimental **Move Threads** feature. + - Applied a wording change for active and activated users in the **System Console** user list. + - Applied a wording change for active and activated users in the **Team Statistics** page. + +#### Administration + - Added safety limit error message in compiled Team Edition and Enterprise Edition deployments when enterprise scale and access control automation features are unavailable and count of users who are registered and not deactivated exceeds 10,000. ERROR_SAFE_LIMITS_EXCEEDED. + - The ``where`` field is now rendered in ``model.AppError`` only when it's present. + - Added Outgoing Oauth implementation ``Get``/``List`` logic. + - The mmctl bulk import process command in local mode now supports processing an import file without actually uploading it to the server. Simply pass the file path to the import file and the server will directly read from it, and pass the ``--bypass-upload`` flag. There is no need to use the import upload command. NOTE: all of this is applicable only in local mode. + - Added **Monthly Active Users** (MAU) as part of the true-up report. + - Prometheus metrics are now available under the Source Available License. + +#### Performance + - Optimized ``createPost`` performance. + - Improved the performance of emoji uploads. + - Made small optimizations in several database calls: + - ``App.HasPermissionToChannel`` + - ``getPostsForChannelAroundLastUnread`` + - ``publishWebsocketEventForPermalinkPost`` + - ``countMentionsFromPost`` + +#### Plugins + - Plugins are now allowed to register user settings. + - Plugins can now register an action in the **User Settings** section. Plugins can also now disable a section in their **User Settings**. + - Included session id in request payload of the ``WebSocketMessageHasBeenPosted`` plugin hook. + +### Bug Fixes + - Fixed an issue where the right-hand side stopped getting the focus when navigating from **Global Threads** or **Global Drafts**. + - Fixed a theme issue in the notification settings. + - Fixed a regression in compliance exports which did not allow the export job to be canceled gracefully on server shutdown. + - Fixed an error where posts dismissed by a plugin were not properly removed from the view. + - Fixed an issue where if there were multiple websocket connections from a single user, then in case one connection got removed during a broadcast, there was a possibility that the other good connection would not get the event. + - Fixed an issue with true-up reports sending active users and not activated users. + - Fixed an issue where users were not able to navigate through links to private channels they are member of with certain configurations. + +### config.json + - Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``MaximumPayloadSizeBytes`` to add a limit to the payload size of API endpoints passing in arrays. + - Added a configuration setting ``OutgoingIntegrationRequestsDefaultTimeout`` for integration requests. + +#### Changes to the Professional and Enterprise plans: + - Under ``WranglerSettings`` in ``config.json``: + - Added ``AllowedEmailDomain`` - a CSV list of strings, where each is an email domain that is allowed to use the feature (e.g. - on community.mattermost.com, ``mattermost.com`` would allow staff to move a thread, while non-staff cannot). + - ``MoveThreadMaxCount`` - a number representing the maximum number of posts that can be in a thread for it to be moveable. + - ``MoveThreadToAnotherTeamEnable`` - a boolean value representing whether moving should work across teams. + - ``MoveThreadFromPrivateChannelEnable`` - a boolean value representing whether moving should work from within a private channel. + - ``MoveThreadFromDirectMessageChannelEnable`` - a boolean value representing whether moving should be allowed from within a group message. + +#### Changes to the Enterprise plan: + - Under ``DataRetentionSettings`` in ``config.json``: + - Added two new configuration settings, ``MessageRetentionHours`` and ``FileRetentionHours``, in order to support setting your global retention time in hours. ``DataRetentionSettings.MessageRetentionDays`` and ``DataRetentionSettings.FileRetentionDays`` are deprecated but we will continue to use their value until you set something for their hours equivalent. If Days are set then the hours configuration must be 0 and if hours is set then the days config must be 0. We do not support hours for granular retention policies. Due to how our Elasticsearch indexes are stored, Data retention will now also remove elastic search indexes equal to the day of the retention cut-off time. + +### API Changes + - Added a new API endpoint ``POST /api/v4/posts/<post ID>/move``. + - Added ``UpdateChannelMembersNotifications`` plugin API. + - Added plugin APIs and hooks for accessing the **Shared Channels** service via plugins. + - Added a limit to the payload size of API endpoints passing in arrays. + - Added ``PreferencesHaveChanged`` plugin hook. + - Added ``GetPreferenceForUser`` plugin API. + - Added a new API endpoint ``GET /api/v4/users/report`` for system admin user reporting. + - Added a new API endpoint ``GET /api/v4/reports/users/count``. + +### Open Source Components + - Added ``@tanstack/react-table`` and ``prometheus/client_model`` to https://github.com/mattermost/mattermost/. + +### Go Version + - v9.5 is built with Go ``v1.20.7``. + +### Known Issues + - User autocomplete no longer stays closed after pressing ESC key [MM-56748](https://mattermost.atlassian.net/browse/MM-56748). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akbarkz](https://translate.mattermost.com/user/akbarkz), [amyblais](https://github.com/amyblais), [andriuspetrauskis](https://github.com/andriuspetrauskis), [andriuspre](https://github.com/andriuspre), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [azistellar](https://translate.mattermost.com/user/azistellar), [azizthegit](https://github.com/azizthegit), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [c0d33ngr](https://github.com/c0d33ngr), [catenacyber](https://github.com/catenacyber), [cedricongjh](https://github.com/cedricongjh), [Chlbek](https://translate.mattermost.com/user/Chlbek), [chriswachira](https://github.com/chriswachira), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [cripton](https://github.com/cripton), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyberjam](https://github.com/cyberjam), [devinbinnie](https://github.com/devinbinnie), [duttakapil](https://github.com/duttakapil), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [GabrielCasaro](https://github.com/GabrielCasaro), [gabrieljackson](https://github.com/gabrieljackson), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [heisdinesh](https://github.com/heisdinesh), [hmhealey](https://github.com/hmhealey), [hynex](https://translate.mattermost.com/user/hynex), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jespino](https://github.com/jespino), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jones](https://translate.mattermost.com/user/jones), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kerochelo](https://github.com/kerochelo), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matoro](https://github.com/matoro), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://translate.mattermost.com/user/milotype), [mkaraki](https://github.com/mkaraki), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [Nityanand13](https://github.com/Nityanand13), [norma596](https://translate.mattermost.com/user/norma596), [Omar8345](https://github.com/Omar8345), [phoinixgrr](https://github.com/phoinixgrr), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [Rutam21](https://github.com/Rutam21), [RyoKub](https://github.com/RyoKub), [sapnasivakumar](https://github.com/sapnasivakumar), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [ShrootBuck](https://github.com/ShrootBuck), [SkyDusH](https://translate.mattermost.com/user/SkyDusH), [sonichigo](https://github.com/sonichigo), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [TealWater](https://github.com/TealWater), [thinkGeist](https://github.com/thinkGeist), [thomasbrq](https://github.com/thomasbrq), [ThrRip](https://github.com/ThrRip), [titanventura](https://github.com/titanventura), [toninis](https://github.com/toninis), [trangology](https://github.com/trangology), [tsabi](https://translate.mattermost.com/user/tsabi), [Utsav-Ladani](https://github.com/Utsav-Ladani), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [VishalB98](https://github.com/VishalB98), [wiggin77](https://github.com/wiggin77), [Willy-Wakam](https://github.com/Willy-Wakam), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yaz](https://translate.mattermost.com/user/yaz), [yomiadetutu1](https://github.com/yomiadetutu1) + +---- + +(release-v9-4-feature-release)= +## Release v9.4 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.4.5, released 2024-03-26** + - Mattermost v9.4.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.4.5 contains no database or functional changes. +- **9.4.4, released 2024-03-06** + - Mattermost v9.4.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.4.4 contains no database or functional changes. +- **9.4.3, released 2024-02-14** + - Mattermost v9.4.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.4.3 contains no database or functional changes. + - Pre-packaged Jira plugin version [v4.1.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.0). +- **9.4.2, released 2024-01-30** + - Mattermost v9.4.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with true-up reports sending active users and not activated users. Added **Monthly Active Users** (MAU) as part of the true-up reports. + - Mattermost v9.4.2 contains no database or functional changes. +- **9.4.1, released 2024-01-16** + - Fixed an issue where ``getChannelMemberOnly`` failed to fetch data when certain fields were NULL. +- **9.4.0, released 2024-01-16** + - Original 9.4.0 release. + +### Important Upgrade Notes + - MySQL v5.7 is at end of life. We recommend all customers to upgrade to at least 8.x. For now, we are logging a warning. From Mattermost v9.5, which is the next Extended Support Release, we will stop supporting MySQL v5.7 altogether. + +```{Important} +If you upgrade from a release earlier than v9.3, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated the minimum required Edge version to v118+. + +### Improvements + +See [this walkthrough video](https://www.youtube.com/watch?v=bEMp4vYLi6c&feature=youtu.be&ab_channel=Mattermost) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Updated the pre-packaged GitHub plugin version to [v2.1.7](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v2.1.7). + - Pre-packaged Calls plugin version [v0.22.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.22.2). + - Improved the user interface of the channel notifications modal. + - Emojis are now enlarged in emoji tooltips on mouse hover. + - Added a gap of 8px between buttons in the modal footer when opened in the mobile web view. + - Updated empty states to align with new branding and made changes to the empty state copy. + - Adjusted the position of the suggestion list in "Add <user> to a channel" modal to be below or above the text field. + +#### Administration + - Added support for IP Filtering in Cloud (Cloud Enterprise plan) (this feature is disabled by default and behind a feature flag). + - Added support for Bring Your Own Key (BYOK) Encryption (Cloud Enterprise plan). + - An optional dedicated filestore is now used for compliance exports if configured (Cloud Enterprise plan). + - ``MessageExportSettings.GlobalRelaySettings.CustomerType`` now supports "CUSTOM". + - Added new ``ServerMetrics`` hook to allow plugins to register a custom HTTP endpoint to serve their metrics under the server's metrics HTTP listener. + - Admins now have the ability to pipe the output of ``mmctl websocket`` into the JSON parser. + - Added stores for OAuth **Outgoing Connections**. + - Added last login timestamp for users, and added a materialized view and a refresh job to keep track of post stats for PostgreSQL. + - Allowed plugin requests to include **Authorization** headers from external systems. + - Added a mmctl command ``mmctl system supportpacket`` to download the **Support Packet**. + - Added a new mmctl command ``oauth list`` for listing registered OAuth2 applications. + +### Bug Fixes + - Fixed an issue with the emoji reaction toggle behavior. + - Fixed an issue with the spacing between Playbooks and the separator in the Apps bar. + +### config.json + - Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``RefreshPostStatsRunTime`` in ``config.json``: + - Added ``RefreshPostStatsRunTime`` to add last login timestamp for users and to add materialized view and refresh job to keep track of post stats for PostgreSQL. + +#### Changes to the Enterprise plan: + - Under ``GlobalRelayMessageExportSettings`` in ``config.json``: + - Added two new configuration settings ``CustomSMTPServerName`` and ``CustomSMTPPort`` to allow setting a custom URL and port for Global Relay export. This enables compliance export to integrate with Proofpoint. + +### Open Source Components: + - Added ``@mattermost/desktop-api`` and ``ipaddr.js`` to https://github.com/mattermost/mattermost/. + +### Go Version + - v9.4 is built with Go ``v1.20.7``. + +### Known Issues + - Non-channel-admin users can no longer use message links in private channels [MM-56575](https://mattermost.atlassian.net/browse/MM-56575). + - Preview doesn't work when editing a channel header [MM-56572](https://mattermost.atlassian.net/browse/MM-56572). + - The channel member count shows as zero in the **Browse channels** modal [MM-56266](https://mattermost.atlassian.net/browse/MM-56266). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [AayushChaudhary0001](https://github.com/AayushChaudhary0001), [aditipatelpro](https://github.com/aditipatelpro), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akbarkz](https://github.com/akbarkz), [Alpha-4](https://github.com/Alpha-4), [amyblais](https://github.com/amyblais), [andrius](https://translate.mattermost.com/user/andrius), [andriuspetrauskis](https://github.com/andriuspetrauskis), [andrleite](https://github.com/andrleite), [arthurhrg](https://github.com/arthurhrg), [arush-vashishtha](https://github.com/arush-vashishtha), [asaadmahmood](https://github.com/asaadmahmood), [avas27JTG](https://github.com/avas27JTG), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [caotanduc99](https://github.com/caotanduc99), [CI-YU](https://github.com/CI-YU), [codejagaban](https://github.com/codejagaban), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyberjam](https://github.com/cyberjam), [danielsischy](https://github.com/danielsischy), [Dev-A-Line](https://translate.mattermost.com/user/Dev-A-Line), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [dkkb](https://github.com/dkkb), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [fmartingr](https://github.com/fmartingr), [FokinAleksandr](https://github.com/FokinAleksandr), [GabrielCasaro](https://github.com/GabrielCasaro), [gabrieljackson](https://github.com/gabrieljackson), [gabsfrancis](https://translate.mattermost.com/user/gabsfrancis), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [harsh4723](https://github.com/harsh4723), [harshilsharma63](https://github.com/harshilsharma63), [hasancankucuk](https://github.com/hasancankucuk), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://translate.mattermost.com/user/jprusch), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [ludvigbolin](https://github.com/ludvigbolin), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [morgancz](https://github.com/morgancz), [mvitale1989](https://github.com/mvitale1989), [neflyte](https://github.com/neflyte), [nickmisasi](https://github.com/nickmisasi), [Paul-Stern](https://github.com/Paul-Stern), [pgteekens](https://translate.mattermost.com/user/pgteekens), [phoinixgrr](https://github.com/phoinixgrr), [PromoFaux](https://github.com/PromoFaux), [PulkitGarg-code](https://github.com/PulkitGarg-code), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rajatdangat](https://github.com/rajatdangat), [relwell](https://github.com/relwell), [roaslin](https://github.com/roaslin), [rohan-kapse](https://github.com/rohan-kapse), [rohitkbc](https://github.com/rohitkbc), [Rutam21](https://github.com/Rutam21), [RyoKub](https://github.com/RyoKub), [saakshiraut28](https://github.com/saakshiraut28), [San4es](https://github.com/San4es), [sapnasivakumar](https://github.com/sapnasivakumar), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [ShlokJswl](https://github.com/ShlokJswl), [sinansonmez](https://github.com/sinansonmez), [srappan](https://github.com/srappan), [sri-byte](https://github.com/sri-byte), [srisri332](https://github.com/srisri332), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [svelle](https://github.com/svelle), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [tanmaythole](https://github.com/tanmaythole), [TealWater](https://github.com/TealWater), [thomasbrq](https://github.com/thomasbrq), [ThrRip](https://github.com/ThrRip), [toninis](https://github.com/toninis), [tsabi](https://github.com/tsabi), [umrkhn](https://github.com/umrkhn), [varghesejose2020](https://github.com/varghesejose2020), [Vinecreeper888](https://github.com/Vinecreeper888), [weblate](https://github.com/weblate), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) + +---- + +(release-v9-3-feature-release)= +## Release v9.3 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.3.3, released 2024-03-06** + - Mattermost v9.3.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.3.3 contains no database or functional changes. +- **9.3.2, released 2024-02-14** + - Mattermost v9.3.2 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.3.2 contains no database or functional changes. + - Pre-packaged Jira plugin version [v4.1.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.0). +- **9.3.1, released 2024-01-30** + - Mattermost v9.3.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.3.1 contains no database or functional changes. +- **9.3.0, released 2023-12-15** + - Original 9.3.0 release. + +### Important Upgrade Notes + - Please read the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) before upgrading. + +### Compatibility + - Updated minimum required Firefox version to v115+. + - Updated minimum supported Chromium version to 118+. + +### Improvements + +See [this walkthrough video](https://www.youtube.com/watch?v=eXA8emM97Bo) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Updated pre-packaged Playbooks plugin version to [v1.39.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.1). + - Updated pre-packaged Calls version to [v0.21.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.21.1). + - Updated pre-packaged Jira plugin version to [v4.0.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.0.1). Also see [v4.0.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.0.0) for recent breaking changes. + - Added Vietnamese (Beta) as a new language. + - Added the ability to passively track keywords with highlights without triggering a notification (Professional and Enterprise plans). + - Updated the **Settings** modal with an improved user interface. + - Added a new **Jump to recents** banner when a channel is scrolled up. + - Modified the behavior of the code button (Ctrl+Alt+C) to create inline codes or code blocks. + - Disabled markdown keybindings within code blocks. + - Added a **Back** button to the ``/access_problem`` page. + - Added a default limit of the number of reactions per post. + +#### Performance + - Removed pre-fetch preference and set new prefetch limits for the webapp. + - Improved websocket event marshaling performance. + - Batched loading of recently used emojis on initial load. + +#### Administration + - The tooltip on the announcement bar in the **System Console** is now widened. + - Improved the error message when trying to activate a plugin in an unsupported environment. + - Added a file storage permission check to the workspace health dashboard. + - Performed a cleanup in preparation for adding support for multi-word keywords that trigger notification. + - Added a warning log message when the app runs as root. + - Removed all uses of the ``ExperimentalTimezone`` setting. The Timezone feature is now always enabled and no longer behind a configuration setting. + - Added support for previewing WebVTT attachments. + - Introduced separate ``AdvancedLogging`` levels for LDAP messages. + - Introduced trace logging level for LDAP messages. + - Added a new way to modify ``WebSocket`` messages sent to individual connections. + - Added a new server side hook ``MessagesWillBeConsumed`` to allow modifying post objects after they are grabbed from the database but before they are delivered to the client. This is behind a feature flag and disabled by default. + - Users and posts are now pretty-printed in the logs. + - Improved file extraction logging. + - Exposed ``ThreadView`` and ``AdvancedCreateComment`` components in the webapp plugin exported components list. + - Added **Logging > Advanced Logging** setting to the **System Console** to allow admins to configure custom log targets via the user interface. + +### Bug Fixes + - Fixed an issue where marking a Group Message as unread didn't show the badge count correctly. + - Fixed an issue where ``invite_id`` was being reset on all team changes. + - Fixed an issue where interactive dialog elements with subtype ``number`` didn't handle a ``0`` value properly. + - Fixed an issue with the download link in channel file search items when including a path in the **Site URL** setting. + - Fixed an issue with the formatting of special mentions in the right-hand side. + - Fixed ``MessageWillBeUpdated`` plugin hook to allow rejections. + - Fixed an issue with some shortcuts not working as expected. + - Fixed the message history not clearing the input on the center channel. + - Fixed an issue where a higher contrast was generated for some usernames. + - Fixed an issue where newly created Group Messages showed having 0 members. + - Fixed an issue where an incorrect timestamp was assigned to support packet files. + - Fixed an issue where the **Reset Password** link was not displayed if only LDAP/AD was enabled. + - Fixed an issue where **Recent Mentions** showed posts for other similar named users. + - Fixed an error that appeared when updating the header of Group Messages. + - Fixed an issue that caused the server to get stuck during shutdown due to a deadlock in a dependency. + - Fixed an issue where Desktop App clients would be shown an error when trying to open file preview links. + - Fixed an issue with double URL encoding of Oauth redirect URI params. + - Fixed an issue where users couldn't at-mention custom groups in group constrained teams and channels. + - Fixed an issue where the channel admin wasn't being set when converting a Group Message to a private channel. + +### config.json + - Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Removed ``DisplaySettings.ExperimentalTimezone`` setting. + - Under ``ServiceSettings`` in ``config.json``: + - Added ``DefaultUniqueReactionsPerPost`` and ``MaxUniqueReactionsPerPost`` to fix an issue where invalid reactions could be added to posts and to add a default limit for the number of reactions per post. + +### API Changes + - Added an API to batch requests for custom emojis on page load. + +### Database Changes + - ``NextSyncAt`` and ``Description`` columns are removed from the ``SharedChannelsRemotes`` table. Migration impact is considered to be minimal considering the possible table size. + +### Go Version + - v9.3 is built with Go ``v1.20.7``. + +### Known Issues + - Mattermost Omnibus: Unable to install omnibus due to unmet dependencies [MM-56080](https://mattermost.atlassian.net/browse/MM-56080). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [AirGoatOne](https://github.com/AirGoatOne), [akbarkz](https://github.com/akbarkz), [amigo7kr](https://github.com/amigo7kr), [amyblais](https://github.com/amyblais), [anneschuth](https://github.com/anneschuth), [ARJ2160](https://github.com/ARJ2160), [Arslan-work](https://github.com/Arslan-work), [arthurh](https://translate.mattermost.com/user/arthurh), [arthurhrg](https://github.com/arthurhrg), [Aryakoste](https://github.com/Aryakoste), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [avas27JTG](https://github.com/avas27JTG), [AvaterClasher](https://github.com/AvaterClasher), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BandhiyaHardik](https://github.com/BandhiyaHardik), [BenCookie95](https://github.com/BenCookie95), [Benjamin-Loison](https://github.com/Benjamin-Loison), [calebroseland](https://github.com/calebroseland), [catenacyber](https://github.com/catenacyber), [cedarice](https://github.com/cedarice), [CI-YU](https://github.com/CI-YU), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [Davut97](https://github.com/Davut97), [deepakumarvu](https://github.com/deepakumarvu), [devinbinnie](https://github.com/devinbinnie), [Dhoni77](https://github.com/Dhoni77), [DimitriDR](https://translate.mattermost.com/user/DimitriDR), [edwardnguyen225](https://github.com/edwardnguyen225), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [Emil-Carlsson](https://github.com/Emil-Carlsson), [enahum](https://github.com/enahum), [escofresco](https://github.com/escofresco), [fandour](https://translate.mattermost.com/user/fandour), [fazil-syed](https://github.com/fazil-syed), [fmartingr](https://github.com/fmartingr), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshal2030](https://github.com/harshal2030), [harshilsharma63](https://github.com/harshilsharma63), [heisdinesh](https://github.com/heisdinesh), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [imamimam113](https://github.com/imamimam113), [imkrishnasarathi](https://github.com/imkrishnasarathi), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jonathanwiemers](https://github.com/jonathanwiemers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kapdev](https://translate.mattermost.com/user/kapdev), [kayazeren](https://github.com/kayazeren), [Kimbohlovette](https://github.com/Kimbohlovette), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [LeonardJouve](https://github.com/LeonardJouve), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [linkvn](https://github.com/linkvn), [ludvigbolin](https://github.com/ludvigbolin), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [maxtrem271991](https://github.com/maxtrem271991), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mozi47](https://github.com/mozi47), [mvitale1989](https://github.com/mvitale1989), [nathanaelhoun](https://github.com/nathanaelhoun), [newdominic](https://github.com/newdominic), [nickmisasi](https://github.com/nickmisasi), [nosyn](https://github.com/nosyn), [otilor](https://github.com/otilor), [pacop](https://github.com/pacop), [Paul-Stern](https://github.com/Paul-Stern), [Paul-vrn](https://github.com/Paul-vrn), [phoinixgrr](https://github.com/phoinixgrr), [proggga](https://github.com/proggga), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [rahulsuresh-git](https://github.com/rahulsuresh-git), [rashmibharambe](https://github.com/rashmibharambe), [Reene-Simon](https://github.com/Reene-Simon), [rohan-kapse](https://github.com/rohan-kapse), [rohitkbc](https://github.com/rohitkbc), [rubinaga](https://github.com/rubinaga), [RyoKub](https://github.com/RyoKub), [san70sh](https://github.com/san70sh), [sapnasivakumar](https://github.com/sapnasivakumar), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [Sharuru](https://github.com/Sharuru), [shivamjosh](https://github.com/shivamjosh), [sinansonmez](https://github.com/sinansonmez), [Sn-Kinos](https://github.com/Sn-Kinos), [sp6370](https://github.com/sp6370), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [sudheer121](https://github.com/sudheer121), [Syed-Ali-Abbas-Zaidi](https://github.com/Syed-Ali-Abbas-Zaidi), [tanmaythole](https://github.com/tanmaythole), [tejas161](https://github.com/tejas161), [thomasbrq](https://github.com/thomasbrq), [ThrRip](https://github.com/ThrRip), [TomerPacific](https://github.com/TomerPacific), [toninis](https://github.com/toninis), [trivikr](https://github.com/trivikr), [tsabi](https://github.com/tsabi), [turretkeeper](https://github.com/turretkeeper), [umrkhn](https://github.com/umrkhn), [vish9812](https://github.com/vish9812), [wcdfilll](https://translate.mattermost.com/user/wcdfilll), [wiebel](https://github.com/wiebel), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1) + +---- + +(release-v9-2-feature-release)= +## Release v9.2 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.2.6, released 2024-02-14** + - Mattermost v9.2.6 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.2.6 contains no database or functional changes. + - Pre-packaged Jira plugin version [v4.1.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.0). +- **9.2.5, released 2024-01-30** + - Mattermost v9.2.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.2.5 contains no database or functional changes. +- **9.2.4, released 2024-01-09** + - Mattermost v9.2.4 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.2.4 contains the following functional changes: + - Fixed an issue where invalid reactions could be added to posts. Added default limit of the number of reactions per post. +- **9.2.3, released 2023-11-29** + - Mattermost v9.2.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.2.3 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.21.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.21.1). +- **9.2.2, released 2023-11-08** + - Mattermost v9.2.2 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Playbooks plugin version [v1.39.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.1). + - Fixed an issue where the **About Mattermost** dialog reported an incorrect server version. +- **9.2.1, released 2023-11-06** + - Fixed an issue where Ubuntu GLIBC errors were thrown on Ubuntu 20.04 and Debian Bullseye versions. +- **9.2.0, released 2023-11-02** + - Original 9.2.0 release + +### Important Upgrade Notes + - Fixed data retention policies to run jobs when any custom retention policy is enabled even when the global retention policy is set to **keep-forever**. Before this fix, the enabled custom data retention policies wouldn’t run as long as the global data retention policy was set to **keep-forever** or was disabled. After the fix, the custom data retention policies will run automatically even when the global data retention policy is set to **keep-forever**. Once the server is upgraded, posts may unintentionally be deleted. Admins should make sure to disable all custom data retention policies before upgrading, and then re-enable them again after upgrading. + +```{Important} +If you upgrade from a release earlier than v9.1, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated minimum required Edge version to 116+. + +### Improvements + +See [this walkthrough video](https://www.youtube.com/watch?v=udC2OCTGooc&feature=youtu.be&ab_channel=Mattermost) on some of the improvements in our latest release below. + +#### User Interface (UI) + - Improved readability by displaying system messages on multiple lines when editing a channel header. + - Combined "joined/left" event types in system messages. + - Added a new user preference to disable webapp prefetching via **Settings > Advanced > Allow Mattermost to prefetch channel posts**. You must enable **Client Performance Debugging** in the System Console by going to **Environment > Developer** in order for this setting to appear. This setting and Client Performance Debugging should only be enabled temporarily if users are experiencing performance issues. + - Pre-packaged NPS plugin version [v1.3.3](https://github.com/mattermost/mattermost-plugin-nps/releases/tag/v1.3.3). + - Pre-packaged Todo plugin version [v0.7.1](https://github.com/mattermost/mattermost-plugin-todo/releases/tag/v0.7.1). + +#### Administration + - JSON null value cases are now handled correctly by also checking that the pointer is no longer null when unmarshalling to a pointer. + - An annotated logger is now used to capture LDAP and SAML logs. + - Replaced ``github.com/mattermost/gziphandler`` with ``github.com/klauspost/compress/gzhttp``. + - Performance metrics now contain information on if a given request was sent during a page load or a websocket reconnect. + - Elasticsearch aggregation jobs no longer start when a bulk indexing job is currently running. + - Added heap profile, CPU profile, and goroutines profile to the support package. + - Merged WIP i18n locales, but disallowed selecting unsupported locales. + +### Bug Fixes + - Fixed a panic where a simple worker would crash if it failed to get a job. + - Fixed post props on update to properly see channel links. + - Fixed an issue where the API for drafts would return empty drafts. + - Fixed the alignment of the **Help** menu in the global header. + - Fixed a broken link in the **Edit Channel** header modal. + - Fixed an issue that prevented users to be added to channels from the System Console. + - Fixed an issue where the channel member count increased when adding an already present user. + - Fixed an issue where plugin developers were unable to create a ``textarea`` in interactive dialogs. + - Fixed an issue where copy pasting images from Chrome failed. + +### config.json + - Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``LogSettings`` in ``config.json``: + - Added a new configuration setting ``MaxFieldSize`` to add the ability to size-limit log fields during logging. + +### API Changes + - Added ``origin_client`` to the ``mattermost_api_time`` metrics. + +### Go Version + - v9.2 is built with Go ``v1.20.7``. + +### Known Issues + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [aayushborkar14](https://github.com/aayushborkar14), [AayushChaudhary0001](https://github.com/AayushChaudhary0001), [AbhineshJha](https://github.com/AbhineshJha), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akaMrDC](https://github.com/akaMrDC), [akbarkz](https://github.com/akbarkz), [alejdg](https://github.com/alejdg), [Alphanum404](https://github.com/Alphanum404), [amigo7kr](https://translate.mattermost.com/user/amigo7kr), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [andrew-delph](https://github.com/andrew-delph), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [aniketh-varma](https://github.com/aniketh-varma), [anneschuth](https://translate.mattermost.com/user/anneschuth), [apshada](https://github.com/apshada), [ARJ2160](https://github.com/ARJ2160), [ArturBa](https://github.com/ArturBa), [asaadmahmood](https://github.com/asaadmahmood), [AsisRout](https://github.com/AsisRout), [avas27JTG](https://github.com/avas27JTG), [AvaterClasher](https://github.com/AvaterClasher), [ayrotideysarkar](https://github.com/ayrotideysarkar), [ayusht2810](https://github.com/ayusht2810), [balajik](https://github.com/balajik), [Bangik](https://github.com/Bangik), [bartaz](https://translate.mattermost.com/user/bartaz), [BaumiCoder](https://github.com/BaumiCoder), [BenCookie95](https://github.com/BenCookie95), [bishalpal](https://github.com/bishalpal), [calebroseland](https://github.com/calebroseland), [cedarice](https://translate.mattermost.com/user/cedarice), [cescpmantidfly](https://translate.mattermost.com/user/cescpmantidfly), [CI-YU](https://github.com/CI-YU), [Ciggzy1312](https://github.com/Ciggzy1312), [codeEmpress1](https://github.com/codeEmpress1), [coltoneshaw](https://github.com/coltoneshaw), [costa-neto](https://github.com/costa-neto), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danialkeimasi](https://github.com/danialkeimasi), [Delaney](https://github.com/Delaney), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [dhnlr](https://github.com/dhnlr), [dipandhali2021](https://github.com/dipandhali2021), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [escofresco](https://github.com/escofresco), [esethna](https://github.com/esethna), [fazil-syed](https://github.com/fazil-syed), [fmartingr](https://github.com/fmartingr), [frjaraur](https://github.com/frjaraur), [fyfirman](https://github.com/fyfirman), [gabrieljackson](https://github.com/gabrieljackson), [Gauravpadam](https://github.com/Gauravpadam), [gibsonliketheguitar](https://github.com/gibsonliketheguitar), [h1usertest](https://translate.mattermost.com/user/h1usertest), [hanzei](https://github.com/hanzei), [harsh-solanki21](https://github.com/harsh-solanki21), [harshal2030](https://github.com/harshal2030), [harshalkh](https://github.com/harshalkh), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [ifoukarakis](https://github.com/ifoukarakis), [imamimam113](https://translate.mattermost.com/user/imamimam113), [isacikgoz](https://github.com/isacikgoz), [iyampaul](https://github.com/iyampaul), [izruff](https://github.com/izruff), [janlengyel](https://github.com/janlengyel), [jannikbertram](https://github.com/jannikbertram), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jgilliam17](https://github.com/jgilliam17), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [josephjosedev](https://github.com/josephjosedev), [jprusch](https://github.com/jprusch), [js029](https://github.com/js029), [jufab](https://github.com/jufab), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kalvdans](https://github.com/kalvdans), [kayazeren](https://github.com/kayazeren), [komodin](https://github.com/komodin), [Kritik-J](https://github.com/Kritik-J), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [letehaha](https://github.com/letehaha), [libklein](https://github.com/libklein), [lieut-data](https://github.com/lieut-data), [linkvn](https://github.com/linkvn), [ludvigbolin](https://github.com/ludvigbolin), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [ManuMinue](https://github.com/ManuMinue), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [maxtrem271991](https://github.com/maxtrem271991), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://translate.mattermost.com/user/milotype), [mishmanners](https://github.com/mishmanners), [MixeroTN](https://github.com/MixeroTN), [mnj93](https://github.com/mnj93), [mujpao](https://github.com/mujpao), [mustdiechik](https://github.com/mustdiechik), [mvitale1989](https://github.com/mvitale1989), [namanh-asher](https://github.com/namanh-asher), [Navystack](https://github.com/Navystack), [nickmisasi](https://github.com/nickmisasi), [Nico7as](https://translate.mattermost.com/user/Nico7as), [Nityanand13](https://github.com/Nityanand13), [NohaFahmi](https://github.com/NohaFahmi), [otilor](https://github.com/otilor), [Paul-vrn](https://github.com/Paul-vrn), [Peyo6565](https://github.com/Peyo6565), [phoinixgrr](https://github.com/phoinixgrr), [pvev](https://github.com/pvev), [qryptdev](https://github.com/qryptdev), [Quijuletim470](https://translate.mattermost.com/user/Quijuletim470), [returnedinformation](https://github.com/returnedinformation), [riteshmukim](https://github.com/riteshmukim), [rubinaga](https://github.com/rubinaga), [Rutam21](https://github.com/Rutam21), [saideepesh000](https://github.com/saideepesh000), [SaketKaswa20](https://github.com/SaketKaswa20), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [seoyeongeun](https://translate.mattermost.com/user/seoyeongeun), [Sharuru](https://github.com/Sharuru), [sjcode99](https://github.com/sjcode99), [sondrekje](https://github.com/sondrekje), [sonu27](https://github.com/sonu27), [sp6370](https://github.com/sp6370), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [StreakInTheSky](https://github.com/StreakInTheSky), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [sudheer121](https://github.com/sudheer121), [syedzubeen](https://github.com/syedzubeen), [Tahanima](https://github.com/Tahanima),[tanmaythole](https://github.com/tanmaythole), [this-is-tobi](https://github.com/this-is-tobi), [ThrRip](https://github.com/ThrRip), [TomerPacific](https://github.com/TomerPacific), [toninis](https://github.com/toninis), [trilopin](https://github.com/trilopin), [umrkhn](https://github.com/umrkhn), [varghesejose2020](https://github.com/varghesejose2020), [venugopal1234567](https://github.com/venugopal1234567), [vip2441](https://github.com/vip2441), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yesbhautik](https://github.com/yesbhautik), [ylac](https://github.com/ylac), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) + +---- + +(release-v9-1-feature-release)= +## Release v9.1 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **9.1.5, released 2024-01-09** + - Mattermost v9.1.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.1.5 contains the following functional changes: + - Fixed an issue where invalid reactions could be added to posts. Added default limit of the number of reactions per post. +- **9.1.4, released 2023-11-29** + - Mattermost v9.1.4 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.1.4 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.21.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.21.1). +- **9.1.3, released 2023-11-13** + - Mattermost v9.1.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.1.3 contains no database or functional changes. + - Pre-packaged Playbooks plugin version [v1.39.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.1). + - Fixed an issue where the **About Mattermost** dialog reported an incorrect server version. +- **9.1.2, released 2023-11-06** + - Mattermost v9.1.2 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.1.2 contains no database or functional changes. +- **9.1.1, released 2023-10-27** + - Mattermost v9.1.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Focalboard plugin [v7.11.4](https://github.com/mattermost/focalboard/releases/tag/v7.11.4). + - Mattermost v9.1.1 contains the following functional changes: + - Added a new configuration setting ``MaxFieldSize`` to add the ability to size-limit log fields during logging. + - Added a restriction to the mobile Oauth / SAML redirection to match the ``NativeAppSettings.AppCustomURLSchemes`` configuration setting. +- **9.1.0, released 2023-10-16** + - Original 9.1.0 release + +### Important Upgrade Notes + - Improved performance on data retention ``DeleteOrphanedRows`` queries. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for notes on a new migration that was added. Removed feature flag ``DataRetentionConcurrencyEnabled``. Data retention now runs without concurrency in order to avoid any performance degradation. Added a new configuration setting ``DataRetentionSettings.RetentionIdsBatchSize``, which allows admins to to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100. + - Minimum supported Desktop App version is now v5.3. OAuth/SAML flows were modified to include ``desktop_login`` which makes earlier versions incompatible. + +```{Important} +If you upgrade from a release earlier than v9.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated Chromium minimum supported version to 116+. + +### Highlights + +#### Never Miss Group Messages Again + - Group messages (GMs) now behave like direct messages (DMs). [The badge count increases for every new message](https://docs.mattermost.com/collaborate/channel-types.html#group-messages). + +#### Convert Group Messages to Private Channels + - Added the ability to [convert a group message to a private channel](https://docs.mattermost.com/collaborate/convert-group-messages.html). + +See [this walkthrough video](https://www.youtube.com/watch?v=dbHg-63J9dA) on the highlights and some of the below improvements in our latest release. + +### Improvements + +#### User Interface (UI) + - Added a **Cancel** button to the **Delete category** modal. + - Added the ability to resize the channel sidebar and right-hand sidebar. + - Added two new filtering options (show all channel types and show private channels) to the **Browse channels** modal. + - Pre-packaged GitLab plugin version [v1.7.0](https://github.com/mattermost/mattermost-plugin-gitlab/releases/tag/v1.7.0). + - Pre-packaged Calls plugin version [v0.20.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.20.0). + - Pre-packaged Playbooks version [v1.39.0](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.0). + - Added additional reaction options when viewing threads or messages when the sidebar is larger than its minimum width. + - Added a link to [notification documentation](https://docs.mattermost.com/preferences/manage-your-notifications.html) in the **Notification Settings** modal. + - Updated the post textbox measurement code to be more reliable. + - The ``/invite`` slash command now supports custom user groups. + - Re-enabled the remote marketplace functionality, when configured as per ``PluginSettings.EnableRemoteMarketplace`` [documentation](https://docs.mattermost.com/configure/plugins-configuration-settings.html#plugins-enableremotemarketplace). + +#### Administration + - Added ``mattermost-plugin-api`` into the ``mattermost`` GitHub repository. + - Updated the public server module version to v0.0.9. + - Added 2 new URL parameters to ``GET /api/v4/groups``: ``include_archived`` and ``filter_archived``. Added the ability to restore archived groups from the user groups modal. + - Added file storage information to the support package. + - A ``user_id`` is now included in all HTTP logs (debug level) to help determine who is generating unexpected traffic. + - Added new URL parameter to ``GET /api/v4/groups`` and ``GET /api/v4/groups/:group_id``. ``include_member_ids`` will add all the members ``user_ids`` to the group response objects. You can now also add group members to a channel, any members that are not part of the team can be added to the team through this flow and subsequently added the channel. + +#### Plugin Changes + - Added new frontend plugin extension point for the new messages separator bar. + - Added a new plugin extensibility point to add actions to the code blocks. + - Added the plugin hook ``UserHasBeenDeactivated``. + - Added a new server side plugin API method to set the searchable content for file info (``SetFileSearchableContent``). The ``MessageHasBeenPosted`` plugin hook is now executed after the attachments are linked to the post. + +### Bug Fixes + - Fixed keyboard support for the left-hand side channel menu, the left-hand side category menu, and the post dot menu. + - Fixed display name in the ``comment_on`` component. + - Fixed an issue with keyboard support for some menus with submenus. + - Fixed an issue with disappearing punctuation when following a group mention. + - Fixed an issue where compliance export jobs were not able to start after disabling and enabling the compliance export. + - Fixed a potential read after write issue when loading a license. + - Fixed the API to block any changes to direct and group messages names, display name, or purpose. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Removed ``ServiceSettingsDefaultGfycatAPISecret`` and ``ServiceSettingsDefaultGfycatAPIKey`` configuration settings. + - Under ``TeamSettings`` in ``config.json``: + - Added a new config setting ``EnableJoinLeaveMessageByDefault`` that sets the default value for ``UserSetting``, ``ADVANCED_FILTER_JOIN_LEAVE``. + - Under ``DisplaySettings`` in ``config.json``: + - Added a setting ``MaxMarkdownNodes`` to limit the maximum complexity of markdown text on mobile. + + #### Changes to Enterprise plan: + - Under ``DataRetentionSettings`` in ``config.json``: + - Added a new configuration setting ``RetentionIdsBatchSize``, which allows admins to to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100. + +### API Changes + - Added the ``X-Forwarded-For`` request header to the audit stream for all Rest API calls. + - Added API endpoint ``POST /api/v4/user/login/desktop_login``. Modified OAuth/SAML flows to include ``desktop_login`` where applicable. + - Added new API endpoint ``GET`` ``/api/v4/channels/<channel-id>/common_teams`` to fetch list of teams common between members of a group message. + - Added new API endpoint ``POST`` ``/api/v4/channels/<channel-id>/convert_to_channel`` to convert a group message to a private channel. + - Added a new ``MessageHasBeenDeleted`` hook to the plugin API. + - Moved the ``request`` package into the public shared folder. + +### Go Version + - v9.1 is built with Go ``v1.20.7``. + +### Known Issues + - Converting a group message to a channel should show an error "A channel with that name already exists on the same team" for duplicate channel names [MM-54713](https://mattermost.atlassian.net/browse/MM-54713). + - Marking a group message as unread doesn't resurface the numbered notification badge [MM-54778](https://mattermost.atlassian.net/browse/MM-54778). + - Thread/posts jump when switching to and from preview mode [MM-54758](https://mattermost.atlassian.net/browse/MM-54758). + - Desktop UI doesn't show all content when the right-hand side thread is opened [MM-54696](https://mattermost.atlassian.net/browse/MM-54696). + - Left-hand side resize option overrides the **Browse/Create Channel** menu if To-Do plugin is installed [MM-54367](https://mattermost.atlassian.net/browse/MM-54367). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [abhinav700](https://github.com/abhinav700), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [alexdecamillo](https://github.com/alexdecamillo), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [AsisRout](https://github.com/AsisRout), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [cedarice](https://translate.mattermost.com/user/cedarice), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [Crere89](https://translate.mattermost.com/user/Crere89), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [deivisonrpg](https://github.com/deivisonrpg), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fmartingr](https://github.com/fmartingr), [FokinAleksandr](https://github.com/FokinAleksandr), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hibou.sage](https://translate.mattermost.com/user/hibou.sage), [hmhealey](https://github.com/hmhealey), [homerCOD](https://translate.mattermost.com/user/homerCOD), [ialorro](https://github.com/ialorro), [ifoukarakis](https://github.com/ifoukarakis), [intdev32](https://github.com/intdev32), [IronOnet](https://github.com/IronOnet), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [LimJiAn](https://github.com/LimJiAn), [limod](https://github.com/limod), [linkvn](https://github.com/linkvn), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marie0394](https://translate.mattermost.com/user/marie0394), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mickmister](https://github.com/mickmister), [milotype](https://translate.mattermost.com/user/milotype), [MohammedElansary-dev](https://translate.mattermost.com/user/MohammedElansary-dev), [mornaistar](https://github.com/mornaistar), [mt26691](https://translate.mattermost.com/user/mt26691), [mvitale1989](https://github.com/mvitale1989), [Navystack](https://translate.mattermost.com/user/Navystack), [nickmisasi](https://github.com/nickmisasi), [pvev](https://github.com/pvev), [RayYH](https://github.com/RayYH), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [sinansonmez](https://github.com/sinansonmez), [speedhs](https://github.com/speedhs), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [teamzamong](https://github.com/teamzamong), [TheRealJoeFriel](https://github.com/TheRealJoeFriel), [ThrRip](https://github.com/ThrRip), [timmycheng](https://github.com/timmycheng), [toninis](https://github.com/toninis), [varghese.jose](https://github.com/varghesejose2020), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [y4aniv](https://github.com/y4aniv), [yasserfaraazkhan](https://github.com/yasserfaraazkhan) + +---- + +(release-v9-0-major-release)= +## Release v9.0 - [Major Release](https://docs.mattermost.com/upgrade/release-definitions.html#major-release) + +- **9.0.5, released 2023-11-29** + - Mattermost v9.0.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.0.5 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.21.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.21.1). +- **9.0.4, released 2023-11-13** + - Mattermost v9.0.4 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.0.4 contains no database or functional changes. + - Pre-packaged Playbooks plugin version [v1.39.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.1). + - Fixed an issue where the **About Mattermost** dialog reported an incorrect server version. +- **9.0.3, released 2023-11-06** + - Mattermost v9.0.3 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.0.3 contains no database or functional changes. +- **9.0.2, released 2023-10-27** + - Mattermost v9.0.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Focalboard plugin [v7.11.4](https://github.com/mattermost/focalboard/releases/tag/v7.11.4). + - Mattermost v9.0.2 contains the following functional changes: + - Added a new configuration setting ``MaxFieldSize`` to add the ability to size-limit log fields during logging. + - Added a restriction to the mobile Oauth / SAML redirection to match the ``NativeAppSettings.AppCustomURLSchemes`` configuration setting. +- **9.0.1, released 2023-10-06** + - Mattermost v9.0.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v9.0.1 contains no database or functional changes. +- **9.0.0, released 2023-09-15** + - Original 9.0.0 release + +### Important Upgrade Notes + - Removed the deprecated Insights feature. + - Mattermost Boards and various other plugins have transitioned to being fully community supported. See this [forum post](https://forum.mattermost.com/t/upcoming-product-changes-to-boards-and-various-plugins/16669) for more details. + - The ``channel_viewed`` websocket event was changed to ``multiple_channels_viewed``, and is now only triggered for channels that actually have unread messages. + +```{Important} +If you upgrade from a release earlier than v8.1, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Dev/Sec/ChatOps in Strict Security Environments with Jira, Confluence, and Mattermost + - Accelerate mission-critical workflows that keep your team aligned and your data secure on [the Mattermost and Atlassian platforms](https://mattermost.com/atlassian/). + +#### Air-Gapped, Edge-Ready Generative AI with Defense Unicorn's LeapfrogAI + - Deploy and utilize local GenAI models in edge, air-gapped, and zero-trust environments with [LeapfrogAI and Mattermost](https://defenseunicorns.com/leapfrogai). + +#### AI-Accelerated Collaboration + - Mattermost partner Mobius Logic has enhanced the MS Teams Connector for the Microsoft 365 platform by embedding Mattermost directly inside [Microsoft Teams](https://docs.mattermost.com/about/mattermost-for-microsoft-teams.html). + +#### MLOps and Secure Federation with Customer Compliance + - Our partnership with SOS International (SOSi) enables the integration of advanced military-grade federation using XMPP. Read the [exoINSIGHT announcement from Exovera](https://exovera.com/press-release/exovera-unveils-exoinsight/). + +#### Improving Your Organization’s Core Collaboration + - To optimize the core platform experience, we are reinforcing the fundamentals to ensure Mattermost continues being resilient, stable, and best-in-breed for your critical operations. + +### Improvements + +#### User Interface (UI) + - The number of channel members is now shown in the **Browse channels** modal. + - An error is now displayed if a post edit history fails to load. + - Added functionality to bulk mark a whole channel category as read. + - Removed Boards product tour code. + - Replaced Gfycat with Giphy in the gif picker. + - Pre-packaged Calls version v0.19.0. + - Updated Focalboard plugin version to 7.11.3. + - Pre-packaged Playbooks version 1.38.1. + - Upgraded prepackaged Zoom plugin to v1.6.2. + - Upgraded prepackaged Antivirus plugin version to 1.0.0. + +#### Administration + - API examples are now updated to reflect latest Go API conventions, deprecating older code samples. + - Updated the public server module version to v0.0.8. + - Added a ``Post Action`` plugin hook to allow plugins to register new items in the post menu. + - Added a ``Post Editor Action`` plugin hook to allow plugins to register new items in the post editor menu. + - Improved logging on plugin initialization, activation, and removal. + - Removed the deprecated ``ManifestExecutables`` struct. + - Removed the deprecated ``UserAuth.Password`` field. + - [Remote users](https://docs.mattermost.com/onboard/shared-channels.html) are no longer counted as part of the license. + - Improved data retention logs. + - Removed ``/opengraph`` endpoint as it was unused. + - Transitionally prepackaged plugins are now installed to the filestore for continuity when a future release stops prepackaging those plugins. + - Removed the deprecated ``Manifest.RequiredConfig`` field. + - Added a ``NotificationWillBePushed`` plugin hook invoked before the push notification is processed and sent to the notification service. Plugins may modify or reject the push notification. + - Added a `SendPushNotification` plugin api method which allows plugins to send push notifications to a specific user's mobile sessions. + - Disabled ``PluginSettings.EnableRemoteMarketplace`` functionality. + +### Bug Fixes + - Fixed the error returned by ``PUT /api/v4/channels/{channelid}`` when the provided name already existed in the team. + - Fixed an issue where CRLF line endings passed to mmctl commands were not being stripped from commands. + - Fixed an issue where text copied from Microsoft OneNote is pasted as an image. + - Fixed an issue preventing successful activation of trial licenses. + - Fixed an issue where a custom group wouldn't get marked as a mention if it was not part of the webapp's local state. + - Fixed an issue with the in-product marketplace theming. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``ServiceSettings`` in the ``config.json``: + - Added ``GiphySdkKey`` to replace Gfycat with Giphy in the gif picker. + +### Go Version + - v9.0 is built with Go ``v1.19.5``. + +### Open Source Components + - Added ``@giphy/js-fetch-api`` and ``@giphy/react-components`` to https://github.com/mattermost/mattermost/. + - Added ``@react-native/eslint-config``, ``@react-native/metro-config``, and ``@tsconfig/react-native`` to https://github.com/mattermost/mattermost-mobile/. + +### Known Issues + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [abdulsmapara](https://github.com/abdulsmapara), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akaravashkin](https://github.com/akaravashkin), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [angeloskyratzakos](https://github.com/angeloskyratzakos), [apollo13](https://github.com/apollo13), [aqurilla](https://github.com/aqurilla), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [Benjamin-Loison](https://github.com/Benjamin-Loison), [calebroseland](https://github.com/calebroseland), [cdmwebs](https://github.com/cdmwebs), [chumano](https://github.com/chumano), [CI-YU](https://github.com/CI-YU), [Coelho](https://translate.mattermost.com/user/Coelho), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [deivisonrpg](https://github.com/deivisonrpg), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [douglasstasiak](https://github.com/douglasstasiak), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [gabrieljackson](https://github.com/gabrieljackson), [gary-sixgen](https://github.com/gary-sixgen), [Gobbit69](https://translate.mattermost.com/user/Gobbit69), [grubbins](https://github.com/grubbins), [guneshsji](https://github.com/guneshsji), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshal2030](https://github.com/harshal2030), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [hpkhanh1610](https://github.com/hpkhanh1610), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [ivakorin](https://github.com/ivakorin), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [lieut-data](https://github.com/lieut-data), [LimJiAn](https://github.com/LimJiAn), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [mahmoudfarouq](https://github.com/mahmoudfarouq), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://translate.mattermost.com/user/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [MatthewDorner](https://github.com/MatthewDorner), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://translate.mattermost.com/user/milotype), [mvitale1989](https://github.com/mvitale1989), [nickmisasi](https://github.com/nickmisasi), [panoramix360](https://github.com/panoramix360), [Partizann](https://github.com/Partizann), [penghao_chn](https://translate.mattermost.com/user/penghao_chn), [phoinixgrr](https://github.com/phoinixgrr), [pjenicot](https://translate.mattermost.com/user/pjenicot), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [RichardScottOZ](https://github.com/RichardScottOZ), [robinsdm](https://github.com/robinsdm), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [ShrootBuck](https://github.com/ShrootBuck), [sinansonmez](https://github.com/sinansonmez), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [StreakInTheSky](https://github.com/StreakInTheSky), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [tasawar-hussain](https://github.com/tasawar-hussain), [TealWater](https://github.com/TealWater), [thinkGeist](https://github.com/thinkGeist), [ThrRip](https://translate.mattermost.com/user/ThrRip), [timmycheng](https://translate.mattermost.com/user/timmycheng), [toninis](https://github.com/toninis), [tschuyebuhl](https://github.com/tschuyebuhl), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [y4aniv](https://translate.mattermost.com/user/y4aniv), [yash2189](https://github.com/yash2189), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [ZubairImtiaz3](https://github.com/ZubairImtiaz3) + +(release-v8-1-extended-support-release)= +## Release v8.1 - [Extended Support Release](https://docs.mattermost.com/upgrade/release-definitions.html#extended-support-release-esr) + +```{Important} + +- **8.1.13, released 2024-04-25** + - Mattermost v8.1.13 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.13 contains no database or functional changes. + - Pre-packaged Playbooks version [v1.39.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.3). + - Increased the default payload size limit (``MaximumPayloadSizeBytes``) from 100 kB to 300 kB. +- **8.1.12, released 2024-03-26** + - Mattermost v8.1.12 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.12 contains no database or functional changes. +- **8.1.11, released 2024-03-06** + - Mattermost v8.1.11 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.11 contains no database or functional changes. + - Pre-packaged Calls version [v0.23.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.23.1). +- **8.1.10, released 2024-02-14** + - Mattermost v8.1.10 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.10 contains no database or functional changes. + - Pre-packaged Jira plugin version [v4.1.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.1.0). +- **8.1.9, released 2024-01-30** + - Mattermost v8.1.9 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with true-up reports sending active users and not activated users. Added **Monthly Active Users** (MAU) as part of the true-up reports. + - Mattermost v8.1.9 contains no database or functional changes. +- **8.1.8, released 2024-01-09** + - Mattermost v8.1.8 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with double URL encoding of Oauth redirect URI params. + - Pre-packaged Jira plugin version [v4.0.1](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.0.1). Also see [v4.0.0](https://github.com/mattermost/mattermost-plugin-jira/releases/tag/v4.0.0) for recent breaking changes. + - Mattermost v8.1.8 contains the following functional changes: + - Fixed an issue where invalid reactions could be added to posts. Added default limit of the number of reactions per post. +- **8.1.7, released 2023-11-29** + - Mattermost v8.1.7 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.7 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.21.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.21.1). + - Fixed an issue where users couldn't at-mention custom groups in group constrained teams and channels. +- **8.1.6, released 2023-11-13** + - Mattermost v8.1.6 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.6 contains no database or functional changes. + - Pre-packaged Playbooks plugin version [v1.39.1](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.39.1). + - Pre-packaged ToDo plugin version [v0.7.1](https://github.com/mattermost/mattermost-plugin-todo/releases/tag/v0.7.1). + - Fixed an issue where the **About Mattermost** dialog reported an incorrect server version. +- **8.1.5, released 2023-11-06** + - Mattermost v8.1.5 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.5 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.20.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.20.0). + - Fixed an issue where **Recent Mentions** showed posts for other similar named users. +- **8.1.4, released 2023-10-27** + - Mattermost v8.1.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Focalboard plugin [v7.11.4](https://github.com/mattermost/focalboard/releases/tag/v7.11.4). + - Fixed an issue where plugin developers were unable to create a ``textarea`` in interactive dialogs. + - Fixed an issue where copy pasting images from Chrome failed. + - Mattermost v8.1.4 contains the following functional changes: + - Added a new configuration setting ``MaxFieldSize`` to add the ability to size-limit log fields during logging. + - Added a restriction to the mobile Oauth / SAML redirection to match the ``NativeAppSettings.AppCustomURLSchemes`` configuration setting. + - When ``ServiceSettings.ExperimentalEnableHardenedMode`` is enabled, standard users authenticated via username and password will not be able to use post props reserved for integrations, such as ``override_username`` or ``override_icon_url``. +- **8.1.3, released 2023-10-06** + - Mattermost v8.1.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.3 contains no database or functional changes. + - Fixed a potential read after write issue when loading license. + - Prepackaged Calls plugin version [v0.18.2](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.18.2). + - Fixed a panic where a simple worker would crash if it failed to get a job. +- **8.1.2, released 2023-09-08** + - Mattermost v8.1.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.2 contains the following database changes: + - Improved performance on data retention ``DeleteOrphanedRows`` queries. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for notes on a new migration that was added. Removed feature flag ``DataRetentionConcurrencyEnabled``. Data retention now runs without concurrency in order to avoid any performance degradation. Added a new configuration setting ``DataRetentionSettings.RetentionIdsBatchSize``, which allows admins to to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100. +- **8.1.1, released 2023-09-01** + - Mattermost v8.1.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.1.1 contains no database or functional changes. + - Fixed an issue preventing successful activation of trial licenses. + - Fixed several issues with loading of licenses. + - Fixed an issue where text copied from Microsoft OneNote pasted it as an image. + - Replaced Gfycat with Giphy in the gif picker. + - Fixed an issue where compliance export jobs were not able to start after disabling and enabling the compliance export. +- **8.1.0, released 2023-08-24** + - Original 8.1.0 release + +### Improvements + +#### User Interface (UI) + - Updated the user interface for the **Browse channels** modal. + - Increased the nickname field in the user interface from 22 to 64 characters. + - Updated links to documentation in the **System Console**. + - Emoji size is now in scale with the text size in the channel header. + - The emoji picker view modal is now displayed on mobile browsers. + - Prepackaged v1.2.2 of the Apps plugin. + - Prepackaged Focalboard plugin version 7.11.2. + - Prepackaged Playbooks version 1.38.0. + - Prepackaged Calls plugin version 0.18.0. + +#### Administration + - Added support for a separate Export storage and S3 presigned URLs generation for downloading the export files. + - Using ``https://github.com/reduxjs/redux-devtools`` in production builds is now allowed for webapp. + - Added a new feature flag, ``DataRetentionConcurrencyEnabled``, to enable/disable concurrency for data retention batch deletion. Also added a new configuration setting ``DataRetentionSettings.TimeBetweenBatchesMilliseconds`` to control the sleep time between batch deletions. + - Added a setting under **System Console > Authentication > Guest Access > Show Guest Tag** to remove the **Guest** badges from within the product. +- Added Apache 2.0 license to the public submodule, explicitly signalling to [pkg.go.dev](https://pkg.go.dev/github.com/mattermost/mattermost/server/public@v0.0.6) the license in play for this source code. + - Added the ability for admins to hide or customize the **Forgot password** link on the login page. + - The ``mattermost database reset`` command no longer starts the application server. It will only start the store layer and truncate the tables excluding the migrations table. + +### Bug Fixes + - Fixed an issue where scrollbars were not visible enough on the **File Preview** screen. + - Fixed an issue where SAML Admin Attribute only compared the first value instead of looping through the assertion values array. + - Fixed an issue where updates to recent emojis were not batched when multiple emojis were posted at once. + - Reverted a change that could cause the webapp to forget the current user's authentication method. + - Fixed an issue where drafts would persist after sending an ``@here`` mention in the right-hand side. + - Fixed an issue where the **New messages** toast appeared on channels that were completely visible. + - Fixed an UI issue related to profile popover on channel member search in the right hand pane. + - Fixed an issue where the multi-line channel header preview was too narrow on mobile web view. + - Fixed the render of the **Add Slash Command** page in the backstage area. + - Fixed an issue where user's timezone affected the date selection in the calendar. + - Fixed the clickable area of post textboxes being too small. + - Fixed an UI bug in the bot profile popover. + - Fixed an issue with missing time zone metadata in the Docker container. + - Fixed an issue with the ``registerMessageWillBeUpdatedHook`` plugin hook. + - Fixed an issue where the **Saved Posts** section would not show channel and team names. + - Fixed accessibility issues: tab support at login, reset and signup pages, and controls at the Apps bar. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Under ``PasswordSettings`` in ``config.json``: + - Added ``EnableForgotLink`` to add the ability for admins to hide or customize the **Forgot password** link on the login page. + - Under ``FileSettings`` + - Added various export store settings to add support for a new Export storage. + +#### Changes to Professional and Enterprise plans: + - Under ``GuestAccountsSettings`` in ``config.json``: + - Added ``HideTags`` to add the ability to remove the **Guest** badges from within the product. + +#### Changes to Enterprise plan: + - ``DataRetentionSettings`` in ``config.json``: + - Added ``TimeBetweenBatchesMilliseconds`` setting to control the sleep time between batch deletions. + +### Go Version + - v8.1 is built with Go ``v1.19.5``. + +### Known Issues + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [3kami3](https://github.com/3kami3), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akaMrDC](https://github.com/akaMrDC), [Alanchen](https://translate.mattermost.com/user/Alanchen), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [austin-denoble](https://github.com/austin-denoble), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [azistellar](https://translate.mattermost.com/user/azistellar), [bartoszpijet](https://github.com/bartoszpijet), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [BodhiHu](https://github.com/BodhiHu), [CI-YU](https://translate.mattermost.com/user/CI-YU), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielcw-fortuna](https://github.com/danielcw-fortuna), [devinbinnie](https://github.com/devinbinnie), [dirosv-eden](https://translate.mattermost.com/user/dirosv-eden), [dsharma522](https://github.com/dsharma522), [EduardoSellanes](https://github.com/EduardoSellanes), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [esarafianou](https://github.com/esarafianou), [esethna](https://github.com/esethna), [fmartingr](https://github.com/fmartingr), [gabrieljackson](https://github.com/gabrieljackson), [guuw](https://translate.mattermost.com/user/guuw), [hanh.h.pham](https://translate.mattermost.com/user/hanh.h.pham), [harshal2030](https://github.com/harshal2030), [harshilsharma63](https://github.com/harshilsharma63), [hchorfispiria](https://github.com/hchorfispiria), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [janostgren](https://github.com/janostgren), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jlandells](https://github.com/jlandells), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [kaakaa](https://github.com/kaakaa), [karan2704](https://github.com/karan2704), [kayazeren](https://github.com/kayazeren), [komoon8934](https://github.com/komoon8934), [krmh04](https://github.com/krmh04), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [LeonardJouve](https://github.com/LeonardJouve), [lieut-data](https://github.com/lieut-data), [linkvn](https://github.com/linkvn), [loganrosen](https://github.com/loganrosen), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [mahaker](https://github.com/mahaker), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matinzd](https://github.com/matinzd), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [mkdbns](https://github.com/mkdbns), [morgancz](https://github.com/morgancz), [mustdiechik](https://github.com/mustdiechik), [mvitale1989](https://github.com/mvitale1989), [namanh-asher](https://github.com/namanh-asher), [nickmisasi](https://github.com/nickmisasi), [notlelouch](https://github.com/notlelouch), [orta-contrib](https://github.com/orta-contrib), [panoramix360](https://github.com/panoramix360), [PedroHmaker](https://github.com/PedroHmaker), [phoinix-mm-test](https://github.com/phoinix-mm-test), [phoinixgrr](https://github.com/phoinixgrr), [pjenicot](https://github.com/pjenicot), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [qryptdev](https://github.com/qryptdev), [ridwankabeer435](https://github.com/ridwankabeer435), [roadt](https://github.com/roadt), [saideepesh000](https://github.com/saideepesh000), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [ShrootBuck](https://github.com/ShrootBuck), [sinansonmez](https://github.com/sinansonmez), [sonichigo](https://github.com/sonichigo), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [thefourcraft](https://github.com/thefourcraft), [thinkGeist](https://github.com/thinkGeist), [ThrRip](https://github.com/ThrRip), [timmycheng](https://github.com/timmycheng), [toninis](https://github.com/toninis), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [veronicadip](https://github.com/veronicadip), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yigitcan-prospr](https://github.com/yigitcan-prospr), [yomiadetutu1](https://github.com/yomiadetutu1) + +---- + +(release-v8-0-major-release)= +## Release v8.0 - [Major Release](https://docs.mattermost.com/upgrade/release-definitions.html#major-release) + +```{Important} +Support for Mattermost Server v8.0 [Major Release](https://docs.mattermost.com/about/release-policy.html#release-types) has come to the end of its life cycle on October 15, 2023. [Upgrading Mattermost Server](https://docs.mattermost.com/about/mattermost-server-releases.html#latest-releases) is required. +``` + +- **8.0.4, released 2023-10-06** + - Mattermost v8.0.4 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.0.4 contains no database or functional changes. + - Prepackaged Calls plugin version [v0.17.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.17.1). +- **v8.0.3, released 2023-09-08** + - Mattermost v8.0.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.0.3 contains no database or functional changes. +- **v8.0.2, released 2023-09-01** + - Mattermost v8.0.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.0.2 contains no database or functional changes. + - Fixed an issue with missing time zone metadata in the Docker container. + - Fixed an issue preventing successful activation of trial licenses. + - Replaced Gfycat with Giphy in the gif picker. +- **v8.0.1, released 2023-07-26** + - Mattermost v8.0.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v8.0.1 contains no database or functional changes. + - Added support for embedding Mattermost in a Microsoft Teams iframe. + - Fixed an issue where the v8.0.0 **About Mattermost** dialog reported an incorrect server version in the Free Plan [MM-53681](https://mattermost.atlassian.net/browse/MM-53681). + - Prepackaged Focalboard plugin version 7.11.2. +- **8.0.0, released 2023-07-14** + - Original 8.0.0 release + +### Important Upgrade Notes + + - Insights has been deprecated for all new instances and for existing servers that upgrade to v8.0. See more details in [this forum post](https://forum.mattermost.com/t/proposal-to-revise-our-insights-feature-due-to-known-performance-issues/16212) on why Insights has been deprecated. + - The Focalboard plugin is now disabled by default for all new instances and can be enabled in the **System Console > Plugin settings**. + - The Channel Export and Apps plugins are now disabled by default. + - Apps Bar is now enabled by default for on-prem servers. ``ExperimentalSettings.EnableAppBar`` was also renamed to ``ExperimentalSettings.DisableAppBar``. See more details at: + - https://docs.mattermost.com/configure/experimental-configuration-settings.html#disable-app-bar + - https://forum.mattermost.com/t/channel-header-plugin-changes/13551 + - Introduced the [public](https://github.com/mattermost/mattermost/tree/master/server/public) submodule, housing the familiar `model` and `plugin` packages, but now discretely versioned from the server. It is no longer necessary to `go get` a particular commit hash, as Go programs and plugins can now opt-in to importing `github.com/mattermost/mattermost-server/server/public` and managing versions idiomatically. While this submodule has not yet shipped a v1 and will introduce breaking changes before stabilizing the API, it remains both forwards and backwards compatible with the Mattermost server itself. + - In the main `server package`, the Go module path has changed from ``github.com/mattermost/mattermost-server/server/v8`` to ``github.com/mattermost/mattermost/server/v8``. But with the introduction of the `public` submodule, it should no longer be necessary for third-party code to import this `server` package. + - As part of the `public` submodule above, a ``context.Context`` is now passed to ``model.Client4`` methods. + - Removed support for PostgreSQL v10. The new minimum PostgreSQL version is now v11. + - The Mattermost public API for Go is now available as a distinctly versioned package. Instead of pinning a particular commit hash, use idiomatic Go to add this package as a dependency: go get ``github.com/mattermost/mattermost-server/server/public``. This relocated Go API maintains backwards compatibility with Mattermost v7. Furthermore, the existing Go API previously at github.com/mattermost/mattermost-server/v6/model remains forward compatible with Mattermost v8, but may not contain newer features. Plugins do not need to be recompiled, but developers may opt in to using the new package to simplify their build process. The new public package is shipping alongside Mattermost v8 as version 0.5.0 to allow for some additional code refactoring before releasing as v1 later this year. + - Three configuration fields have been added, ``LogSettings.AdvancedLoggingJSON``, ``ExperimentalAuditSettings.AdvancedLoggingJSON``, and ``NotificationLogSettings.AdvancedLoggingJSON`` which support multi-line JSON, escaped JSON as a string, or a filename that points to a file containing JSON. The ``AdvancedLoggingConfig`` fields have been deprecated. + - The Go MySQL driver has changed the ``maxAllowedPacket`` size from 4MiB to 64MiB. This is to make it consistent with the change in the server side default value from MySQL 5.7 to MySQL 8.0. If your ``max_allowed_packet`` setting is not 64MiB, then please update the MySQL config DSN with an additional param of ``maxAllowedPacket`` to match with the server side value. Alternatively, a value of 0 can be set to to automatically fetch the server side value, on every new connection, which has a performance overhead. + - Removed ``ExperimentalSettings.PatchPluginsReactDOM``. If this setting was previously enabled, confirm that: + + 1. All Mattermost-supported plugins are updated to the latest versions. + 2. Any other plugins have been updated to support React 17. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for v7.7 for more information. + + - Removed deprecated ``PermissionUseSlashCommands``. + - Removed deprecated ``model.CommandArgs.Session``. + - Pass a ``context.Context`` to Client4 methods. + - For servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the ``ServiceSettings.AllowCorsFrom`` [configuration setting](https://docs.mattermost.com/configure/integrations-configuration-settings.html#enable-cross-origin-requests-from). Also ensure that the ``siteURL`` is set correctly. + - In v8.0, the following repositories are merged into one: ``mattermost-server``, ``mattermost-webapp`` and ``mmctl``. Developers should read the updated [Developer Guide](https://developers.mattermost.com/contribute/developer-setup/) for details. + - Fixed an issue caused by a migration in the previous release. Query takes around 11ms on a PostgreSQL 14 DB t3.medium RDS instance. Locks on the preferences table will only be acquired if there are rows to delete, but the time taken is negligible. + - Fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in PostgreSQL: Execution time: 58.11 sec, DELETE 2766690. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). + - The file info stats query is now optimized by denormalizing the ``channelID`` column into the table itself. This will speed up the query to get the file count for a channel when selecting the right-hand pane. Migration times: + + - On a PostgreSQL 12.14 DB with 1731 rows in FileInfo and 11M posts, it took around 0.27s + - On a MySQL 8.0.31 DB with 1405 rows in FileInfo and 11M posts, it took around 0.3s + +```{Important} +If you upgrade from a release earlier than v7.10, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Private cloud LLMs, Azure AI, and OpenAI integrations + - Mattermost provides an OpenOps framework to integrate with private cloud LLMs, Azure AI, and OpenAI models to embed generative AI assistance in collaborative workflows and automation. [Learn more about OpenOps here](https://github.com/mattermost/openops). + +#### Mattermost for Microsoft Teams + - We’re extending our integration with the Microsoft 365 platform with a new embedded experience directly inside Microsoft Teams, as well as our updated MS Teams Connector. + +#### Mattermost for Atlassian Suite + - Uplevel your workflows within Mattermost using your Atlassian toolset. [Learn more about Mattermost for Atlassian Suite here](https://mattermost.com/atlassian/). + +#### Performance and efficiency with PostgreSQL + - To simplify management and scalability challenges, Mattermost 8.0 recommends deploying PostgreSQL over MySQL. + +#### New End User Training + - We’re introducing [9 new training modules](https://academy.mattermost.com/p/mattermost-end-user-onboarding) dedicated to educating users on the key components of the Mattermost platform and an additional [10 new use case modules](https://academy.mattermost.com/courses/category/use-case-training) tackling technical scenarios within DevOps, Security Ops, and Incident Management. + +### Improvements + +#### User Interface (UI) + - Persistent notifications (Professional and Enterprise Plans) allow users to notify recipients repeatedly until action is taken on an urgent message. Check out [our documentation](https://docs.mattermost.com/channels/message-priority.html#send-persistent-notifications) for more details. + - The apps bar is now enabled by default for on-prem servers. ``ExperimentalSettings.EnableAppBar`` was also renamed to ``ExperimentalSettings.DisableAppBar``. See more details at: + - https://docs.mattermost.com/configure/experimental-configuration-settings.html#disable-app-bar + - https://forum.mattermost.com/t/channel-header-plugin-changes/13551 + - Added a **Mattermost Marketplace** option to the bottom of the apps bar. The option is visible when the Marketplace is enabled, and the user has ``SYSCONSOLE_WRITE_PLUGINS`` permissions. + - Calls v0.17.0 introduces a new ringing feature (Beta): Calls in Direct and Group Message channels will ring and pop up a visual notification for the incoming call. Check out the Calls v0.17.0 release notes and [Calls documentation](https://docs.mattermost.com/channels/make-calls.html) for more details. + - Added an **Add channels** button to the bottom of the left-hand sidebar to make the action more obvious for users who want to create or join channels. + - Removed the Webapp Build Hash from **Main Menu > About Mattermost** since it is now identical to Server Build Hash. + - Replaced the ``compass-components`` icon component with ``compass-icons``. + - Added **hours ahead** timezone details to the user profile popover. + - Added an experimental feature to disable re-fetching of channel and channel members on browser focus. + - Bot users are now hidden in the user selector in apps forms. + - Removed the fetching of archived channels on page load. + - The **Channel Type** dropdown within the **Browse Channels** modal can now be focused. + - Removed in-app help pages that were no longer accessible. + - Removed system join/leave messages from thread replies and post them instead in the main channel. + - Added [an experimental setting](https://docs.mattermost.com/configure/experimental-configuration-settings.html#delay-channel-autocomplete) to make the channel autocomplete only appear after typing two characters instead of immediately after the tilde (~). + - Default user profile pictures will now regenerate a new picture when the username changes. + - Implemented URL auto generation on channel creation for when there's no URL-safe characters on its name. + - Added a new option to auto-follow all threads in the channel **Notification Preference** settings. + - ``CTRL/CMD + K`` shortcut can now be used to insert link formatting when text is selected. + - ``pas`` and ``pascal`` code blocks are now higlighted. + - Removed websocket state effects for the collapse/expand state of categories. + - Pre-packaged Jira plugin version 3.2.5. + - Pre-packaged GitHub plugin version 2.1.6. + - Pre-packaged Autolink plugin version 1.4.0. + - Pre-packaged Welcomebot plugin version 1.3.0. + - Pre-packaged NPS plugin version 1.3.2. + - Prepackaged Focalboard plugin version 7.11.0. + - Prepackaged Playbooks plugin version 1.37.0. + - Added support to specify different desktop notification sounds per channel. + - Calls: Ringing sounds can be enabled/disabled and selected in the **Desktop Notifications** preferences panel. + +#### Administration + - Added a new ``ConfigurationWillBeSaved`` plugin hook which is invoked before the configuration object is committed to the backing store. + - Admins can now specify index names to ignore while purging indexes from Elasticsearch with the ``ElasticsearchSettings.IgnoredPurgeIndexes`` setting. + - Added an option to use the German HPNS notification proxy. + - New flags were added to the [database migrate command](https://docs.mattermost.com/manage/command-line-tools.html#mattermost-db-migrate) as following: + + - ``auto-recover``: If the migration plan receives an error during migrations, this command will try to rollback migrations already applied within the plan. This option is not recommended to be added without reviewing migration plan. You can review the plan by combining ``--save-plan`` and ``--dry-run`` flags. + - ``save-plan``: The plan for the migration will be saved into the file store so that it can be used for reviewing the plan or to be used for downgrading. + - ``dry-run``: Does not apply the migrations, but it validates how the migration would run with the given conditions. + + - A new [database subcommand](https://docs.mattermost.com/manage/command-line-tools.html#mattermost-db-downgrade) "downgrade" was added to be able to rollback database migrations. The command either requires an update plan to rollback, or comma separated version numbers. + - Removed ``/api/v4/users/stats`` network request from ``InviteMembersButton``. + - Self-hosted admins can now define a separate shipping address during in-product license purchase. + - Added updates to the trial request forms to allow for a more tailored trial experience. + - First admins will now have an onboarding experience that includes first team creation based on company name and invite members link steps. + - Adds the ability to expand seats in-product for self-hosted servers. + - Added the ability to search a partial first name, last name, nickname, or username on the **System Console > Users** page. + - **Contact Support** now redirects users to Zendesk and pre-fills known information. + - Added a mechanism for public routes on products and used it to support publicly shared Board links. + - The database section in the **System Console** now has an additional read-only section which shows the active search backend in use. This can be helpful to confirm which search engine is currently active when there are multiple configured. + - Updated Docker Base Image from Debian to Ubuntu 22.04 LTS. + - Type-generated settings will now be generated (only for future generations) with a URL-safe version of base64 encoding. + - Mattermost is now resilient against database replica outages and will dynamically choose a replica if it's alive. Also a config parameter ``ReplicaMonitorIntervalSeconds`` was added and the default value is 5. This controls how frequently unhealthy replicas will be monitored for liveness check. + +#### Performance + - Improved the performance of webapp related to timezone calculations. + - Improved performance of code used for post list screen reader support. + +### API Changes + - An underscore is now used in the timeline API (``event-id`` -> ``event_id``) for consistency with other API arguments. + +### Bug Fixes + - Fixed a scrolling issue in the purchase modals. + - Fixed an issue where the experimental Shared Channels feature failed to synchronize if a previously removed table column was still present. + - Fixed an issue where clicking on a channel link (for a channel the user was not a part of) caused the webapp to refresh, dropping the user from a call. + - Fixed an issue with PDF preview rendering for certain Japanese characters. + - Fixed an issue where the screen reader did not announce the action of copying the link in the invite modal. + - Fixed an issue with post metadata not generating correctly for images due to missing content-type in response. This would result in certain embedded images not to display on mobile clients. + - Fixed an issue where edits to messages persisted after canceling. + - Added a condition for bot tags for webhook posts when a bot account is used for webhooks. + - Fixed the sorting value of categories in ``CreateSidebarCategoryForTeamForUser``. + - Fixed a potential crash when opening the user profile popover. + - Fixed permalink and thread reply navigation between teams. + - Fixed an issue with the installation of pre-packaged plugins that are not in the Marketplace. + - Fixed an issue caused by a migration in a previous release. The query takes around 11ms on a PostgreSQL 14 DB t3.medium RDS instance. Locks on the preferences table will only be acquired if there are rows to delete, but the time taken is negligible. + - Fixed an issue where modals did not close when clicking below them on certain screen sizes. + - Fixed an issue with a few translation labels that couldn't be translated. + - Fixed an issue where the server log UI for plain text formatting was unexpectedly removed in a previous release. + - Fixed an issue where combined system messages did not display in chronological order. + - Fixed an issue where the current user and status were not updated on WebSocket reconnect. + - Fixed an issue where certain hashtags were not searchable when using database search. + - Fixed the **New Messages** line overlapping date lines in the post list. + - Fixed an issue where post reactions disappeared when the search sidebar was open. + - Fixed an issue with broken "medical_symbol", "male_sign", and "female_sign" emojis. + - Fixed a panic where a JSON null value was passed as a channel update. + - Fixed an issue where the draft counter badge remained in cases where a deleted parent post was removed. + - Fixed an issue where posts were not fully sanitized for audit output when a link preview was included. + - Fixed an issue where the footer with **Save/Cancel** buttons did not get anchored properly in the System Console. + - Fixed an issue where the undo history was erased when links, tables, or code was pasted into the textbox. + - Fixed an issue where Elasticsearch didn't properly start on startup when enabled. Also added a missing ``IsEnabled`` method to Elasticsearch. + - Fixed an issue where text couldn't be copied from the post textbox. + - Fixed an issue where using **SHIFT+TAB** with a screen reader placed the cursor focus at the bottom of the channel rather than at the post that was linked to. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to all plans: + - Removed ``EnableInactivityEmail`` config setting. + - Added a new config setting section ``ProductSettings``. + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``DelayChannelAutocomplete``, to make the channel autocomplete only appear after typing a couple letters instead of immediately after a tilde. + - Added ``DisableRefetchingOnBrowserFocus``, to disable re-fetching of channel and channel members on browser focus. + - Added ``DisableAppBar`` to enable apps bar by default. + - Three configuration fields have been added, ``LogSettings.AdvancedLoggingJSON``, ``ExperimentalAuditSettings.AdvancedLoggingJSON``, and ``NotificationLogSettings.AdvancedLoggingJSON`` which support multi-line JSON, escaped JSON as a string, or a filename that points to a file containing JSON. The ``AdvancedLoggingConfig`` fields have been deprecated. + +#### Changes to Professional and Enterprise plans: + - Under ``ServiceSettings`` in ``config.json``: + - Added new configuration settings ``AllowPersistentNotifications``, ``PersistentNotificationIntervalMinutes``, ``PersistentNotificationMaxCount``, ``PersistentNotificationMaxRecipients``, to add a persistent notification option when sending urgent priority posts. + +#### Changes to Enterprise plan: + - Under ``ElasticsearchSettings`` in ``config.json``: + - Now you can specify index names to ignore while purging indexes from Elasticsearch with the ``IgnoredPurgeIndexes`` setting. + +### Go Version + - v8.0 is built with Go ``v1.19.5``. + +### Open Source Components: + - Added ``date-fns`` to https://github.com/mattermost/mattermost/. + +### Known Issues + - White screen might appear when creating a slash command [MM-53665](https://mattermost.atlassian.net/browse/MM-53665). + - When sending a draft message in a Thread, the message is not cleared if the thread is open in the right-hand side [MM-53520](https://mattermost.atlassian.net/browse/MM-53520). + - Channel and team names are missing from **Saved Posts** in the right-hand side [MM-53636](https://mattermost.atlassian.net/browse/MM-53636). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akaMrDC](https://translate.mattermost.com/user/akaMrDC), [akaravashkin](https://github.com/akaravashkin), [amyblais](https://github.com/amyblais), [andriusbal](https://github.com/andriusbal), [andrleite](https://github.com/andrleite), [aqurilla](https://github.com/aqurilla), [asaadmahmood](https://github.com/asaadmahmood), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [chumano](https://translate.mattermost.com/user/chumano), [CI-YU](https://translate.mattermost.com/user/CI-YU), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [creeper-0910](https://translate.mattermost.com/user/creeper-0910), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [diciwall](https://translate.mattermost.com/user/diciwall), [DieAkuteSense](https://github.com/DieAkuteSense), [dirosv-eden](https://github.com/dirosv-eden), [Ele7o](https://translate.mattermost.com/user/Ele7o), [Eleferen](https://translate.mattermost.com/user/Eleferen), [enahum](https://github.com/enahum), [Esterjudith](https://github.com/Esterjudith), [fmartingr](https://github.com/fmartingr), [fnogcps](https://github.com/fnogcps), [gabrieljackson](https://github.com/gabrieljackson), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ifoukarakis](https://github.com/ifoukarakis), [ilies-bel](https://github.com/ilies-bel), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [ivalkshfoeif](https://github.com/ivalkshfoeif), [iyampaul](https://github.com/iyampaul), [janostgren](https://github.com/janostgren), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [jupenur](https://github.com/jupenur), [kaakaa](https://translate.mattermost.com/user/kaakaa), [karan2704](https://github.com/karan2704), [kayazeren](https://github.com/kayazeren), [kostaspt](https://github.com/kostaspt), [krmh04](https://github.com/krmh04), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [leonambeez](https://github.com/leonambeez), [LeonardJouve](https://github.com/LeonardJouve), [lieut-data](https://github.com/lieut-data), [lmedoshvili](https://translate.mattermost.com/user/lmedoshvili), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [mahaker](https://github.com/mahaker), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [MattSilvaa](https://github.com/MattSilvaa), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [morgancz](https://github.com/morgancz), [muratbayan](https://translate.mattermost.com/user/muratbayan), [mvitale1989](https://github.com/mvitale1989), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://translate.mattermost.com/user/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nihaldivyam](https://github.com/nihaldivyam), [pablo-suazo](https://github.com/pablo-suazo), [panklobouk](https://translate.mattermost.com/user/panklobouk), [Partizann](https://github.com/Partizann), [phoinix-mm-test](https://github.com/phoinix-mm-test), [phoinixgrr](https://github.com/phoinixgrr), [pjenicot](https://translate.mattermost.com/user/pjenicot), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [ridwankabeer435](https://github.com/ridwankabeer435), [rOt779kVceSgL](https://translate.mattermost.com/user/rOt779kVceSgL), [RoyI99](https://github.com/RoyI99), [saideepesh000](https://github.com/saideepesh000), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shivamjosh](https://github.com/shivamjosh), [sinansonmez](https://github.com/sinansonmez), [SkyLuke91](https://translate.mattermost.com/user/SkyLuke91), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [tejaskarelia17](https://github.com/tejaskarelia17), [tfromont](https://translate.mattermost.com/user/tfromont), [ThrRip](https://translate.mattermost.com/user/ThrRip), [timmycheng](https://github.com/timmycheng), [toninis](https://github.com/toninis), [tsabi](https://translate.mattermost.com/user/tsabi), [ujwalkumar1995](https://github.com/ujwalkumar1995), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1), [zhsj](https://github.com/zhsj) + +---- + +## Release v7.11 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + + - The Mattermost v7.11 release has been canceled as we are working on architectural changes for the Mattermost platform. The next scheduled release is v8.0 this summer. + +(release-v7-10-feature-release)= +## Release v7.10 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.10.5, released 2023-07-26** + - Mattermost v7.10.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.10.5 contains no database or functional changes. + - Fixed an issue where line breaks were introduced when pasting hyperlinks in the chat. + - Prepackaged Focalboard plugin version 7.10.5. +- **v7.10.4, released 2023-07-12** + - Mattermost v7.10.4 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.10.4 contains no database or functional changes. + - Fixed an issue where posts were not fully sanitized for audit output when a link preview was included. + - Updated prepackaged Playbooks plugin version to 1.36.2. +- **v7.10.3, released 2023-06-15** + - Mattermost v7.10.3 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Updated prepackaged Boards to v7.10.4. + - Included prepackaged Welcomebot plugin v1.3.0. + - For servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the ``ServiceSettings.AllowCorsFrom`` [configuration setting](https://docs.mattermost.com/configure/integrations-configuration-settings.html#enable-cross-origin-requests-from). Also ensure that the ``siteURL`` is set correctly. +- **v7.10.2, released 2023-05-18** + - Fixed an issue where v7.10 reported an incorrect mmctl version. +- **v7.10.1, released 2023-05-16** + - Mattermost v7.10.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690. + - Prepackaged version 1.2.1 of the Apps plugin. + - Prepackaged version 2.1.5 of the GitHub plugin. + - Updated prepackaged Playbooks v1.36.1. + - Fixed an issue where true-up review submissions always failed. + - Fixed an issue caused by a migration in the previous release. Query takes around 11ms on a PostgreSQL 14 DB t3.medium RDS instance. Locks on the preferences table will only be acquired if there are rows to delete, but the time taken is negligible. +- **v7.10.0, released 2023-04-14** + - Original 7.10.0 release + +Mattermost v7.10.0 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + + - In the next release, v7.11, the following repositories will be merged into one: ``mattermost-server``, ``mattermost-webapp``, ``focalboard`` and ``mattermost-plugin-playbooks``. Developers should read the updated [Developer Guide](https://developers.mattermost.com/contribute/developer-setup/) for details. **Playbooks and Boards will be core parts of the product that cannot be disabled**. + +```{Important} +If you upgrade from a release earlier than v7.9, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Improvements + +#### User Interface (UI) + - Added the ability to set a reminder to read a message at a specific time via the **More** menu in messages. + - Mentions from muted channels are no longer shown or counted on the browser and desktop tabs. + - Updated descriptions for **Environment > Developer** settings in the **System Console** to clarify that changes require a server restart to take effect. + - The custom user status is now shown in the right-hand side **Members** pane and in **System Console > Users**. + - Added the ability to invite multiple people at a time by email to a Mattermost instance. + - Added accessibility support to the date picker. + - System admins are prompted to complete a feedback survey during a workspace downgrade process from Cloud Professional to Cloud Free. + - Migrated the message (...) **More** option to a Material UI (MUI) menu. + - Updated pre-packaged Boards to v7.10.0. + - Updated pre-packaged Calls to v0.15.1. + +#### Administration + - The ``ServiceSettings.PostEditTimeLimit`` config setting no longer affects Plugins, Shared Channels, Integration Actions, or Mattermost Products. + - The app server no longer starts if the telemetry ID in the systems table doesn't exist. Although there is no action required by the administrators, it may be good to be aware of this change. If the ID doesn't exist, administrators can read the error log and take action against it. + - Added additional values to the support packet. + - Self-hosted instances will now show invoices in **System Console > Billing & Account > Billing History*** for prior self-serve purchases. + - A 404 error is now returned if an invoice could not be fetched for a self-hosted deployment. + +#### Performance + - Writes to websocket now take 13% less memory and happen 22% faster per message. + +### API Changes + - Added a ``exclude_files_count`` parameter to exclude file counts from channel stats API. + +### Bug Fixes + - Fixed an issue where Shared Channels wasn't properly added to the Professional license. + - Fixed new teams to use the updated translation for default channels after a config change. + - Fixed issues with spacing in the channel categories and maintained the same spacing in the left-hand side. + - Fixed disproportionate height issues for tall single images. + - Fixed an issue where a single WebSocket reconnect could be handled multiple times which would negatively affect performance. + - Fixed an issue in **Top DM Insights**, where a deleted participant caused DM Insights to fail. + - Fixed an issue where Cloud limits would briefly flash in the System Console before disappearing. + - Fixed an issue with the compact message mode. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in the ``config.json``: + - ``SelfHostedExpansion`` config setting was added to support incremental additions/changes to this feature. + +### Go Version + - v7.10 is built with Go ``v1.19.5``. + +### Open Source Components + - Added ``date-fns`` to https://github.com/mattermost/mattermost-webapp/. + +### Known Issues + - Updating from v7.9.x to Focalboard 7.10.4 causes Boards attachments to be lost [MM-53240](https://mattermost.atlassian.net/browse/MM-53240). + - Users have trouble logging into Mattermost mobile app when the DiagnosticId is not properly stored in cache after startup [MM-53195](https://mattermost.atlassian.net/browse/MM-53195). + - Users are unexpectedly forced to enable JSON logging [MM-51453](https://mattermost.atlassian.net/browse/MM-51453). + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. See the `Insights `__ documentation for details. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [11sma](https://github.com/11sma), [adj2908](https://github.com/adj2908), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [andrius.balsevicius](https://translate.mattermost.com/user/andrius.balsevicius), [angeloskyratzakos](https://github.com/angeloskyratzakos), [AntalaFilip](https://github.com/AntalaFilip), [anx-ag](https://github.com/anx-ag), [aputtu](https://github.com/aputtu), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [avas27JTG](https://github.com/avas27JTG), [ayusht2810](https://github.com/ayusht2810), [BenCookie95](https://github.com/BenCookie95), [bfontaine](https://github.com/bfontaine), [byigorv](https://github.com/byigorv), [calebroseland](https://github.com/calebroseland), [coltoneshaw](https://github.com/coltoneshaw), [ConorMacpherson](https://github.com/ConorMacpherson), [cpoile](https://github.com/cpoile), [creeper-0910](https://translate.mattermost.com/user/creeper-0910), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [d-wierdsma](https://github.com/d-wierdsma), [DaDummy](https://github.com/DaDummy), [devinbinnie](https://github.com/devinbinnie), [Dmitry](https://translate.mattermost.com/user/Dmitry), [dylanrichards](https://github.com/dylanrichards), [EduardoSellanes](https://github.com/EduardoSellanes), [Eleferen](https://translate.mattermost.com/user/Eleferen), [Elpunical](https://github.com/Elpunical), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [ericgaspar](https://github.com/ericgaspar), [esarafianou](https://github.com/esarafianou), [ewwollesen](https://github.com/ewwollesen), [fmartingr](https://github.com/fmartingr), [fnogcps](https://github.com/fnogcps), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gitstart](https://github.com/gitstart), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hattori611](https://github.com/hattori611), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [ifoukarakis](https://github.com/ifoukarakis), [isaacbegit](https://github.com/isaacbegit), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jnsgruk](https://github.com/jnsgruk), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kaykayehnn](https://github.com/kaykayehnn), [KBeDevel](https://github.com/KBeDevel), [khoipro](https://github.com/khoipro), [kmaed](https://github.com/kmaed), [komoon8934](https://translate.mattermost.com/user/komoon8934), [koox00](https://github.com/koox00), [kostaspt](https://github.com/kostaspt), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [kwiersgalla](https://github.com/kwiersgalla), [larkox](https://github.com/larkox), [leonambeez](https://translate.mattermost.com/user/leonambeez), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://translate.mattermost.com/user/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [MatthewDorner](https://github.com/MatthewDorner), [MattSilvaa](https://github.com/MattSilvaa), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michael_kim](https://translate.mattermost.com/user/michael_kim), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mini-bomba](https://github.com/mini-bomba), [mirshahriar](https://github.com/mirshahriar), [moatasim](https://translate.mattermost.com/user/moatasim), [MoatazMuhammad51](https://github.com/MoatazMuhammad51), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [muratbayan](https://translate.mattermost.com/user/muratbayan), [mvitale1989](https://github.com/mvitale1989), [natalie-hub](https://github.com/natalie-hub), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [Nityanand13](https://github.com/Nityanand13), [NixemDEV](https://translate.mattermost.com/user/NixemDEV), [oraliahdz](https://github.com/oraliahdz), [paolo-rossi](https://github.com/paolo-rossi), [Peytob](https://github.com/Peytob), [phoinixgrr](https://github.com/phoinixgrr), [pjenicot](https://translate.mattermost.com/user/pjenicot), [plant99](https://github.com/plant99), [plut0s](https://translate.mattermost.com/user/plut0s), [potatogim](https://translate.mattermost.com/user/potatogim), [pureiris](https://github.com/pureiris), [pvev](https://github.com/pvev), [Qui3t0wL](https://github.com/Qui3t0wL), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [roadt](https://github.com/roadt), [Rutboy](https://translate.mattermost.com/user/Rutboy), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [Sharuru](https://github.com/Sharuru), [sibasankarnayak](https://github.com/sibasankarnayak), [simcard0000](https://github.com/simcard0000), [sinansonmez](https://github.com/sinansonmez), [Sjazz](https://github.com/Sjazz), [smallcms](https://github.com/smallcms), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [stevemudie](https://github.com/stevemudie), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [tanmay-des](https://github.com/tanmay-des), [tanmaythole](https://github.com/tanmaythole), [Tasy218](https://translate.mattermost.com/user/Tasy218), [toninis](https://github.com/toninis), [trilopin](https://github.com/trilopin), [varghesejose2020](https://github.com/varghesejose2020), [Wainwright0830](https://github.com/Wainwright0830), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wuwinson](https://github.com/wuwinson), [xiao](https://translate.mattermost.com/user/xiao), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yomiadetutu1](https://github.com/yomiadetutu1) + +---- + +(release-v7-9-feature-release)= +## Release v7.9 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.9.6, released 2023-07-12** + - Mattermost v7.9.6 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.9.6 contains no database or functional changes. + - Fixed an issue where posts were not fully sanitized for audit output when a link preview was included. + - Updated prepackaged Playbooks plugin version to 1.36.2. +- **v7.9.5, released 2023-06-15** + - Mattermost v7.9.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Updated prepackaged Boards to v7.9.6. + - For servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the ``ServiceSettings.AllowCorsFrom`` [configuration setting](https://docs.mattermost.com/configure/integrations-configuration-settings.html#enable-cross-origin-requests-from). Also ensure that the ``siteURL`` is set correctly. +- **v7.9.4, released 2023-05-16** + - Mattermost v7.9.4 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690. + - Prepackaged version 1.2.1 of the Apps plugin. + - Prepackaged version 2.1.5 of the GitHub plugin. + - Backporting fix for oauth 2. Query times depend on if you have rows to delete or not. Please see the [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. +- **v7.9.3, released 2023-04-27** + - Mattermost v7.9.3 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where true-up review submissions always failed. +- **v7.9.2, released 2023-04-12** + - Mattermost v7.9.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Updated prepackaged Boards to v7.9.3. + - Updated prepackaged Playbooks to v1.36.1. + - Fixed an issue with compact message mode. + - Fixed an issue where ``NotifyAdmin`` job reported an error for unlicensed servers. +- **v7.9.1, released 2023-03-17** + - Mattermost v7.9.1 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.9.0, released 2023-03-16** + - Original 7.9.0 release + +Mattermost v7.9.0 contains a low severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + +- Added a new index on ``Posts(OriginalId)``. For a database with 11.8 million posts, on a machine with a i7-11800H CPU (8 cores, 16 threads), 32GiB of RAM and SSD, the index creation takes 98.51s on MYSQL and 2.6s on PostgreSQL. +- In PostgreSQL databases, the ``Posts`` table will be locked during index creation. To avoid locking this table, admins can create the index manually before performing the upgrade using the following non-blocking query: ``CREATE INDEX CONCURRENTLY idx_posts_original_id ON Posts(OriginalId);``. +- Admins managing PostgreSQL deployments containing fewer posts may prefer that the migration process creates the index, and accept that ``Posts`` table will remain locked until the migration is complete. + +```{Important} +If you upgrade from a release earlier than v7.8, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated Firefox minimum supported version to 102+. + - Updated Safari minimum supported version to 16.2+. + - Updated Windows minimum supported version to 10+. + - Updated Chromium minimum supported version to 110+. + - Updated Edge minimum supported version to 110+. + +### Highlights + +#### Boards + - System and team admins are now able to join any board on the team as a board admin via the board URL. + - Additional Compliance APIs to return the history of boards and blocks, including deleted items (available in Mattermost Enterprise Edition and above). + +### Improvements + +#### User Interface (UI) + - Prepackaged Calls v0.14.0. + - All post components were removed in favor of a unified approach. + - App bindings are now refreshed when a App plugin-enabled event gets triggered. + - Improvements were added to the sidebar channel and category menus. + - Removed right-click hijacking on code blocks in messages. + - The order of the Leave Channel and Archive Channel settings were updated to match the mobile app. + - Added the condition to remove unread styling for archived channels and to filter archived channels from local data. + - Changed the collapsed post fade out effect to be less buggy. + - Users now have the ability to see the history of edited messages and to restore an old message version with the current version. + - Improved the user interface of the user profile popover. + +#### Administration + - Boards cards are no longer mentioned as being limited in the **System Console**, the limits usage modal, the downgrade modal, or the left-hand side menu. + - Removed unused ``ProductLimits.Integrations``. + - Export files now contain the read and unread status for channels. + - Added an error message when running an LDAP sync with ``SyncEnabled`` set to ``false``. + - Added Admin log table filtering and sorting. + - GraphQL APIs are now correctly counted when measuring performance telemetry. + - Added a dynamic call-to-action under **System Console > Site Statistics and > Team Statistics** for air-gapped and non-air-gapped systems. The banner reminding about true-up follows the schedule [outlined here](https://docs.mattermost.com/about/self-hosted-subscriptions.html#quarterly-true-up-report). + - Screened self-hosted purchases now block the Admin from re-attempting a purchase for three days. + +#### Performance + - Reduced the rate that unreads are resynced when the window is focused from ten seconds to two minutes. + - The center channel is no longer shown as loading when switching teams. + - Added logging fixes: empty ``short_message`` for Gelf formatter is no longer allowed and ``params.Host`` is now used over ``params.IP`` for syslog config. + +### Bug Fixes + - Fixed an issue where the System Console link to purchase a self-hosted license would get stuck showing the in-product purchase progress modal. + - Fixed an issue where the true-up notification in the invite modal did not render the call-to-action correctly. + - Fixed new teams to use the updated translation for default channels after a configuration change. + - Fixed a layout issue in the System Console for smaller-sized tablets. + - Fixed an issue where a "plugin configured with a nil SecureConfig" warning was logged when starting each plugin. + - Fixed an issue where portal availability was checked when not on Enterprise edition. + - Fixed an issue where C# syntax highlighting was not working. + - Fixed an issue where incoming webhooks changed the user's activity while the user was offline/away. + - Fixed an issue where usernames were not clickable in the right-hand side. + +### API Changes + - Added an ``exclude_files_count`` parameter to exclude file counts from the channel stats API. + - Added a new API endpoint ``GET api/v4/posts/[POST_ID]/edit_history``. + - Added a new API endpoint ``DELETE /api/v4/cloud/delete-workspace``. + +### Database Changes + - Added the ``SentAt`` column to ``NotifyAdmin``. + - Updated ``NotifyAdmin.RequiredFeature`` column type to ``varchar(255)``. + - Updated ``NotifyAdmin.RequiredPlan`` column type to ``varchar(100)``. + +### Go Version + - v7.9 is built with Go ``v1.19.0``. + +### Open Source Components + - Added ``@mui/base``, ``@mui/material`` and ``@mui/styled-engine-sc``, and removed ``form-data`` from https://github.com/mattermost/mattermost-webapp/. + +### Known Issues + - Users are unexpectedly forced to enable JSON logging [MM-51453](https://mattermost.atlassian.net/browse/MM-51453). + - Checkmarks are missing from the left-hand side submenus [MM-51091](https://mattermost.atlassian.net/browse/MM-51091). + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - The Playbooks left-hand sidebar doesn't update when a user is added to a run or playbook without a refresh. + - If a user isn't a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels, or remove those channels from the run configuration. + +### Contributors + - [11sma](https://translate.mattermost.com/user/11sma), [aashish0909](https://github.com/aashish0909), [AbhinavVihan](https://github.com/AbhinavVihan), [aeomin](https://github.com/aeomin), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [akaMrDC](https://github.com/akaMrDC), [alzee](https://github.com/alzee), [amyblais](https://github.com/amyblais), [andrleite](https://github.com/andrleite), [AntalaFilip](https://translate.mattermost.com/user/AntalaFilip), [anurag6713](https://github.com/anurag6713), [anx-ag](https://github.com/anx-ag), [aputsiak](https://translate.mattermost.com/user/aputsiak), [aputtu](https://github.com/aputtu), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [avas27JTG](https://github.com/avas27JTG), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [cedricstocke](https://github.com/cedricstocke), [CI-YU](https://github.com/CI-YU), [coltoneshaw](https://github.com/coltoneshaw), [ConorMacpherson](https://github.com/ConorMacpherson), [cpoile](https://github.com/cpoile), [creeper-0910](https://github.com/creeper-0910), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [d-wierdsma](https://github.com/d-wierdsma), [davidboto](https://github.com/davidboto), [david.mach@mdsystem.cz](https://translate.mattermost.com/user/david.mach@mdsystem.cz), [devinbinnie](https://github.com/devinbinnie), [doc-sheet](https://github.com/doc-sheet), [DummyThatMatters](https://github.com/DummyThatMatters), [Eleferen](https://translate.mattermost.com/user/Eleferen), [Elpunical](https://github.com/Elpunical), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [fmartingr](https://github.com/fmartingr), [FMP-Dev](https://github.com/FMP-Dev), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [gitstart](https://github.com/gitstart), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hattori611](https://translate.mattermost.com/user/hattori611), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [ichistmeinname](https://github.com/ichistmeinname), [icq4ever](https://github.com/icq4ever), [ifoukarakis](https://github.com/ifoukarakis), [iogungbade](https://github.com/iogungbade), [iot-defcon](https://github.com/iot-defcon), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [javaguirre](https://github.com/javaguirre), [jecepeda](https://github.com/jecepeda), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jordanafung](https://github.com/jordanafung), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kjh0523](https://github.com/kjh0523), [kayazeren](https://translate.mattermost.com/user/kayazeren), [KazminM](https://translate.mattermost.com/user/KazminM), [KBeDevel](https://translate.mattermost.com/user/KBeDevel), [koox00](https://github.com/koox00), [kostaspt](https://github.com/kostaspt), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [liz-segura98](https://github.com/liz-segura98), [m-ripper](https://github.com/m-ripper), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [marciohouse](https://github.com/marciohouse), [marciosantos](https://translate.mattermost.com/user/marciosantos), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mdsystem](https://github.com/mdsystem), [metanerd](https://github.com/metanerd), [mhd-sln](https://github.com/mhd-sln), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [microolapshare](https://github.com/microolapshare), [milotype](https://github.com/milotype), [mini-bomba](https://translate.mattermost.com/user/mini-bomba), [mirshahriar](https://github.com/mirshahriar), [MoatazMuhammad51](https://translate.mattermost.com/user/MoatazMuhammad51), [moussetc](https://github.com/moussetc), [munish7771](https://github.com/munish7771), [mvitale1989](https://github.com/mvitale1989), [mylonsuren](https://github.com/mylonsuren), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [nishit-prasad](https://github.com/nishit-prasad), [Nityanand13](https://github.com/Nityanand13), [nltb99](https://github.com/nltb99), [OGreSiv](https://translate.mattermost.com/user/OGreSiv), [oleksandr-kucheriavyi](https://github.com/oleksandr-kucheriavyi), [orsczech](https://translate.mattermost.com/user/orsczech), [OstapMelnychuk](https://github.com/OstapMelnychuk), [phoinixgrr](https://github.com/phoinixgrr), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [Rizumu85](https://github.com/Rizumu85), [Roy-Orbison](https://github.com/Roy-Orbison), [saturninoabril](https://github.com/saturninoabril), [satya-vinay](https://github.com/satya-vinay), [sbishel](https://github.com/sbishel), [Schleuse](https://github.com/Schleuse), [Sharuru](https://github.com/Sharuru), [shinnlok](https://github.com/shinnlok), [sinansonmez](https://github.com/sinansonmez), [Sjazz](https://github.com/Sjazz), [Sn-Kinos](https://translate.mattermost.com/user/Sn-Kinos), [Soldierplayz6867](https://github.com/Soldierplayz6867), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [stevemudie](https://github.com/stevemudie), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Sudhanva-Nadiger](https://github.com/Sudhanva-Nadiger), [tboulis](https://github.com/tboulis), [tiagodll](https://github.com/tiagodll), [toninis](https://github.com/toninis), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [Udval.O](https://translate.mattermost.com/user/Udval.O), [Van-cmyk](https://github.com/Van-cmyk), [varghesejose2020](https://github.com/varghesejose2020), [vhaarr](https://translate.mattermost.com/user/vhaarr), [Wainwright0830](https://github.com/Wainwright0830), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xiao](https://translate.mattermost.com/user/xiao), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [zclk](https://github.com/zclk) + +---- + +(release-v7-8-extended-support-release)= +## Release v7.8 - [Extended Support Release](https://docs.mattermost.com/upgrade/release-definitions.html#extended-support-release-esr) + +```{Important} +Support for Mattermost Server v7.8 [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) has come to the end of its life cycle on November 15, 2023. [Upgrading Mattermost Server](https://docs.mattermost.com/about/mattermost-server-releases.html#latest-releases) is required. +``` + +- **7.8.15 released 2023-11-13** + - Mattermost v7.8.15 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.15 contains no database or functional changes. + - Pre-packaged Playbooks plugin version [v1.36.3](https://github.com/mattermost/mattermost-plugin-playbooks/releases/tag/v1.36.3). +- **7.8.14, released 2023-11-06** + - Mattermost v7.8.14 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.14 contains no database or functional changes. + - Pre-packaged Calls plugin version [v0.20.0](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.20.0). + - Fixed an issue where **Recent Mentions** showed posts for other similar named users. +- **7.8.13, released 2023-10-27** + - Mattermost v7.8.13 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Pre-packaged Focalboard plugin [v7.8.9](https://github.com/mattermost/focalboard/releases/tag/v7.8.9). + - Mattermost v7.8.13 contains the following functional changes: + - Added a new configuration setting ``MaxFieldSize`` to add the ability to size-limit log fields during logging. + - Added a restriction to the mobile Oauth / SAML redirection to match the ``NativeAppSettings.AppCustomURLSchemes`` configuration setting. + - When ``ServiceSettings.ExperimentalEnableHardenedMode`` is enabled, standard users authenticated via username and password will not be able to use post props reserved for integrations, such as ``override_username`` or ``override_icon_url``. +- **7.8.12, released 2023-10-06** + - Mattermost v7.8.12 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.12 contains no database or functional changes. + - Prepackaged Calls plugin version upgraded [v0.13.1](https://github.com/mattermost/mattermost-plugin-calls/releases/tag/v0.13.1). +- **v7.8.11, released 2023-09-08** + - Mattermost v7.8.11 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.11 contains the following database changes: + - Improved performance on data retention ``DeleteOrphanedRows`` queries. See the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for notes on a new migration that was added. Removed feature flag ``DataRetentionConcurrencyEnabled``. Data retention now runs without concurrency in order to avoid any performance degradation. Added a new configuration setting ``DataRetentionSettings.RetentionIdsBatchSize``, which allows admins to to configure how many batches of IDs will be fetched at a time when deleting orphaned reactions. The default value is 100. +- **v7.8.10, released 2023-09-01** + - Mattermost v7.8.10 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.10 contains no database or functional changes. + - Fixed an issue with missing time zone metadata in the Docker container. + - Replaced Gfycat with Giphy in the gif picker. +- **v7.8.9, released 2023-07-26** + - Mattermost v7.8.9 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.9 contains no database or functional changes. + - Prepackaged Focalboard plugin version 7.8.8. +- **v7.8.8, released 2023-07-07** + - Mattermost v7.8.8 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.8 contains no database or functional changes. + - Fixed an issue where posts were not fully sanitized for audit output when a link preview was included. + - Updated prepackaged Playbooks plugin version to 1.36.2. + - Fixed an issue where line breaks were introduced when pasting hyperlinks in the chat. + - New feature flag ``DataRetentionConcurrencyEnabled`` was added to enable/disable concurrency for data retention batch deletion. New config setting ``DataRetentionSettings.TimeBetweenBatchesMilliseconds`` was added to control the sleep time between batch deletions. +- **v7.8.7, released 2023-06-15** + - Mattermost v7.8.7 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Mattermost v7.8.7 contains no database or functional changes. + - Updated prepackaged Boards to v7.8.7. + - Fixed typo in the database migration scripts that broke idempotency. + - For servers wanting to allow websockets to connect from origins other than the origin of the site URL, please set the ``ServiceSettings.AllowCorsFrom`` [configuration setting](https://docs.mattermost.com/configure/integrations-configuration-settings.html#enable-cross-origin-requests-from). Also ensure that the ``siteURL`` is set correctly. +- **v7.8.6, released 2023-05-31** + - Fixed an issue where the total user count was fetched for every client connection. It is only necessary to fetch this once. + - Prepackaged version 1.3.0 of the Welcomebot plugin. +- **v7.8.5, released 2023-05-17** + - Mattermost v7.8.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where a user would still see threads in the threads view of channels they have left. Migration execution time in MySQL: Query OK, 2766769 rows affected (4 min 47.57 sec). Migration execution time in PostgreSQL: 58.11 sec, DELETE 2766690. + - Prepackaged version 1.2.1 of the Apps plugin. + - Prepackaged version 2.1.5 of the GitHub plugin. + - Updated the Docker Base Image from Debian to Ubuntu 22.04 LTS. + - Backported a fix related to Oauth 2. Query times depend on if you have rows to delete or not. Please see the [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html) for more details. +- **v7.8.4, released 2023-04-27** + - Mattermost v7.8.4 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Limited channel search results to 50 to fix a performance issue. + - Fixed an issue where true-up review submissions always failed. +- **v7.8.3, released 2023-04-12** + - Mattermost v7.8.3 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Updated prepackaged Boards to v7.8.4. + - Updated prepackaged Playbooks to v1.36.1. + - Added additional values to the support packet. +- **v7.8.2, released 2023-03-17** + - Mattermost v7.8.2 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a ``exclude_files_count`` parameter to exclude file counts from channel stats API. + - Excluded the file count on channel stats API call on from channel header. + - Fixed an issue where the Shared Channels feature wasn't properly included in the Professional license. +- **v7.8.1, released 2023-03-01** + - Mattermost v7.8.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.8.0, released 2023-02-16** + - Original 7.8.0 release + +Mattermost v7.8.0 contains low to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + + - [Message Priority & Acknowledgement](https://docs.mattermost.com/configure/site-configuration-settings.html#message-priority) is now enabled by default for all instances. You may disable this feature in the System Console by going to **Posts > Message Priority** or via the config ``PostPriority`` setting. + +```{Important} +If you upgrade from a release earlier than v7.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Boards + - Added support for person, multi-person, and date property filters in Boards. + - Added support for person property groups in Boards. + - See [the docs](https://docs.mattermost.com/end-user-guide/project-management/groups-filter-sort.html) for more details. + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls v0.13.0. + - Pre-packaged Playbooks v1.36.0. + - Insights and drafts are now included when navigating through channels in the channel sidebar using ALT+UP/DOWN arrow keyboard keys. + - Added an onboarding tour point for Global Drafts. + - Updated prepackaged version of Apps plugin to 1.2.0. + - Added group members count to the group autocomplete. + - Selecting a group mention now displays group details and membership. + - Improved the collapsed state of the message formatting toolbar. + - App Framework channel and user fields now support multi-select properties to allow users to select multiple values in a form. + - Increased the character count for desktop notifications on Windows to 120 from 50. + - Prioritized members of recently viewed direct or group messages when adding users to a channel. + - Added support for multiple users and channels to the ``/invite`` slash command. + +#### Administration + - Self-hosted admins can now purchase licenses in-app when service setting ``SelfHostedPurchase`` is true. + - Endpoint to portal added to detect whether a license is suitable for self-expansion. Customers over their seat limit can expand their license seats. + - Airgapped purchase experience is now shown only when appropriate and a simplified authentication flow is now used for the self-hosted purchase. + - The export file now contains the server version and a creation timestamp. + - Total Activated Users was changed back to Total Active Users on the **System Console > Reporting > Site Statistics** page. + - Added ``restore_group`` permission to the mmctl and to the **System Console > Permissions**. + - Improved bulk export logging. + - Compliance export jobs can now cancel the SQL query execution during server shutdown which will allow the job to exit faster. + - The message export compliance job can now survive server restarts. The job will pause and save state when the server is shutting down, and resume from the previously saved state when the server starts back up. + - Only one instance of the job will be automatically scheduled to run as per the ``MessageExportSettings.DailyRunTime`` config value. + - Mattermost will throw an error if it detects an Elasticsearch version greater than 7. + - The maximum size of uploaded emojis is reduced to 512KB to reduce image download bandwidth. + - Users can now monitor the progress of the bulk export job via its metadata field. It is available at ``mmctl export job show ``. + - Compliance exports no longer time out when uploading to S3. + - Users can now supply a certificate authority (CA) file and client certificates for the Elasticsearch client. + - Enabled ``EnableOAuthServiceProvider`` by default. + - Grafana metrics are now available for database connection metrics. They are: + - ``max_open_connections`` + - ``open_connections`` + - ``in_use_connections`` + - ``idle_connections`` + - ``wait_count_total`` + - ``wait_duration_seconds_total`` + - ``max_idle_closed_total`` + - ``max_idle_time_closed_total`` + - ``max_lifetime_closed_total`` + - Made the ``registerChannelIntroButtonAction`` plugin API usable by plugins other than Boards. + - The following new HTTP headers and values are now written on all responses. These default values should make sense in most installations and can be overridden by a reverse proxy or ingress configuration. Note that the empty ``Permissions-Policy`` header does not have any actual effect. Users are recommended to change it to a more restrictive value based on their use case. For more information, see the [W3C Reference](https://www.w3.org/TR/permissions-policy/) or [this article](https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy). + + ``` + Permissions-Policy: + Referrer-Policy: no-referrer + X-Content-Type-Options: nosniff + ``` + +### Bug Fixes + - Fixed an issue where if a self-hosted purchase was not available, an air-gapped modal was shown instead of going to the CWS purchase portal experience directly. + - Fixed small visual issues with self-hosted purchase modal. Adjusted wording for admins trying to purchase when a purchase is already in progress. + - Fixed an issue where attempting to create a team with a duplicate URL displayed the wrong error. + - Fixed an issue where the custom status modal did not close when navigating to the custom emoji page. + - Fixed an issue where selections within a code block were not properly copied to clipboard. + - Fixed an issue where threads with 0 replies would show in all threads. + - Fixed an issue with the styling of date pickers. + - Fixed an issue with fetching the latest user's profile picture in Insights. + - Fixed an issue where ``--center-channel-text`` CSS variable was used instead of ``--center-channel-color``. + - Fixed an issue where the screen reader timestamp announcement was too long. + - Fixed an issue where profile pictures, usernames, and full names did not update instantly in Insights. + - Fixed an issue where the metrics server restarted for every config change. + - Fixed the slash command description help text. + - Fixed an issue where selecting **Contact Sales** didn't pre-fill the reason for contacting sales. + - Fixed an issue where the screen readers did not announce the selected state of the sidebar submenu items. + - Fixed an issue where the metrics server was not prevented from starting while running export commands. + - Fixed an issue where long group mentions and user mentions didn't wrap properly. + - Fixed an issue with fetching first/last name for GitLab user using OpenID. + - Fixed an issue with the plugin ``/public`` handling for subpaths. + - Fixed an issue where selecting **Pinned** on a post in the Threads view would result in the right-hand side being stuck in a loading state. + - Fixed an issue where the profile popover did not dismiss when opening a modal through a shortcut. + - Fixed an issue where the **Run Deletion Job Now** button for Data Retention wasn’t disabled when all policies were set to **keep forever**. + - Fixed an issue that prevented the creation of the initial admin user for new servers. + - Fixed an issue where making a channel non-read-only required a refresh of the client to see the change. + - Fixed an issue where Top Channels for Insights didn't show results if the current user's configured timezone wasn't present in MySQL's ``mysql.time_zone_name table``. + - Fixed an issue where a white screen appeared when a guest was removed from the last channel while on Threads. + - Fixed an issue where a Direct Message thread did not get disabled when a user was deactivated. + - Fixed an issue where email notifications for Direct Messages from Playbooks contained broken URLs. + - Fixed an issue where bulk import crashed with invalid memory address or nil pointer dereference. + - Fixed an issue with special characters in the System Console log filename causing logging configuration to break. + - Fixed an issue where the PDF renderer was not rendering all the pages. + - Fixed a 404 error from requests to ``/api/v4/system/notices/`` on page load. + - Fixed an issue where file uploading appeared "stuck" in processing state. + - Fixed an issue where archived channels appeared as unread in the channel switcher. + +### API Changes + - Added new API endpoint ``GET /api/v4/posts/:post_id/info`` to allow checking if the post that a permalink is pointing to is accessible by joining teams or channels. + - Added validity checks for role related parameters in ``GET /users``. + +### Go Version + - v7.8 is built with Go ``v1.18.1``. + +### Known Issues + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in high availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in high availability mode. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [AbhinavVihan](https://github.com/AbhinavVihan), [adityash1](https://github.com/adityash1), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amayasova](https://github.com/amayasova), [amyblais](https://github.com/amyblais), [andrewbrown00](https://github.com/andrewbrown00), [andrleite](https://github.com/andrleite), [anurag6713](https://github.com/anurag6713), [anx-ag](https://github.com/anx-ag), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [avinashlng1080](https://github.com/avinashlng1080), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [bobf7](https://github.com/bobf7), [calebroseland](https://github.com/calebroseland), [cedricstocke](https://github.com/cedricstocke), [CI-YU](https://github.com/CI-YU), [coltoneshaw](https://github.com/coltoneshaw), [ConorMacpherson](https://github.com/ConorMacpherson), [core](https://translate.mattermost.com/user/core), [cpoile](https://github.com/cpoile), [creeper-0910](https://github.com/creeper-0910), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cybersmurf](https://github.com/cybersmurf), [d-wierdsma](https://github.com/d-wierdsma), [david.mach@mdsystem.cz](https://translate.mattermost.com/user/david.mach@mdsystem.cz), [devinbinnie](https://github.com/devinbinnie), [dfun90](https://github.com/dfun90), [dontoisme](https://github.com/dontoisme), [Eleferen](https://translate.mattermost.com/user/Eleferen), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [exbu](https://github.com/exbu), [florian-busch](https://github.com/florian-busch), [fmartingr](https://github.com/fmartingr), [fr0mdual](https://github.com/fr0mdual), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [geonmo](https://github.com/geonmo), [hamzaMM](https://github.com/hamzaMM), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [icq4ever](https://translate.mattermost.com/user/icq4ever), [ifoukarakis](https://github.com/ifoukarakis), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [ivenkwan](https://github.com/ivenkwan), [jasonblais](https://github.com/jasonblais), [javaguirre](https://github.com/javaguirre), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [KazminM](https://github.com/KazminM), [kevfocke](https://github.com/kevfocke), [koox00](https://github.com/koox00), [kostaspt](https://github.com/kostaspt), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [kwiersgalla](https://github.com/kwiersgalla), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [li11amy](https://github.com/li11amy), [lieut-data](https://github.com/lieut-data), [luc-ass](https://github.com/luc-ass), [lynn915](https://github.com/lynn915), [m-ripper](https://github.com/m-ripper), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo), [manojmalik20](https://github.com/manojmalik20), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mdsystem](https://github.com/mdsystem), [mhd-sln](https://github.com/mhd-sln), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mirshahriar](https://github.com/mirshahriar), [misaka10843](https://github.com/misaka10843), [mkraft](https://github.com/mkraft), [munish7771](https://github.com/munish7771), [mylonsuren](https://github.com/mylonsuren), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [Nityanand13](https://github.com/Nityanand13), [noxer](https://github.com/noxer), [NuriInfos_JSK](https://translate.mattermost.com/user/NuriInfos_JSK), [nydhy](https://github.com/nydhy), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [okias](https://github.com/okias), [oleksandr-kucheriavyi](https://github.com/oleksandr-kucheriavyi), [phuoc94](https://github.com/phuoc94), [pjenicot](https://github.com/pjenicot), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [rimakan](https://github.com/rimakan), [ronzim](https://github.com/ronzim), [Roy-Orbison](https://github.com/Roy-Orbison), [sadohert](https://github.com/sadohert), [safakkizkin](https://github.com/safakkizkin), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [SeoJoonsoo](https://github.com/SeoJoonsoo), [seoyeongeun](https://github.com/seoyeongeun), [Sharuru](https://github.com/Sharuru), [simcard0000](https://github.com/simcard0000), [sinansonmez](https://github.com/sinansonmez), [Sjazz](https://github.com/Sjazz), [sonichigo](https://github.com/sonichigo), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [stevemudie](https://github.com/stevemudie), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [tboulis](https://github.com/tboulis), [tintou](https://github.com/tintou), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [wgshtg](https://github.com/wgshtg), [wiggin77](https://github.com/wiggin77), [witjem](https://github.com/witjem), [worldworm](https://github.com/worldworm), [wuwinson](https://github.com/wuwinson), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [zeraussiul](https://github.com/zeraussiul), [zygfryd](https://github.com/zygfryd) + +---- + +(release-v7-7-feature-release)= +## Release v7.7 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.7.4, released 2023-04-12** + - Mattermost v7.7.4 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.7.3, released 2023-03-17** + - Mattermost v7.7.3 contains a high severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.7.2, released 2023-03-01** + - Mattermost v7.7.2 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - [Message Priority & Acknowledgement](https://docs.mattermost.com/configure/site-configuration-settings.html#message-priority) is now enabled by default for all instances. You may disable this feature in the System Console by going to **Posts > Message Priority** or via the config ``PostPriority`` setting. + - Fixed an issue where threads were not marked as unread in the Threads view. + - Fixed an issue where the server sent a wrong badge number when marking a message as unread in a Direct Message channel. + - Fixed an issue where the Team edition returned a 400 Bad request for attempts to check CWS availability. + - Fixed an issue where file uploading would appear "stuck" in processing state. + - Fixed an issue where the Shared Channels feature wasn't properly included in the Professional license. +- **v7.7.1, released 2023-01-20** + - Fixed an issue that prevented the creation of the initial admin user for new servers [MM-49720](https://mattermost.atlassian.net/browse/MM-49720). + - Fixed an issue where the Top Channels for Insights didn't show results if the current user's configured timezone wasn't present in MySQL's ``mysql.time_zone_name table`` [MM-49688](https://mattermost.atlassian.net/browse/MM-49688). +- **v7.7.0, released 2023-01-16** + - Original 7.7.0 release + +Mattermost v7.7.0 contains low severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + + - Plugins with a webapp component may need to be updated to work with Mattermost v7.7 release and the updated ``React v17`` dependency. + - This is to avoid plugins crashing with an error about ``findDOMNode`` being called on an unmounted component. While our [starter template](https://github.com/mattermost/mattermost-plugin-starter-template) depended on an external version of ``React``, it did not do the same for ``ReactDOM``. Plugins need to update their ``webpack.config.js`` directives to externalize ``ReactDOM``. For reference, see https://github.com/mattermost/mattermost-plugin-playbooks/pull/1489. Server-side only plugins are unaffected. This change can be done for existing plugins any time prior to upgrading to Mattermost v7.7 and is backwards compatible with older versions of Mattermost. If you run into issues, you can either enable ``ExperimentalSettings.PatchPluginsReactDOM`` or just disable the affected plugin while it's updated. + - Denormalized ``Threads`` table by adding the ``ThreadTeamId`` column. See details for schema changes in the [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). + - Starting with the Calls version shipping with v7.7, there's now a minimum version requirement when using the external RTCD service. This means that if Calls is configured to use the external service, customers need to upgrade RTCD first to at least version 0.8.0 or the plugin will fail to start. + +```{Important} +If you upgrade from a release earlier than v7.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated the minimum version of MacOS to 11+. + +### Highlights + +#### Calls +- [Audio calling and screen sharing](https://docs.mattermost.com/configure/calls-deployment-guide.html) in channels is now generally available to all Mattermost customers. + - Updated [the keyboard shortcut](https://docs.mattermost.com/channels/keyboard-shortcuts-for-channels.html#calls-shortcuts) to start and join calls. + - Please see [the docs](https://docs.mattermost.com/configure/plugins-configuration-settings.html#calls) for additional details on configuration setting updates. + +#### Boards + - Boards now supports [file attachments](https://docs.mattermost.com/end-user-guide/project-management/work-with-cards.html#attach-files), including PDFs, images, videos, and any other file types. + - Users can now [drag and drop boards and categories](https://docs.mattermost.com/end-user-guide/project-management/navigate-boards.html#manage-boards-on-the-sidebar) on the sidebar and organize them in any order they prefer. + - The [template picker](https://docs.mattermost.com/end-user-guide/project-management/work-with-boards.html#choose-a-board-template) has been improved to make it easier for users to find the best template for their project. + +#### Playbooks + - Added an option to [run playbooks](https://docs.mattermost.com/playbooks/work-with-playbooks.html#runs-and-channel-behavior) without creating a new channel every time in order to reduce the unnecessary overhead. + - In addition to the daily digest, users can now also view [a task inbox](https://docs.mattermost.com/playbooks/work-with-tasks.html#task-inbox) from the global header bar while in Playbooks. + +#### Message Priority and Acknowledgments + - Added [message priority labels](https://docs.mattermost.com/channels/message-priority.html) to the Threads view. + - Added support for users to request acknowledgements on posts and to acknowledge posts (Professional license). + +#### Global Drafts + - Added [a centralized Drafts view](https://docs.mattermost.com/channels/send-messages.html#draft-messages) for draft messages. + +#### ServiceNow Integration + - ServiceNow customers can now access and share their ServiceNow data from within Mattermost. + +#### ServiceNow Virtual Agent Integration + - The [Mattermost ServiceNow Virtual Agent Integration](https://mattermost-2.wistia.com/medias/ixvgukv2qf) makes it easy for employees and customers to resolve issues fast. + +#### GitLab Playbooks Integration + - Through the updated [GitLab integration and playbook task actions](https://mattermost.com/marketplace/gitlab-plugin/), teams can automate release management processes to help increase efficiency and reduce errors. + +### Improvements + +#### User Interface (UI) + - Implemented progressive image loading in the webapp. + - When the "Custom Brand Text" is left blank with custom branding enabled, the default text is now hidden. + - The **Mark as Unread** option was added to the **More** (...) menu for channels in the left-hand side sidebar. Pressing Alt while selecting a channel on the left-hand side now also marks the last post in the channel as unread. + - Channel members are now able to remove themselves from a channel via the right-hand side channel members list. + - Removed video check to allow the browser to decide what video types it can play. + - Added a tooltip to the right-hand side files filter icon. + - The number of users that can be added to a user group at once was increased to 256. + - Keyboard and focus handling was improved in profile popovers and @mentions. + - Updated prepackaged version of plugins affected by React 17 upgrade. + - Updated the **Remove license and download** text in-product to clarify that server will be downgraded to Mattermost Free as a result. + - Updated prepackaged NPS version to 1.3.1. + - Updated in-product confirmation modal for ``@here`` mentions to clarify that people & timezone counts don't include the current user. + - Downgraded French language support to Beta. + +#### Administration + - If an Admin encounters an invitation error “SMTP is not configured in System Console", a link to the SMTP configuration within the **System Console** is now included in the error message. + - Crashing jobs now sets the job status to "failed". + - Optimized ``ThreadStore.MarkAllAsUnreadByTeam``. + - SQL migrations for PostgreSQL will now filter by the current schema name when checking for information from the ``information_schema.columns`` view. This does not affect anything because usually there's only one installation in a given database, but this gives flexibility to users to store multiple Mattermost instances under a single database. + - **My Insights** was added to the Free plan. + - Team scheme APIs are now allowed to be administered with a Professional plan. + - A global banner as well as a notice banner are displayed to admins on the **Invite** modal and on **System Console > Site Statistics > Total Activated Users** page when the workspace exceeds the maximum number of users allowed. If the number of actual users exceeds the number of paid users by less than 5%, the banner is dismissible. If the number of actual users exceeds the number of paid users by more than 10%, the banner is non-dismissible until the license seat count has been updated. + - For admins to see if the amount of users exceeds the license seats, a warning is now shown in the **System Console > Team Statistics** page. + - Added a new menu item on the **System Console > Users** page that re-adds users to all of their default teams and channels associated with the groups they're a member of. + - Added ``acknowledgements`` field to the post's metadata. + - Added support for product websocket messages on high availability instances. + - The import job now logs the progress of the import. + - Exports to S3 no longer time out. + - Shared Channels (Experimental) was moved to Professional license. + +### Bug Fixes + - Fixed an issue where custom group actions were appearing in the user interface even when the user didn't have the permissions for them. + - Fixed issues with branding in email notifications. + - Fixed an issue where text could be dragged and dropped into input-fields. + - Fixed an issue where the profile popover failed to dismiss when selecting one of the options from the popover. + - Fixed an issue where imports containing the team name with the wrong capitalization crashed the import job. + - Fixed an issue where ``getPostSince`` didn't properly return deleted posts when Collapsed Reply Threads was enabled. + - Fixed an issue where the screen reader did not announce emojis from the autocomplete list. + - Fixed an issue where the scroll position in a channel was not maintained when opening reply message permalinks. + - Fixed an issue where ``OwnerId`` was not set for bots created via ``EnsureBotUser``. + - Fixed an issue where exports did not contain favorited Direct Message channels. + - Fixed an issue where screen readers did not announce search results on the **Invite members to channel** modal. + - Fixed an issue where screen readers did not announce the status of the user when hovering over the user status icon. + - Fixed an issue where users with narrow screens could not see the **Profile Settings** section within the **Settings** modal. + - Fixed an issue where users were unable to access the **Create an account** option on narrow screens. + - Fixed an issue where users on desktop were unable to grab the vertical scroll bar without accidently resizing the window. + - Fixed an issue where special characters weren't allowed in group mention names. + - Fixed an issue where screen readers didn't read the **Switch Channels** modal header. + - Fixed an issue in OAuth services where malformed redirect URLs were generated if the registered callback URLs already had static query parameters. + - Fixed an issue where suggestion dividers were displayed as undefined. + - Fixed an issue where a blank message was displayed in threads if the leave/join messages were disabled. + - Fixed an issue where threads would appear duplicated in the Threads view after leaving a channel. + - Fixed an issue with email search when using a PostgreSQL database. + - Fixed an issue where message drafts were not saved after pasting them into the post textbox. + - Fixed an issue where the team name in the channel sidebar header was not accessible. + - Fixed an issue where users were unable to open the user's profile popover from the channel members list in the right panel. + - Fixed an issue where the OAuth 2.0 deprecation notice was still displayed in the system console. + - Fixed an issue where clicking on a reply post time stamp in the global threads inbox opened two right-hand side panels. + - Fixed an issue where batch notifications failed while rendering. + - Prevented browsers and CDNs from caching remote entrypoint files. + - Fixed an issue where the unreads button in the channel sidebar was missing alternative text for screen readers. + - Fixed a potential read-after-write issue when uploading data through the resumable uploads API. + - Removed duplicate text in the self-hosted pricing modal. + - Fixed the position of the Boards icon in the Apps Bar when Boards is running without a plugin. + - Fixed ability to create a board when Boards is running without a plugin. + - Fixed Boards tour tips not appearing when Boards is running without a plugin. + - Fixed an issue where a confusing System Console banner was displayed when a license was set to expire. + - Fixed an issue where screen readers did not announce selected state of the sidebar submenu items. + - Fixed an issue where servers with an encrypted key did not throw an error during startup. + - Fixed an issue where the **Test Connection** button in **System Console > Environment > Elasticsearch** did not correctly take the right config settings specified in the page. Earlier, it would always take the previously saved config. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in the ``config.json``: + - ``PostPriority``, to add an option to select a message priority label for root posts. + - ``AllowSyncedDrafts``, to add an option to display a centralized page for draft messages. + - ``SelfHostedPurchase``, to add an option for self-hosted admins to purchase licenses in-app. + - Under ``ExperimentalSettings`` in the ``config.json``: + - ``PatchPluginsReactDOM``, to enable the patching of the React DOM library when loading web app plugins so that the plugin uses the version matching the web app. + +### API Changes + - The resumable uploads API was exposed to plugins. + - Added a new API endpoint ``POST /api/v4/ldap/users/:user_id/group_sync_memberships`` to add (or re-add) users to all of their default teams and channels for all of the groups they're a member of. + - Added two new URL parameters to the ``GET /api/v4/groups`` endpoint to get the ``ChannelMemberCount`` for a group. + - Added new API endpoints ``POST /api/v4/users/:user_id/posts/:post_id/ack`` and ``DELETE /api/v4/users/:user_id/posts/:post_id/ack``. + - Added a new API endpoint ``POST /api/v4/groups/:group_id:/restore``. + - Added an allowed value ``sort=display_name`` to ``GET /api/v4/users?in_group=<groupid>``. + - Added a new endpoint ``api/v4/cloud/products/selfhosted``. + - A new API method ``RegisterCollectionAndTopic(collectionType, topicType string) (error)`` was added to the Plugin API and the following hooks. This API method is in beta, subject to change, and not covered by our backwards compatibility guarantee. + - ``UserHasPermissionToCollection(c *Context, userID, collectionType, collectionId string, permission *model.Permission) (bool, error)`` + - ``GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error)`` + - ``GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error)`` + - ``GetTopicRedirect(c *Context, topicType, topicID string) (string, error)`` + - ``GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]model.CollectionMetadata, error)`` + - ``GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error)`` + +### Database Changes + - Added a new Database table ``PostAcknowledgements``. + +### Websocket Event Changes + - Added new websocket events ``post_acknowledgement_added`` and ``post_acknowledgement_removed``. + +### Go Version + - v7.7 is built with Go ``v1.18.1``. + +### Known Issues + - Your profile image moves up when changing your status manually [MM-49159](https://mattermost.atlassian.net/browse/MM-49159). + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in high availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in high availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - Boards linked to a channel you're a member of do not automatically appear on your sidebar unless you're an explicit member of the board. As a workaround, you can access the board from the channel RHS or by searching for the board via the board switcher (Ctrl/Cmd+K). Alternatively, you can ask the board admin to add you to the board as an explicit member. See the [issue-focalboard-4179](https://github.com/mattermost/focalboard/issues/4179) for more details. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + - If a user is not a member of a configured broadcast channel, posting a status update might fail without any error feedback. As a temporary workaround, join the configured broadcast channels or remove those channels from the run configuration. + +### Contributors + - [abhijit-singh](https://github.com/abhijit-singh), [AbhinavVihan](https://github.com/AbhinavVihan), [adithyaakrishna](https://github.com/adithyaakrishna), [aeomin](https://github.com/aeomin), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [aiden](https://translate.mattermost.com/user/aiden), [alauregaillard](https://github.com/alauregaillard), [alexkuryshko](https://github.com/alexkuryshko), [alexpjohnson](https://github.com/alexpjohnson), [alzee](https://github.com/alzee), [Amin913](https://github.com/Amin913), [amitpatelx3](https://github.com/amitpatelx3), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [andrewbrown00](https://github.com/andrewbrown00), [andrewwutw](https://github.com/andrewwutw), [anurag6713](https://github.com/anurag6713), [ariyonaty](https://github.com/ariyonaty), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [avas27JTG](https://github.com/avas27JTG), [avinashlng1080](https://github.com/avinashlng1080), [axilleas](https://github.com/axilleas), [ayrotideysarkar](https://github.com/ayrotideysarkar), [ayusht2810](https://github.com/ayusht2810), [azigler](https://github.com/azigler), [babinderrathi](https://github.com/babinderrathi), [ballista01](https://github.com/ballista01), [batebobo](https://github.com/batebobo), [belope](https://github.com/belope), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [bpodwinski](https://github.com/bpodwinski), [calebroseland](https://github.com/calebroseland), [cecilysullivan](https://github.com/cecilysullivan), [ChandanChainani](https://github.com/ChandanChainani), [chay](https://translate.mattermost.com/user/chay), [CI-YU](https://github.com/CI-YU), [cinlloc](https://github.com/cinlloc), [coltoneshaw](https://github.com/coltoneshaw), [ConorMacpherson](https://github.com/ConorMacpherson), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [cs4p](https://github.com/cs4p), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyrilzhang-mm](https://github.com/cyrilzhang-mm), [d-wierdsma](https://github.com/d-wierdsma), [developbit](https://github.com/developbit), [devinbinnie](https://github.com/devinbinnie), [dfun90](https://translate.mattermost.com/user/dfun90), [Drishti-jain21](https://github.com/Drishti-jain21), [DSchalla](https://github.com/DSchalla), [dsharma522](https://github.com/dsharma522), [dylanrichards](https://github.com/dylanrichards), [ehsandiary](https://github.com/ehsandiary), [Eleferen](https://translate.mattermost.com/user/Eleferen), [ellisonleao](https://github.com/ellisonleao), [emmyni](https://github.com/emmyni), [enahum](https://github.com/enahum), [EricssonLiu](https://github.com/EricssonLiu), [esethna](https://github.com/esethna), [Eugene-grb](https://github.com/Eugene-grb), [Fjoerfoks](https://github.com/Fjoerfoks), [fmartingr](https://github.com/fmartingr), [furqanmlk](https://github.com/furqanmlk), [gabor-boros](https://github.com/gabor-boros), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [Genei180](https://github.com/Genei180), [Gitnube](https://github.com/Gitnube), [gkech](https://github.com/gkech), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henry-shxu](https://github.com/henry-shxu), [hereje](https://github.com/hereje), [hionay](https://github.com/hionay), [hmhealey](https://github.com/hmhealey), [hokandil](https://github.com/hokandil), [homerCOD](https://github.com/homerCOD), [Hunter-Thompson](https://github.com/Hunter-Thompson), [idChef](https://github.com/idChef), [ifoukarakis](https://github.com/ifoukarakis), [Inutit](https://translate.mattermost.com/user/Inutit), [iomodo](https://github.com/iomodo), irdiOL, [isacikgoz](https://github.com/isacikgoz), [ivenkwan](https://translate.mattermost.com/user/ivenkwan), [iyampaul](https://github.com/iyampaul), [JakobMiksch](https://github.com/JakobMiksch), [javaguirre](https://github.com/javaguirre), [jecepeda](https://github.com/jecepeda), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johnsonbrothers](https://github.com/johnsonbrothers), [jordanafung](https://github.com/jordanafung), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), k4awon, [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kamre](https://github.com/kamre), [Kaorw](https://github.com/Kaorw), [kelderek](https://github.com/kelderek), [koox00](https://github.com/koox00), [kostaspt](https://github.com/kostaspt), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [ksankeerth](https://github.com/ksankeerth), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [ludovicobesana](https://github.com/ludovicobesana), [lynn915](https://github.com/lynn915), [m-ripper](https://github.com/m-ripper), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [maddy8381](https://github.com/maddy8381), [majo](https://translate.mattermost.com/user/majo), [manhdd610](https://translate.mattermost.com/user/manhdd610), [Manishpandey11](https://github.com/Manishpandey11), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://translate.mattermost.com/user/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [mastersb](https://github.com/mastersb), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mattlam88](https://github.com/mattlam88), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [mhd-sln](https://github.com/mhd-sln), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [michkrej](https://github.com/michkrej), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mirshahriar](https://github.com/mirshahriar), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [muratbayan](https://github.com/muratbayan), [mvitale1989](https://github.com/mvitale1989), [mylonsuren](https://github.com/mylonsuren), [nab-77](https://github.com/nab-77), [naggie](https://github.com/naggie), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [noxer](https://github.com/noxer), [NuriInfos_JSK](https://translate.mattermost.com/user/NuriInfos_JSK), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [PhilippeWeidmann](https://translate.mattermost.com/user/PhilippeWeidmann), [phoinixgrr](https://github.com/phoinixgrr), [Pinjasaur](https://github.com/Pinjasaur), [pjenicot](https://github.com/pjenicot), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [prashant-15](https://github.com/prashant-15), [PSyton](https://github.com/PSyton), [pvev](https://github.com/pvev), [raghavaggarwal2308](https://github.com/raghavaggarwal2308), [Rajat-Dabade](https://github.com/Rajat-Dabade), [redhoyasa](https://github.com/redhoyasa), [remyj38](https://translate.mattermost.com/user/remyj38), [RoyI99](https://github.com/RoyI99), [s4kh](https://github.com/s4kh),[sadohert](https://github.com/sadohert), [sarz4fun](https://translate.mattermost.com/user/sarz4fun), [saturninoabril](https://github.com/saturninoabril), [satya-vinay](https://github.com/satya-vinay), [sbishel](https://github.com/sbishel), [seowglen](https://github.com/seowglen), [seoyeongeun](https://github.com/seoyeongeun), [sgmadankar](https://translate.mattermost.com/user/sgmadankar), [ShajithaMohammed](https://github.com/ShajithaMohammed), [simcard0000](https://github.com/simcard0000), [sinansonmez](https://github.com/sinansonmez), [sk409](https://github.com/sk409), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sumanpaikdev](https://github.com/sumanpaikdev), [svbnbyrk](https://github.com/svbnbyrk), [tanmay-des](https://github.com/tanmay-des), [tboulis](https://github.com/tboulis), [tiagocorreiaalmeida](https://github.com/tiagocorreiaalmeida), [toomore](https://github.com/toomore), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [varunKT001](https://github.com/varunKT001), [VictorAssunc](https://github.com/VictorAssunc), [vish9812](https://github.com/vish9812), [vitorcruzfaculdade](https://github.com/vitorcruzfaculdade), [vivekkj123](https://github.com/vivekkj123), [wget](https://translate.mattermost.com/user/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [WilliamLongKing](https://github.com/WilliamLongKing), [Willyfrog](https://github.com/Willyfrog), [witjem](https://github.com/witjem), [wuwinson](https://github.com/wuwinson), [Yakikim](https://github.com/Yakikim), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [yegorov-p](https://github.com/yegorov-p), [zefhemel](https://github.com/zefhemel), [ziriuz84](https://github.com/ziriuz84), [zuhairHussain](https://github.com/zuhairHussain), [ZurabBalamtsarashvili](https://github.com/ZurabBalamtsarashvili) + +---- + +## Release v7.6 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + + - The Mattermost v7.6 release has been cancelled as we are working on investigating performance issues. The next scheduled release is v7.7 in January 16th, 2023. + +## Release v7.5 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.5.2, released 2022-12-21** + - Mattermost v7.5.2 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where email notifications looked broken when email batching was enabled [MM-48521](https://mattermost.atlassian.net/browse/MM-48521). + - Updated prepackaged Boards version to 7.5.4. + - Updated prepackaged NPS version to 1.3.1. +- **v7.5.1, released 2022-11-16** + - Fixed an upgrade issue affecting servers on Ubuntu v18.04. +- **v7.5.0, released 2022-11-16** + - Original 7.5.0 release + +Mattermost v7.5.0 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + + - Adds a new schema migration to ensure ``ParentId`` column is dropped from the ``Posts`` table. Depending on the table size, if the column is not dropped before, a significant spike in database CPU usage is expected on MySQL databases. Writes to the table will be limited during the migration. + - For ``PluginRegistry.registerCustomRoute``, when you register a custom route component, you must specify a CSS ``grid-area`` in order for it to be placed properly into the root layout (recommended: ``grid-area: center``). + +```{Important} +If you upgrade from a release earlier than v7.4, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Compatibility + - Updated the minimum version of Chrome and Edge to v106+. + +### Highlights + +#### Calls + - Added new message threads with emoji reactions and @mentions to calls. After joining a call, expand the widget to the window mode, and then select the comment button to access the real-time message thread in the right-hand sidebar. + +#### Boards + - Added additional standard [board templates](https://docs.mattermost.com/end-user-guide/project-management/work-with-boards.html#choose-a-board-template) to help users kick-off their next projects. + - Filters now support all [text properties](https://docs.mattermost.com/end-user-guide/project-management/work-with-cards.html#work-with-property-types). + - Added two new tiles for System Console [Boards metrics](https://docs.mattermost.com/administration-guide/configure/reporting-configuration-settings.html#site-statistics) under **System Console > Site Statistics**. + +#### Last active status + - Added a [“Last active” status](https://docs.mattermost.com/end-user-guide/preferences/manage-your-display-options.html#share-last-active-time) to the profile popover and to the **Direct Message** channel header that indicates when a user was last online. This status only displays for users who are Away, Offline, or in do-not-disturb (DND). This can be disabled via **Settings > Display > Share last active time**. + +### Improvements + +#### User Interface (UI) + - Renamed "Starter" plan to "Free" plan in product. + - Added a new grid-based layout to the right-hand side and globalized the right-hand side and the Apps Bar. + - A confirmation modal is now displayed before a user marks all threads as read. + - Added the ability to hide the “required” asterisk in the App Field. + - Added a fading effect to the Apps Modal body while an Apps Modal is refreshing. + - Insights now filters out posts made by plugins and OAuth apps. + - Added a shortcut ``Ctrl/Cmd + Shift + U`` to filter channels by unread. + - The default number of **Direct Message** channels shown in the sidebar is now 40. + - Added Insights to the channel switcher. + - Added a button to easily copy the content of text or code files in file previews. + - The team unread icon for muted channels is now hidden in the sidebar. + - Added the ability to create a new channel along with a new board associated with the created channel. + - Added markdown formatting for hyperlinks when pasted into the text editor. + - Email notifications from new messages now also support displaying Slack attachments from the channel post. + - Updated NPS plugin to version 1.3.0. + - Downgraded Bulgarian, Persian, and Simplified Chinese language support to Alpha. + +#### Administration + - After 90 days since missing a payment, admins will see a modal where they can choose between updating the billing status or staying on the Free subscription. + - Autocomplete results using Elasticsearch or Bleve will correctly show a user as a channel member in direct message and group message channels. To force this change to appear, a re-indexing will be necessary. + - Introduced an **Invite Guests** prompt to self-hosted. + - Added JSON-compatible nested configuration value parsing from environment variables. + - An AD/LDAP prompt banner is now shown for self-hosted instances with a Professional license when visiting the invite guests modal. + - Self-hosted Admins now see "User Groups" in the product switcher with a call to action (CTA) to start a trial. + - Added logic to package product version of Boards with production builds. + +### Bug Fixes + - Fixed an issue where Enterprise features labeled as "Professional Feature" appeared in the **System Console** sidebar. + - Fixed an issue where the transparency for PNG images in image previews and thumbnails was not preserved. + - Fixed an issue where screen readers failed to announce “No results found” in the direct message modal. + - Fixed an issue where minipreview data was not generated nor stored for images imported from Slack. + - Fixed the error message that appears on the **Reset Password** page when inputting a password with fewer than five characters. + - Fixed an issue where ``Get categories`` with the "exclude" option did not return categories for deleted teams a user was no longer a member of. + - Fixed an issue where a randomly-generated default message-ID wasn't added for every outgoing email. + - Fixed an issue where custom groups could be created with @mention names that are reserved words (@channel, @here, @all). + - Fixed an issue where 404 errors were shown when APIv4 had an incorrect content-type header. + - Fixed an issue where messages from bots and webhooks could not be forwarded. + - Fixed an issue where inline images did not appear in the channel header. + - Fixed an issue with the emoji skin tone selector animation. + - Fixed an issue where the screen reader did not announce a successful login when logging in. + - Fixed a few broken links at **System Console > User Management > Permission Schemes**. + - Fixed an issue where users were able to forward messages to users who are deactivated. + - Fixed an issue where "Threads" were not shown in the unread filter view even if there weren't unread threads. + - Fixed an issue where the user’s full name was not shown when adding people to a channel via the ``Add people`` modal. + - Fixed an issue where formatting keyboard shortcuts were conflicting with existing shortcuts. + - Fixed an issue where the markdown style for horizontal rules was too thick. + - Fixed an issue where the emoji reaction overlay blocked part of the message it belonged to in compact view. + - Fixed an issue with incorrect mention counts in unread channels. + - Fixed an issue where the cursor displayed as a pointer instead of as an arrow in embedded YouTube preview images. + - Fixed an issue where formatting was applied to selected spaces after a word. + - Fixed an issue where screen readers did not announce that the channel interface language dropdown in **Settings > Display > Language > Change** is a dropdown. + - Fixed a bug where role filters weren't being applied for ``GetProfilesInChannel``. + - Fixed an issue where the guest onboarding checklist contained an “Invite team members” link as a tour point. + - Fixed an issue where the **Enterprise license is expired** banner was non-dismissible. + - Fixed an issue where the **Renew Now** option was not showing in-product and always defaulted to Contact Sales. + - Fixed an issue where ``getPostSince`` didn't properly return deleted posts when Collapsed Reply Threads was enabled. + - Fixed an issue where ``OwnerId`` was not set for bots created via ``EnsureBotUser``. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``TeamSettings`` in the ``config.json``: + - Added ``EnableLastActiveTime`` to add a **Last active** status to the profile popover and to the **Direct Message** channel header that indicates when a user was last online. + +### API Changes + - Added a new response-header ``First-Inaccessible-File-Time`` to the APIs fetching single file information. + - Added a new query parameter to include deleted posts as long as it's requested by a system admin in ``/api/v4/channels/{channel_id}/posts``. + - Added new plugin endpoints to ``PermissionService`` interface. + +### Go Version + - v7.5 is built with Go ``v1.18.1``. + +### Known Issues + - Guest users are unable to return to the login screen after being removed from all channels [MM-48438](https://mattermost.atlassian.net/browse/MM-48438). + - Users are unable to open threads from recent mentions when switching to another team [MM-48399](https://mattermost.atlassian.net/browse/MM-48399). + - When the right-hand side is expanded, an overlay is displayed with the Threads help text popup [MM-48412](https://mattermost.atlassian.net/browse/MM-48412). + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in high availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in high availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - Boards linked to a channel you're a member of do not automatically appear on your sidebar unless you're an explicit member of the board. As a workaround, you can access the board from the channel RHS or by searching for the board via the board switcher (Ctrl/Cmd+K). Alternatively, you can ask the board admin to add you to the board as an explicit member. See the [issue-focalboard-4179](https://github.com/mattermost/focalboard/issues/4179) for more details. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [f2010126](https://translate.mattermost.com/user/f2010126/), [AbhinavVihan](https://github.com/AbhinavVihan), [adithyaakrishna](https://github.com/adithyaakrishna), [Aditya-Kapadiya](https://github.com/Aditya-Kapadiya), [adj2908](https://github.com/adj2908), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [akhil-ghatiki](https://github.com/akhil-ghatiki), [alannatodd](https://github.com/alannatodd), [alauregaillard](https://github.com/alauregaillard), [alexkuryshko](https://translate.mattermost.com/user/alexkuryshko/), [alexpjohnson](https://github.com/alexpjohnson), [alzee](https://github.com/alzee), [amogh2019](https://github.com/amogh2019), [amyblais](https://github.com/amyblais), [andrewwutw](https://translate.mattermost.com/user/andrewwutw/), [angeloskyratzakos](https://github.com/angeloskyratzakos), [aniketh-varma](https://github.com/aniketh-varma), [AntiGhot](https://github.com/AntiGhot), [anwarchk](https://github.com/anwarchk), [anx-ag](https://github.com/anx-ag), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [atlekbai](https://github.com/atlekbai), [ayrotideysarkar](https://github.com/ayrotideysarkar), [Azanul](https://github.com/Azanul), [azigler](https://github.com/azigler), [babinderrathi](https://github.com/babinderrathi), [batebobo](https://github.com/batebobo), [BediNimret](https://github.com/BediNimret), [BenCookie95](https://github.com/BenCookie95), [bpodwinski](https://translate.mattermost.com/user/bpodwinski/), [calebroseland](https://github.com/calebroseland), [cannalee90](https://github.com/cannalee90), [cecilysullivan](https://github.com/cecilysullivan), [chirag-ghosh](https://github.com/chirag-ghosh), [cinlloc](https://github.com/cinlloc), [codewithshariq](https://github.com/codewithshariq), [Conor0Callaghan](https://github.com/Conor0Callaghan), [ConorMacpherson](https://github.com/ConorMacpherson), [core](https://translate.mattermost.com/user/core/), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyberbuff](https://github.com/cyberbuff), [cyrilzhang-mm](https://github.com/cyrilzhang-mm), [d-wierdsma](https://github.com/d-wierdsma), [daniloff200](https://github.com/daniloff200), [den13501](https://github.com/den13501), [devinbinnie](https://github.com/devinbinnie), [devXprite](https://github.com/devXprite), [dibash](https://translate.mattermost.com/user/dibash/), [dibashthapa](https://github.com/dibashthapa), [Drishti-jain21](https://github.com/Drishti-jain21), [dsharma522](https://github.com/dsharma522), [Eleferen](https://translate.mattermost.com/user/Eleferen/), [emmyni](https://github.com/emmyni), [enahum](https://github.com/enahum), [enderahmetyurt](https://github.com/enderahmetyurt), [eraykisabacak](https://github.com/eraykisabacak), [erezo9](https://github.com/erezo9), [EricssonLiu](https://github.com/EricssonLiu), [ermanimer](https://github.com/ermanimer), [esethna](https://github.com/esethna), [EshaanAgg](https://github.com/EshaanAgg), [f2010126](https://github.com/f2010126), [Fanch](https://translate.mattermost.com/user/Fanch/), [Fjoerfoks](https://github.com/Fjoerfoks), [fmartingr](https://github.com/fmartingr), [francisco-core](https://github.com/francisco-core), [furqanmlk](https://github.com/furqanmlk), [gabor-boros](https://github.com/gabor-boros), [gabrieljackson](https://github.com/gabrieljackson), [gaston-flores](https://github.com/gaston-flores), [gbochora](https://github.com/gbochora), [gvlx](https://translate.mattermost.com/user/gvlx/), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hawkril](https://github.com/hawkril), [henry-shxu](https://github.com/henry-shxu), [hereje](https://github.com/hereje), [hmhealey](https://github.com/hmhealey), [hmmmmmmm](https://github.com/hmmmmmmm), [hokandil](https://github.com/hokandil), [homerCOD](https://github.com/homerCOD), [ifoukarakis](https://github.com/ifoukarakis), [iogungbade](https://github.com/iogungbade), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [javaguirre](https://github.com/javaguirre), [jeromegrosse](https://github.com/jeromegrosse), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jordanafung](https://github.com/jordanafung), [joremysh](https://github.com/joremysh), [josephjosedev](https://github.com/josephjosedev), [josevcsouza](https://translate.mattermost.com/user/josevcsouza/), [joshalling](https://github.com/joshalling), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [kscheel](https://github.com/kscheel), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [KuSh](https://github.com/KuSh), [kVarunkk](https://github.com/kVarunkk), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [ludovicobesana](https://translate.mattermost.com/user/ludovicobesana/), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo/), +[master7/](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-src](https://github.com/matthew-src), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [matthewbirtch](https://github.com/matthewbirtch), [mgdelacroix](https://github.com/mgdelacroix), [mhd-sln](https://github.com/mhd-sln), [michelengelen](https://github.com/michelengelen), [michizhou](https://github.com/michizhou), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [misantron](https://github.com/misantron), [mukul-kr](https://github.com/mukul-kr), [munish7771](https://github.com/munish7771), [nab-77](https://github.com/nab-77), [nayane95](https://github.com/nayane95), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [noxer](https://github.com/noxer), [oetiker](https://github.com/oetiker), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [patatman](https://github.com/patatman), [phoinixgrr](https://github.com/phoinixgrr), [Phrynobatrachus](https://github.com/Phrynobatrachus), [pikami](https://github.com/pikami), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [pvev](https://github.com/pvev), [rafaelrubbioli](https://github.com/rafaelrubbioli), [Rajat-Dabade](https://github.com/Rajat-Dabade), [RobBie1221](https://github.com/RobBie1221), [rolwin100](https://github.com/rolwin100), [RoyI99](https://github.com/RoyI99), [s4kh](https://github.com/s4kh), [saturninoabril](https://github.com/saturninoabril), [satya-vinay](https://github.com/satya-vinay), [sbishel](https://github.com/sbishel), [seanohue](https://github.com/seanohue), [seoyeongeun](https://translate.mattermost.com/user/seoyeongeun/), [shawnaym](https://github.com/shawnaym), [shikhar13012001](https://github.com/shikhar13012001), [simcard0000](https://github.com/simcard0000), [sinansonmez](https://github.com/sinansonmez), [sk409](https://github.com/sk409), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [tboulis](https://github.com/tboulis), [thenishantsapkota](https://github.com/thenishantsapkota), [tilto0822](https://github.com/tilto0822), [TomerPacific](https://github.com/TomerPacific), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [uravgkarthik](https://github.com/uravgkarthik), [varghesejose2020](https://github.com/varghesejose2020), [varunKT001](https://github.com/varunKT001), [vish9812](https://github.com/vish9812), [VishakhaPoonia](https://github.com/VishakhaPoonia), [vitorcruzfaculdade](https://github.com/vitorcruzfaculdade), [vivekkj123](https://github.com/vivekkj123), [Wetula](https://github.com/Wetula), [WhiteHsu](https://github.com/WhiteHsu), [wiggin77](https://github.com/wiggin77), [WilliamLongKing](https://github.com/WilliamLongKing), [Willyfrog](https://translate.mattermost.com/user/Willyfrog/), [wralith](https://github.com/wralith), [yakuter](https://github.com/yakuter), [Yordaniss](https://translate.mattermost.com/user/Yordaniss/), [zafar-hussain](https://github.com/zafar-hussain), [zefhemel](https://github.com/zefhemel) + +---- + +(release-v7-4-feature-release)= +## Release v7.4 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.4.1, released 2022-12-21** + - Mattermost v7.4.1 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a new schema migration to ensure ``ParentId`` column is dropped from the ``Posts`` table. Depending on the table size, if the column is not dropped before, a significant spike in database CPU usage is expected on MySQL databases. Writes to the table will be limited during the migration. + - Updated prepackaged Boards version to 7.4.3. +- **v7.4.0, released 2022-10-16** + - Original 7.4.0 release + +Mattermost v7.4.0 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Highlights + +#### Boards + - Added new [board roles](https://docs.mattermost.com/end-user-guide/project-management/share-and-collaborate.html#roles), **Commenter** and **Viewer**. + - Added [minimum default board roles](https://docs.mattermost.com/end-user-guide/project-management/share-and-collaborate.html#manage-team-access) to reduce permissioning ambiguity and to prevent security loopholes. + - Added support for [guest accounts](https://docs.mattermost.com/administration-guide/onboard/guest-accounts.html). + - Added the ability to add a team member to a board by selecting their name from [an autocomplete list](https://docs.mattermost.com/end-user-guide/project-management/work-with-cards.html#mention-people). + - Added channel notifications for linked boards. + - Added a new [multi-person property](https://docs.mattermost.com/end-user-guide/project-management/work-with-cards.html#work-with-property-types) to easily set multiple assignees or owners on a card. + +#### Calls + - Added new [keyboard shortcuts for Calls](https://docs.mattermost.com//end-user-guide/collaborate/keyboard-shortcuts.html#calls). + +### Improvements + +#### User Interface (UI) + - Added a red destructive action color to the **Leave Channel** button in the channel header. + - Downgraded Brazilian Portuguese and Romanian language support to Alpha. + - Pre-packaged Playbooks v1.32.6. + +#### Administration + - A ``batchSize`` option has been added to the ``mattermost export`` CLI command to limit the number of items exported. By default, if it is not included, it exports all posts. + - Added more context to the “Notify admin” feature to help Admins, such as who asked to upgrade, why they requested the upgrade, and how many people requested it. + +### Bug Fixes + - Fixed an issue with a nil point exception error during imports. + - Fixed an issue where users were unable to download a [Support Packet](https://docs.mattermost.com/administration-guide/manage/admin/generating-support-packet.html) using the Desktop App. + - Fixed an issue with the **Message forward** modal where the auto-complete in the comment box moved with the text cursor. + - Fixed an issue where muted channels with an at-mention were displayed under the **Unreads** section of the channel switcher. + - Fixed an issue where the Collapsed Reply Threads setting was displayed in the **System Console > Experimental Features** section. + - Fixed an issue with the badge count on the mobile app when a channel/thread was viewed. + - Fixed an issue where typing ``@`` in the right-hand side rendered a cut-off user suggestion list. + - Fixed an issue where an error screen was briefly flashed when the first Admin signed up into a new server. + - Fixed an issue where users were unable to add Japanese comments correctly in the message **Forward** modal. + - Fixed an issue where unsaved edits to a post were lost when switching channels or threads. + - Fixed an issue on larger screen sizes where the Insights widgets were pushed to the side when the right-hand side was open. + - Fixed an issue where the ability to forward messages from public channels wasn't possible when messaging someone directly for the first time. + - Fixed an issue where custom emojis were sometimes not visible in **Insights > Top Reactions**. + - Fixed an issue where channels with no posts within a particular timeframe didn't show in **Insights > Least Active Channel**. + - Fixed an issue where the Channel Info right-hand side shortcut was not disabled in the Insights view. + - Fixed an issue where an in-product link was missing from **Integrations > Bot Accounts > Add Bot Account**. + - Reverted the new search of names in PostgreSQL using full text search introduced in v7.3.0 due to a performance regression. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableAPITriggerAdminNotifications`` to add an option to receive more context from the “Notify admin” feature to help Admins. + +### API Changes + - If ``EnableConfirmNotificationsToChannel`` is disabled, channel member counts by group API are no longer called. + +### Websocket Event Changes + - Added ``OmitConnection`` to the websocket broadcast parameters. + +### Go Version + - v7.4 is built with Go ``v1.18.1``. + +### Known Issues + - The **More** menu for Pinned posts on the right-hand side is cut-off [MM-46987](https://mattermost.atlassian.net/browse/MM-46987). + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [abhijit-singh](https://github.com/abhijit-singh), [AbhinavVihan](https://github.com/AbhinavVihan), [adrian.lee](https://translate.mattermost.com/user/adrian.lee), [aerokite](https://github.com/aerokite), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alauregaillard](https://translate.mattermost.com/user/alauregaillard), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [anx-ag](https://github.com/anx-ag), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [azigler](https://github.com/azigler), [babinderrathi](https://github.com/babinderrathi), [BenCookie95](https://github.com/BenCookie95), [boahc077](https://github.com/boahc077), [bpodwinski](https://translate.mattermost.com/user/bpodwinski), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [cecilysullivan](https://github.com/cecilysullivan), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [cyrilzhang-mm](https://github.com/cyrilzhang-mm), [d-wierdsma](https://github.com/d-wierdsma), [danielsischy](https://github.com/danielsischy), [darkLord19](https://github.com/darkLord19), [devinbinnie](https://github.com/devinbinnie), [dezerb](https://github.com/dezerb), [dontoisme](https://github.com/dontoisme), [edlerd](https://github.com/edlerd), [ehsan](https://translate.mattermost.com/user/ehsan), [enahum](https://github.com/enahum), [fmartingr](https://github.com/fmartingr), [frstier](https://github.com/frstier), [ftonato](https://github.com/ftonato), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [gvlx](https://github.com/gvlx), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [henry-shxu](https://github.com/henry-shxu), [hmhealey](https://github.com/hmhealey), [Hornet-Wing](https://github.com/Hornet-Wing), [info4pdv](https://github.com/info4pdv), [iomodo](https://github.com/iomodo), [jaskiratsingh2000](https://github.com/jaskiratsingh2000), [jasonblais](https://github.com/jasonblais), [javaguirre](https://github.com/javaguirre), [jespino](https://github.com/jespino), [Jio007](https://github.com/Jio007), [johnsonbrothers](https://github.com/johnsonbrothers), [josevcsouza](https://translate.mattermost.com/user/josevcsouza), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [ksankeerth](https://github.com/ksankeerth), [Kshitij-Katiyar](https://github.com/Kshitij-Katiyar), [lafriks](https://github.com/lafriks), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matthewbirtch](https://github.com/matthewbirtch), [mehran-prs](https://github.com/mehran-prs), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mjnagel](https://github.com/mjnagel), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [MusabShakeel576](https://github.com/MusabShakeel576), [mylonsuren](https://github.com/mylonsuren), [natalie-hub](https://github.com/natalie-hub), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [noxer](https://github.com/noxer), [ogi-m](https://github.com/ogi-m), [orlandorode97](https://github.com/orlandorode97), [pejotu](https://github.com/pejotu), [pfltdv](https://github.com/pfltdv), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [Rajat-Dabade](https://github.com/Rajat-Dabade), [rolwin100](https://github.com/rolwin100), [RoyI99](https://github.com/RoyI99), [safakkizkin](https://github.com/safakkizkin), [salmanmanekia](https://github.com/salmanmanekia), [SaptarshiSarkar12](https://github.com/SaptarshiSarkar12), [sashashura](https://github.com/sashashura), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [SelyanKab](https://github.com/SelyanKab), [shiken](https://translate.mattermost.com/user/shiken), [simcard0000](https://github.com/simcard0000), [sinansonmez](https://github.com/sinansonmez), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [tboulis](https://github.com/tboulis), [tilto0822](https://translate.mattermost.com/user/tilto0822), [TMaYaD](https://github.com/TMaYaD), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [urvesh20](https://github.com/urvesh20), [varghesejose2020](https://github.com/varghesejose2020), [vdvukhzhilov](https://github.com/vdvukhzhilov), [vetash](https://github.com/vetash), [vish9812](https://github.com/vish9812), [VishakhaPoonia](https://github.com/VishakhaPoonia), [wgshtg](https://github.com/wgshtg), [wiggin77](https://github.com/wiggin77), [yangyangdaji](https://github.com/yangyangdaji), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v7.3 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.3.1, released 2022-10-14** + - Mattermost v7.3.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Reverted the new search of names in PostgreSQL using full text search introduced in v7.3.0 due to a performance regression. +- **v7.3.0, released 2022-09-16** + - Original 7.3.0 release + +Mattermost v7.3.0 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - Boards is moving from a channel-based to a role-based permissions system. The migration will happen automatically, but your administrator should perform a backup prior to the upgrade. We removed workspaces, so if you were a member of many boards prior to migration, they will now all appear under the same sidebar. Please see [this document](https://docs.mattermost.com/welcome/whats-new-in-v72.html) for more details. + +```{Important} +If you upgrade from a release earlier than v7.2, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Playbooks + - Navigate between teams in Playbooks with the new team switcher. + - Manage playbooks and runs in the new left-hand sidebar. + - View the runs you're participating in or following in the **Runs** sidebar category, and view the playbooks you're a member of in the **Playbooks** sidebar category. + - Favorite runs or playbooks to prioritize them in the **Favorites** category. + - Participants now have access to every run feature on the new run details page. + - Users can now request status updates (Professional). + +#### Boards + - All the boards you’re currently a member of from your current team will appear on the sidebar without needing to switch workspaces. + - Organize boards on the sidebar with custom categories. + - Press CTRL+K/CMD+K to find additional boards. + - Navigate between teams in Boards with the new team switcher. + - Set board and template permissions in the new **Share** setting. + - Link boards to channels to automatically grant board permissions to channel members. + - See [the documentation](https://docs.mattermost.com/welcome/whats-new-in-v72.html) for more details. + +#### Calls + - Added support for standalone Calls server and Kubernetes (Enterprise). + +#### New Insights Widgets + - Added four new [Insights widgets](https://docs.mattermost.com/welcome/insights.html): Most Active Direct Messages, Least Active Channels, Top Playbooks, and New Team Members. + +### Improvements + +#### User Interface (UI) + - Added Calls keyboard shortcuts to the **Keyboard shortcuts** help modal. + - Updated the "Contact Sales" link to ``mattermost.com/pl/contact-sales`` and update the pricing modal user interface. + - Introduced a new ``/marketplace`` slash command that brings up the marketplace modal for the Admin, and changed the ``/help`` command so that it now keeps the user internal to Mattermost. + - Team unreads are now calculated based on the channel membership and threads only. Team membership is no longer taken into account. + - For introducing Boards and Playbooks to new users, an “explore other tools in platform” item was added to the end user onboarding checklist. + - Added the **Save** option to the post menu. + - Only the most recent message is now marked as unread when marking a thread as unread from the Threads list. + - Insights filters now persist instead of being reset to default when switching to channels and returning back to the Insights view. + - Code blocks now have better support for language filetype extensions and are a smaller bundle size. + - A Desktop App prompt is now always shown on first visit to a Mattermost server from an email notification. + - Search dropdown options now allow focusing by pressing the tab key. + - Downgraded Bulgarian language support to Beta. + +#### Administration + - Added a **View Plan** button within the plan card via **System Console > License**. + - Started tracking the join time of team members and added a new API endpoint to retrieve information about team members who have joined during a given time. + - Introduced an optional ``shouldRender`` function parameter to ``registerchannelHeaderMenuAction`` plugin function. This allows menu items to conditionally render depending on the current state prior to rendering. + - Plugins can now hide plugin settings based on the server's hosting environment. + - Customers who are on a 30-day free trial are now notified three days before the trial ends. + +### Bug Fixes + - Fixed an issue where muted channels with an at-mention were displayed under the **Unreads** section of the channel switcher. + - Fixed an issue where starting a trial failed if ``SiteURL`` was not set. + - Fixed an issue where reading a thread on the mobile app caused a negative mention count to display on the web app. + - Fixed an issue where the user's profile image persisted after user account deletion. + - Fixed an issue where exports generated via mmctl without attachments still included the file properties in the post, so they couldn't be imported. + - Fixed an issue that caused a crash when unread posts were fetched. + - Fixed an issue where updating a profile image and creating new emojis used multipart uploads when using S3 storage. + - Fixed an issue where the input legend on the custom group modal was cut off in Chrome. + - Fixed an issue where the **Disable post formatting** setting was hidden when the advanced text editor was enabled. + - Fixed an issue where we didn’t fall back to the user's default picture if a profile picture failed to load. + - Fixed an issue where disabling a WebApp plugin from its configuration page resulted in the radio button reverting to ``true``. + - Fixed an issue where the cursor sometimes jumped to the center channel textbox when the right-hand side was open. + - Fixed an issue where closing the right-hand side also closed the edited post in the center channel. + - Fixed an issue where selecting "Try free now" opened the top three enterprise features instead of the "Your trial has started" modal. + - Fixed an issue where the Threads view displayed as unread even if there were no unread threads. + - Fixed an issue where configuration changes could not be saved in the **System Console** in some cases. + - Fixed typos in some translations that caused some in-product links to be broken. + +### API Changes + - Added new API endpoints: + + - ``GET /api/v4/users/me/top/dms`` + - ``GET /api/v4/users/me/top/threads`` + - ``GET /api/v4/teams/:team_id/top/team_members`` + - ``GET /api/v4/teams/:team_id:/top/threads`` + - Added ``first_inaccessible_post_time`` to post API responses. + - Adds query parameter ``include_deleted`` to endpoint: ``{{[http://your-mattermost-url.com/api/v4/posts/{post_id}/files/info}}](http://your-mattermost-url.com/api/v4/posts/%7Bpost_id%7D/files/info%7D%7D)``. + +### Go Version + - v7.3 is built with Go ``v1.18.1``. + +### Open Source Components + - Added ``@floating-ui/react-dom-interactions`` to https://github.com/mattermost/mattermost-webapp. + +### Known Issues + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - On larger screens, the Insights widgets are pushed to the side when the right-hand side is open [MM-46886](https://mattermost.atlassian.net/browse/MM-46886). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + - The Playbooks left-hand sidebar does not update when a user is added to a run or playbook without a refresh. + +### Contributors + - [97amarnathk](https://github.com/97amarnathk), [AbhinavVihan](https://github.com/AbhinavVihan), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [AlexanderMC8533](https://github.com/AlexanderMC8533), [amyblais](https://github.com/amyblais), [antonbuks](https://github.com/antonbuks), [anx-ag](https://github.com/anx-ag), [aperez900907](https://github.com/aperez900907), [asaadmahmood](https://github.com/asaadmahmood), [asatkinson](https://github.com/asatkinson), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [ComicShrimp](https://github.com/ComicShrimp), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [d-wierdsma](https://github.com/d-wierdsma), [danielsischy](https://github.com/danielsischy), [devinbinnie](https://github.com/devinbinnie), [dimeko](https://github.com/dimeko), [dipak-demansol](https://github.com/dipak-demansol), [dsharma522](https://github.com/dsharma522), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [francescbassas](https://github.com/francescbassas), [frstier](https://github.com/frstier), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [gmerz](https://github.com/gmerz), [HandsomeChoco](https://github.com/HandsomeChoco), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [hyugabokko](https://github.com/hyugabokko), [ijansky](https://github.com/ijansky), [iogungbade](https://github.com/iogungbade), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jacodaybson](https://github.com/jacodaybson), [jaskiratsingh2000](https://github.com/jaskiratsingh2000), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jpmastermind](https://github.com/jpmastermind), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [krisfremen](https://github.com/krisfremen), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [Liberontissauri](https://github.com/Liberontissauri), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m1lt0n](https://github.com/m1lt0n), [majo](https://translate.mattermost.com/user/majo), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mbc](https://translate.mattermost.com/user/mbc), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mjnagel](https://github.com/mjnagel), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [nadeem-hassan](https://github.com/nadeem-hassan), [natalie-hub](https://github.com/natalie-hub), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [noxer](https://github.com/noxer), [orlandorode97](https://github.com/orlandorode97), [petrmifek](https://github.com/petrmifek), [pfltdv](https://github.com/pfltdv), [pheel](https://github.com/pheel), [phoinixgrr](https://github.com/phoinixgrr), [phpfs](https://github.com/phpfs), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [RoyI99](https://github.com/RoyI99), [rtfm98](https://github.com/rtfm98), [sadohert](https://github.com/sadohert), [safakkizkin](https://github.com/safakkizkin), [salmanmanekia](https://github.com/salmanmanekia), [santoniriccardo](https://github.com/santoniriccardo), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [shamboozles](https://github.com/shamboozles), [sibasankarnayak](https://github.com/sibasankarnayak), [sinansonmez](https://github.com/sinansonmez), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [suzutatsu](https://github.com/suzutatsu), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [TalelingFantasy](https://translate.mattermost.com/user/TalelingFantasy), [tboulis](https://github.com/tboulis), [thepra](https://translate.mattermost.com/user/thepra), [thinkGeist](https://github.com/thinkGeist), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [varundey](https://github.com/varundey), [vetash](https://github.com/vetash), [vish9812](https://github.com/vish9812), [wgshtg](https://translate.mattermost.com/user/wgshtg), [whiver](https://github.com/whiver), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wsh](https://translate.mattermost.com/user/wsh), [wuwinson](https://github.com/wuwinson), [yangyangdaji](https://github.com/yangyangdaji), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v7.2 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v7.2.1, released 2022-10-14** + - Mattermost v7.2.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.2.0, released 2022-08-16** + - Original 7.2.0 release + +Mattermost v7.2.0 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes +Several schema changes impose additional database constraints to make the data more strict. All the commands listed below were tested on a 8 core, 16GB RAM machine. Here are the times recorded: + +**PostgreSQL (131869 channels, 2 teams)**: + +- ``CREATE TYPE channel_type AS ENUM ('P', 'G', 'O', 'D');`` took 14.114 milliseconds +- ``ALTER TABLE channels alter column type type channel_type using type::channel_type;`` took 3856.790 milliseconds (3.857 seconds) +- ``CREATE TYPE team_type AS ENUM ('I', 'O');`` took 4.191 milliseconds +- ``ALTER TABLE teams alter column type type team_type using type::team_type;`` took 116.205 milliseconds +- ``CREATE TYPE upload_session_type AS ENUM ('attachment', 'import');`` took 4.266 milliseconds +- ``ALTER TABLE uploadsessions alter column type type upload_session_type using type::upload_session_type;`` took 37.099 milliseconds + +**MySQL (270959 channels, 2 teams)**: + +- ``ALTER TABLE Channels MODIFY COLUMN Type ENUM("D", "O", "G", "P");`` took 13.24 seconds +- ``ALTER TABLE Teams MODIFY COLUMN Type ENUM("I", "O");`` took 0.04 seconds +- ``ALTER TABLE UploadSessions MODIFY COLUMN Type ENUM("attachment", "import");`` took 0.03 seconds + +```{Important} +If you upgrade from a release earlier than v7.1, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Message Forwarding + - You can now easily share messages as permalinks and respective permalink previews via the new [Post Forwarding feature](https://docs.mattermost.com/channels/forward-messages.html). Simply select the new **Forward** option from the **More** section of the message hover actions menu on a given message, choose a desired destination, and optionally add a comment for context. + +#### Audit Log v2 (Beta) + - Added support for new [schema and output log types](https://docs.mattermost.com/comply/audit-log.html). Contrary to the previous audit log implementation, all audit log records now have the same schema. + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls v0.7.1. + - Added the option to colorize usernames in compact display mode when **Account Settings > Display > Message Display > Compact** is selected. + - Added a setting to always land users at the newest messages in a channel via **Account settings > Advanced > Scroll position when viewing an unread channel**. + - Added email headers to notification emails so they can be threaded by email clients. + - Added **Save** and **Cancel** buttons for post inline editing. + - Enterprise trial details are now displayed for end users in the product switcher menu. + - Updated the **Edit Header** modal text description to be applicable to channels, direct messages, and group messages. + - Added a red destructive action color to ``Archive Channel`` and ``Leave Channel`` menu actions. + - Plugin activation errors now show in the plugin management page and marketplace. + - Added accessibility to the emoji picker skin tone selector and reversed the order of the skin tone selections in the emoji selector. + +#### Administration + - Added an **Upgrade** button for Admins on the navigation bar. + - Added the ability for Admins to quickly view different paid license options inside the product. + - Added the ability to start a trial from the **Invite People** modal. + - Admins are now able to search for channel IDs via **System Console > User Management > Channels** page. + - In the **System Console** left-hand side, paid features icons are now displayed on the menu entries to indicate enterprise features. + - Added ``webSocketClient`` to ``Pluggable`` and ``PostWillRenderEmbed`` plugin registered components. + - Added a new static system-level role called [Custom Group Manager](https://docs.mattermost.com/onboard/system-admin-roles.html). This role has permissions to create, edit, and delete custom user groups via User Groups in the Products menu. It can be used to assign individual users this ability when Custom Groups permissions are removed for All Members via the **System Console** (**System Console > Permissions > Edit Scheme > Custom Groups**). + - Export file names now contain the ID of the job they were generated by. + +### Performance + - Removed ``getLastPostPerChannel`` selector for improved performance in channel sorting. + +### Bug Fixes + - Fixed an issue with pasting a GitHub code snippet in the message box when text is selected. + - Fixed an issue where fully typed emojis that contained a capital letter were not correctly displayed. + - Fixed an issue where the archive icon for channels did not display correctly in dark themes. + - Fixed an issue where password requirements were not enforced when Development Mode was enabled. + - Fixed an issue where users were able to attempt to edit the channel header of an archived channel on the right-hand side. + - Fixed an issue where the “Your Trial Ended” banner hid the product switcher menu. + - Fixed an issue where the custom status date format was not set to ``YYYY-MM-DD``. + - Fixed an issue where users were unable to remove themselves from a custom role. + - Fixed an issue where some images in link previews overflowed. + - Fixed an issue where accessing the **System Console** and then exiting changed the user's status to "Offline". + - Fixed an issue where the **New Messages** line sometimes appeared when viewing a channel that was previously read. + - Fixed an issue with incorrectly formatted text in the **System Console**. + - Fixed an issue where the thread's view would appear as if it has unread threads even if no unread threads existed. + - Fixed an issue that caused a crash when fetching unread posts. + - Fixed an issue where the mobile app crashed when unfollowing a thread of a channel that a user was no longer a member of. + - Fixed an issue where the Custom Brand text was not centered and Site Description configuration did not show a placeholder. + - Fixed an issue where the group permissions had an extra level of nesting in the user interface. Also the permissions checkboxes were split out into their individual custom group permissions for a greater granularity of control. + - Fixed an issue where the OpenID Connect authentication button was missing from the signup page. + - Fixed an issue with autocomplete sorting regression in channels and threads. + - Fixed an issue where the custom branding logo was distorted on the login screen. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``FileSettings`` in ``config.json``: + - A new config setting ``AmazonS3RequestTimeoutMilliseconds`` was added which sets a timeout for requests to AWS S3. By default, the timeout is at 30 seconds. + +#### API Changes + - Added a new response-header ``Has-Inaccessible-Posts`` for ``getPost`` and ``getPostByIDs`` APIs. + +### Go Version + - v7.2 is built with Go ``v1.18.1``. + +### Open Source Components + - Added ``@types/color-hash``, ``color-contrast-checker``, ``color-hash``, and ``webpack`` to https://github.com/mattermost/mattermost-webapp. + +### Known Issues + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - Forwarding messages: pressing Enter key on an auto-complete item in the comment box sends the forward message [MM-46142](https://mattermost.atlassian.net/browse/MM-46142). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [64bitpandas](https://github.com/64bitpandas), [Afsoon](https://github.com/Afsoon), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [Apahadi73](https://github.com/Apahadi73), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [avinashlng1080](https://github.com/avinashlng1080), [azigler](https://github.com/azigler), [ballista01](https://github.com/ballista01), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [d-wierdsma](https://github.com/d-wierdsma), [debasish4patra](https://github.com/debasish4patra), [devinbinnie](https://github.com/devinbinnie), [eggmoid](https://github.com/eggmoid), [filipeandrade6](https://github.com/filipeandrade6), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [Haliax](https://github.com/Haliax), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hegocre](https://github.com/hegocre), [hmhealey](https://github.com/hmhealey), [ifnotak](https://github.com/ifnotak), [imasdekar](https://github.com/imasdekar), [imskr](https://github.com/imskr), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [iyampaul](https://github.com/iyampaul), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [jonathanwiemers](https://github.com/jonathanwiemers), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [KantinHoll](https://translate.mattermost.com/user/KantinHoll), [karistuck](https://github.com/karistuck), [kayazeren](https://github.com/kayazeren), [komarnitskyi](https://github.com/komarnitskyi), [koox00](https://github.com/koox00), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [kyeongsoosoo](https://github.com/kyeongsoosoo), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [manojmalik20](https://github.com/manojmalik20), [MarkAndersonTrocme](https://github.com/MarkAndersonTrocme), [master7](https://translate.mattermost.com/user/master7), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [muratbayan](https://github.com/muratbayan), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [noxer](https://github.com/noxer), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [pfltdv](https://github.com/pfltdv), [phoinixgrr](https://github.com/phoinixgrr), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [pjenicot](https://github.com/pjenicot), [plant99](https://github.com/plant99), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [RKRohk](https://github.com/RKRohk), [RoyI99](https://github.com/RoyI99), [sadohert](https://github.com/sadohert), [samia64saleem](https://github.com/samia64saleem), [santoniriccardo](https://github.com/santoniriccardo), [saosangmo](https://github.com/saosangmo), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [serhack](https://github.com/serhack), [shamboozles](https://github.com/shamboozles), [Sharuru](https://github.com/Sharuru), [sibasankarnayak](https://github.com/sibasankarnayak), [SilverKnightKMA](https://github.com/SilverKnightKMA), [sinansonmez](https://github.com/sinansonmez), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [t0mm0](https://github.com/t0mm0), [tboulis](https://github.com/tboulis), [thePanz](https://github.com/thePanz), [thinkGeist](https://github.com/thinkGeist), [tiagodll](https://github.com/tiagodll), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [vdvukhzhilov](https://github.com/vdvukhzhilov), [vish9812](https://github.com/vish9812), [weblate](https://github.com/weblate), [whiver](https://github.com/whiver), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yoikeda](https://github.com/yoikeda), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v7.1 - [Extended Support Release](https://docs.mattermost.com/upgrade/release-definitions.html#extended-support-release-esr) + +```{Important} +Support for Mattermost Server v7.1 [Extended Support Release](https://docs.mattermost.com/about/release-policy.html#extended-support-releases) has come to the end of its life cycle on May 15, 2023. [Upgrading Mattermost Server](https://docs.mattermost.com/about/mattermost-server-releases.html#latest-releases) is required. +``` + +- **v7.1.9, released 2023-04-27** + - Mattermost v7.1.9 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.1.8, released 2023-04-12** + - Mattermost v7.1.8 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.1.7, released 2023-03-17** + - Added a ``exclude_files_count`` parameter to exclude file counts from channel stats API. + - Excluded the file count on channel stats API call on from channel header. +- **v7.1.6, released 2023-03-01** + - Mattermost v7.1.6 contains medium to high severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where threads were not marked as unread in the Threads view. + - Fixed an issue where the server sent a wrong badge number when marking a message as unread in a Direct Message channel. +- **v7.1.5, released 2022-12-21** + - Mattermost v7.1.5 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a new schema migration to ensure ``ParentId`` column is dropped from the ``Posts`` table. Depending on the table size, if the column is not dropped before, a significant spike in database CPU usage is expected on MySQL databases. Writes to the table will be limited during the migration. + - Fixed an issue where **Renew Now** option was not available in-product for self-serve eligible licenses [MM-47045](https://mattermost.atlassian.net/browse/MM-47045). + - ``getPostSince`` now properly returns deleted posts when Collapsed Reply Threads is enabled. + - Fixed an issue where the ``Enterprise license is expired`` banner was undismissable [MM-47396](https://mattermost.atlassian.net/browse/MM-47396). + - Fixed an issue where screen readers did not announce search results in the "Invite members to channel" modal [MM-44859](https://mattermost.atlassian.net/browse/MM-44859). + - Fixed an issue where screen readers did not announce emojis in the autocomplete list [MM-44877](https://mattermost.atlassian.net/browse/MM-44877). + - Fixed an issue where screen readers did not announce successful logins [MM-46596](https://mattermost.atlassian.net/browse/MM-46596). + - Fixed an issue where screen readers incorrectly announced the **Settings > Display > Language > Change interface language** field [MM-44114](https://mattermost.atlassian.net/browse/MM-44114). + - Fixed an issue where the search dropdown options did not allow focusing with a tab [MM-34969](https://mattermost.atlassian.net/browse/MM-34969). + - Fixed an issue where screen readers failed to announce "no results found" in the **Direct Message** modal [MM-44858](https://mattermost.atlassian.net/browse/MM-44858). + - Fixed an issue where the **Test Connection** button in **System Console > Environment > Elasticsearch** did not correctly take the right config settings specified in the page. Earlier, it would always take the previously saved config [MM-47154](https://mattermost.atlassian.net/browse/MM-47154). +- **v7.1.4, released 2022-10-14** + - Mattermost v7.1.4 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.1.3, released 2022-08-23** + - Mattermost v7.1.3 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where Admins were unable to save configuration changes in the **System Console** in some cases [MM-45875](https://mattermost.atlassian.net/browse/MM-45875). +- **v7.1.2, released 2022-07-21** + - Fixed an issue where mmctl checked the server version incorrectly. +- **v7.1.1, released 2022-07-15** + - Fixed an issue where selecting "Update" next to an outdated Marketplace plugin didn't work [MM-45731](https://mattermost.atlassian.net/browse/MM-45731). +- **v7.1.0, released 2022-07-15** + - Original 7.1.0 release + +Mattermost v7.1.0 contains low severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - A new configuration option ``MaxImageDecoderConcurrency`` indicates how many images can be decoded concurrently at once. The default is -1, and the value indicates the number of CPUs present. This affects the total memory consumption of the server. The maximum memory of a single image is dictated by ``MaxImageResolution * 24 bytes``. Therefore, we recommend that ``MaxImageResolution * MaxImageDecoderConcurrency * 24`` should be less than the allocated memory for image decoding. + - Mattermost v7.1 introduces schema changes in the form of a new column and its index. The following notes our test results for the schema changes: + - MySQL 12M Posts, 2.5M Reactions - ~1min 34s (instance: PC with 8 cores, 16GB RAM) + - PostgreSQL 12M Posts, 2.5M Reactions - ~1min 18s (instance: db.r5.2xlarge) + - You can run the following SQL queries before the upgrade to obtain a lock on ``Reactions`` table, so that users' reactions posted during this time won't be reflected in the database until the migrations are complete. This is fully backwards-compatible. + - For MySQL: + - ``ALTER TABLE Reactions ADD COLUMN ChannelId varchar(26) NOT NULL DEFAULT "";`` + - ``UPDATE Reactions SET ChannelId = COALESCE((select ChannelId from Posts where Posts.Id = Reactions.PostId), '') WHERE ChannelId="";`` + - ``CREATE INDEX idx_reactions_channel_id ON Reactions(ChannelId) LOCK=NONE;`` + + - For PostgreSQL: + - ``ALTER TABLE reactions ADD COLUMN IF NOT EXISTS channelid varchar(26) NOT NULL DEFAULT '';`` + - ``UPDATE reactions SET channelid = COALESCE((select channelid from posts where posts.id = reactions.postid), '') WHERE channelid='';`` + - ``CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_reactions_channel_id on reactions (channelid);`` + +```{Important} +If you upgrade from a release earlier than v7.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Insights (Beta) (Enterprise and Professional) + - Added workplace insights consisting of usage and behavior data, which helps Enterprises further increase productivity of their employees through Mattermost functionality. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + +### Improvements + +#### User Interface (UI) + - Pre-packaged Playbooks v1.29.1, Boards v7.1.0, and Calls v0.7.0. + - Recent emojis are now sorted based on the number of times an emoji has been used. + - Improved the link preview user interface. + - Added new search shortcuts to the **Keyboard Shortcuts** modal. + - CMD+F (macOS) and CTRL+F (Windows) for Desktop App + - CMD+SHIFT+F (macOS) and CTRL+SHIFT+F (Windows) for webapp + - Changed some tooltips to appear when focused instead of just on hover. +- Added support for syntax highlighting for 1C:Enterprise (BSL) language. + +#### Administration + - Default password requirements have been loosened to eight characters and no numeric, casing, or special characters required. These requirements can be configured by the System Admin as needed via **System Console > Password**. + - The System Console now also searches and returns channels based on the channel ID. A new parameter ``IncludeSearchById`` was added to the channel search endpoint, allowing requests to include searches that match IDs in response. + - Search results in PostgreSQL will now respect the ``default_text_search_config`` value instead of being hardcoded to English. Mattermost System Admins should check this value in case of any discrepancies with what is expected. + - Moved ``UserHasJoinedTeam`` callback to after a user is added to a team. + +#### Performance + - Reduced the number of calls made to ``viewChannel`` API during regular usage. + - Added pagination to the ``getPostThread`` API calls. + +### Bug Fixes + - Fixed an issue where links to internal help pages did not always open in a new browser tab. + - Fixed an issue that caused the Channel Members right-hand side search input to not search all the members of a channel. + - Fixed an issue where the feature discovery page still displayed a **Start Trial** button after a trial was completed. + - Fixed an issue where channel recency sorting was not consistent between mobile and webapp. + - Fixed an issue with uploading SVG files. + - Fixed an issue where thread posts were not left-aligned in compact message display mode. + - Fixed an error about a missing column for the Shared Channels experimental feature. + - Fixed an issue where the channel menu drop-down option "Move to..." was skipped when pressing the TAB keyboard key. + - Fixed an issue where the bulk import failed due to reply ``CreateAt`` being greater than that of the parent post. + - Fixed an undefined error when leaving a channel with the Unreads filter enabled. + - Fixed an issue where clicking on a quick emoji reaction opened the right-hand pane. + - Fixed an issue where the keyboard focus did not go back to the post textbox after hitting CTRL/CMD+SHIFT+P twice. + - Fixed an issue where the upload files button was positioned incorrectly. + - Fixed an issue where duplicated emojis sometimes displayed as recently used emojis. + - Fixed an issue where autocomplete "@" search for names did not normalize UTF-8 characters. + - Fixed an issue where **Group Messages** with long display names didn't have a tooltip in the left-hand sidebar. + - Fixed an issue where the file icon was sometimes unresponsive. + - Fixed a race condition where switching teams to an unread channel did not appear to mark that channel as read. + - Fixed an issue where the error message did not appear if a user drafted a too long post. + - Fixed an issue where channels with more than 100 members only showed 100 channel members in the right-hand side. + - Fixed an issue where the preview mode in the advanced text editor did not reset after posting a message. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - The setting ``EnableInsecureOutgoingConnections`` is now applicable to S3 clients as well. If that is set, s3 clients will skip TLS verification. + +#### API Changes + - To allow Admins to retrieve contents of posts whether they are deleted or not, ``include_deleted`` query parameter was introduced to ``GetPost`` endpoint. + +### Go Version + - v7.1 is built with Go ``v1.18.1``. + +### Open Source Components + - Added ``@floating-ui/react-dom`` and removed ``superagent`` and ``jasny-bootstrap`` from https://github.com/mattermost/mattermost-webapp/. + +### Known Issues + - The new Insights feature has some performance costs that we are working to optimize. This feature can be disabled by setting the ``MM_FEATUREFLAGS_INSIGHTSENABLED`` environment variable to ``false``. + - The Top Boards widget in Insights is slow to load. + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport results in duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [3ach](https://github.com/3ach), [abhijit-singh](https://github.com/abhijit-singh), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alejdg](https://github.com/alejdg), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [antonbuks](https://github.com/antonbuks), [anurag6713](https://github.com/anurag6713), [armanchand](https://github.com/armanchand), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [azigler](https://github.com/azigler), [Ballista01](https://github.com/Ballista01), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [d-wierdsma](https://github.com/d-wierdsma), [darkLord19](https://github.com/darkLord19), [devinbinnie](https://github.com/devinbinnie), [dimoiko100](https://github.com/dimoiko100), [dipak-demansol](https://github.com/dipak-demansol), [dontoisme](https://github.com/dontoisme), [DSchalla](https://github.com/DSchalla), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [engineereng](https://github.com/engineereng), [erezo9](https://github.com/erezo9), [esethna](https://github.com/esethna), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [gbyx3](https://github.com/gbyx3), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [imasdekar](https://github.com/imasdekar), [imskr](https://github.com/imskr), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [ismaaylSpiria](https://github.com/ismaaylSpiria), [IsmailTakriti](https://translate.mattermost.com/user/IsmailTakriti/), [it33](https://github.com/it33), [jaskiratsingh2000](https://github.com/jaskiratsingh2000), [jasonblais](https://github.com/jasonblais), [jbattistispiria](https://github.com/jbattistispiria), [jespino](https://github.com/jespino), [jfcastroluis](https://github.com/jfcastroluis), [jgilliam17](https://github.com/jgilliam17), [johnsonbrothers](https://github.com/johnsonbrothers), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [keremkurtulus](https://github.com/keremkurtulus), [Kirill](https://github.com/Kirill), [koox00](https://github.com/koox00), [krisfremen](https://github.com/krisfremen), [kyeongsoosoo](https://github.com/kyeongsoosoo), [lapaz17](https://github.com/lapaz17), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://translate.mattermost.com/user/maksimatveev/), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7/), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [mayur_dhamecha](https://github.com/mayur_dhamecha), [metanerd](https://github.com/metanerd), [metehankaraca](https://github.com/metehankaraca), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [miltalex](https://github.com/miltalex), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [mvitale1989](https://github.com/mvitale1989), [natalie-hub](https://github.com/natalie-hub), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [Ngwind](https://github.com/Ngwind), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [noxer](https://github.com/noxer), [ogi-m](https://github.com/ogi-m), [pfltdv](https://github.com/pfltdv), [pheel](https://github.com/pheel), [phoinixgrr](https://github.com/phoinixgrr), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [prathers](https://github.com/prathers), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [respinffs](https://github.com/respinffs), [rodrigopinero](https://github.com/rodrigopinero), [RoyI99](https://github.com/RoyI99), [Rutam21](https://github.com/Rutam21), [sadohert](https://github.com/sadohert), [santoniriccardo](https://github.com/santoniriccardo), [sayanta66](https://github.com/sayanta66), [sbishel](https://github.com/sbishel), [serhack](https://github.com/serhack), [sinansonmez](https://github.com/sinansonmez), [sonichigo](https://github.com/sonichigo), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [tboulis](https://github.com/tboulis), [thinkGeist](https://github.com/thinkGeist), [topelrapha](https://github.com/topelrapha), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wuwinson](https://github.com/wuwinson), [yasserfaraazkhan](https://github.com/yasserfaraazkhan), [YetAnotherBlogArticle](https://github.com/YetAnotherBlogArticle), [zefhemel](https://github.com/zefhemel), [zsichina](https://github.com/zsichina) + +---- + +## Release v7.0 - [Major Release](https://docs.mattermost.com/upgrade/release-definitions.html#major-release) + +```{Important} +Support for Mattermost Server v7.0 [Major Release](https://docs.mattermost.com/about/release-policy.html#release-types) has come to the end of its life cycle on September 15, 2022. [Upgrading Mattermost Server](https://docs.mattermost.com/about/mattermost-server-releases.html#latest-releases) is required. +``` + +- **v7.0.2, released 2022-08-23** + - Mattermost v7.0.2 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v7.0.1, released 2022-06-24** + - Fixed an issue where mmctl checked the server version incorrectly [MM-45161](https://mattermost.atlassian.net/browse/MM-45161). + - Fixed an issue where the file icon was sometimes unresponsive [MM-45097](https://mattermost.atlassian.net/browse/MM-45097). + - Fixed an issue with Compliance Exports where the zip file creation failed when adding attachments to a post [MM-40179](https://mattermost.atlassian.net/browse/MM-40179). + - Fixed the notification title for ``id_loaded`` push notifications [MM-43655](https://mattermost.atlassian.net/browse/MM-43655). + - Pre-packaged Playbooks v1.28.2. +- **v7.0.0, released 2022-06-15** + - Original 7.0.0 release + +Mattermost v7.0.0 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - **IMPORTANT:** Session length configuration settings have changed from using a unit of *days* to *hours*. Instances using a config.json file or a database configuration for the following values should be automatically migrated to the new units, but instances using environment variables must make the following changes: + 1. replace `MM_SERVICESETTINGS_SESSIONLENGTHWEBINDAYS` with `MM_SERVICESETTINGS_SESSIONLENGTHWEBINHOURS` (x24 the value). + 2. replace `MM_SERVICESETTINGS_SESSIONLENGTHMOBILEINDAYS` with `MM_SERVICESETTINGS_SESSIONLENGTHMOBILEINHOURS` (x24 the value). + 3. replace `MM_SERVICESETTINGS_SESSIONLENGTHSSOINDAYS` with `MM_SERVICESETTINGS_SESSIONLENGTHSSOINHOURS` (x24 the value). + - MySQL self-hosted customers may notice the migration taking longer than usual when having a large number of rows in the ``FileInfo`` table. For MySQL, it takes around 19 seconds for a table of size 700,000 rows. The time required for PostgreSQL is negligible. The testing was performed on a machine with specifications of ``CPU - Intel i7 6-cores @ 2.6 GHz`` and ``Memory - 16 GB``. + - When a new configuration setting via **System Console > Experimental > Features > Enable App Bar** is enabled, all channel header icons registered by plugins will be moved to the new Apps Bar, even if they do not explicitly use the new registry function to render a component there. The setting for Apps Bar defaults to ``false`` for self-hosted deployments. + - The value of ``ServiceSettings.TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details [here](https://docs.mattermost.com/configure/configuration-settings.html#trusted-proxy-ip-header). + - Upgrading the Microsoft Teams Calling plugin to v2.0.0 requires users to reconnect their accounts. + +```{Important} +If you upgrade from a release earlier than v6.7, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Collapsed Reply Threads (General Availability) + - [Collapsed Reply Threads](https://docs.mattermost.com/channels/organize-conversations.html) is now generally available. Please reference [this article](https://support.mattermost.com/hc/en-us/articles/6880701948564-Administrator-s-guide-to-enabling-Collapsed-Reply-Threads) for more information and guidance for enabling the feature. + +#### Calls (Beta) + - [Native voice calling and screen sharing](https://docs.mattermost.com/channels/make-calls.html) is now available. This is a Channels-specific integration. + +#### Apps Bar (Beta) + - Channel header is now decluttered when a new configuration setting via **System Console > Experimental > Features > Enable App Bar** is enabled, to make it more obvious how to access Calls, Playbooks, and Boards when viewing a channel. All channel header icons registered by plugins will be moved to the new Apps Bar when the configuration setting is enabled, while Calls remains in the channel header. We recommend enabling the Apps Bar for servers with Calls enabled since the Apps Bar helps make space for the dedicated **Start Call** button in the channel header. + +#### Playbooks Updates + - Users can now easily keep processes up-to-date with [the inline playbook editor](https://docs.mattermost.com/playbooks/customize-a-playbook.html). + - A new statistics dashboard was added that displays the number of playbooks and run instances within the server alongside other system statistics in the **System Console**. + - Run triggers and actions now provide more control over where [status updates are posted](https://docs.mattermost.com/playbooks/customize-a-run.html) throughout a run. + +#### Message Formatting Toolbar + - The [new formatting toolbar](https://docs.mattermost.com/channels/format-messages.html#use-the-messaging-formatting-toolbar) makes Markdown accessible to everyone with easy to use controls for commonly used message formatting, such as bold, headings, links, and more. + +### Improvements + +#### User Interface (UI) + - For toggling the channel information in the right-hand pane, a shortcut CTRL/CMD+ALT+I was added. + - Added an "Unread Channels" section to the channel switcher and included threads in the results. + - Users are no longer hidden from search results in the "Add members" modal, even if they are already members of the channel. + - Applied new designs for the Login screen. + - Enabled the new onboarding task list for end users. + - The legacy **Settings > Advanced Settings > Preview Pre-release Features** setting is now deprecated in favor of the the new formatting toolbar. + - Romanian language support was downgraded to Beta. + +#### Performance + - Improved the performance of aggregate queries related to Collapsed Reply Threads. Learn more about these server performance optimizations in [this article](https://support.mattermost.com/hc/en-us/articles/6880701948564-Administrator-s-guide-to-enabling-Collapsed-Reply-Threads). + +#### Integrations + - To keep users in Mattermost when opening documentation links from the **System Console > Plugin** settings page, all the links now open in another tab. + - Changed **Actions** post menu hover text to **Message Actions**. + - Updated Apps Framework to version 1.1.0 to add improved logging. + +#### Administration + - Timestamps are now enabled in the default audit configuration. + - The Collapsed Reply Threads configuration option was moved in the **System Console** from **Experimental** to **Site Configuration > Posts**. + +#### Enterprise Subscription + - Upgraded the minor version of the ElasticSearch development Docker image. + - The Support Packet now contains two additional fields in the ``support_packet.yaml`` file: Active users and License-supported users. + +### Bug Fixes + - Fixed an issue with ADA Accessibility where screen readers did not TAB to or read "This channel has guests" in the channel header bar. + - Fixed an issue where the @mention autosuggest of users was no longer grouped by channel membership status. + - Fixed an issue where the New Messages toast was not fully tappable in narrow view. + - Fixed an issue where the shortcut modal for channel info showed ``ALT`` instead of ``SHIFT`` for Mac. + - Fixed an issue where the **Help > Report a Problem** link was not hidden when a URL was not set for **System Console > Customization > Report a Problem**. + - Fixed an issue with the timing of selector performance metrics. + - Fixed an issue where the S3 **Test Connection** button deceptively failed unless the user pressed **Save** first. + - Fixed an issue where Workspace Optimization did not load in the System Console on subpath servers. + - Fixed an issue where an error was logged when ``SendEmailNotifications`` was not set to ``true``. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Changed ``SessionLengthWebInDays`` to ``SessionLengthWebInHours``. + - Changed ``SessionLengthMobileInDays`` to ``SessionLengthMobileInHours``. + - Changed ``SessionLengthSSOInDays`` to ``SessionLengthSSOInHours``. + - The value of ``TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. + - Added ``always-on`` and ``default-on`` settings to **System Console > Posts** for Collapsed Reply Threads. When enabled (default-on), users see Collapsed Reply Threads by default and have the option to disable it in **Settings**. When always on, users are required to use Collapsed Reply Threads and can't disable it. + - The default for ``CollapsedThreads`` has been changed to ``always_on``. This change impacts new Mattermost deployments, and doesn't affect existing configurations where this value is already set to some other value. + - Under ``ExperimentalSettings`` in ``config.json``: + - Added a new config setting ``EnableAppBar`` to enable and disable the new Apps Bar. This setting is disabled by default, but we recommend enabling the Apps Bar for servers with Calls enabled since the Apps Bar helps make space for the dedicated **Start Call** button in the channel header. + +#### API Changes + - Added new API endpoints ``GET /api/v4/teams/:team_id/top/channels`` and ``GET /api/v4/users/me/top/channels`` to get top channels for a team and user. + +#### Websocket Event Changes + - Added a new ``ConnectionId`` field to ``model.WebsocketBroadcast`` that allows broadcasting a message only to a specific connection. + +### Go Version + - v7.0 is built with Go ``v1.18.1``. + +### Known Issues + - Post list doesn't always scroll down to show new messages [MM-44131](https://mattermost.atlassian.net/browse/MM-44131). + - Mentions incorrectly shows users as not in a channel [MM-44157](https://mattermost.atlassian.net/browse/MM-44157). + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicate boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [Abrahamology](https://github.com/Abrahamology), [AbrahamQll](https://translate.mattermost.com/user/AbrahamQll), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [Altaaya](https://github.com/Altaaya), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [bobmaster](https://translate.mattermost.com/user/bobmaster), [Borknab](https://github.com/Borknab), [bpmct](https://github.com/bpmct), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chenilim](https://github.com/chenilim), [cohu-dev](https://github.com/cohu-dev), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [debasish4patra](https://github.com/debasish4patra), [devinbinnie](https://github.com/devinbinnie), [dipak-demansol](https://github.com/dipak-demansol), [djanda97](https://github.com/djanda97), [eggmoid](https://github.com/eggmoid), [elyscape](https://github.com/elyscape), [enahum](https://github.com/enahum), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gavin-luo](https://github.com/gavin-luo), [gbochora](https://github.com/gbochora), [gin-melodic](https://github.com/gin-melodic), [hamzaMM](https://github.com/hamzaMM), [HandsomeChoco](https://github.com/HandsomeChoco), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jbattistispiria](https://github.com/jbattistispiria), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [jonathanwiemers](https://github.com/jonathanwiemers), [jprusch](https://github.com/jprusch), [jsoref](https://github.com/jsoref), [jtdspiria](https://github.com/jtdspiria), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [kkennethlee](https://github.com/kkennethlee), [koox00](https://github.com/koox00), [krisfremen](https://github.com/krisfremen), [krmh04](https://github.com/krmh04), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lisez](https://github.com/lisez), [lkyuchukov](https://github.com/lkyuchukov), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [master7](https://translate.mattermost.com/user/master7), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [matt-w99](https://github.com/matt-w99), [maxtrem271991](https://github.com/maxtrem271991), [metanerd](https://github.com/metanerd), [metehankaraca](https://translate.mattermost.com/user/metehankaraca/), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [miltalex](https://github.com/miltalex), [mjnagel](https://github.com/mjnagel), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [munish7771](https://github.com/munish7771), [neallred](https://github.com/neallred), [nickmisasi](https://github.com/nickmisasi), [nzeemin](https://github.com/nzeemin), [pfltdv](https://github.com/pfltdv), [phoinixgrr](https://github.com/phoinixgrr), [Phrynobatrachus](https://github.com/Phrynobatrachus), [plykung](https://translate.mattermost.com/user/plykung/), [prakharporwal](https://github.com/prakharporwal), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [RoyI99](https://github.com/RoyI99), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [sibasankarnayak](https://github.com/sibasankarnayak), [SiderealArt](https://github.com/SiderealArt), [sinansonmez](https://github.com/sinansonmez), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [TQuock](https://github.com/TQuock), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [vaaas](https://github.com/vaaas), [vadimasadchi](https://github.com/vadimasadchi), [vaheed](https://github.com/vaheed), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [windane](https://translate.mattermost.com/user/windane) + +---- + +(release-v6-7-feature-release)= +## Release v6.7 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v6.7.2, released 2022-06-15** + - Fixed an issue with Compliance Exports where the zip file creation failed when adding attachments to a post [MM-40179](https://mattermost.atlassian.net/browse/MM-40179). +- **v6.7.1, released 2022-06-13** + - Mattermost v6.7.1 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The value of ``ServiceSettings.TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening +in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details [here](https://docs.mattermost.com/configure/configuration-settings.html#trusted-proxy-ip-header). +- **v6.7.0, released 2022-05-16** + - Original 6.7.0 release + +Mattermost v6.7.0 contains low severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Compatibility + - Updated Chrome recommended minimum version to v100+. + +### Important Upgrade Notes + - New schema changes were introduced in the form of a new index. The following summarizes the test results measuring how long it took for the database queries to run with these schema changes: + - MySQL 7M Posts - ~17s (Instance: db.r5.xlarge) + - MySQL 9M Posts - 2min 12s (Instance: db.r5.large) + - Postgres 7M Posts - ~9s (Instance: db.r5.xlarge) + - For customers wanting a zero downtime upgrade, they are encouraged to apply this index prior to doing the upgrade. This is fully backwards compatible and will not acquire any table lock or affect any existing operations on the table when run manually. Else, the queries will run during the upgrade process and will lock the table in non-MySQL environments. Run the following to apply this index: + - For MySQL: `CREATE INDEX idx_posts_create_at_id on Posts(CreateAt, Id) LOCK=NONE;` + - For Postgres: `CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_posts_create_at_id on posts(createat, id);` + +```{Important} +If you upgrade from a release earlier than v6.6, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Playbooks Updates + - To keep procedures on track while reducing noise, task due dates can now be added to playbook runs (Professional and Enterprise subscriptions). + +### Improvements + +#### User Interface (UI) + - Added Files and Pinned Messages to the right-hand side Channel Info. + - Improved the New Channel modal user interface. + - Added the channel members list to the right-hand side Channel Info modal. + - Added the ability to invite new users to a team from the **Add to channel** modal. + - To be able to download images and copy public links for images more quickly, a copy URL and download buttons were added to image thumbnails. + - Added the ability to have one character long channel names. + - Pre-packaged Calls v0.4.9 with Mattermost server v6.7 (closed Beta). To participate in Beta testing, please contact [Mattermost](https://mattermost.com/contact-sales/). + - Updated the NPS plugin to version 1.2.0 to add a new **Give Feedback** menu item to the **Help** menu to send feedback at anytime. + +#### Performance + - Improved the performance of ``GetTeamsUnreadForUser`` when Collapsed Reply Threads is enabled. + - Added an index to the ``UserGroups DisplayName`` for improved autosuggest query performance. + - Improved the performance of permission selectors. + - Improved the performance of configuration read/writes if the configuration is stored on a database. + +#### Administration + - To add the ability to toggle sending inactivity email notification to Admins, a configuration setting ``EmailSettings.EnableInactivityEmail`` was added. + - To filter out deactivated users in the System Console, an **Active** filter was added for users and Admins in **System Console > User Management > Users**. + - Added a ``threadsOnly`` query parameter for getting user threads. + - To allow Admins to add a new license without having to first remove the old one, a new “License" button was added to **System Console > Edition and License**. + +#### Enterprise Subscription + - The Elasticsearch indexing job is resumable now. Stopping a server while the job is running will put the job in pending status and will resume the job when the server starts. The job can still be explicitly canceled via the **System Console**. + +### Bug Fixes + - Fixed an issue where permalinks to direct and group message posts did not show a preview. + - Fixed an issue when Collapsed Reply Threads are enabled where marking a root post with a mention as unread displayed both a mention badge and the thread item being bolded. + - Fixed an issue where the public link to generate the API was getting called even if public links were disabled. + - Fixed an issue with onboarding page view events. + - Fixed an issue where the custom emoji **Next** button was out of view when a banner was present. + - Fixed an issue where it would appear that a user had a negative number of unread threads. + - Fixed an issue where marking the last post in a thread as unread didn't mark the thread as unread. + - Restored the rendering of main menu items from plugins in non-mobile view. + - Fixed the overflow of text in **Manage Channel Members** modal title. + - Fixed an issue where pagination was broken in **System Console > Groups**. + - Fixed an issue where thread updates did not show correctly after the computer woke up. + - Fixed an issue where a negative unread count sometimes appeared with Collapsed Reply Threads enabled. + - Fixed an issue where the modal to create a Custom Group got closed when pressing ENTER. + - Fixed an issue where group mention did not get highlighted in Professional subscription. + - Fixed an issue where users were unable to edit posts with markdown code blocks. + - Fixed an issue where sending test (empty) notifications was allowed even when the ``SendPushNotifications`` config setting was set to ``false``. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``EmailSettings`` in ``config.json``: + - Added ``EnableInactivityEmail`` setting to be able to disable inactive server email notifications. + - Under ``JobSettings`` in ``config.json``: + - Added a new cleanup job to regularly remove outdated config entries from the database. The threshold for this setting can be adjusted with ``CleanupConfigThresholdDays``. + - Under ``ElasticsearchSettings`` in ``config.json``: + - Elasticsearch (Enterprise subscription) and Bleve indexing have been revamped to be much more efficient and faster. The config parameter ``BulkIndexingTimeWindowSeconds`` for both Elasticsearch and Bleve is now deprecated and no longer used. A new config parameter called ``BatchSize`` has been introduced instead. This parameter controls the number of objects that can be indexed in a single batch. This makes things more efficient and maintains a constant workload. + +#### API Changes + - Added a new API endpoint ``POST /api/v4/users/{user_id}/teams/{team_id}/threads/{thread_id}/set_unread/{post_id}`` to set a thread as unread by post id. + - Added new API endpoints ``GET /api/v4/teams/:team_id/top/reactions`` and ``GET /api/v4/users/me/top/reactions`` to get top reactions for a team and user. + - Fixed an issue where the ``UpdateUser`` API endpoint required a ``create_at`` field. + - ``api/v4/file/s3_test`` now requires ``FileSettings`` to be all set to run. + - ``api/v4/email/test`` now requires ``EmailSettings`` to be all set to run. + - Added ``fromWebhook`` property to the webapp plugin API. + +### Go Version + - v6.7 is built with Go ``v1.18.1``. + +### Open Source Components + - Added ``react-native-math-view`` to https://github.com/mattermost/mattermost-mobile. + - Removed ``flux`` and ``react-slidedown`` from https://github.com/mattermost/mattermost-webapp. + - Added ``@mattermost/compass-icons``, ``bootstrap-dark``, ``fs-extra``, and ``pretty-bytes`` to https://github.com/mattermost/desktop. + +### Known Issues + - Channels with more than 100 members only show 100 members in the right-hand side [MM-44159](https://mattermost.atlassian.net/browse/MM-44159). + - Shortcut modal for channel info shows ``Alt`` instead of ``Shift`` for Mac [MM-44172](https://mattermost.atlassian.net/browse/MM-44172). + - A blank screen is seen when returning from the System Console while the Channel Info is open on the right-hand side [MM-44435](https://mattermost.atlassian.net/browse/MM-44435). + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alexkoala](https://github.com/alexkoala), [alieh-rymasheuski](https://github.com/alieh-rymasheuski), [allonios](https://github.com/allonios), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [andrewodri](https://github.com/andrewodri), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [bermelmike](https://translate.mattermost.com/user/bermelmike), [boxiyang](https://translate.mattermost.com/user/boxiyang), [bpodwinski](https://github.com/bpodwinski), [calebroseland](https://github.com/calebroseland), [cdump](https://github.com/cdump), [cecilysullivan](https://github.com/cecilysullivan), [chenilim](https://github.com/chenilim), [cleferman](https://github.com/cleferman), [codedsun](https://github.com/codedsun), [coltoneshaw](https://github.com/coltoneshaw), [cota-eng](https://translate.mattermost.com/user/cota-eng), [cpoile](https://github.com/cpoile), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [devinbinnie](https://github.com/devinbinnie), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [HandsomeChoco/](https://translate.mattermost.com/user/HandsomeChoco/), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jbattistispiria](https://github.com/jbattistispiria), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jpaldeano](https://github.com/jpaldeano), [jprusch](https://github.com/jprusch), [JtheBAB](https://translate.mattermost.com/user/JtheBAB), [JulienTant](https://github.com/JulienTant), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [KevinSJ](https://github.com/KevinSJ), [kherwata](https://translate.mattermost.com/user/kherwata), [KobeBergmans](https://github.com/KobeBergmans), [koox00](https://github.com/koox00), [krmh04](https://github.com/krmh04), [kyeongsoosoo](https://github.com/kyeongsoosoo), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lkyuchukov](https://github.com/lkyuchukov), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7/), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [maxtrem271991](https://translate.mattermost.com/user/maxtrem271991), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [mikebermel](https://github.com/mikebermel), [milotype](https://github.com/milotype), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [muratbayan](https://github.com/muratbayan), [mvitale1989](https://github.com/mvitale1989), [mylonsuren](https://github.com/mylonsuren), [nat-gunner](https://github.com/nat-gunner), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [nickmisasi](https://github.com/nickmisasi), [ogi-m](https://github.com/ogi-m), [pfltdv](https://github.com/pfltdv), [phoinixgrr](https://github.com/phoinixgrr), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [pvev](https://github.com/pvev), [Rajat-Dabade](https://github.com/Rajat-Dabade), [rebornwwp](https://github.com/rebornwwp), [RoyI99](https://github.com/RoyI99), [ryoarmanda](https://github.com/ryoarmanda), [saturninoabril](https://github.com/saturninoabril), [sayanta66](https://github.com/sayanta66), [sbishel](https://github.com/sbishel), [serhack](https://github.com/serhack), [seoyeongeun](https://translate.mattermost.com/user/seoyeongeun), [shadowshot-x](https://github.com/shadowshot-x), [SiderealArt](https://translate.mattermost.com/user/SiderealArt), [silentyak](https://github.com/silentyak), [sinansonmez](https://github.com/sinansonmez), [Sonichigo](https://github.com/Sonichigo), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [TQuock](https://github.com/TQuock), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [TylerStilson](https://github.com/TylerStilson), [unode](https://github.com/unode), [vadimasadchi](https://github.com/vadimasadchi), [varghesejose2020](https://github.com/varghesejose2020), [VishakhaPoonia](https://github.com/VishakhaPoonia), [Vovcharaa](https://github.com/Vovcharaa), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v6.6 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v6.6.2, released 2022-06-13** + - Mattermost v6.6.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The value of ``ServiceSettings.TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening +in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details [here](https://docs.mattermost.com/configure/configuration-settings.html#trusted-proxy-ip-header). + - Fixed a bug that allowed to send test (empty) notifications even if the ``SendPushNotifications`` config was set to ``false``. +- **v6.6.1, released 2022-04-28** + - Mattermost v6.6.1 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Replaced an expired GPG key which is used to verify the enterprise binary. + - Fixed an issue with null values in the OAuthApps table's MattermostAppID column, which was introduced in v6.6.0 [MM-43500](https://mattermost.atlassian.net/browse/MM-43500). + - Fixed an issue where the Workspace Optimization dashboard mentioned that the workspace had reached over 100 users, when fewer than 100 users were registered [MM-43215](https://mattermost.atlassian.net/browse/MM-43215). +- **v6.6.0, released 2022-04-16** + - Original 6.6.0 release + +Mattermost v6.6.0 contains a low severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Compatibility + - Updated Safari recommended minimum version to v14.1+. + +### Important Upgrade Notes + - The Apps Framework protocol for binding/form submissions has changed, by separating the single `call` into separate `submit`, `form`, `refresh` and `lookup` calls. If any users have created their own Apps, they have to be updated to the new system. + +```{Important} +If you upgrade from a release earlier than v6.5, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). + ``` + +### Highlights + +#### Apps Framework 1.0: General Availability + - The Apps Framework allows developers to build integrations with Mattermost that seamlessly work across Mattermost’s desktop and mobile clients. Apps can be developed using any programming language, as opposed to plugins which must be developed in Go. + +#### Triggers and Actions + - Channel admins can now configure [certain actions](https://docs.mattermost.com/channels/create-channels.html) to be executed automatically based on trigger conditions without writing any code. Users running an older Playbooks release need to upgrade their Playbooks instance to at least v1.26 to take advantage of the channel actions functionality. + +#### Actions Restructure + - The **Actions** menu was restructured to reduce the clutter from Plugins and Apps. + +#### Playbook Updates + - Added [retrospective metrics](https://docs.mattermost.com/playbooks/metrics-and-goals.html) (Enterprise edition) to track up to four key metrics that indicate performance of every run. + +### Improvements + +#### User Interface (UI) + - Pre-packaged Calls v0.4.8 with Mattermost server v6.6 (closed Beta). To participate in Beta testing, please contact [Mattermost](https://mattermost.com/contact-sales/). + - Added nested previews for permalinks. + - Added a right-hand side Channel Info panel to see and interact with channel information. + - Added support for inline editing of posts. + - Changed the Mattermost indigo theme to match the dark theme in code blocks. + - Updated in-product links from legacy domain about.mattermost.com to mattermost.com. + - Made it easier to copy code blocks by adding a copy button on hover. + - Made it easier to copy a message via a new **Copy Text** post menu item. + - Added a loading indicator to the **Threads** global list each time more posts are fetched on infinite scroll. + - Added search guidance to the **Threads** global list when no more posts can be loaded. This is only shown if you’ve scrolled to load older posts and reach the end of the list. + - Added accessibility support for custom statuses. + - Tooltip is now only displayed when text is too long in the announcement banner. + - When restricting direct messages to users on the same team, bots are now excluded from that restriction. + - Brazilian Portuguese language support was downgraded to Beta. + +#### Performance + - Improved performance when clearing notifications with Collapsed Reply Threads enabled. + - Improved performance of Collapsed Reply Threads when ``ThreadAutoFollow`` is enabled but ``CollapsedThreads`` is disabled. + - Fixed a potential memory leak in the sidebar when using accessibility hotkeys. + - Virtualized the emoji picker and added other performance improvements to the emoji picker. + - Improved the performance of storing users in webapp. + - Fixed a small memory leak in the **System Console**. + +#### Plugins + - Updated the plugin registry's ``registerCallButtonAction`` method to allow for displaying custom calls buttons in the channel header. + - Added a debugging setting to turn off client-side plugins for the current user. + - Added performance metrics related to plugin loading on page load. + +#### Administration + - The default for [``ThreadAutoFollow``](https://docs.mattermost.com/configure/configuration-settings.html#automatically-follow-threads) has been changed to ``true``. This does not affect existing configurations where this value is already set to ``false``; however, we recommend enabling ``ThreadAutoFollow`` if you plan to enable [Collapsed Reply Threads](https://docs.mattermost.com/channels/organize-conversations.html) in the future. + - Improved the license upload flow. + - The Start Trial CTA presents a modal exposing the benefits the client gets by starting the trial, encouraging Admins to request a trial license and engage them with the product. + - A new field was added to the client configuration to let clients know the database schema version of the server. The applied database migrations have also been added to the **System Console**. + - Added a ``Automatically Follow Threads`` configuration setting to the **System Console** to expose the ``threadAutoFollow`` config setting to the User Interface. + - An error is now shown on the email invitation modal if SMTP is not configured but email invitations are ``true``. + - Logs from third-party libraries are now included in the default logging configuration. + - Added additional performance debugging settings. + - The support email field has moved from **Customization** to **Notifications** in the System Console. Also, a support email is now required when configuring email notifications. + - The ping endpoint can now receive a device ID, which will report whether the device is able to receive push notifications. + - [Feature flags](https://developers.mattermost.com/contribute/server/feature-flags/) are now automatically refreshed when the server undergoes a restart. + - Added a sort order to the category API, and included category data in the websocket category update event. + - Permissions for private playbooks are now hidden unless running an Enterprise license. + +### Bug Fixes + - Fixed an error that occured when a non-logged-in user attempted to view a page that required being logged in while MFA was required on the server. + - Fixed an issue where the channel switcher displayed channels from teams the Admin was no longer part of. + - Fixed an issue where ``ThreadStore.GetThreadsForUser`` did not count correctly when no team ID was specified. + - Fixed an issue where ``zip`` file creation failed when adding attachments. + - Fixed an issue where emoji short codes written in Markdown were not added to recently used emojis. + - Fixed the positioning of SVGs in admin onboarding when the screen doesn't have a previous button. + - Fixed an issue with the displayed channel name in the channel tutorial tip. + - Fixed an issue with the clickable area for emojis in the emoji picker to match the interface. + - Fixed an issue where usernames with periods in the channel switcher input showed Group Messages over matching Direct Messages. + - Fixed an issue on Collapsed Reply Threads compact message view where clicking on the thread footer avatar did not open the profile modal. + - Fixed a scan error on column name "LastRootPostAt": converting NULL to int64. + - Fixed an issue where selecting a custom status from Recent statuses used the original expiration time. + - Fixed an issue that caused a gap to appear on the left-hand side in products using the team sidebar. + - Fixed an issue where moving up or down in the channel switcher didn’t work as expected when Global Threads was in the background. + - Fixed an issue where pressing ENTER opened the onboarding tutorial tip. + - Fixed an issue where some permission checkboxes had been moved to different categories in the System Console. + - Fixed an issue where a blank screen occurred upon leaving a currently open unread channel with the channel unread grouping enabled. + - Fixed an issue related to disabling and re-enabling Custom Terms of Service. + - Fixed an issue where channel links on hover overlapped the channels menus. + - Fixed the positioning of the post menu in mobile web view. + - Fixed an issue where closing the keyboard shortcut modal by "CTRL/CMD + /" didn’t work. + - Fixed an issue where the channel keyboard navigation was broken in the Threads view. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - The default for ``ThreadAutoFollow`` has been changed to ``true``. This does not affect existing configurations where this value is already set to ``false``. + +### Go Version + - v6.6 is built with Go ``v1.16.7``. + +### Open Source Components + - Added ``@tippyjs/react``, ``react-popper``, ``react-slidedown`` and ``smooth-scroll-into-view-if-needed`` , and removed ``prettier`` and ``xregexp`` from https://github.com/mattermost/mattermost-webapp. + +### Known Issues + - On subpath, 404 can be seen on OpenID or SAML redirect after changing login method. The login change is successful, and manually adding the subpath name into the URL opens the expected page [MM-43114](https://mattermost.atlassian.net/browse/MM-43114). + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [AccountingMattermost](https://github.com/AccountingMattermost), [aeomin](https://translate.mattermost.com/user/aeomin/), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [akkivasu](https://github.com/akkivasu), [Alexnoj](https://github.com/Alexnoj), [amyblais](https://github.com/amyblais), [andreygolubkow](https://github.com/andreygolubkow), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [azigler](https://github.com/azigler), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [blocodenotas](https://github.com/blocodenotas), [bobertoyin](https://github.com/bobertoyin), [Borknab](https://github.com/Borknab), [bpodwinski](https://github.com/bpodwinski), [calebroseland](https://github.com/calebroseland), [CeesJol](https://github.com/CeesJol), [chenilim](https://github.com/chenilim), [ChristieBavelaar](https://github.com/ChristieBavelaar), [cleferman](https://github.com/cleferman), [coltoneshaw](https://github.com/coltoneshaw), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ct7amz](https://translate.mattermost.com/user/ct7amz/), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkonovkina](https://translate.mattermost.com/user/darkonovkina/), [debasish4patra](https://github.com/debasish4patra), [devinbinnie](https://github.com/devinbinnie), [dipak-demansol](https://github.com/dipak-demansol), [dontoisme](https://github.com/dontoisme), [DSchalla](https://github.com/DSchalla), [emdecr](https://github.com/emdecr), [emilyacook](https://github.com/emilyacook), [enahum](https://github.com/enahum), [EragonRD](https://github.com/EragonRD), [erdeerdeerde](https://github.com/erdeerdeerde), [ericocesar](https://github.com/ericocesar), [ewwollesen](https://github.com/ewwollesen), [flynbit](https://github.com/flynbit), [fromhro](https://github.com/fromhro), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [glennschler](https://github.com/glennschler), [gmerz](https://github.com/gmerz), [gyeben](https://github.com/gyeben), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [htlcnn](https://github.com/htlcnn), [hydeenoble](https://github.com/hydeenoble), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johndavidlugtu](https://github.com/johndavidlugtu), [johnsonbrothers](https://github.com/johnsonbrothers), [jordanafung](https://github.com/jordanafung), [jpetazzo](https://github.com/jpetazzo), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), k4awon, [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [karistuck](https://github.com/karistuck), [kayazeren](https://github.com/kayazeren), [KevinSJ](https://github.com/KevinSJ), [koox00](https://github.com/koox00), [krmh04](https://github.com/krmh04), [kzmi](https://translate.mattermost.com/user/kzmi/), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7/), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [metanerd](https://github.com/metanerd), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mkdbns](https://github.com/mkdbns), [mkraft](https://github.com/mkraft), [Mshahidtaj](https://github.com/Mshahidtaj), [mylonsuren](https://github.com/mylonsuren), [nasermoein](https://github.com/nasermoein), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [Nothing23yeh](https://github.com/Nothing23yeh), [noxer](https://github.com/noxer), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [pfltdv](https://github.com/pfltdv), [Phrynobatrachus](https://github.com/Phrynobatrachus), [potatogim](https://github.com/potatogim), [pvev](https://github.com/pvev), [ramirezjag00](https://github.com/ramirezjag00), [rodcorsi](https://github.com/rodcorsi), [ruckc](https://github.com/ruckc), [ryoarmanda](https://github.com/ryoarmanda), [saturninoabril](https://github.com/saturninoabril), [sayanta66](https://github.com/sayanta66), [sbishel](https://github.com/sbishel), [sc](https://translate.mattermost.com/user/_sc/), [sibasankarnayak](https://github.com/sibasankarnayak), [sinansonmez](https://github.com/sinansonmez), [spirosoik](https://github.com/spirosoik), [src-r-r](https://github.com/src-r-r), [sri-byte](https://github.com/sri-byte), [sridhar02](https://github.com/sridhar02), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [superkkt](https://github.com/superkkt), [Szymongib](https://github.com/Szymongib), [ThiefMaster](https://github.com/ThiefMaster), [thorkemado](https://github.com/thorkemado), [tilto0822](https://github.com/tilto0822), [tmotyl](https://github.com/tmotyl), [tomaszn](https://github.com/tomaszn), [TQuock](https://github.com/TQuock), [trilopin](https://github.com/trilopin), [tsabi](https://github.com/tsabi), [vadimasadchi](https://github.com/vadimasadchi), [varghesejose2020](https://github.com/varghesejose2020), [vish9812](https://github.com/vish9812), [VishakhaPoonia](https://github.com/VishakhaPoonia), [wandersiemers](https://github.com/wandersiemers), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wuwinson](https://github.com/wuwinson), [Zxce3](https://github.com/Zxce3) + +---- + +## Release v6.5 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v6.5.2, released 2022-06-13** + - Mattermost v6.5.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The value of ``ServiceSettings.TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening +in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details [here](https://docs.mattermost.com/configure/configuration-settings.html#trusted-proxy-ip-header). + - Fixed a bug that allowed to send test (empty) notifications even if the ``SendPushNotifications`` config was set to ``false``. + - The ping endpoint now can receive a device ID, which will report whether the device is able to receive push notifications. +- **v6.5.1, released 2022-04-28** + - Mattermost v6.5.1 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue on schema migrations where the Mattermost server failed to restart after having an error in the migration process. + - Fixed an issue where the Get trial endpoint did not seem to complete. +- **v6.5.0, released 2022-03-16** + - Original 6.5.0 release + +Mattermost v6.5.0 contains low to medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Compatibility + - Updated the recommended minimum supported Firefox version to v91+. + +### Important Upgrade Notes + - The ``mattermost version`` CLI command does not interact with the database anymore. Therefore the database version is not going to be printed. Also, the database migrations are not going to be applied with the version sub command. [A new db migrate sub command](https://docs.mattermost.com/manage/command-line-tools.html#mattermost-db-migrate) is added to enable administrators to trigger migrations. + +```{Important} +If you upgrade from a release earlier than v6.4, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Custom User Groups (Beta; Professional and Enterprise Plans) + - Added the ability to mention a group of members at a time in a workspace. Users can create groups, edit group details, join groups, archive groups, and add group members. + +#### Cross-team Channel Navigation + - You can now find and jump to channels across all your teams by typing any channel name in the **Find Channels** modal. + +#### Workspace Optimizations + - System Admins can now review their overall health and growth scores and take recommended actions for ensuring their workspace is running smoothly, so users can get the most out of Mattermost. + +#### Playbook Updates + - Added a new onboarding tour for Playbooks. + - Existing playbooks can now be duplicated by copying and modifying your colleague’s processes. Playbooks can also be exported. + +#### Boards Updates + - Added a new onboarding tour for Boards. + - Improved the share boards user interface. + - A link to Boards is now included in the channel intro whenever a new channel or direct message is started. + - Added in-app links to import Help Docs. + +### Improvements + +#### User Interface (UI) + - Added Persian as an official supported language (Beta). + - Added a new onboarding experience for first System Admin user. + - Added new tutorial tours for Channels, Boards, and Playbooks to help orient first time users. + - Removed extra telemetry events that were tracked during page loads. + - Added a feature card slide for Playbooks. + - Removed ``admin-advisor`` bot's ability to notify admins about missing support email. + - Clarified in-product error string "Oops!" as "Unable to continue" for both translators and target audiences in cases where a user doesn't have sufficient permissions to add users or guests. + - Removed incorrect in-product string text from the **Send full message contents** email notification option description displayed via **System Console > Site Configuration > Notifications**. + - Added the ability to send an unsanitized user to the source user on ``user_updated`` event. + - In the compact view, the sender's username is now always shown on posts. + - The post menu is now only rendered on the root post on hover over. + - Updated a library used for storing drafts and other data in browser storage. + - Enabled performance telemetry tracking for production deployments not running in developer mode. This telemetry tracking is disabled when telemetry is toggled off. + - Inactive server email notifications will now be sent to System Admins occasionally if there have been no telemetry events on their server for 100 hours or more. Inactivity is determined by reviewing all activity on the server. This feature can also be disabled using the ``MM_FeatureFlag_EnableInactivityCheckJob`` feature flag. + +#### Performance + - Improved database performance when ``ThreadAutoFollow`` is enabled but ``CollapsedThreads`` is disabled. Learn more about ``ThreadAutoFollow`` and Collapsed Reply Threads [here](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta). + - Improved perceived typing performance by moving heavy code around and effective memoization related to the textbox component. + - Fixed a memory leak caused by the post textbox. + - Reduced the number of menu components listening for keyboard and mouse events. + - Re-rendering of ``CustomStatusEmoji`` component is now avoided on post hovering. + - Removed the collapsed sidebar menu from the DOM on sidebar collapse and expand. + - Re-rendering of ``TextBox`` links component below the post box while typing is now avoided. + +#### Plugins + - Added an ``OnInstall()`` plugin hook. + - Added an ``OnSendDailyTelemetry()`` plugin hook. + - Added a new plugin registry entry to append menu items to the user guide dropdown. + +### Bug Fixes + - Fixed an issue with clicking images in the message attachment. + - Fixed an issue that caused Rudder to create their cookies on the top-level domain when Mattermost was installed on a subdomain. + - Fixed an issue where **Total Posts** and **Active Users With Posts** graphs did not render in **System Console** > **Team Statistics**. + - Fixed an issue where telemetry events attempted to get sent even when blocked by an ad blocker. + - Fixed an issue where the channel switcher stopped showing search results when the first few characters were removed. + - Fixed an issue where notification sounds didn't trigger on the Desktop App for new accounts. + - Fixed an issue where users got multiple sounds for a single notification on the Linux Desktop App. + - Fixed an issue where posting frequent messages to followed threads caused jittery typing. + - Fixed an issue where the **Add to channel** permission was available in private channels for non-admin users. + - Fixed an issue where the reply notification setting was still in effect even when Collapsed Reply Threads was enabled. + - Fixed an issue where running ``mmctl config migrate`` reset the configuration settings to defaults if the settings were already in the database. + - Fixed an issue where the custom status menu option was missing the "x" to clear status. + - Fixed an issue where the password reset link was valid for 1 hour instead of 24 hours. + - Fixed an issue where the Mattermost import failed if an export contained a soft-deleted team. + - Fixed an issue where search results in the right-hand side did not clear when changing screens from file results to any other. + - Fixed an issue where an emoji import failed when the emoji name conflicted with a system emoji. + - Fixed an issue where the **Edition and License** page displayed a prompt to upgrade to Enterprise for servers that already had an E20 license. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added a new ``EnableClientPerformanceDebugging`` setting to enable some options for users on the web app to enable and disable different parts of the web app to help us isolate performance issues while debugging. + - Added a new ``EnableCustomGroups`` setting to create and delete custom groups and to add and remove custom group members. + +#### API Changes + - Added new endpoint GET /api/v4/users/invalid_emails. This endpoint will return a list of non-guest users who are not in your whitelisted domains on a server where EnableOpenServer is false. + - Added new API endpoint ``POST /system/onboarding/complete`` to complete onboarding. + - Added a new API endpoint ``GET api/v4/latest_version`` to fetch the latest Mattermost version. + - Modified an existing API endpoint ``${baseUrl}/api/v4/channels/search?system_console=false`` and added additional parameters ``${baseUrl}/api/v4/users/me/channels`` to fetch all the channel across teams and ``${baseUrl}/api/v4/users/${userId/channel_members`` to fetch all the channel_members across teams). + +#### Websocket Changes + - Refactored `user-update` websocket event handler to prevent extra get request to server for unsanitized user. + - Added a new ``ReliableClusterSend`` field to ``model.WebsocketBroadcast`` to allow sending events through the cluster using the reliable channel. + +### Go Version + - v6.5 is built with Go ``v1.16.7``. + +### Known Issues + - The mmctl command built into version v6.5.0 appears to be from v6.4.1 [MM-42588](https://mattermost.atlassian.net/browse/MM-42588). + - The new onboarding menu icon obscures System Console menu items [MM-42353](https://mattermost.atlassian.net/browse/MM-42353). + - For Custom Groups, the user activity doesn't sync in two sessions [MM-42242](https://mattermost.atlassian.net/browse/MM-42242). + - For Custom Groups, the last action popup menu is cut off [MM-42189](https://mattermost.atlassian.net/browse/MM-42189). + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [97amarnathk](https://github.com/97amarnathk), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [akshitarora921](https://github.com/akshitarora921), [alerque](https://github.com/alerque), [amyblais](https://github.com/amyblais), [andrewbrown00](https://github.com/andrewbrown00), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [CeesJol](https://github.com/CeesJol), [chenilim](https://github.com/chenilim), [chris-nee](https://github.com/chris-nee), [codedsun](https://github.com/codedsun), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cvockrodt](https://github.com/cvockrodt), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [debasish4patra](https://github.com/debasish4patra), [devinbinnie](https://github.com/devinbinnie), [dipak-demansol](https://github.com/dipak-demansol), [DIVYA-19](https://github.com/DIVYA-19), [dontoisme](https://github.com/dontoisme), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [EragonRD](https://github.com/EragonRD), [fromhro](https://github.com/fromhro), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [ggu1012](https://github.com/ggu1012), [gohyinhao](https://github.com/gohyinhao), [GR34SE](https://github.com/GR34SE), [gtapiasgt](https://github.com/gtapiasgt), [gyeben](https://translate.mattermost.com/user/gyeben/), [haardikdharma10](https://github.com/haardikdharma10), [hamzaMM](https://github.com/hamzaMM), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [hojin-kim](https://translate.mattermost.com/user/hojin-kim/), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [ITKozak](https://github.com/ITKozak), [jaz-on](https://github.com/jaz-on), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [joriki](https://github.com/joriki), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [jsoref](https://github.com/jsoref), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [julmondragon](https://github.com/julmondragon), [jupriano](https://github.com/jupriano), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [karistuck](https://github.com/karistuck), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [krmh04](https://github.com/krmh04), [krotovkk](https://github.com/krotovkk), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [mamounjamous](https://github.com/mamounjamous), [manojmalik20](https://github.com/manojmalik20), [master7](https://translate.mattermost.com/user/master7/), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [matthewbirtch](https://github.com/matthewbirtch), [maurobraggio](https://github.com/maurobraggio), [metanerd](https://github.com/metanerd), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mkraft](https://github.com/mkraft), [mylonsuren](https://github.com/mylonsuren), [nasermoein](https://github.com/nasermoein), [nathanaelhoun](https://github.com/nathanaelhoun), [NathanBnm](https://github.com/NathanBnm), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [Nothing23yeh](https://github.com/Nothing23yeh), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [penthaapatel](https://github.com/penthaapatel), [persian@mattermost.com](https://translate.mattermost.com/user/persiantranslator@mattermost.com/), [persiantranslator@mattermost.com](https://translate.mattermost.com/user/persiantranslator@mattermost.com/), [Phrynobatrachus](https://github.com/Phrynobatrachus), [Pinjasaur](https://github.com/Pinjasaur), [plant99](https://github.com/plant99), [poflankov](https://github.com/poflankov), [potatogim](https://github.com/potatogim), [Profesor08](https://github.com/Profesor08), [pvev](https://github.com/pvev), [rodcorsi](https://github.com/rodcorsi), [Rutam21](https://github.com/Rutam21), [saeid.hmdr](https://translate.mattermost.com/user/saeid.hmdr/), [sargreal](https://github.com/sargreal), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [scottaudet](https://github.com/scottaudet), [seoyeongeun](https://github.com/seoyeongeun), [serhack](https://github.com/serhack), [sibasankarnayak](https://github.com/sibasankarnayak), [sinansonmez](https://github.com/sinansonmez), [snan](https://github.com/snan), [Sonichigo](https://github.com/Sonichigo), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [superkkt](https://github.com/superkkt), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [ThiefMaster](https://github.com/ThiefMaster), [tilto0822](https://github.com/tilto0822), [TQuock](https://github.com/TQuock), [tsabi](https://github.com/tsabi), [ukewea](https://github.com/ukewea), [varghesejose2020](https://github.com/varghesejose2020), [vinod-demansol](https://github.com/vinod-demansol), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wuwinson](https://github.com/wuwinson), [zefhemel](https://github.com/zefhemel), [Zxce3](https://translate.mattermost.com/user/Zxce3/). + +---- + +## Release v6.4 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html#feature-release) + +- **v6.4.3, released 2022-04-28** + - Mattermost v6.4.3 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue on schema migrations where the Mattermost server failed to restart after having an error in the migration process. +- **v6.4.2, released 2022-03-10** + - Mattermost v6.4.2 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where the webapp did not route notifications correctly when the computer was locked. +- **v6.4.1, released 2022-02-25** + - Fixed a major web and desktop app performance issue for users with a large accumulated number of Direct Messages and Group Messages. +- **v6.4.0, released 2022-02-16** + - Original 6.4.0 release + +Mattermost v6.4.0 contains low severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - A new schema migration system has been introduced, so we strongly recommend backing up the database before updating the server to this version. The new migration system will run through all existing migrations to record them to a new table. This will only happen for the first run in order to migrate the application to the new system. The table where migration information is stored is called ``db_migrations``. Additionally, a ``db_lock`` table is used to prevent multiple installations from running migrations in parallel. Any downtime depends on how many records the database has and whether there are missing migrations in the schema. In case of an error while applying the migrations, please check this table first. If you encounter an issue please file [an Issue](https://github.com/mattermost/mattermost-server/issues) by including the failing migration name, database driver/version, and the server logs. + - On MySQL, if you encounter an error "Failed to apply database migrations" when upgrading to v6.4.0, it means that there is a mismatch between the table collation and the default database collation. You can manually fix this by changing the database collation with ``ALTER DATABASE COLLATE = 'utf8mb4_general_ci',``. Then do the server upgrade again and the migration will be successful. + - It has been commonly observed on MySQL 8+ systems to have an error ``Error 1267: Illegal mix of collations`` when upgrading due to changing the default collation. This is caused by the database and the tables having different collations. If you get this error, please change the collations to have the same value with, for example, ``ALTER DATABASE COLLATE = '<collation>'``. + - The new migration system requires the MySQL database user to have additional *EXECUTE*, *CREATE ROUTINE*, *ALTER ROUTINE* and *REFERENCES* privileges to run schema migrations. + +```{Important} +If you upgrade from a release earlier than v6.3, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Playbook Updates + - The Team and Starter plans no longer have a limit to the number of playbooks that can be created. + +#### Boards Updates + - Redesigned the Boards template selector to help users find the best template for projects. + - Board archives now support images. All image attachments on cards will be included the next time a board archive is exported and imported. The archive format is changing with a new ``.boardarchive`` extension and all new exports will only be in this format. + - Added card badges to indicate the type of content in a card, such as the description, comments, and checklists, without needing to open the card. + - The entire text on URL properties is now clickable, so users can easily open links from a card without needing to click on a small link icon. + - GIF file types are now supported as image attachments in card descriptions. + +### Improvements + +#### User Interface (UI) + - Updated **Account Settings** terminology to **Settings**. + - Added Accept-Language header to generate link previews in the default Server language. + - The **Invite Members** button is now hidden when the Direct Message category is collapsed. + - Added Collapsed Reply Threads (Beta) tour functionality. + - Added a keyboard shortcut to open and expand the right-hand pane. + - UX improvements to the **System Console > Licensing** page: added a new modal for the upload license workflow. + +#### Administration + - Improved plugins performance by re-initializing only after plugin configuration changes. + - Removed dead struct ``ManifestExecutables``. + - Added support for exporting and importing the post type and ``edit_at`` post details. + - Added support for ``postgresql`` schema designator. + +### Bug Fixes + - Fixed an issue where the "Make channel admin" option did not display without a license. + - Fixed an issue where the user menu header was visible when custom statuses were disabled. + - Fixed an issue where the "New Replies" banner on the right-hand side was displayed for a thread that was entirely visible. + - Fixed an issue where the markdown **Preview** link was not hidden in read-only channels. + - Fixed an issue that caused a gap to appear on the left-hand side in products using the team sidebar. + - Fixed an issue with Collapsed Reply Threads (Beta) where clearing a deleted root post left the right-hand side blank. + - Fixed an issue where the **Add** channel member button text was cut off in Safari. + - Fixed an issue where the file preview modal info bar showed the channel id instead of the channel name for Direct Messages. + - Fixed an issue to add a loader when fetching data from the backend in the channel switcher if there are no results matching local data. + - Fixed an issue where the **Get a Public Link** button in the file preview modal was hidden if the image was an external link. + - Fixed an issue where the click effect on **Copy** invite link button was incorrect. + - Reinstalling a previously-enabled plugin now correctly reports enabled status as false. + - Fixed an issue where the Ctrl/Cmd+Shift+A hotkey to open **Settings** didn't work in desktop view. + - Fixed an issue where the "Leave Channel" button didn't work from the channel sidebar 3-dot menu when clicking on it a second time. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``DataRetentionSettings`` in ``config.json``: + - Added ``EnableBoardsDeletion`` and ``BoardsRetentionDays`` to add support for Global Retention Policy for Boards. + +#### API Changes + - The ``api/v4/config/migrate`` API endpoint has been removed in favor of the mmctl ``--local`` endpoint. API clients won't be able to access this endpoint without having physical access to the server. + +### Go Version + - v6.4 is built with Go ``v1.16.7``. + +### Open Source Components + - Removed ``@formatjs/intl-pluralrules`` and ``@formatjs/intl-relativetimeformat`` from https://github.com/mattermost/mattermost-webapp. + - Added ``msgpack/msgpack`` and ``pako`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - Adding an @mention at the start of a post draft and pressing the left or right arrow key can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors + - [3ach](https://github.com/3ach), [abdusabri](https://github.com/abdusabri), [abhijit-singh](https://github.com/abhijit-singh), [adithyaakrishna](https://github.com/adithyaakrishna), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alauregaillard](https://github.com/alauregaillard), [alieh-rymasheuski](https://github.com/alieh-rymasheuski), [amyblais](https://github.com/amyblais), [anurag6713](https://github.com/anurag6713), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [balajivenkatesh](https://github.com/balajivenkatesh), [BenHargreaves](https://github.com/BenHargreaves), [BenLloydPearson](https://github.com/BenLloydPearson), [bhimeshchauhan](https://github.com/bhimeshchauhan), [bobychaudhary](https://github.com/bobychaudhary), [calebroseland](https://github.com/calebroseland), [ChaseKnowlden](https://github.com/ChaseKnowlden), [chenilim](https://github.com/chenilim), [codedsun](https://github.com/codedsun), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [debasish4patra](https://github.com/debasish4patra), [debci](https://translate.mattermost.com/user/debci/), [devinbinnie](https://github.com/devinbinnie), [dfun90](https://github.com/dfun90), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [flynbit](https://translate.mattermost.com/user/flynbit/), [frnkshin](https://github.com/frnkshin), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbochora](https://github.com/gbochora), [gtapias](https://translate.mattermost.com/user/gtapias/), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [jihoon-seo](https://github.com/jihoon-seo), [johnsonbrothers](https://github.com/johnsonbrothers), [josephjosedev](https://github.com/josephjosedev), [jpaldeano](https://github.com/jpaldeano), [jprusch](https://github.com/jprusch), [jsoref](https://github.com/jsoref), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [JulienTant](https://github.com/JulienTant), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [K3UL](https://github.com/K3UL), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [krmh04](https://github.com/krmh04), [krotovkk](https://github.com/krotovkk), [LaoshuBaby](https://github.com/LaoshuBaby), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [manojmalik20](https://github.com/manojmalik20), [MarcCeleiro](https://translate.mattermost.com/user/MarcCeleiro/), [marianunez](https://github.com/marianunez), [master7](https://translate.mattermost.com/user/master7/), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [Mercbot7](https://github.com/Mercbot7), [meshal](https://translate.mattermost.com/user/meshal/), [Meshalaw](https://github.com/Meshalaw), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mkbox](https://github.com/mkbox), [mkraft](https://github.com/mkraft), [mxschumacher](https://github.com/mxschumacher), [mylonsuren](https://github.com/mylonsuren), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [nickmisasi](https://github.com/nickmisasi), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [onoklin](https://github.com/onoklin), [pablovelezvidal](https://github.com/pablovelezvidal), [patatman](https://github.com/patatman), [Phrynobatrachus](https://github.com/Phrynobatrachus), [potatogim](https://github.com/potatogim), [R](https://translate.mattermost.com/user/R/), [RenePinnow](https://github.com/RenePinnow), [ricosega](https://github.com/ricosega), [rinkimekari](https://github.com/rinkimekari), [sadohert](https://github.com/sadohert), [sangramrath](https://github.com/sangramrath), [sanjaydemansol](https://github.com/sanjaydemansol), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [Schweinepriester](https://github.com/Schweinepriester), [scottaudet](https://github.com/scottaudet), [seoyeongeun](https://github.com/seoyeongeun), [shadowshot-x](https://github.com/shadowshot-x), [shrzkhn](https://github.com/shrzkhn), [sibasankarnayak](https://github.com/sibasankarnayak), [spirosoik](https://github.com/spirosoik), [sri-byte](https://github.com/sri-byte), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [tilto0822](https://github.com/tilto0822), [TQuock](https://github.com/TQuock), [tsabi](https://github.com/tsabi), [tw-ayush](https://github.com/tw-ayush), [varghesejose2020](https://github.com/varghesejose2020), [venarius](https://github.com/venarius), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [willpwa](https://github.com/willpwa), [Willyfrog](https://github.com/Willyfrog), [wqweto](https://translate.mattermost.com/user/wqweto/), [wuwinson](https://github.com/wuwinson), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v6.3 - [Extended Support Release](https://docs.mattermost.com/upgrade/release-definitions.html#extended-support-release-esr) + +- **v6.3.10, released 2022-08-23** + - Mattermost v6.3.10 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v6.3.9, released 2022-06-13** + - Mattermost v6.3.9 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The value of ``ServiceSettings.TrustedProxyIPHeader`` defaults to empty from now on. A previous bug prevented this from happening +in certain conditions. Customers are requested to check for these values in their config and set them to nil if necessary. See more details [here](https://docs.mattermost.com/configure/configuration-settings.html#trusted-proxy-ip-header). + - Fixed a bug that allowed to send test (empty) notifications even if the ``SendPushNotifications`` config was set to ``false``. + - Pre-packaged Playbooks v1.23.2. +- **v6.3.8, released 2022-04-28** + - Mattermost v6.3.8 contains a medium severity level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Ping endpoint now can receive a device ID, which will report whether the device is able to receive push notifications. +- **v6.3.7, released 2022-04-13** + - Fixed an issue where users were able to attempt to create private playbooks with the Professional license. +- **v6.3.6, released 2022-03-24** + - Fixed an issue with a slow delete of posts and ``context deadline exceeded`` errors after upgrading to v6.3. + - Fixed an issue where the announcement banner caused the top team to be partially obstructed [MM-40887](https://mattermost.atlassian.net/browse/MM-40887). +- **v6.3.5, released 2022-03-10** + - Mattermost v6.3.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved the performance of code for storing users in the webapp. + - Fixed a memory leak caused by the post textbox. + - Removed the collapsed sidebar menu from the DOM on sidebar collapse and expand. + - Fixed an issue with disabling and re-enabling Custom Terms of Service. +- **v6.3.4, released 2022-02-21** + - Fixed a major web and desktop app performance issue for users with a large accumulated number of Direct Messages and Group Messages. + - The right-hand side dot menu of root posts are now rendered to DOM only when hovered upon. + - The re-rendering of the ``CustomStatusEmoji`` component is now avoided on post hover. + - The re-rendering of the ``TextBox`` links component below post box is now avoided while typing. + - Reduced the number of post components listening for keyboard and mouse events. +- **v6.3.3, released 2022-02-03** + - Mattermost v6.3.3 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The default for ``ThreadAutoFollow`` has been changed to ``false``. This does not affect existing configurations where this value is already set to ``true`` [MM-41351](https://mattermost.atlassian.net/browse/MM-41351). + - Prevented some instances where operations relating to Collapsed Reply Threads added load to the database server even when the ``ThreadAutoFollow`` and ``CollapsedThreads`` config settings were disabled [MM-41350](https://mattermost.atlassian.net/browse/MM-41350). + - ``.pages`` content search is no longer available due to technical difficulties. + - Fixed an issue where the "New Replies" banner displayed in the right-hand side for threads that were entirely visible [MM-40317](https://mattermost.atlassian.net/browse/MM-40317). +- **v6.3.2, released 2022-01-28** + - Fixed an issue where MySQL installations re-triggered the v6.0 migration on server restart [MM-41330](https://mattermost.atlassian.net/browse/MM-41330). + - Fixed an issue where Actiance compliance jobs caused the Mattermost server process to crash with a panic [MM-41245](https://mattermost.atlassian.net/browse/MM-41245). +- **v6.3.1, released 2022-01-21** + - Mattermost v6.3.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Updated Mattermost Boards to v0.12.1 with various bug fixes. + - Added the ability to normalize DN strings if they were returned with a different attribute letter casing for LDAP users versus LDAP group members [MM-40753](https://mattermost.atlassian.net/browse/MM-40753). + - Removed file attachment options in channels when file attachments are disabled on the server [MM-38054](https://mattermost.atlassian.net/browse/MM-38054). + - Fixed a bug causing the team sidebar to display for servers running in a subpath. +- **v6.3.0, released 2022-01-16** + - Original 6.3.0 release + +### Important Upgrade Notes + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html), available in beta, are known to have a negative impact on server performance. If you cannot easily scale up and tune your database, or if you are running the Mattermost application server and database server on the same machine, we recommended disabling [``ThreadAutoFollow``](https://docs.mattermost.com/configuration-settings.html#automatically-follow-threads) and [``CollapsedThreads``](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta) until Collapsed Reply Threads is promoted to general availability in Q2 2022. Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + +IMPORTANT: If you upgrade from a release earlier than v6.2, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). + +### Highlights + +#### Playbook Updates + - (Enterprise Edition) Granular permission schemes enable more access control of playbooks. + - Playbooks is now completely translatable with over a dozen languages in-progress. + - All in-channel notifications are removed, with high-value notifications being delivered via direct message from the Playbooks Bot to reduce channel noise. + +#### Boards Updates + - Boards is now officially in General Availability (GA). + - Ability to follow cards and get a message notification with details of all the changes made on the card. + - Ability to quickly identify users and assign them tasks with avatars now supported in the person properties. + - Newest comments are now sorted at the top to easily find the most recent comment. + +### Improvements + +#### User Interface (UI) + - Webapp plugins can now register components in the App Bar on the right-hand side of the screen. This feature is hidden behind a feature flag and disabled by default. + - Updated “Terms of Service” terminology to “Terms of Use” product-wide. + - Added threaded replies to search results when Collapsed Reply Threads is enabled. + - Updated the “One-click reactions on messages” user setting to “Quick reactions on messages”. + - Added tab focus support to the global header and user avatars. + - Added a new Replies banner to the right-hand side Thread viewer. + - Updated the About Mattermost Team Edition modal to change the community link from `mattermost.org` to `mattermost.com/community/`. + - Invite to team modal now auto-focuses its email search input. + +#### Enterprise Edition + - Added a new dialog for Remove License confirmation. + - The **Renew Now** button is no longer shown if the license ID does not exist in the portal. Instead, **Contact Sales** is shown. + - System Admins are now able to upgrade the server to the Enterprise edition and request the trial license with a single click for a simplified user experience. + +#### Administration + - The config setting ``ServiceSettings.EnableReliableWebSockets`` promoted to general availability. For compatibility with older clients, the server will always return ``true`` for the ``/v4/config/client`` endpoint. + - Added server support for receiving binary (messagepack encoded) WebSocket messages. + - Added new flag ``showTeamSidebar`` in ``registerProducts``, which, when set to ``true``, displays the team sidebar in the product. + - Memberlist logs and buckets are now parsed by DEBUG, INFO, WARN, or ERROR appropriately. + - Increased key length in plugin KV store to 150. + +### Bug Fixes + - Fixed an issue where when selecting the **Upgrade to Enterprise Edition** option. The upgrade progress bar and the **Restart** button were no longer shown once the progress reached 100%. + - Fixed an issue where the user avatar wasn’t removed from the participants list after the user’s only post in a thread was deleted. + - Fixed an issue with the exit animation on the invitation modal. + - Fixed an issue where the status menu unexpectedly closed when selecting the “Disable Notifications Until” header. + - Fixed an issue where using CMD/CTRL + SHIFT + F in global threads did not add a search term automatically. + - Fixed the alignment of the “X” button in the “message deleted” system message. + - Fixed an issue where the long post “Show More/Less” background was broken in the Thread viewer. + - Changed Client4 to properly set Content-Type as application/json on API calls. + - Fixed an issue with post hover menu overlap. + +### config.json + +#### Changes to Team Edition and Enterprise Edition: +- The config setting ``ServiceSettings.EnableReliableWebSockets`` was removed, and the ability to buffer messages during a connection loss has been promoted to general availability. This setting is enabled for older clients to maintain backwards compatibility. + +### Go Version + - v6.3 is built with Go ``v1.16.7``. + +### Known Issues + - Announcement banner can cause the top team to be partially obstructed [MM-40887](https://mattermost.atlassian.net/browse/MM-40887). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - ``CTRL/CMD + SHIFT + A`` shortcut does not open **Account Settings** [MM-38236](https://mattermost.atlassian.net/browse/MM-38236). + - Known issues related to the Collapsed Reply Threads (Beta) are [listed here](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - Boards export and reimport duplicates boards because all IDs are replaced by new ones on the server. See the [GitHub issue](https://github.com/mattermost/focalboard/issues/1924) for more information. + +### Contributors +- [AccountingMattermost](https://github.com/AccountingMattermost), [Adovenmuehle](https://github.com/Adovenmuehle), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [asaadmahmood](https://github.com/asaadmahmood), [AshishDhama](https://github.com/AshishDhama), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [ChristophKaser](https://github.com/ChristophKaser), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [craph](https://github.com/craph), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet/), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), darmen, [darmenerk](https://github.com/darmenerk), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [dunak-debug](https://github.com/dunak-debug), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [gbochora](https://github.com/gbochora), [Grucqq](https://github.com/Grucqq), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [JenyaFTW](https://github.com/JenyaFTW), [jespino](https://github.com/jespino), [johnsonbrothers](https://github.com/johnsonbrothers), [JoomlaEstonia](https://github.com/JoomlaEstonia), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [JulienTant](https://github.com/JulienTant), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [krotovkk](https://github.com/krotovkk), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majo](https://translate.mattermost.com/user/majo/), [maksimatveev](https://github.com/maksimatveev), [master7](https://translate.mattermost.com/user/master7/), [mateioprea](https://github.com/mateioprea), [matt-w99](https://github.com/matt-w99), [matthew-w](https://translate.mattermost.com/user/matthew-w/), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mjnagel](https://github.com/mjnagel), [mrckndt](https://github.com/mrckndt), [Mshahidtaj](https://github.com/Mshahidtaj), [nab-77](https://github.com/nab-77), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [nishantwrp](https://github.com/nishantwrp), [ogi-m](https://github.com/ogi-m), [olaysco](https://github.com/olaysco), [pablovelezvidal](https://github.com/pablovelezvidal), [Phrynobatrachus](https://github.com/Phrynobatrachus), [poflankov](https://github.com/poflankov), [Profesor08](https://github.com/Profesor08), [puerco](https://github.com/puerco), [rubenmeza](https://github.com/rubenmeza), [sanjaydemansol](https://github.com/sanjaydemansol), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [SebastianSpeitel](https://github.com/SebastianSpeitel), [seoyeongeun](https://translate.mattermost.com/user/seoyeongeun/), [serhack](https://github.com/serhack), [shadowshot-x](https://github.com/shadowshot-x), [shazm](https://github.com/shazm), [sibasankarnayak](https://github.com/sibasankarnayak), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [tilto0822](https://github.com/tilto0822), [tsabi](https://github.com/tsabi), [varghese.jose](https://translate.mattermost.com/user/varghese.jose/), [vinod-demansol](https://github.com/vinod-demansol), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [YairFernando67](https://github.com/YairFernando67), [YC](https://github.com/YC) + +---- + +## Release v6.2 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html) + +- **v6.2.5, released 2022-03-10** + - Mattermost v6.2.5 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v6.2.4, released 2022-02-21** + - Fixed a major web and desktop app performance issue for users with a large accumulated number of Direct Messages and Group Messages. +- **v6.2.3, released 2022-02-03** + - Mattermost v6.2.3 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The default for ``ThreadAutoFollow`` has been changed to ``false``. This does not affect existing configurations where this value is already set to ``true`` [MM-41351](https://mattermost.atlassian.net/browse/MM-41351). + - Prevented some instances where operations relating to Collapsed Reply Threads added load to the database server even when the ``ThreadAutoFollow`` and ``CollapsedThreads`` config settings were disabled [MM-41350](https://mattermost.atlassian.net/browse/MM-41350). + - ``.pages`` content search is no longer available due to technical difficulties. + - Fixed an issue where MySQL installations re-triggered the v6.0 migration on server restart [MM-41330](https://mattermost.atlassian.net/browse/MM-41330). +- **v6.2.2, released 2022-01-21** + - Mattermost v6.2.2 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with the v6 migration where the ``Users.Timezone`` column had a default. This affected servers that had Mattermost v4.9 or earlier installed before upgrading to v6.0 or later [MM-39297](https://mattermost.atlassian.net/browse/MM-39297). + - Fixed an issue where attempting to parse an empty flag resulted in a spurious log line which clogged up the console. +- **v6.2.1, released 2021-12-17** + - Mattermost v6.2.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue where a SIGSEGV error occurred after upgrading to v6.2.0 when plugins were disabled in configuration. +- **v6.2.0, released 2021-12-16** + - Mattermost v6.2.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - Channel results in the channel autocomplete will include private channels. Customers using [Bleve](https://docs.mattermost.com/configure/bleve-search.html) or [Elasticsearch](https://docs.mattermost.com/scale/elasticsearch.html) for autocomplete will have to reindex their data to get the new results. Since this can take a long time, we suggest disabling autocomplete and running indexing in the background. When this is complete, re-enable autocomplete. Note that only channel members will see private channel names in autocomplete results. + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html), available in beta, are known to have a negative impact on server performance. If you cannot easily scale up and tune your database, or if you are running the Mattermost application server and database server on the same machine, we recommended disabling [``ThreadAutoFollow``](https://docs.mattermost.com/configure/configuration-settings.html#automatically-follow-threads) and [``CollapsedThreads``](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta) until Collapsed Reply Threads is promoted to general availability in Q2 2022. Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + +```{Important} +If you upgrade from a release earlier than v6.1, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Playbook Updates + - Added the ability to follow playbook runs to stay informed about the procedures you care about. + - Added other improvements including the ability to search playbooks, share URLs of individual runs and playbooks, and filter runs by playbook. + +#### Boards Updates + - Added a calendar view to stay on track with deadlines. + - Added the ability to @mention someone on a card with ease. + +### Improvements + +#### User Interface (UI) + - Clarified Latex Rendering config setting descriptions and fixed a broken product documentation link. + - Updated the "One-click reactions on messages" user setting to "Quick reactions on messages". + - Updated **Account Settings** terminology to **Profile**. + - Updated instances of **switch** to **navigate**. + - Updated in-product text terminology to shift from **comments** to **conversations** and **replies**. + - Added a **Click to open thread** setting for all users, to allow users to click anywhere on a message to open the reply thread. + - Do Not Disturb option for **Tomorrow** now displays the expiry time. + - Recent emojis now get updated based on the default selected skin tone. + - Updated **SingleImageView** to hide the image name for attached images until the image is collapsed. + - Moved the expand arrow to the left of an image name. + - The image expansion icon now appears on image hover. + - Added online status to profile images on user autocomplete. + - App Commands now have an option to be opened as modals. + - Added support for navigating through Collapsed Reply Threads via arrow keys. + - Added support for focusing the input box in Collapsed Reply Threads while typing. + - Added support for blurring the input box in Collapsed Reply Threads by pressing ESCAPE. + - Adjusted the channel override desktop notification preference for Threads. + - User interface is now improved when no text is set for a custom status. + +#### Performance + - Added a general performance fix for loading the web application and typing. + - Improved performance while typing by moving some autocomplete layout calculations. + - Improved performance by reducing DOM usage during render. + +#### Enterprise Edition + - Implemented a new design for the current **Edition and License** System Console page in Self-Hosted installs. + +### Bug Fixes + - Fixed an issue where OpenID redirects didn't work when hosting Mattermost on a subdirectory. + - Fixed an issue where the webapp crashed sometimes when clicking on an image file from "Recent files". + - Fixed an issue where the default log rotation file size was mistakenly set to 10GB, and is now reverted back to 100MB. + - Fixed an issue where emoji reaction buttons on posts did not respect user permissions. + - Fixed an issue where unchecking the automatic timezone changed the timezone in the selector. + - Fixed an issue where emoji names were being truncated too soon in the emoji picker. + - Fixed an issue where the thread footer did not allow the user to follow a Thread. + - Fixed an issue where the app crashed when switching to Threads view after leaving a channel. + - Fixed an issue where Mattermost crashed when deleting a root post from Global Threads. + - Fixed an issue where push notifications did not clear from the lock screen or the notification center with Collapsed Reply Threads enabled. + - Fixed an issue where Direct Message notifications were missing the sender name with Collapsed Reply Threads enabled. + - Fixed an issue where keyboard shortcuts were not working with Global Threads. + - Fixed an issue where API allowed changing the name of the Town Square channel. + - Fixed an issue where errors were logged if a user disabled notifications. + - Fixed an issue where a channel was not immediately removed from the sidebar when the current user was removed from it. + - Fixed a potential server crash when creating or updating posts with permalink previews. + - Fixed an issue where permalinks created from saved posts did not correctly redirect to the correct team. + - Fixed an issue where long file extension names pushed out of the bounds of the module. + - Fixed slow channel loading for instances with website link previews enabled. + - Removed real-time updates of a couple of features to prevent overloading servers on user updates. The "This channel has guests" indicator and the number of timezones displayed when notifying members of a group will only be updated on channel change now. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added a new config setting ``DeveloperFlags``. + - Removed ``DesktopLatestVersion`` and ``DesktopMinVersion`` config settings. + +### API Changes + - Added a new ``IsEnterpriseReady()`` plugin API. + - Added a new ``GET /api/v4/roles`` API endpoint. + - Added new ``UpdateCustomStatus`` and ``RemoveUserCustomStatus`` plugin APIs for user custom status. + - Added CRUD methods for user sessions to the plugin API. + +### Go Version + - v6.2 is built with Go ``v1.16.7``. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - Member type is missing from autocomplete [MM-38989](https://mattermost.atlassian.net/browse/MM-38989). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - ``CTRL/CMD + SHIFT + A`` shortcut does not open **Settings** [MM-38236](https://mattermost.atlassian.net/browse/MM-38236). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - Boards are not refreshing on creation. See the [GitHub discussion](https://github.com/mattermost/focalboard/discussions/1971) for more information. + - When selecting the **Upgrade to Enterprise Edition** button, the upgrade progress bar and the restart button are no longer shown once progress reaches 100%. Users can't restart the server directly from the Mattermost user interface, and must restart the server manually. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ahills60](https://github.com/ahills60), [alauregaillard](https://github.com/alauregaillard), [amyblais](https://github.com/amyblais), [anchepiece](https://github.com/anchepiece), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [AWerbrouck](https://github.com/AWerbrouck), [BenCookie95](https://github.com/BenCookie95), [berkeka](https://github.com/berkeka), [bretanac93](https://github.com/bretanac93), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [cleferman](https://github.com/cleferman), [clovis1122](https://github.com/clovis1122), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [daovansonbg](https://github.com/daovansonbg), [De1ain](https://github.com/De1ain), [devinbinnie](https://github.com/devinbinnie), [dipak-demansol](https://github.com/dipak-demansol), [dontoisme](https://github.com/dontoisme), [ekl1773](https://github.com/ekl1773), [emdecr](https://github.com/emdecr), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [engineereng](https://github.com/engineereng), [Ericliu1912](https://github.com/Ericliu1912), [erik](https://translate.mattermost.com/user/erik), [erni27](https://github.com/erni27), [esethna](https://github.com/esethna), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [Genei180](https://github.com/Genei180), [gigawhitlocks](https://github.com/gigawhitlocks), [Grucqq](https://github.com/Grucqq), [gtanczyk](https://github.com/gtanczyk), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [iOSGeekster](https://github.com/iOSGeekster), [ironbyte](https://github.com/ironbyte), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [ivernus](https://github.com/ivernus), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [JenyaFTW](https://github.com/JenyaFTW), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [joseph.jose](https://translate.mattermost.com/user/joseph.jose), [jprusch](https://github.com/jprusch), [jrester](https://github.com/jrester), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [JulienTant](https://github.com/JulienTant), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kaitrin](https://github.com/kaitrin), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [kayge](https://github.com/kayge), [kirtilodha](https://github.com/kirtilodha), [KKVANONYMOUS](https://github.com/KKVANONYMOUS), [koox00](https://github.com/koox00), [korvmoij](https://github.com/korvmoij), [kott](https://github.com/kott), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [LSantos06](https://github.com/LSantos06), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [marcvelasco](https://github.com/marcvelasco), [marianunez](https://github.com/marianunez), [majo](https://translate.mattermost.com/user/majo), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7), [mathiasvr](https://github.com/mathiasvr), [matthew-w](https://translate.mattermost.com/user/matthew-w), [matt-w99](https://github.com/matt-w99), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [milotype](https://github.com/milotype), [mkraft](https://github.com/mkraft), [mr-aboutin](https://github.com/mr-aboutin), [mRuggi](https://github.com/mRuggi), [Mshahidtaj](https://github.com/Mshahidtaj), [namreg](https://github.com/namreg), [nat-gunner](https://github.com/nat-gunner), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaiz](https://translate.mattermost.com/user/nikolaiz/), [nikolaizah](https://github.com/nikolaizah), [nishantwrp](https://github.com/nishantwrp), [ogi-m](https://github.com/ogi-m), [pablovelezvidal](https://github.com/pablovelezvidal), [pascalhein](https://github.com/pascalhein), [penthaapatel](https://github.com/penthaapatel), [Phrynobatrachus](https://github.com/Phrynobatrachus), [poflankov](https://github.com/poflankov), [prakharporwal](https://github.com/prakharporwal), [Prassud](https://github.com/Prassud), [puerco](https://github.com/puerco), [Quentin](https://translate.mattermost.com/user/Quentin), [rakshit087](https://github.com/rakshit087), [ramiyengar](https://github.com/ramiyengar), [Roy-Orbison](https://github.com/Roy-Orbison), [sadohert](https://github.com/sadohert), [saeid.hmdr](https://translate.mattermost.com/user/saeid.hmdr/), [saeidkh6991](https://github.com/saeidkh6991), [sangramrath](https://github.com/sangramrath), [sarvani1997](https://github.com/sarvani1997), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [serhack](https://github.com/serhack), [shadowshot-x](https://github.com/shadowshot-x), [SharathHuddar](https://github.com/SharathHuddar), [shzmr](https://github.com/shzmr), [sibasankarnayak](https://github.com/sibasankarnayak), [SiderealArt](https://github.com/SiderealArt), [sondv](https://translate.mattermost.com/user/sondv), [spirosoik](https://github.com/spirosoik), [srijit2002](https://github.com/srijit2002), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [teamzamong](https://github.com/teamzamong), [tsabi](https://github.com/tsabi), [valentinrozman](https://github.com/valentinrozman), [varghese.jose](https://translate.mattermost.com/user/varghese.jose), vicky-demansol, [weblate](https://github.com/weblate), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [YairFernando67](https://github.com/YairFernando67), [YoheiZuho](https://github.com/YoheiZuho), [zchezgi](https://github.com/zchezgi), [Zeezee1210](https://github.com/Zeezee1210), [Ziggiz](https://github.com/Ziggiz) + +---- + +## Release v6.1 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html) + +- **v6.1.3, released 2022-02-03** + - Mattermost v6.1.3 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The default for ``ThreadAutoFollow`` has been changed to ``false``. This does not affect existing configurations where this value is already set to ``true`` [MM-41351](https://mattermost.atlassian.net/browse/MM-41351). + - Prevented some instances where operations relating to Collapsed Reply Threads added load to the database server even when the ``ThreadAutoFollow`` and ``CollapsedThreads`` config settings were disabled [MM-41350](https://mattermost.atlassian.net/browse/MM-41350). + - ``.pages`` content search is no longer available due to technical difficulties. + - Fixed an issue where MySQL installations re-triggered the v6.0 migration on server restart [MM-41330](https://mattermost.atlassian.net/browse/MM-41330). +- **v6.1.2, released 2022-01-21** + - Mattermost v6.1.2 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with the v6 migration where the ``Users.Timezone`` column had a default. This affected servers that had Mattermost v4.9 or earlier installed before upgrading to v6.0 or later [MM-39297](https://mattermost.atlassian.net/browse/MM-39297). +- **v6.1.1, released 2021-12-17** + - Mattermost v6.1.1 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a general performance fix for loading the web application and typing. + - Improved performance while typing by moving some autocomplete layout calculations. + - Improved performance by reducing DOM usage during render. + - Removed real-time updates of a couple of features to prevent overloading servers on user updates. The "This channel contains guests" indicator and the number of timezones displayed when notifying members of a group will only be updated on channel change now. + - Fixed slow channel loading for instances with website link previews enabled. + - Fixed an issue with Focalboard where an empty white screen appeared in Mattermost desktop app on reload. + - Fixed an issue where v6.1 reported an incorrect mmctl version. +- **v6.1, released 2021-11-16** + - Mattermost v6.1.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Important Upgrade Notes + - Please refer to [the schema migration analysis](https://gist.github.com/streamer45/997b726a86b5d2a624ac2af435a66086) when upgrading to v6.1. + - The Bleve index has been updated to use the scorch index type. This new default index type features some efficiency improvements which means that the indexes use significantly less disk space. To use this new type of index, after upgrading the server version, run a purge operation and then a reindex from the Bleve section of the System Console. Bleve is still compatible with the old indexes, so the currently indexed data will work fine if the purge and reindex is not run. + - A composite index has been added to the jobs table for better query performance. For some customers with a large jobs table, this can take a long time, so we recommend adding the index during off-hours, and then running the migration. A table with more than 1 million rows can be considered as large enough to be updated prior to the upgrade. + - For PostgreSQL: ``create index concurrently idx_jobs_status_type on jobs (status,type);`` + - For MySQL: ``create index idx_jobs_status_type on Jobs (Status,Type);`` + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html), available in beta, are known to have a negative impact on server performance. If you cannot easily scale up and tune your database, or if you are running the Mattermost application server and database server on the same machine, we recommended disabling [``ThreadAutoFollow``](https://docs.mattermost.com/configure/configuration-settings.html#automatically-follow-threads) and [``CollapsedThreads``](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta) until Collapsed Reply Threads is promoted to general availability in Q2 2022. Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + +```{Important} +If you upgrade from a release earlier than v6.0, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Timed Do Not Disturb + - Added the ability to disable all notifications for a specified period of time to avoid distractions, without losing important messages when you're back. + +#### Cross-team Recent Mentions + - Recent mentions and saved posts now show across all teams. + +#### Playbooks Updates + - Added a wiki-style page with a playbook preview as well as new playbook notifications. + +#### Boards Updates + - Added a new create board user interface, Board calculations to quickly get basic metrics on projects, at-mention notifications, as well as card previews. + +### Improvements + +#### User Interface (UI) + - Polish is promoted to an officially supported language. + - Added one-click reactions for posts. A user's three most recently used emojis display when the user hovers over a message. + - Added support for selecting names and aliases in the emoji picker. + - Changed the user interface of the edit-indicator of posts and moved it inline. + - Added a query param to translate in-product help pages when opened from the Desktop App. + - Updated in-product text for the invitation modal for clarity. + - Updated the file attachment limits and sizes within in-product help documentation. + - Added rendering for posts containing markdown in email notifications. + - Added support for inline Latex rendering. + - Added the **Move to...** option menu item to the channel header dropdown. + - Added keyboard shortcuts to tooltips. The shortcut key component is now used for displaying keys. + - Added support for Global threads infinite scroll. + - Added ``@here`` mention to the ``EnableConfirmNotificationsToChannel`` config setting to show a warning modal when over 5 members might be alerted with ``@here``. + +#### Integrations + - Added support for multi-select on Apps slash commands. + - App commands now make a distinction between the central channel and the right-hand side channel. + - App bindings now recognize the post menu options for each channel they live in. + - Added new ``registerMessageWillBeUpdatedHook(newPost, oldPost)`` client-side plugin hook to intercept edited messages. + +#### Performance + - Improved performance around rendering of system messages. + - Reduced storage-related slow-downs on page load. + +#### Administration + - Bulk imports with attached files now log and continue when a file fails to upload instead of halting. + - ``get flagged posts`` endpoint will now return only flagged posts for channels the user is a member of. + - Updated Bleve to v2 to use the scorch index type. + - Minimum supported browser versions changes: + - Chrome updated from ``61+`` to ``89+``. + - Firefox updated from ``60+`` to ``78+``. + - MacOS updated from ``10.9+`` to ``10.14+``. + +#### Enterprise Edition + - Once the user has selected **Start Trial**, they will see a modal that lists all of the features now available to them through the Enterprise plan. + - Once a non-licensed server has reached 10 users, a one-time modal is displayed to System Admins encouraging them to start a 30-day trial. + - Prometheus metrics are now enabled when running a standalone jobserver. + +### Bug Fixes + - Fixed a broken link to the **Custom Emoji** page on servers with a subpath configured. + - Fixed an issue where a "No results found" error string was displayed in the **Direct Messages** modal. + - Fixed an issue where the caret was placed in the middle of the emojis when picking two emojis from the emoji picker. + - Fixed an issue where **System Console > Channels > Channel Management** displayed an option to toggle group management in Team Edition, Starter, and Professional. + - Fixed an issue where the channel switcher was missing the "(You)" indicator on the user's own Direct Message channel. + - Fixed an issue where the clock format set by the user was not respected on the edit indicator popover. + - Replaced Metropolis font files with a new set to correct a kerning issue. + - Fixed an issue where deep links opened on mobile displayed an incorrect message directing users to open the Desktop app. + - Addressed various user interface style bugs from v6.0 release. + - Fixed emails templates for clients that do not support the ``style`` tag. + - Fixed an issue where the scrollbar was hardly visible with Denim & Sapphire themes. + - Fixed an issue where creating a bot with an invalid username returned an "invalid email" error. + - Fixed an issue where using ``/code`` did not render initial whitespace characters. + - Fixed an issue where **Try Enterprise for Free** option was missing spacing in mobile webview. + - Fixed an issue where the SQLStore cache was relied on when populating the WebConn channel memberships. + - Fixed an issue where logging was not re-configured when the server config was changed via the System Console. + - Fixed a display issue with the Indigo theme when returning from Playbooks to Channels. + - Fixed an issue where the offline indicator color did not use the correct theme color. + - Fixed various bugs for the Collapsed Reply Threads (Beta) feature, including: + - Fixed an issue where the recent sidebar sorting option didn't only consider parent posts. + - Fixed an issue where a badge was displayed on a thread list when the thread was started by another user in a Direct Message. + - Fixed an issue where the user avatar was displayed in the participants list after their post was deleted when the user had no other posts in the thread. + - Fixed an issue where the ephemeral message was not displyaed as the centre post. + - Fixed an issue with dragging and dropping files on a thread while on the Threads panel. + - Fixed an issue where permalinks were not highlighting a post on a thread that was already open on the right-hand side. + - Fixed an issue with missing threads in the Threads list. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableInlineLatex`` to add support for inline Latex rendering. + - Under ``JobSettings`` in ``config.json`` + - Added ``CleanupJobsThresholdDays``. This defines the time gap in days beyond which older jobs will be removed. Default is -1 which means the feature is disabled. Setting to 0 will clean all completed jobs. + +#### Database Changes + - Extended the maximum size to 256 characters for the following database columns: + - ``Sessions.Roles`` + - ``ChannelMembers.Roles`` + - ``TeamMembers.Roles`` + +### API Changes + - Added a new API endpoint ``POST /api/v4/posts/search`` to perform searches across all channels. + +### Go Version + - v6.1 is built with Go ``v1.16.7``. + +### Open Source Components + - Added ``fast-deep-equal``, ``luxon``, and ``react-window-infinite-loader`` to https://github.com/mattermost/mattermost-webapp. + - Added ``@mattermost/react-native-paste-input`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it's [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga/). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - Created permalinks from saved posts do not correctly redirect to the correct team [MM-39816](https://mattermost.atlassian.net/browse/MM-39816). + - Recent Mentions search sometimes includes incorrect results [MM-39867](https://mattermost.atlassian.net/browse/MM-39867). + - Experimental timezones and custom statuses can cause an increase in CPU usage and database connections for servers with an E20 license. A current workaround is to disable custom statuses or to disable experimental timezones. + - Webapp sometimes crashes when clicking an image from "Recent files" [MM-38239](https://mattermost.atlassian.net/browse/MM-38239). + - Member type is missing from autocomplete [MM-38989](https://mattermost.atlassian.net/browse/MM-38989). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - ``Ctrl/Cmd+Shift+A`` shortcut does not open **Account Settings** [MM-38236](https://mattermost.atlassian.net/browse/MM-38236). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [A9u](https://github.com/A9u), [aaronrothschild](https://github.com/aaronrothschild), [abhijit-singh](https://github.com/abhijit-singh), [achie27](https://github.com/achie27), [achromik](https://translate.mattermost.com/user/achromik/), [adithyaakrishna](https://github.com/adithyaakrishna), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alauregaillard](https://github.com/alauregaillard), [alejandrovelez7](https://github.com/alejandrovelez7), [alieh-rymasheuski](https://github.com/alieh-rymasheuski), [aloks98](https://github.com/aloks98), [amyblais](https://github.com/amyblais), [anchepiece](https://github.com/anchepiece), [andrewbrown00](https://github.com/andrewbrown00), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anoopmsivadas](https://github.com/anoopmsivadas), [anurag6713](https://github.com/anurag6713), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [astraldawn](https://github.com/astraldawn), [audreyaudz](https://github.com/audreyaudz), [Audrey Kon](https://github.com/audreyaudz), [Avinaba-Mazumdar](https://github.com/Avinaba-Mazumdar), [avinashlng1080](https://github.com/avinashlng1080), [AWerbrouck](https://github.com/AWerbrouck), [b4sen](https://github.com/b4sen), [banaboi](https://github.com/banaboi), [bartfelder](https://github.com/bartfelder), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [bensiauu](https://github.com/bensiauu), [berkeka](https://github.com/berkeka), [bhaveshgoyal182](https://github.com/bhaveshgoyal182), Bhavin789, [Bruno-366](https://github.com/Bruno-366), [calebroseland](https://github.com/calebroseland), [caugner](https://github.com/caugner), [chenilim](https://github.com/chenilim), [chetanyakan](https://github.com/chetanyakan), [chrysillala](https://github.com/chrysillala), [cinlloc](https://github.com/cinlloc), [cleferman](https://github.com/cleferman), [cognvn](https://github.com/cognvn), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [craph](https://github.com/craph), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkLord19](https://github.com/darkLord19), [DarshanKansara2015](https://github.com/DarshanKansara2015), [deanwhillier](https://github.com/deanwhillier), [DeeJayBro](https://github.com/DeeJayBro), [devinbinnie](https://github.com/devinbinnie), [dialvarezs](https://github.com/dialvarezs), [dimitraz](https://github.com/dimitraz), [dizlv](https://github.com/dizlv), [donno2048](https://github.com/donno2048), [drobiu](https://github.com/drobiu), [Duaard](https://github.com/Duaard), [echobash](https://github.com/echobash), [elyscape](https://github.com/elyscape), [emdecr](https://github.com/emdecr), [emilyacook](https://github.com/emilyacook), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [EranKricheli](https://github.com/EranKricheli), [erezo9](https://github.com/erezo9), Erik Pfeiffer, [esethna](https://github.com/esethna), [fareskalaboud](https://github.com/fareskalaboud), [fcoiuri](https://github.com/fcoiuri), [firasm](https://github.com/firasm), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gagandeepp](https://github.com/gagandeepp), [garanews](https://github.com/garanews), [gaurav-baghel](https://github.com/gaurav-baghel), [Gauravsaha-97](https://github.com/Gauravsaha-97), [GianOrtiz](https://github.com/GianOrtiz), [gigawhitlocks](https://github.com/gigawhitlocks), [gpt14](https://github.com/gpt14), [grsky360](https://github.com/grsky360), [gupsho](https://github.com/gupsho), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [Hard-Coder05](https://github.com/Hard-Coder05), [harshilsharma63](https://github.com/harshilsharma63), [hmhealey](https://github.com/hmhealey), [Hridoy-31](https://github.com/Hridoy-31), [iamquang95](https://github.com/iamquang95), [icelander](https://github.com/icelander), [igordsm](https://github.com/igordsm), [im-endangered](https://github.com/im-endangered), [iomodo](https://github.com/iomodo), [iOSGeekster](https://github.com/iOSGeekster), [isacikgoz](https://github.com/isacikgoz), [jamiehurewitz](https://github.com/jamiehurewitz), [Jasmin F](https://github.com/jasmezz), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [JenyaFTW](https://github.com/JenyaFTW), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jlram](https://github.com/jlram), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [joremysh](https://github.com/joremysh), [josephbaylon](https://github.com/josephbaylon), [joshalling](https://github.com/joshalling), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kaitrin](https://github.com/kaitrin), [kamre](https://github.com/kamre), [kanitmann](https://github.com/kanitmann), [KavyaJaiswal](https://github.com/KavyaJaiswal), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [korvmoij](https://translate.mattermost.com/user/korvmoij/), [krmh04](https://github.com/krmh04), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [leosunmo](https://github.com/leosunmo), [levb](https://github.com/levb), [lex111](https://github.com/lex111), [lieut-data](https://github.com/lieut-data), [lindy65](https://github.com/lindy65), [lonnelars](https://github.com/lonnelars), [LSantos06](https://github.com/LSantos06), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majo](https://translate.mattermost.com/user/majo/), [maknop](https://github.com/maknop), [marcvelasco](https://github.com/marcvelasco), [marianunez](https://github.com/marianunez), [Mark E Fuller](https://github.com/mefuller), [Markus Hermann](https://github.com/MarHerUMR), [maruTA-bis5](https://github.com/maruTA-bis5), [master7](https://translate.mattermost.com/user/master7/), [mathiasvr](https://github.com/mathiasvr), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [Matthew Williams](https://github.com/matthew-w), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [michizhou](https://github.com/michizhou), [mickmister](https://github.com/mickmister), [mishmanners](https://github.com/mishmanners), [mjnagel](https://github.com/mjnagel), [mkraft](https://github.com/mkraft), [mohitsaxenaknoldus](https://github.com/mohitsaxenaknoldus), [Mshahidtaj](https://github.com/Mshahidtaj), [NakulChauhan2001](https://github.com/NakulChauhan2001), [naltang](https://github.com/naltang), [namreg](https://github.com/namreg), [naresh1205](https://github.com/naresh1205), [nathanaelhoun](https://github.com/nathanaelhoun), [neallred](https://github.com/neallred), [NeroBurner](https://github.com/NeroBurner), [nevyangelova](https://github.com/nevyangelova), [ngmmartins](https://github.com/ngmmartins), [nishantwrp](https://github.com/nishantwrp), [noviicee](https://github.com/noviicee), [ogi-m](https://github.com/ogi-m), [pablovelezvidal](https://github.com/pablovelezvidal), [pascalhein](https://github.com/pascalhein), [pawankm21](https://github.com/pawankm21), [penthaapatel](https://github.com/penthaapatel), [Phrynobatrachus](https://github.com/Phrynobatrachus), [pikami](https://github.com/pikami), [pjenicot](https://github.com/pjenicot), [poflankov](https://github.com/poflankov), [prabhigupta](https://github.com/prabhigupta), [prakharporwal](https://github.com/prakharporwal), [prapti](https://github.com/prapti), [Privatecoder](https://github.com/Privatecoder), [prograde](https://translate.mattermost.com/user/prograde/), [puerco](https://github.com/puerco), [radiantly](https://github.com/radiantly), [rafaeelaudibert](https://github.com/rafaeelaudibert), [Ray0Emma](https://github.com/Ray0Emma), [rbradleyhaas](https://github.com/rbradleyhaas), [rootbid](https://github.com/rootbid), [Roy-Orbison](https://github.com/Roy-Orbison), [rutulganatra](https://github.com/rutulganatra), [s4kh](https://github.com/s4kh), [sadohert](https://github.com/sadohert), [sahil9001](https://github.com/sahil9001), [sakaitsu](https://github.com/sakaitsu), [sangramrath](https://github.com/sangramrath), [sanjaydemansol](https://github.com/sanjaydemansol), [sapora1](https://github.com/sapora1), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [seoyeongeun](https://github.com/seoyeongeun), [shadowshot-x](https://github.com/shadowshot-x), [shazm](https://github.com/shazm), [shinnlok](https://github.com/shinnlok), [shzmr](https://github.com/shzmr), [sibasankarnayak](https://github.com/sibasankarnayak), [spinales](https://github.com/spinales), [spirosoik](https://github.com/spirosoik), [srijit2002](https://github.com/srijit2002), [ssensalo](https://github.com/ssensalo), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [syauqy](https://github.com/syauqy), [Szymongib](https://github.com/Szymongib), [TautZuk](https://github.com/TautZuk), [teamzamong](https://translate.mattermost.com/user/teamzamong/), [TheLaw1337](https://github.com/TheLaw1337), [tiago154](https://github.com/tiago154), [triogempar](https://github.com/triogempar), [tsabi](https://github.com/tsabi), [ucyang](https://github.com/ucyang), [vblz](https://github.com/vblz), [vinod-demansol](https://github.com/vinod-demansol), [void-hr](https://github.com/void-hr), [weblate](https://github.com/weblate), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xMicky24GIT](https://github.com/xMicky24GIT), [yeongeun.seo](https://github.com/seoyeongeun), [ZeeshanAmjad0495](https://github.com/ZeeshanAmjad0495), [Zeezee1210](https://github.com/Zeezee1210), [zefhemel](https://github.com/zefhemel), [zolikonta](https://github.com/zolikonta), [zulmarij](https://github.com/zulmarij) + +---- + +(release-v6-0-feature-release)= +## Release v6.0 - [Feature Release](https://docs.mattermost.com/upgrade/release-definitions.html) + +- **v6.0.4, released 2021-12-17** + - Mattermost v6.0.4 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a general performance fix for loading the web application and typing. + - Improved performance while typing by moving some autocomplete layout calculations. + - Improved performance by reducing DOM usage during render. + - Removed real-time updates of a couple of features to prevent overloading servers on user updates. The "This channel contains guests" indicator and the number of timezones displayed when notifying members of a group will only be updated on channel change now. + - Fixed slow channel loading for instances with website link previews enabled. + - Fixed an issue where v6.0 reported an incorrect mmctl version. +- **v6.0.3, released 2021-11-15** + - Mattermost v6.0.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a possible panic during data retention jobs when ``DataRetentionSettings.EnableMessageDeletion`` was set to ``true`` [MM-39378](https://mattermost.atlassian.net/browse/MM-39378). + - Fixed a potential panic during the message export job [MM-39521](https://mattermost.atlassian.net/browse/MM-39521). + - Fixed some sentry crashes [MM-38565](https://mattermost.atlassian.net/browse/MM-38565), [MM-39208](https://mattermost.atlassian.net/browse/MM-39208), [MM-39420](https://mattermost.atlassian.net/browse/MM-39420). +- **v6.0.2, released 2021-10-27** + - Mattermost v6.0.2 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a race condition in telemetry IDs on High Availability servers [MM-39343](https://mattermost.atlassian.net/browse/MM-39343). + - Update prepackaged Boards version to 0.9.4. +- **v6.0.1, released 2021-10-18** + - Mattermost v6.0.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a panic in translations that caused the server to not run properly. The panic caused the server to be terminated [MM-39299](https://mattermost.atlassian.net/browse/MM-39299). + - Fixed an issue with the v6.0 migration where the ``Users.Timezone`` column had a default. This affected servers that had Mattermost v4.9 or earlier installed before upgrading [MM-39297](https://mattermost.atlassian.net/browse/MM-39297). + - Fixed an issue where a migration check failed for MariaDB databases. The data type JSON was aliased to ``LONGTEXT`` and the check was failing and causing the database migrations to run every restart. + - Added a fix to display ``tableName`` and ``columnName`` for JSONB schema failures. When there was a schema upgrade failure related to jsonb columns, the log line didn't mention which table/column was affected. + - Fixed an issue where selecting the "..." post menu on a System message crashed the webapp [MM-39116](https://mattermost.atlassian.net/browse/MM-39116). +- **v6.0.0, released 2021-10-13** + - Original 6.0.0 release + +### Deprecations + +1. [Legacy Command Line Tools](https://docs.mattermost.com/manage/command-line-tools.html). Most commands have been replaced by [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) and new commands have been added over the last few months, making this tool a robust replacement. + +2. [Slack Import via the web app](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-web-app). The Slack import tool accessible via the Team Setting menu has been replaced by the [mmetl](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-mmetl-tool-and-bulk-import) tool that is much more comprehensive for the types of data it can assist in uploading. + +3. MySQL versions below 5.7.12. Minimum support is now for 5.7.12+. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). + +4. Elasticsearch 5 and 6 - [versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 is Elasticsearch version 7.0. + +5. Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We no longer provide support for Mattermost Desktop App issues on Windows 7. + +6. [DisableLegacyMFAEndpoint](https://docs.mattermost.com/configure/configuration-settings.html#disable-legacy-mfa-api-endpoint) configuration setting. + +7. [ExperimentalTimezone](https://docs.mattermost.com/configure/configuration-settings.html#timezone) configuration setting. The config setting is removed and the feature is promoted to general availability. + +8. All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access [custom, collapsible channel categories](https://mattermost.com/blog/custom-collapsible-channel-categories/) among many other channel organization features. The deprecated settings include: + + - [EnableLegacySidebar](https://docs.mattermost.com/configure/configuration-settings.html#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-read-only-experimental) (Please see [channel moderation settings](https://docs.mattermost.com/onboard/advanced-permissions.html#read-only-channels), which allow you to set any channel as read-only, including Town Square) + - [ExperimentalHideTownSquareinLHS](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-hidden-in-left-hand-sidebar-experimental) + - [EnableXToLeaveChannelsFromLHS](https://docs.mattermost.com/configure/configuration-settings.html#enable-x-to-leave-channels-from-left-hand-sidebar-experimental) + - [CloseUnusedDirectMessages](https://docs.mattermost.com/configure/configuration-settings.html#autoclose-direct-messages-in-sidebar-experimental) + - [ExperimentalChannelOrganization](https://docs.mattermost.com/configure/configuration-settings.html#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](https://docs.mattermost.com/configure/configuration-settings.html#experimental-sidebar-features) + +9. [All configuration settings previously marked as “Deprecated”](https://docs.mattermost.com/configure/configuration-settings.html#deprecated-configuration-settings). + +10. Changes to ``mattermost-server/model`` for naming consistency. + +### Important Upgrade Notes + + - Longer migration times can be expected. See [this document](https://gist.github.com/streamer45/59b3582118913d4fc5e8ff81ea78b055) for the estimated upgrade times with datasets of 10+ million posts. See [this document](https://gist.github.com/streamer45/868c451164f6e8069d8b398685a31b6e) for the estimated upgrade times with datasets of 70+ million posts. The field type of Data in model.ClusterMessage was changed to []byte from string. Therefore, a major thing to note is that a v6 server is incompatible to run along with a v5 server in a cluster. Customers upgrading from 5.x to 6.x cannot do a High Availability upgrade. While upgrading, it is required that no other v5 server runs when a v6 server is brought up. A v6 server will run significant database schema changes that can cause a large startup time depending on the dataset size. Zero downtime will not be possible, but depending on the efforts made during the migration process, it can be minimized to a large extent. It is recommended to start Mattermost directly and not through systemctl to avoid the server process getting killed during the migration. This can happen since the value of ``TimeoutStartSec`` in the provided systemctl service file is set to 1 hour. Customers using the Mattermost Kubernetes operator should be aware of the above migration information and choose the path that is most appropriate for them. If (1) is acceptable, then the normal upgrade process using the operator will suffice. For minimum downtime, follow (2) before using the operator to update Mattermost following the normal upgrade process. + 1. Low effort, long downtime - This is the usual process of starting a v6 server normally. This has 2 implications: during the migration process, various tables will be locked which will render those tables read-only during that period. Secondly, once the server finishes migration and starts the application, no other v5 server can run in the cluster. + 2. Medium effort, medium downtime - This process will require SQL queries to be executed manually on the server. To avoid causing a table lock, a customer can choose to use the pt-online-schema-change tool for MySQL. For Postgres, the table locking is very minimal. The advantage is that since there are a lot of queries, the customer can take their own time to run individual queries during off-hours. All queries except #11 are safe to be executed this way. Then the usual method of (1) can be followed. + 3. High effort, low downtime - This process requires everything of (2), plus it tries to minimize the impact of query #11. We can do this by following step 2, and then starting v6 along with a running v5 server, and then monitor the application logs. As soon as the v6 application starts up, we need to bring down a v5 node. This minimizes the downtime to only a few seconds. + - While trying to upgrade to a Mattermost version >= 6.0.x, you might encounter the following error: ``Failed to alter column type. It is likely you have invalid JSON values in the column. Please fix the values manually and run the migration again.`` This means that the particular column has some invalid JSON values which need to be fixed manually. A common fix that is known to work is to wipe out all \u0000 characters. Please follow these steps: + 1. Check the affected values by: ``SELECT COUNT(*) FROM <table> WHERE <column> LIKE '%\u0000%';`` + 2. If you get a count more than 0, check those values manually, and confirm they are okay to be removed. + 3. Remove them by ``UPDATE <table> SET <column> = regexp_replace(<column>, '\\u0000', '', 'g') where <column> like '%\u0000%';`` + 4. Then try to start Mattermost again. + - Focalboard plugin has been renamed to Mattermost Boards, and v0.9.1 (released with Mattermost v6.0) is now enabled by default. + - The advanced logging configuration schema changed. This is a breaking change relative to 5.x. See updated [documentation](https://docs.mattermost.com/comply/audit-log.html). + - Some breaking changes to plugins are included: + - Support for left-hand side-specific bot icons was dropped. + - Removed a deprecated "Backend" field from the plugin manifest. + - Converted the "Executables" field in the plugin manifest to a map. + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html), available in beta, are known to have a negative impact on server performance. If you cannot easily scale up and tune your database, or if you are running the Mattermost application server and database server on the same machine, we recommended disabling [``ThreadAutoFollow``](https://docs.mattermost.com/configure/configuration-settings.html#automatically-follow-threads) and [``CollapsedThreads``](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta) until Collapsed Reply Threads is promoted to general availability in Q2 2022. Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + +```{Important} +If you upgrade from a release earlier than v5.39, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Multi-Product Platform + - Mattermost now ships as one platform with three products - Channels, Playbooks, and Boards. + - Playbooks and Boards are visible when [plugins are enabled system-wide](https://docs.mattermost.com/configure/configuration-settings.html#enable-plugins). + +#### Global Product Launcher + - Added a global header for product navigation for Channels, Playbooks, and Boards. This is disabled on the mobile web view and mobile apps. + +#### Branding Changes + - Added a new default brand theme named "Denim". + - The existing theme names and colors, including "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" have been updated to the new "Denim", "Sapphire", "Quartz", "Indigo", and "Onyx" theme names and colors, respectively. Anyone using the existing themes will see slightly modified theme colors after their server or workspace is upgraded. The theme variables for the existing "Mattermost", "Organization", "Mattermost Dark", and "Windows Dark" themes will still be accessible in [our documentation](https://docs.mattermost.com/messaging/customizing-theme-colors.html#custom-theme-examples), so a custom theme can be created with these theme variables if desired. Custom themes are unaffected by this change. + - Added a new light theme named "Quartz" to the default available list of themes. + - Updated email templates to the new branding. + +#### Packaging Changes + - Updated in-product strings referencing E10 & E20 to [new packaging](https://mattermost.com/pricing). + - Features moved from legacy E10 to all plans, including Team Edition: + - System default permissions, e.g. permission to create and archive channels system-wide. + - Specifically, “System Scheme” only in **System Console > User Management > Permissions**. + - Existing permissions/policies in TE/E0 for "Enable Team Creation" and "Allow Team Administrators to edit others’ posts" are properly handled. + - Team and Channel management pages (but without channel moderation, e.g. read-only channels). + - Features moved from legacy E20 to Professional plan: + - SSO with OpenID Connect, SAML, Google and Entra ID + - O365 integrations including MS Teams Calling and MS Calendar + - Jira multi-server support + - Advanced team permissions + - Channel moderation + - E20, Professional, and Enterprise license SKUs are now supported for installing Enterprise plugins. + +#### Beta features Promoted to General Availability + - Archived channels + - Compliance exports + - Custom terms of service + - Guest accounts + - System roles + - Plugins + +#### Permalink Previews + - Added support for permalink previews for posts in Mattermost. Previews are generated to minimize context switching when sharing message links in Channels. + +#### Tutorial Updates + - Added a tip to the **Getting Started** page for downloading Desktop Apps. + - Updated tutorial icons and changed text content in tutorial tips. + - Updated the default treatment for the ``Add channel`` button to the current color and by team name. + - Added a tutorial tip for new settings and status buttons. + - Added a tip for the product switcher. This tip is skipped if not applicable. + +### Improvements + +#### User Interface (UI) + - Added “Invite People” to the main "+" button below the hamburger menu. + - The whole category bounds are now highlighted while holding a channel above a category name on the left-hand side. + - Updated **Account Settings > Display > Timezone** to be more user friendly. + - New theme agnostic file preview modal takes up the full screen. The file preview now has information about the user, channel, and the file, and moves away from text-based buttons to icon-based buttons. + - Increased the limit of uploaded file attachments per post from 5 to 10. + - Added desktop notifications for followed Threads. + - Hungarian and English-Australian are now official languages. + - Added a **Start Trial** call-to action to the **Main Menu**. + - Changed H1-H3 heading font from Open Sans to Metropolis. + +#### Performance + - Improved typing performance when the emoji autocomplete is open. + - Added performance improvements for draft storage with multiple tabs open. + - Improved performance of draft loading. + +#### Integrations + - Pre-packaged Channel Export plugin v1.0.0. + - Added a "rest field" to the App command parser. + - Added support for React components in channel header tooltips registered by plugins. + - Exported ``ChannelInviteModal`` and ``ChannelMembersModal`` components for plugins. + +#### Administration + - Added ``playbooks`` and ``boards`` to restricted team URLs list. Conflict exists if users hit the URL to the team directly without the trailing channel, permalink or threads information (ie server/team) and they have a team name “playbooks” or “boards”. User would expect to be taken to their messaging team. + - Added the ability for Team Edition to edit role permissions. + - Removed a hard-coded override of ``TeamSettings.MaxNotificationsPerChannel`` on unlicensed servers (e.g. Team Edition). + - Migrated the extraction command to mmctl. + - Removed the convert channel endpoint to use ``/channels/{channel_id}/privacy`` instead. + - Removed deprecated ``Posts.ParentId`` in favor of the semantically equivalent ``Posts.RootId``. Also removed ``CommandWebhook.ParentId`` and ``CompliancePost.ParentId`` for the same reason. + - Added a field to each of the compliance export formats (CSV, Global Relay, and Actiance) to indicate that a post was viewable via the new permalink preview feature. + - Removed the following deprecated CLI commands in favor of [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html): + - channel + - command + - config + - extract + - group + - integrity + - ldap + - license + - logs + - permissions + - plugin + - reset + - roles + - sampledata + - team + - user + - webhook + +### Bug Fixes + - Fixed an issue where GitLab ``ButtonText`` and ``ButtonColor`` settings were not reflected on the login screen. + - Fixed an issue with Collapsed Reply Threads (Beta) where replying to a Thread caused users to re-follow the previously unfollowed Thread. + - Fixed an issue where floating timestamps appeared incorrectly on the right-hand side with Collapsed Reply Threads (Beta) enabled. + - Fixed an issue where pinned and saved posts were no longer highlighted. + - Disabled admin support email status check job on server startup. + - Fixed an issue on joining a missing channel as a System Admin. + - Fixed import process for imports with attachments. + - Fixed an error with app locations and binding filtering. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableOnboardingFlow``, for enhanced user onboarding experience feature. + - Added ``EnablePermalinkPreviews`` to enable permalink previews. + - Under ``FileSettings`` in ``config.json``: + - Added ``MaxImageResolution`` config setting to control the maximum dimension (in pixels) of image uploads. + - Removed all of the following configs: + - ``EnableOnlyAdminIntegrations`` + - ``RestrictCustomEmojiCreation`` + - ``RestrictPostDelete`` + - ``AllowEditPost`` + - ``ImageProxyType`` + - ``ImageProxyURL`` + - ``ImageProxyOptions`` + - ``UseExperimentalGossip`` + - ``EnableTeamCreation`` + - ``RestrictTeamInvite`` + - ``RestrictPublicChannelManagement`` + - ``RestrictPrivateChannelManagement`` + - ``RestrictPublicChannelCreation`` + - ``RestrictPrivateChannelCreation`` + - ``RestrictPublicChannelDeletion`` + - ``RestrictPrivateChannelDeletion`` + - ``RestrictPrivateChannelManageMembers`` + - ``DisableLegacyMFAEndpoint`` + - ``ExperimentalTownSquareIsReadOnly`` + - ``ExperimentalHideTownSquareinLHS`` + - ``EnableXToLeaveChannelsFromLHS`` + - ``CloseUnusedDirectMessages`` + - ``ExperimentalChannelOrganization`` + - ``ExperimentalChannelSidebarOrganization`` + - ``EnableLegacySidebar`` + - The legacy MFA endpoint + - ``utils/authorization.go`` and moved any permissions to the ``MakeDefaultRoles()`` function. + +### Database Changes + - Added the following database indexes: + - ``idx_posts_root_id_delete_at_create_at`` + - ``idx_channels_team_id_display_name`` + - ``idx_channels_team_id_type`` + - ``idx_threads_channel_id_last_reply_at`` + - ``idx_channelmembers_user_id_channel_id_last_viewed_at`` + - ``idx_channelmembers_channel_id_scheme_guest_user_id`` + - Removed the following redundant database indexes: + - ``idx_posts_root_id`` + - ``idx_channels_team_id`` + - ``idx_threads_channel_id`` + - ``idx_channelmembers_user_id`` + - Updated all references of ``ToJson/FromJson`` methods to be in the form ``ToJSON/FromJSON``. + - Increased ``Post.Props`` size limit to 800,000 characters. + +### API Changes + - Updated API to use ``per_page`` query parameter instead of ``pageSize``. This makes the threads API consistent with other endpoints, and automatically limits the number of requested threads with our param handling code. The ``pageSize`` query parameter will still be supported until version 6.0 of the server becomes the minimum version required by the mobile client. + +### Websocket Event Changes + - Added Websocket client to products. + - Added plugin Websocket hooks: ``OnWebSocketConnect``, ``OnWebSocketDisconnect`` and ``WebSocketMessageHasBeenPosted``. + +### Library Changes + - Removed deprecated ``model.ComparePassword`` method. + - Removed deprecated ``Context.SourcePluginId`` field. + - Removed ``(*model.Client4).CheckUserMfa``. + - Removed ``(*model.Client4).GetServerBusyExpires``. + - Removed MB constant from model package. + - Removed use of pointers to the following types: + - ``model.ChannelList`` + - ``model.ChannelListWithTeamData`` + - ``model.ChannelMembers`` + - ``model.Preferences`` + - ``model.ProductNotices`` + - Renamed ``plugin.Context.IpAddress`` to ``plugin.Context.IPAddress``. + - Renamed fields in the model package to have more idiomatic names. + +### Go Version + - v6.0 is built with Go ``v1.16.7``. + +### Open Source Components + - Added ``@mattermost/compass-components``, ``@mattermost/compass-icons``, ``styled-components`` and ``timezones.json``, and removed ``react-inlinesvg`` from https://github.com/mattermost/mattermost-webapp. + - Added ``@types/redux-mock-store`` to https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it is [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga/). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - Webapp sometimes crashes when clicking an image from "Recent files" [MM-38239](https://mattermost.atlassian.net/browse/MM-38239). + - Member type is missing from autocomplete [MM-38989](https://mattermost.atlassian.net/browse/MM-38989). + - File upload might fail for SVG files [MM-38982](https://mattermost.atlassian.net/browse/MM-38982). + - Deep link opened on mobile shows incorrect text directing the opening to the Desktop app [MM-38913](https://mattermost.atlassian.net/browse/MM-38913). + - Channel switcher is missing "(You)" indicator on your own Direct Message channel [MM-38798](https://mattermost.atlassian.net/browse/MM-38798). + - ``Ctrl/Cmd+Shift+A`` shortcut does not open **Account Settings** [MM-38236](https://mattermost.atlassian.net/browse/MM-38236). + - Indigo theme glitch may occur when returning from Playbooks [MM-38910](https://mattermost.atlassian.net/browse/MM-38910). + - **System Console > Channels > Channel Management** has an option to toggle group management in Team Edition, Starter, and Professional [MM-39216](https://mattermost.atlassian.net/browse/MM-39216). + - Experimental timezones and custom statuses can cause an increase in CPU usage and database connections for servers with an E20 license. A current workaround is to disable custom statuses or to disable experimental timezones. + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [alieh-rymasheuski](https://github.com/alieh-rymasheuski), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [arpit1912](https://github.com/arpit1912), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [ashutoshpw](https://github.com/ashutoshpw), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [BoFFire](https://github.com/BoFFire), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [chikei](https://github.com/chikei), [cjmartian](https://github.com/cjmartian), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [CuriousCorrelation](https://github.com/CuriousCorrelation), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [darkLord19](https://github.com/darkLord19), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [dihmuzikien](https://github.com/dihmuzikien), [Duaard](https://github.com/Duaard), [emilyacook](https://github.com/emilyacook), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [himanshu007-creator](https://github.com/himanshu007-creator), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [itao](https://github.com/itao), [ivernus](https://github.com/ivernus), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [JtheBAB](https://github.com/JtheBAB), [jtwillis92](https://github.com/jtwillis92), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [KobeBergmans](https://github.com/KobeBergmans), [koox00](https://github.com/koox00), [krmh04](https://github.com/krmh04), [krutarththakkar](https://github.com/krutarththakkar), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majidsajadi](https://github.com/majidsajadi), [marianunez](https://github.com/marianunez), [matthewbirtch](https://github.com/matthewbirtch), [matthew.williams](https://translate.mattermost.com/user/matthew-w/), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mikhailrimashevski](https://github.com/mikhailrimashevski), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [Mshahidtaj](https://github.com/Mshahidtaj), [neallred](https://github.com/neallred), [neflyte](https://github.com/neflyte), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [pablovelezvidal](https://github.com/pablovelezvidal), [petrmifek](https://github.com/petrmifek), [poflankov](https://github.com/poflankov), [puerco](https://github.com/puerco), [rbradleyhaas](https://github.com/rbradleyhaas), [Rina-dsg](https://github.com/Rina-dsg), [rodcorsi](https://github.com/rodcorsi), [Rutam21](https://github.com/Rutam21), [sadohert](https://github.com/sadohert), [sakaitsu](https://translate.mattermost.com/user/sakaitsu/), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [shazm](https://github.com/shazm), [sibasankarnayak](https://github.com/sibasankarnayak), [spirosoik](https://github.com/spirosoik), [sshiv5768](https://github.com/sshiv5768), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [thePanz](https://github.com/thePanz), [tsabi](https://translate.mattermost.com/user/tsabi/), [vadimasadchi](https://github.com/vadimasadchi), [vinod-demansol](https://github.com/vinod-demansol), [Westacular](https://github.com/Westacular), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yedamao](https://github.com/yedamao), [Zeezee1210](https://github.com/Zeezee1210), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v5.39 - [Quality Release](https://docs.mattermost.com/upgrade/release-definitions.html#quality-release) + +- **v5.39.3, released 2021-12-17** + - Mattermost v5.39.3 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a general performance fix for loading the web application and typing. + - Improved performance while typing by moving some autocomplete layout calculations. + - Improved performance by reducing DOM usage during render. + - Removed real-time updates of a couple of features to prevent overloading servers on user updates. The "This channel contains guests" indicator and the number of timezones displayed when notifying members of a group will only be updated on channel change now. + - Fixed an issue where v5.39 reported an incorrect mmctl version. +- **v5.39.2, released 2021-11-15** + - Mattermost v5.39.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v5.39.1, released 2021-10-27** + - Mattermost v5.39.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed an issue with fetching threads upon websocket reconnection. + - Fixed a race condition in telemetry IDs on High Availability servers [MM-39343](https://mattermost.atlassian.net/browse/MM-39343). +- **5.39.0, released 2021-09-16** + - Original 5.39 release + +Mattermost v5.39.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Improvements + +#### User Interface (UI) + - Updated in-product help documentation to fix broken links and to correct outdated information. + - Italian, Polish, Korean, and Ukrainian languages have been downgraded to alpha. Korean and Ukrainian are [no longer actively maintained](https://handbook.mattermost.com/contributors/join-us/localization#translation-quality). + +### Bug Fixes + - Fixed a possible panic during license validation. + - Fixed an issue with loading of emojis in message attachment titles. + - Fixed an issue where the timestamp in deleted messages was not correctly positioned. + - Changed the whitespace in the refresh bar so that it always displays to the user. + - Fixed an issue where email invites were not sent when clicking the **Next** button during onboarding. + - Fixed an issue where clicking "View Message" in an email did not navigate to the post or remember the user's preference to "View in App". + - Fixed an issue with the detection of certain collapsible images. + - Prevented users from having the unreads filter enabled when the button to toggle it was not shown. + - Fixed an issue where Mattermost's shortcut key CTRL+SHIFT+A to open the **Account Settings** clashed with Chrome's CTRL+SHIFT+A that opens a "Search Tabs" pop-up. + - Fixed a crash when markdown images were present on the message attachments and embedded bindings. + - Fixed an issue that kept message attachment fields unaligned. + - Fixed an issue with right-hand side ``SuggestionList`` positioning. + - Fixed an issue where Mattermost panicked on ``docx`` files uploaded with ``.doc`` extension. + - Fixed a bug with the auto-responder where it would incorrectly calculate the time interval and never send the message. + - Fixed a decoding problem for OpenID integration. The requests are now decoded against ``RawURLEncoding``. + - Fixed various bugs for the Collapsed Reply Threads (Beta) feature, including: + - Fixed an issue where a gap appeared between the first and second consecutive message from the same user. + - Fixed an issue where the thread unread state would not update on websocket reconnect. + - Fixed an issue where the main channel view root post timestamp added a horizontal scrollbar on hover. + - The ``ThreadAutoFollow`` setting must now be enabled in order to enable ``CollapsedThreads``. + - Fixed issue with users re-following a previously unfollowed thread when other users replied to the thread. + - Clicking code blocks and in-line code no longer open the associated thread. + - Fixed an issue where two scrollbars appeared in the Threads view on high resolution monitors using zoom. + - Fixed an issue where the quick channel switcher mention counts did not follow collapsed threads logic. + - Fixed an issue where threads started by webhooks/integrations were being auto-followed by the webhook/integration creator when collapsed threads was enabled. + - Fixed an issue where re-connecting to the websocket caused thread mentions to be cleared in the user interface with collapsed reply threads enabled. + - Fixed an issue where the **New messages** line and date separators overlapped text in a thread. + +### Go Version + - v5.39 is built with Go ``1.16.7``. + +### Upcoming Deprecations in Mattermost v6.0 + +The following deprecations are planned for the Mattermost v6.0 release, which is scheduled for 2021/10/13. This list is subject to change prior to the release. + +1. [Legacy Command Line Tools](https://docs.mattermost.com/manage/command-line-tools.html). All commands have been fully replaced by [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) and new commands have been added over the last few months, making this tool a full and robust replacement. + +2. [Slack Import via the web app](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-web-app). The Slack import tool accessible via the Team Setting menu is being replaced by the [mmetl](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-mmetl-tool-and-bulk-import) tool that is much more comprehensive for the types of data it can assist in uploading. + +3. MySQL versions below 5.7.7. Minimum support will now be for 5.7.12. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). + +4. Elasticsearch 5 and 6 - [versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 will be Elasticsearch version 7.0. + +5. Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We will no longer provide support for Mattermost Desktop App issues on Windows 7. + +6. [DisableLegacyMFAEndpoint](https://docs.mattermost.com/configure/configuration-settings.html#disable-legacy-mfa-api-endpoint) configuration setting. + +7. [ExperimentalTimezone](https://docs.mattermost.com/configure/configuration-settings.html#timezone) configuration setting. The config setting will be removed and the feature will be promoted to general availability. + +8. All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access [custom, collapsible channel categories](https://mattermost.com/blog/custom-collapsible-channel-categories/) among many other channel organization features. The settings being deprecated include: + + - [EnableLegacySidebar](https://docs.mattermost.com/configure/configuration-settings.html#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-read-only-experimental) + - [ExperimentalHideTownSquareinLHS](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-hidden-in-left-hand-sidebar-experimental) + - [EnableXToLeaveChannelsFromLHS](https://docs.mattermost.com/configure/configuration-settings.html#enable-x-to-leave-channels-from-left-hand-sidebar-experimental) + - [CloseUnusedDirectMessages](https://docs.mattermost.com/configure/configuration-settings.html#autoclose-direct-messages-in-sidebar-experimental) + - [ExperimentalChannelOrganization](https://docs.mattermost.com/configure/configuration-settings.html#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](https://docs.mattermost.com/configure/configuration-settings.html#experimental-sidebar-features) + +9. [All configuration settings previously marked as “Deprecated”](https://docs.mattermost.com/configure/configuration-settings.html#deprecated-configuration-settings). + +10. Changes to ``mattermost-server/model`` for naming consistency. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it is [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga/). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - Experimental timezones and custom statuses can cause an increase in CPU usage and database connections for servers with an E20 license. A current workaround is to disable custom statuses or to disable experimental timezones. + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Pinned posts are no longer highlighted [MM-34870](https://mattermost.atlassian.net/browse/MM-34870). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [adammorawski1](https://github.com/adammorawski1), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amirmoyousefi](https://github.com/amirmoyousefi), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [anurag6713](https://github.com/anurag6713), [arjitc](https://github.com/arjitc), [ArmanChand](https://github.com/ArmanChand), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [asimsedhain](https://github.com/asimsedhain), [aspleenic](https://github.com/aspleenic), [BenCookie95](https://github.com/BenCookie95), [BenLloydPearson](https://github.com/BenLloydPearson), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [chikei](https://github.com/chikei), [chitramdasgupta](https://github.com/chitramdasgupta), [cobenash](https://github.com/cobenash), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cvockrodt](https://github.com/cvockrodt), [cwarnermm](https://github.com/cwarnermm), [dbpolito](https://github.com/dbpolito), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [DeviousLab](https://github.com/DeviousLab), [DjMagicFingers](https://github.com/DjMagicFingers), [Duaard](https://github.com/Duaard), [elyscape](https://github.com/elyscape), [emilyacook](https://github.com/emilyacook), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [engineereng](https://github.com/engineereng), [ewwollesen](https://github.com/ewwollesen), [fksu](https://github.com/fksu), [flynbit](https://github.com/flynbit), [Francois-D](https://github.com/Francois-D), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gozeloglu](https://github.com/gozeloglu), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haalcala](https://github.com/haalcala), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [ivanaairenee](https://github.com/ivanaairenee), [jadrales](https://github.com/jadrales), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [JtheBAB](https://github.com/JtheBAB), [jufab](https://github.com/jufab), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [KobeBergmans](https://github.com/KobeBergmans), [koox00](https://github.com/koox00), [krutarththakkar](https://github.com/krutarththakkar), [kscheel](https://github.com/kscheel), [larkox](https://github.com/larkox), [LauSam09](https://github.com/LauSam09), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majidsajadi](https://github.com/majidsajadi), [maliur](https://github.com/maliur), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [mattermod](https://github.com/mattermod), [matthewbirtch](https://github.com/matthewbirtch), [matthew.williams](https://translate.mattermost.com/user/matthew-w/), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mmskv](https://github.com/mmskv), [mrckndt](https://github.com/mrckndt), [Mshahidtaj](https://github.com/Mshahidtaj), [nat-gunner](https://github.com/nat-gunner), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [nikolaizah](https://github.com/nikolaizah), [Nog-Frog](https://github.com/Nog-Frog), [pablovelezvidal](https://github.com/pablovelezvidal), [Prassud](https://github.com/Prassud), [rbradleyhaas](https://github.com/rbradleyhaas), [redrru](https://github.com/redrru), [rodcorsi](https://github.com/rodcorsi), [roopakv](https://github.com/roopakv), [rrey](https://github.com/rrey), [Rutam21](https://github.com/Rutam21), [sakaitsu](https://translate.mattermost.com/user/sakaitsu/), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [Shahzayb](https://github.com/Shahzayb), [Shaz-25](https://github.com/Shaz-25), [sibasankarnayak](https://github.com/sibasankarnayak), [sonereker](https://github.com/sonereker), [spirosoik](https://github.com/spirosoik), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [talesmc](https://github.com/talesmc), [thePanz](https://github.com/thePanz), [tsabi](https://translate.mattermost.com/user/tsabi/), [VA2XJM](https://github.com/VA2XJM), [vadimasadchi](https://github.com/vadimasadchi), [vinod-demansol](https://github.com/vinod-demansol), [wget](https://github.com/wget), [WietseWind](https://github.com/WietseWind), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yedamao](https://github.com/yedamao), [YJSoft](https://github.com/YJSoft), [zefhemel](https://github.com/zefhemel), [Ziggiz](https://github.com/Ziggiz) + +---- + +## Release v5.38 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.38.4, released 2021-11-15** + - Mattermost v5.38.4 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v5.38.3, released 2021-10-27** + - Mattermost v5.38.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a race condition in telemetry IDs on High Availability servers [MM-39343](https://mattermost.atlassian.net/browse/MM-39343). +- **v5.38.2, released 2021-08-26** + - Upgraded Go version to 1.16.7 to fix an application crash issue. + - Fixed an issue where mmctl ``config reload`` command was missing local-mode server-side implementation. [MM-38082](https://mattermost.atlassian.net/browse/MM-38082) +- **v5.38.1, released 2021-08-18** + - Fixed an issue where Playbooks v1.16.0 could not be installed as a pre-packaged plugin [MM-37928](https://mattermost.atlassian.net/browse/MM-37928). +- **v5.38.0, released 2021-08-16** + - Original 5.38.0 release + +Mattermost v5.38.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + +### Deprecations + - The “config watcher” (the mechanism that automatically reloads the ``config.json`` file) has been removed in favor of the ``mmctl config reload`` command, which must be run to apply configuration changes after they are made on disk. This change improves configuration performance and robustness. + +### Important Upgrade Notes + - v5.38 adds fixes for some of the incorrect mention counts and unreads around threads and channels since the introduction of Collapsed Reply Threads (Beta). This fix is done through a SQL migration, and it may take several minutes to complete for large databases. The ``fixCRTChannelMembershipCounts`` fix takes 1 minute and 20 seconds for a database containing approximately 4 million channel memberships and about 130,000 channels. The ``fixCRTThreadCountsAndUnreads`` fix takes about 3 minutes and 30 seconds for a database containing 56367 threads, 124587 thread memberships, and 220801 channel memberships. These are on MySQL v5.6.51. + - Focalboard v0.8.2 (released with Mattermost v5.38.0) requires Mattermost v5.37+ due to the new database connection system. + +```{Important} +If you upgrade from a release earlier than v5.37, please read the other [Important Upgrade Notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html). +``` + +### Highlights + +#### Granular Data Retention Policies (Enterprise E20) + - A ``data_retention`` type job can now be run even if the global policy is disabled. The granular (i.e. team and channel-specific) policies will be executed when the data retention job is run. Please note there is a known issue where deleted posts get displayed in channels without new activity after the retention job is run. This issue is tracked with [this ticket](https://mattermost.atlassian.net/browse/MM-36574). + +#### Enhanced User Onboarding Experience + - To help new users get started with Mattermost, new Getting Started steps have been added to the onboarding experience. These steps help users to complete their profile, name their teams, configure desktop notifications, and invite others to join their team. Additionally, once the onboarding is complete, users are provided with helpful tips to get started with channels, plugins, and more. + +#### Playbooks Updates + - ``Incident Collaboration`` was rebranded to ``Playbooks``. Also the channel right-hand sidebar is redesigned, our own playbooks are shared as templates, and more triggers and actions were added. + +#### Focalboard Updates + - Added created-by property and improved performance with shared database connections. Focalboard 0.8.2 requires Mattermost v5.37+ due to a new database connection system. + +### Improvements + +#### User Interface (UI) + - Upgraded German language back to an official language. + - Markdown formatting is now stripped from push notifications. + - Enabled the **Set Status** button if the custom status hasn't changed from currently set status. + - Improved default rendering of images inserted via the GIF picker. + - Small text changes were added to Direct and Group Message menus: **Mute channel** and **Edit Channel Header** now reads as **Mute Conversation** and **Edit Conversation Header**. + +#### Performance + - Improved performance of components that show reactions on posts. + - Improved performance of certain components when viewing non-Direct Message channels. + - Added minor improvements to performance of messages posted in the right-hand side. + - Improved typing performance in affected environments by reducing the frequency in which drafts are saved. + +#### Integrations + - Added icons to apps in the Marketplace. + - Apps can now add arbitrary markdown in between fields on forms. + - Added support for markdown in apps forms, interactive dialogs field descriptions, errors, and slash commands. + - Improved user and channel selector for app commands. + - Added support for ``react-intl`` and ```` usage in plugins. + - Added plugin API methods for user access tokens and OAuth apps. + +#### Administration + - Added a new feature to archive and unarchive teams through **System Console** > **Teams**. + +### Bug Fixes + - Fixed an issue where the "Find channel" channel switcher text overflowed beyond the button for some languages. + - Fixed an issue where inter-plugin requests without a body didn't work. + - Fixed an issue with opening a dialog from an interactive message when returning an empty response. + - Fixed an issue where the **Add Members** modal was incorrectly themed on the Mattermost Dark Theme. + - Fixed a panic in the ``getPrevTrialLicense`` API request when loading the System Console on Team Edition. + - Fixed an issue where admin advisor notifications were accidentally re-enabled in a previous release. + - Fixed various bugs for the Collapsed Reply Threads (Beta) feature, including: + - Fixed an issue where an error occurred while following a thread with no replies. + - Fixed an issue where ``reply_count`` of 0 was always returned for GET single Post on ``/posts/<postid>`` API. + - Fixed an issue where following a single message returned a status 500. + - Fixed an issue where when replying in a thread after unfollowing it, the thread was not auto-followed again. + - Fixed an issue where when enabling Collapsed Reply Threads, channels that had no new activity were showing as unread. + - Fixed an issue with thread unreads when the feature was enabled by a user. + - Fixed an issue where self replies were marking threads as unread. + - Unread threads are now correctly displayed on app load for teams in the sidebar when Collapsed Reply Threads feature is enabled. + - Fixed an issue where "Thread" in the thread viewer was displayed vertically in some languages. + - Fixed an issue where opening global threads containing a root post markdown image crashed the app. + - Fixed an issue where the app crashed when switching to the Threads view after leaving a channel. + - Fixed an issue where replying to a thread from the global threads screen marked the channel as read. + - The **Mark all as unread** button is now no longer disabled for Collapsed Reply Threads. + - Fixed root posts not being shown as followed for the post creator after receiving the first reply that affected servers with Collapsed Reply Threads enabled and database read replicas configured. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``PluginSettings`` in ``config.json``: + - Added ``ChimeraOAuthProxyURL`` to allow specifying Chimera URL that can be used by plugins to connect with pre-created OAuth applications. + - The config setting ``EnableReliableWebSockets`` now defaults to ``true``. + +### API Changes + - Added ``CreateChannelSidebarCategory``, ``GetChannelSidebarCategories`` and ``UpdateChannelSidebarCategories`` to the Plugin API. + - Add a new Plugin API method that allows files to register dropdown menu actions. + +### Go Version + - v5.38 is built with Go ``1.16.0``. + +### Open Source Components + - Added ``classnames`` and ``react-window`` to https://github.com/mattermost/mattermost-webapp/. + - Added ``@react-native-community/datetimepicker``, ``array.prototype.flat``, and ``base-64`` to https://github.com/mattermost/mattermost-mobile/. + +### Upcoming Deprecations in Mattermost v6.0 + +The following deprecations are planned for the Mattermost v6.0 release, which is scheduled for 2021/10/15. This list is subject to change prior to the release. + +1. [Legacy Command Line Tools](https://docs.mattermost.com/manage/command-line-tools.html). All commands have been fully replaced by [mmctl](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) and new commands have been added over the last few months, making this tool a full and robust replacement. + +2. [Slack Import via the web app](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-web-app). The Slack import tool accessible via the Team Setting menu is being replaced by the [mmetl](https://docs.mattermost.com/onboard/migrating-to-mattermost.html#migrating-from-slack-using-the-mattermost-mmetl-tool-and-bulk-import) tool that is much more comprehensive for the types of data it can assist in uploading. + +3. MySQL versions below 5.7.7. Minimum support will now be for 5.7.12. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). + +4. Elasticsearch 5 and 6 - [versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 will be Elasticsearch version 7.0. + +5. Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We will no longer provide support for Mattermost Desktop App issues on Windows 7. + +6. [DisableLegacyMFA](https://docs.mattermost.com/configure/configuration-settings.html#disable-legacy-mfa-api-endpoint) configuration setting. + +7. [ExperimentalTimezone](https://docs.mattermost.com/configure/configuration-settings.html#timezone) configuration setting. + +8. All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access [custom, collapsible channel categories](https://mattermost.com/blog/custom-collapsible-channel-categories/) among many other channel organization features. The settings being deprecated include: + + - [EnableLegacySidebar](https://docs.mattermost.com/configure/configuration-settings.html#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-read-only-experimental) + - [ExperimentalHideTownSquareinLHS](https://docs.mattermost.com/configure/configuration-settings.html#town-square-is-hidden-in-left-hand-sidebar-experimental) + - [EnableXToLeaveChannelsFromLHS](https://docs.mattermost.com/configure/configuration-settings.html#enable-x-to-leave-channels-from-left-hand-sidebar-experimental) + - [CloseUnusedDirectMessages](https://docs.mattermost.com/configure/configuration-settings.html#autoclose-direct-messages-in-sidebar-experimental) + - [ExperimentalChannelOrganization](https://docs.mattermost.com/configure/configuration-settings.html#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](https://docs.mattermost.com/configure/configuration-settings.html#experimental-sidebar-features) + +9. [All configuration settings previously marked as “Deprecated”](https://docs.mattermost.com/configure/configuration-settings.html#deprecated-configuration-settings). + +10. Changes to ``mattermost-server/model`` for naming consistency. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it is [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga/). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - The server version for v5.38.2 for Team Edition is reported as ``5.39.2``. + - Deleted posts get displayed in channels without new activity after the data retention job is run [MM-36574](https://mattermost.atlassian.net/browse/MM-36574). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Fields on the right column in a message attachment render unevenly [MM-36943](https://mattermost.atlassian.net/browse/MM-36943). + - Pinned posts are no longer highlighted. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [aileenpalafox](https://github.com/aileenpalafox), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [arjitc](https://github.com/arjitc), [arvinDarmawan](https://github.com/arvinDarmawan), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [aspleenic](https://github.com/aspleenic), [avinashlng1080](https://github.com/avinashlng1080), [bakurits](https://github.com/bakurits), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [calebroseland](https://github.com/calebroseland), [chenilim](https://github.com/chenilim), [chikei](https://github.com/chikei), [cognvn](https://github.com/cognvn), [colorfusion](https://github.com/colorfusion), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkLord19](https://github.com/darkLord19), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [ditsemto](https://github.com/ditsemto), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [engineereng](https://github.com/engineereng), [esethna](https://github.com/esethna), [evelikov](https://github.com/evelikov), [ewwollesen](https://github.com/ewwollesen), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gbonnefille](https://github.com/gbonnefille), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [hackercat3211](https://github.com/hackercat3211), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [Konghuy](https://github.com/Konghuy), [koox00](https://github.com/koox00), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lordinkavu](https://github.com/lordinkavu), [lynn915](https://github.com/lynn915), [madhavhugar](https://github.com/madhavhugar), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majidsajadi](https://github.com/majidsajadi), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [matthewbirtch](https://github.com/matthewbirtch), [matthew.williams](https://translate.mattermost.com/user/matthew-w/), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mrckndt](https://github.com/mrckndt), [Mshahidtaj](https://github.com/Mshahidtaj), [N3rdP1um23](https://github.com/N3rdP1um23), [nat-gunner](https://github.com/nat-gunner), [natalie-hub](https://github.com/natalie-hub), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [nickboldt](https://github.com/nickboldt), [nickmisasi](https://github.com/nickmisasi), [nika-begiashvili](https://github.com/nika-begiashvili), [nikolaizah](https://github.com/nikolaizah), [ogi-m](https://github.com/ogi-m), [oh6hay](https://github.com/oh6hay), [pablovelezvidal](https://github.com/pablovelezvidal), [papanireal](https://github.com/papanireal), [petrmifek](https://github.com/petrmifek), [Pezhvak](https://github.com/Pezhvak), [robinmetral](https://github.com/robinmetral), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [sakaitsu](https://translate.mattermost.com/user/sakaitsu/), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [source-punk](https://github.com/source-punk), [stafot](https://github.com/stafot), [stevemudie](https://github.com/stevemudie), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [thePanz](https://github.com/thePanz), [thierrymarianne](https://github.com/thierrymarianne), [tronginc](https://github.com/tronginc), [tsabi](https://translate.mattermost.com/user/tsabi/), [VA2XJM](https://github.com/VA2XJM), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xlanor](https://github.com/xlanor), [xuanvi26](https://github.com/xuanvi26), [yedamao](https://github.com/yedamao), [zefhemel](https://github.com/zefhemel) + +---- + +## Release v5.37 - [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) + +- **5.37.10, released 2022-08-31** + - Improved groups query performance by not counting deleted members. + - Prevented the request for counting channel members in a group when the feature is disabled to prevent performance problems at scale. +- **v5.37.9, released 2022-03-10** + - Mattermost v5.37.9 contains medium severity level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). +- **v5.37.8, released 2022-02-03** + - Mattermost v5.37.8 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - The default for ``ThreadAutoFollow`` has been changed to ``false``. This does not affect existing configurations where this value is already set to ``true`` [MM-41351](https://mattermost.atlassian.net/browse/MM-41351). + - Prevented some instances where operations relating to Collapsed Reply Threads added load to the database server even when the ``ThreadAutoFollow`` and ``CollapsedThreads`` config settings were disabled [MM-41350](https://mattermost.atlassian.net/browse/MM-41350). + - ``.pages`` content search is no longer available due to technical difficulties. + - Fixed an issue where Actiance compliance jobs caused the Mattermost server process to crash with a panic [MM-41245](https://mattermost.atlassian.net/browse/MM-41245). +- **v5.37.7, released 2022-01-21** + - Mattermost v5.37.7 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added support for channel moderation for Professional-licensed servers [MM-40824](https://mattermost.atlassian.net/browse/MM-40824). +- **v5.37.6, released 2021-12-17** + - Mattermost v5.37.6 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Added a general performance fix for loading the web application and typing. + - Improved performance while typing by moving some autocomplete layout calculations. + - Improved performance by reducing DOM usage during render. + - Removed real-time updates of a couple of features to prevent overloading servers on user updates. The "This channel contains guests" indicator and the number of timezones displayed when notifying members of a group will only be updated on channel change now. +- **v5.37.5, released 2021-11-30** + - Fixed an issue where OpenID redirect did not work when hosting Mattermost on a subdirectory [MM-40151](https://mattermost.atlassian.net/browse/MM-40151). + - Fixed an issue where v5.37 reported an incorrect mmctl version. +- **v5.37.4, released 2021-11-15** + - Mattermost v5.37.4 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a potential panic during the message export job [MM-39521](https://mattermost.atlassian.net/browse/MM-39521). + - Fixed some sentry crashes [MM-38565](https://mattermost.atlassian.net/browse/MM-38565), [MM-39208](https://mattermost.atlassian.net/browse/MM-39208). + - Updated in-product help documentation to fix broken links and to correct outdated information. +- **v5.37.3, released 2021-10-27** + - Mattermost v5.37.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Fixed a race condition in telemetry IDs on High Availability servers [MM-39343](https://mattermost.atlassian.net/browse/MM-39343). + - Fixed import process for imports with attachments [MM-38375](https://mattermost.atlassian.net/browse/MM-38375). + - Fixed an issue that kept message attachment fields unaligned [MM-36943](https://mattermost.atlassian.net/browse/MM-36943). +- **v5.37.2, released 2021-08-26** + - Upgraded Go version to 1.16.7 to fix an application crash issue. + - Fixed a server panic issue. [MM-37574](https://mattermost.atlassian.net/browse/MM-37574) + - Fixed an issue where saving or updating user statuses caused the logs to be filled with multiple key insertion errors. [MM-37202](https://mattermost.atlassian.net/browse/MM-37202). + - Fixed a panic in the ``getPrevTrialLicense`` API request when loading the System Console on Team Edition. [MM-37108](https://mattermost.atlassian.net/browse/MM-37108) + - Fixed an issue where screen readers read “user object” instead of reading the username or channel in the **Switch Channels** modal. +- **v5.37.1, released 2021-08-04** + - Mattermost v5.37.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/). + - Improved typing performance in affected environments by reducing the frequency at which drafts are saved. + - Fixed an issue in clustering where a mutex would fail to be unlocked when a timeout happened. [MM-37246](https://mattermost.atlassian.net/browse/MM-37246) +- **v5.37.0, released 2021-07-16** + - Original 5.37.0 release + +### Deprecations + - The ``platform`` binary and “--platform” flag have been removed. If you are using the “--platform” flag or are using the ``platform`` binary directly to run the Mattermost server application via a systemd file or custom script, you will be required to use only the mattermost binary. + +### Important Upgrade Notes + - [Collapsed Reply Threads](https://mattermost.com/blog/collapsed-reply-threads-beta/) are available as beta in Mattermost Server v5.37 and later. It’s expected that you may experience bugs as we stabilize the feature. In particular, please be aware of [the known issues documented here](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues). + - v5.37 adds support for emoji standard v13.0. If you have added a custom emoji in the past that uses one of the new system names, then that custom emoji is going to get overwritten by the system emoji. The workaround is to change the custom emoji name. + - Parts of Incident Collaboration are now available to all Mattermost editions. As part of this update, Incident Collaboration will require a minimum server version of v5.37. To learn more about what is available in each edition, visit [our pricing page](https://mattermost.com/pricing/). + - Support for Mattermost Server v5.31 [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) will come to the end of its life cycle on October 15, 2021. Upgrading to Mattermost Server v5.37 or later is required. + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html), available in beta, are known to have a negative impact on server performance. If you cannot easily scale up and tune your database, or if you are running the Mattermost application server and database server on the same machine, we recommended disabling [``ThreadAutoFollow``](https://docs.mattermost.com/configure/configuration-settings.html#automatically-follow-threads) and [``CollapsedThreads``](https://docs.mattermost.com/configure/configuration-settings.html#collapsed-reply-threads-beta) until Collapsed Reply Threads is promoted to general availability in Q2 2022. Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + +```{Important} +If you upgrade from a release earlier than v5.36, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Collapsed Reply Threads (Beta) + - We're excited to give you early access to Collapsed Reply Threads (Beta). It can be enabled in the **System Console > Experimental > Collapsed Reply Threads (Beta)**. Learn more about the features and known issues in [our documentation](https://docs.mattermost.com/help/messaging/organizing-conversations.html). + +#### Emoji Enhancements with Skin Tone Selection + - Added support for emoji standard v13.0. Users now have the ability to choose various skin tones using the Mattermost emoji picker. Mobile support is included in v1.45 Mobile App release (July 16th). + +#### Improved Enterprise Trial Experience (Enterprise Editions E0, E10, E20) + - After a Self-Managed trial ends, admins can optionally contact sales or make a purchase in a single click. + +#### Focalboard: Grouped Table view, New properties, and More (Beta) + - Focalboard tables can now be grouped by a property, for example allowing you to quickly see tasks per epic or owner. + +#### Incident Collaboration Updates + - The update includes availability on all editions, playbook keyword monitoring, retrospective report, and playbook dashboard. + +#### English-Australian Language Support + - Mattermost is now available in English-Australian. + +### Improvements + +#### User Interface (UI) + - In the at-mention autocomplete, the user’s nickname is no longer shown when (you) is present. + - Updated the help text on the **Add Users** channel modal. + - Added the ability to upload ``.jpeg`` files on Linux. Uploading ``.jpg`` files was already supported. + - The **Channel Switcher** now displays recently viewed channels when launched. + - Polish, German, and Italian languages were downgraded to beta as they are [no longer actively maintained](https://handbook.mattermost.com/contributors/contributors/localization#translation-quality). + - Custom statuses can now be set to expire after common time intervals or custom selected dates and times. Mobile App support will be added in a future release. + +#### Performance + - Added some improvements to typing performance. + +#### Administration + - Improved memory performance for large image uploads, particularly PNGs with transparency. + - Optimized the bulk import process by no longer requiring the server to write the incoming archive to the filesystem when unzipping it. + - Added channel restore and channel privacy change endpoints to the local mode using the System bot. + +### Bug Fixes + - Fixed an issue where users were unable to set a custom status emoji via slash command. Added the logic for detecting unicode emoji and setting it as a custom status emoji via slash commands. + - Fixed an issue where messages with fallback text were repeated. + - Fixed an issue where a persistent unread badge showed on the **Main Menu** when **Enable Marketplace** or **Enable Plugins** was disabled. + - Fixed an issue where sidebar icons were not aligned with the navigator area icons. + - Fixed an issue where using CTRL+F in a **Direct Message** channel added the user ID rather than the user's name into the search field. + - Fixed an issue where user icons were displayed at full opacity in muted channels. + - Fixed an issue where a redundant ``user_update`` websocket event was generated for bot users. + - Fixed an issue where a Self-Managed Enterprise Edition E20 trial could be activated more than once without contacting the Mattermost support team. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``CollapsedThreads`` to add support for Collapsed Reply Threads (Beta). + +#### Database Changes + - Removed several redundant Database indexes. + +### API Changes + - Added a new field, team_id, to the response of ``POST api/v4/groups/{group_id}/channels/{channel_id}/link`` to add a team ID to the response when linking a channel to a group. + - Added an optional ``collapsed_threads_supported`` parameter to /channels/members/{userId}/view to indicate that the client supports collapsed threads. + - Added an optional ``collapsed_threads_supported`` parameter to /users/{userId}/posts/{postId}/set_unread to indicate that the client supports collapsed threads. + - Updated the webapp to pass ``collapsed_threads_supported`` parameters to the server to indicate that the webapp supports collapsed reply threads. + - Updated the webapp to correctly mark channels and threads as unread/read when marking root and reply posts as unread/read. + - Added a new endpoint ``GET /trial-license/prev`` for fetching last used trial license. + - Added two new fields in ``CustomStatus`` struct and modified the APIs to validate and handle them. + +### Go Version + - v5.37 is built with Go ``1.15.5``. + +### Open Source Components + - Removed ``reselect`` from https://github.com/mattermost/mattermost-webapp/. + +### Upcoming Deprecations in Mattermost v6.0 + +The following deprecations are planned for the Mattermost v6.0 release, which is scheduled for 2021/10/15. This list is subject to change prior to the release. + +1. [Legacy Command Line Tools](https://docs.mattermost.com/administration/command-line-tools.html). All commands have been fully replaced by [mmctl](https://docs.mattermost.com/administration/mmctl-cli-tool.html) and new commands have been added over the last few months, making this tool a full and robust replacement. + +2. [Slack Import via the web app](https://docs.mattermost.com/administration/migrating.html?highlight=mmetl#migrating-from-slack-using-the-mattermost-web-app). The Slack import tool accessible via the Team Setting menu is being replaced by the [mmetl](https://docs.mattermost.com/administration/migrating.html#migrating-from-slack-using-the-mattermost-mmetl-tool-and-bulk-import) tool that is much more comprehensive for the types of data it can assist in uploading. + +3. MySQL versions below 5.7.7. Minimum support will now be for 5.7.12. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). + +4. Elasticsearch 5 and 6 - [versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 will be Elasticsearch version 7.0. + +5. Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We will no longer provide support for the Desktop App issues on Windows 7. + +6. [DisableLegacyMFA](https://docs.mattermost.com/configure/configuration-settings.html#disable-legacy-mfa-api-endpoint) configuration setting. + +7. [ExperimentalTimezone](https://docs.mattermost.com/configure/configuration-settings.html#timezone) configuration setting. + +8. All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access [custom, collapsible channel categories](https://mattermost.com/blog/custom-collapsible-channel-categories/) among many other channel organization features. The settings being deprecated include: + + - [EnableLegacySidebar](https://docs.mattermost.com/administration/config-settings.html#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](https://docs.mattermost.com/administration/config-settings.html#town-square-is-read-only-experimental) + - [ExperimentalHideTownSquareinLHS](https://docs.mattermost.com/administration/config-settings.html#town-square-is-hidden-in-left-hand-sidebar-experimental) + - [EnableXToLeaveChannelsFromLHS](https://docs.mattermost.com/administration/config-settings.html#enable-x-to-leave-channels-from-left-hand-sidebar-experimental) + - [CloseUnusedDirectMessages](https://docs.mattermost.com/administration/config-settings.html#autoclose-direct-messages-in-sidebar-experimental) + - [ExperimentalChannelOrganization](https://docs.mattermost.com/administration/config-settings.html#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](https://docs.mattermost.com/administration/config-settings.html#experimental-sidebar-features) + +9. [All configuration settings previously marked as “Deprecated”](https://docs.mattermost.com/administration/config-settings.html#deprecated-configuration-settings). + +10. Changes to ``mattermost-server/model`` for naming consistency. + +### Known Issues + - [Collapsed Reply Threads](https://docs.mattermost.com/messaging/organizing-conversations.html) is currently in beta. Before enabling the feature, please ensure you are well versed in the [known issues](https://docs.mattermost.com/messaging/organizing-conversations.html#known-issues), particularly relating to database resource requirements and server performance implications. If you cannot easily scale up your database size, or are running the Mattermost application server and database server on the same machine, we recommended waiting to enable Collapsed Reply Threads until it is [promoted to general availability in Q2 2022](https://mattermost.com/blog/collapsed-reply-threads-ga/). Learn more about these [performance considerations here](https://support.mattermost.com/hc/en-us/articles/4413183568276-What-to-expect-when-enabling-Collapsed-Reply-Threads-Beta). + - When upgrading to 5.37.0, the Incident Collaboration plugin may not be automatically installed in some cases. + - Add Members modal is incorrectly themed on the Mattermost Dark theme [MM-37220](https://mattermost.atlassian.net/browse/MM-37220). + - ``config.json`` can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Fields on the right column in a message attachment render unevenly [MM-36943](https://mattermost.atlassian.net/browse/MM-36943). + - Pinned posts are no longer highlighted. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [Aashimalik](https://github.com/Aashimalik), [Adovenmuehle](https://github.com/Adovenmuehle), [aedott](https://github.com/aedott), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [ahmadkarlam](https://github.com/ahmadkarlam), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [arvinDarmawan](https://github.com/arvinDarmawan), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AshishDhama](https://github.com/AshishDhama), [aspleenic](https://github.com/aspleenic), [balan2010](https://github.com/balan2010), [BenCookie95](https://github.com/BenCookie95), [berkeka](https://github.com/berkeka), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [cedricziel](https://github.com/cedricziel), [chenilim](https://github.com/chenilim), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [cognvn](https://github.com/cognvn), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [danielsischy](https://github.com/danielsischy), [darkLord19](https://github.com/darkLord19), [dbpolito](https://github.com/dbpolito), [devinbinnie](https://github.com/devinbinnie), [elsiehupp](https://github.com/elsiehupp), [elyscape](https://github.com/elyscape), [emilyacook](https://github.com/emilyacook), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [EugenMayer](https://github.com/EugenMayer), [ewwollesen](https://github.com/ewwollesen), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hason](https://github.com/hason), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [itao](https://github.com/itao), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jayaddison-collabora](https://github.com/jayaddison-collabora), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [JoelRummel](https://github.com/JoelRummel), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jplda23](https://github.com/jplda23), [jprusch](https://github.com/jprusch), [jufab](https://github.com/jufab), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kamre](https://github.com/kamre), [kayazeren](https://github.com/kayazeren), [koox00](https://github.com/koox00), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [madhavhugar](https://github.com/madhavhugar), [maisnamrajusingh](https://github.com/maisnamrajusingh), [majidsajadi](https://github.com/majidsajadi), [manojmalik20](https://github.com/manojmalik20), [matheusmosca](https://github.com/matheusmosca), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [maxerenberg](https://github.com/maxerenberg), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [moussetc](https://github.com/moussetc), [MrLemur](https://github.com/MrLemur), [msal4](https://github.com/msal4), [MusiCode1](https://github.com/MusiCode1), [naderm11](https://github.com/naderm11), [neallred](https://github.com/neallred), [nevyangelova](https://github.com/nevyangelova), [ogi-m](https://github.com/ogi-m), [pablovelezvidal](https://github.com/pablovelezvidal), [parsaakbari1209](https://github.com/parsaakbari1209), [prakharporwal](https://github.com/prakharporwal), [prathers](https://github.com/prathers), [rbradleyhaas](https://github.com/rbradleyhaas), [rodcorsi](https://github.com/rodcorsi), [rohit1101](https://github.com/rohit1101), [sadohert](https://github.com/sadohert), [sakaitsu](https://github.com/sakaitsu), [saturninoabril](https://github.com/saturninoabril), [Sayanta66](https://github.com/Sayanta66), [sbishel](https://github.com/sbishel), [senylove1403](https://github.com/senylove1403), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [teresa-novoa](https://github.com/teresa-novoa), [thePanz](https://github.com/thePanz), [tsabi](https://translate.mattermost.com/user/tsabi), [txeli](https://github.com/txeli), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yulyanaR](https://github.com/yulyanaR) + +---- + +## Release v5.36 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.36.2, released 2021-08-04** + - Mattermost v5.36.2 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). +- **v5.36.1, released 2021-06-21** + - Mattermost v5.36.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). + - Added performance improvements by reducing the time taken to re-render when a post is received. +- **v5.36.0, released 2021-06-16** + - Original 5.36.0 release + +Mattermost v5.36.0 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). + +### Important Upgrade Notes + - Gossip clustering mode is now in General Availability and is no longer available as an option. All cluster traffic will always use the gossip protocol. The config setting ``UseExperimentalGossip`` has no effect and has only been kept for compatibility purposes. The setting to use gossip has been removed from the System Console. **Note:** For High Availability upgrades, all nodes in the cluster must use a single protocol. If an existing system is not currently using gossip, one node in a cluster can't be upgraded while other nodes in the cluster use an older version. Customers must either use gossip for their High Availability upgrade, or customers must shut down all nodes, perform the upgrade, and then bring all nodes back up. + +```{Important} +If you upgrade from a release earlier than v5.35, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Focalboard (Beta) + - Focalboard is now integrated with Mattermost as a beta feature in v5.36. To enable Focalboard, open the Marketplace from the sidebar menu, install the Focalboard plugin, then click on **Configure**, enable it, and save. Update your NGINX or Apache web proxy config. + +#### Incident Collaboration (Enterprise Edition E20) + - Includes automated welcome message, team-wide playbook access, and permission control for playbook creation. + +#### Hungarian Language Support (Beta) + - Mattermost is now available in Hungarian. + +### Improvements + +#### User Interface (UI) + - If message autoresponder is set, only one message is now sent to a given user irrespective of how many Direct Message messages the user receives. + - Added status icons on **Add members** to channel and **Add members** to team lists. + - Added a keyboard shortcut to focus on the Search bar and search in the current channel. + - A search tip is now shown when scrolling back in a channel. + - Improved the error text in the **Edit Channel Header** modal. + - Added the ability to clear a custom status when only an emoji and no text is set. + - Redesigned message notification emails. + - When **Show online availability on profile images** is set to **Off**, the online status icon is hidden from the profile image in the center channel and the right-hand side view. + +#### Performance + - Added a performance improvement to the emoji picker overlay to improve typing performance. + - Added performance improvements when receiving new posts. + +#### Administration + - ``TCP_NO_DELAY`` is disabled for Websocket connections to allow for higher throughput. + - Compliance Monitoring CSV files are no longer limited to 30,000 rows. + - The default value of the [Support Email](https://docs.mattermost.com/administration/config-settings.html#support-email) (previously ``_feedback@mattermost.com_``) has been removed. Admin Advisor will now prompt System Admins about missing configuration for the [Support Email](https://docs.mattermost.com/administration/config-settings.html#support-email). This value is required, and it ensures Mattermost account requests are sent to the correct team for resolution. + - The **Marketplace** button in the **Main Menu** is now displayed if the user has the ``sysconsole_write_plugins`` permission. + - Added new feature discoveries in the System Console, including Data Retention Policy and OpenID Connect. + - Added basic intra-cluster communication support for plugins. + - Improved error messages for ``/header`` and ``/purpose`` commands. + - Team-restricted direct channel creation is now also applied to the backend. Previously, this was restricted to the frontend. + - Refactored the config storing logic to improve its robustness and performance. + - Added a visual grouping of related settings under AD/LDAP in the System Console. + +### Bug Fixes + - Fixed an issue where bulk export generated invalid Direct Message channels between deactivated users. + - Fixed an issue where the custom status cleared slash commands on mobile. + - Fixed an issue with an incorrect error message when trying to change handle via API to another one that already existed. + - Fixed an issue where LDAP Group Sync didn't work when using SAML (ADFS) for authentication and AD/LDAP Group Sync unless ``EnableSyncWithLdapIncludeAuth`` was set to ``true``, which caused the ``AuthData`` to be stored in AD/LDAP format. + - Fixed an issue where a user with 'No Access' permission could still access **Groups**, **Channels** and **Teams** configuration pages through a URL. + - Fixed an issue where **Remove from channel** and **Remove Team Member** menu items were visible in a group-synced channel or team. + - Fixed various bugs related to hardcoded theme colours. + - Fixed UI issues related to hardcoded variables and misalignment of the channel header with the **Has guests** text. + - Fixed an issue with SAML Sign-on where System Admins were unable to modify **Service Provider Login URL** unless ``VerifySignature`` was enabled. + - Fixed a race condition where enabling plugins would result in spurious errors in the logs. + - Fixed a bug where team member permissions were not updated after associating a team with a permission scheme. + - Fixed the responses of the role by ID and all roles of API endpoints when the role was associated to channel schemes. + - Removed sticky sidebar headings in favor of fixing nesting errors. + - Fixed an issue where the **Close** button in the **Create New Category** modal was only visible on mouse hover. + - Fixed a bug where session expiration was extended with activity regardless of what the config setting ``ServiceSettings.ExtendSessionLengthWithActivity`` was set to. + - Fixed an issue where the ``idmigrate`` command did not update values if they were not already present as LDAP attributes in the ``config.json``. + - Fixed an issue where the job scheduler server could miss a "changed leader" cluster event. + - Fixed an issue where using ``Ctrl+Cmd+F`` on the MacOS Desktop App opened the search instead of full-screened the app. + - Fixed an issue where the message input box was shadowed when uploading a file in the center channel. + - Fixed an error caused by a post created with a non-string attachment field. + - Fixed the opacity of the read state in the channel sidebar, as well as enhanced the opacity of the channel icon when the channel was unread. + - Fixed an issue where users were unable to sign in with O365 authentication when the AuthData was formatted differently between Office365 OAuth and Office 365 OpenID. + - Fixed an issue where custom emojis for custom statuses were not loaded on page refresh. + - Fixed an issue where the “Set a status” placeholder in the profile popover was not correctly themed. + - Fixed an issue where bots showed the integration owner's custom status in the post header in the right-hand side. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ComplianceSettings`` in ``config.json``: + - Added a new config setting ``BatchSize``. Compliance Monitoring CSV files are no longer limited to 30,000 rows. + - Under ``SupportSettings`` in ``config.json``: + - ``SupportEmail`` default value is now empty instead of ``_feedback@mattermost.com_``. + - Under ``LogSettings`` in ``config.json``: + - A new setting ``EnableColor`` was added to ``LogSettings`` and ``NotificationLogSettings``. Non-JSON console logs will now be colored if that field is set to ``true``. + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableReliableWebSockets``, to make WebSocket messages more reliable by bufferring messages during a connection loss and then re-transmitting all unsent messages when the connection is revived. + +### API Changes + - Added support to include config diff in audit records for the related API calls (``updateConfig`` and ``patchConfig``). + - Response field names changed for experimental API ``GetAllSharedChannels`` to match the field names for other channels APIs. + - Added a new function to the plugin API, ``RequestTrialLicense``. + - The ``/ldap/sync`` endpoint now accepts a parameter ``include_removed_members`` which will force all LDAP group members back into the teams and channels synced to that group. + - Added a new API endpoint to ``removeUserRecentCustomStatus POST /status/custom/recent/delete``. + - Added ``GetGroupMemberUsers and GetGroupsBySource`` to the plugin API to add plugin support for user groups. + - Added a new API endpoint ``POST /api/v4/saml/reset_auth_data`` to reset SAML users' AuthData field to their email. + - Added new API endpoints: + - ``GET /data_retention/policies`` + - ``GET /data_retention/policies_count`` + - ``POST /data_retention/policies`` + - ``GET /data_retention/policies/{policy_id}`` + - ``PATCH /data_retention/policies/{policy_id}`` + - ``DELETE /data_retention/policies/{policy_id}`` + - ``GET /data_retention/policies/{policy_id}/teams`` + - ``POST /data_retention/policies/{policy_id}/teams`` + - ``DELETE /data_retention/policies/{policy_id}/teams`` + - ``POST /data_retention/policies/{policy_id}/teams/search`` + - ``GET /data_retention/policies/{policy_id}/channels`` + - ``POST /data_retention/policies/{policy_id}/channels`` + - ``DELETE /data_retention/policies/{policy_id}/channels`` + - ``POST /data_retention/policies/{policy_id}/channels/search`` + - ``GET /users/{user_id}/data_retention/team_policies`` + - ``GET /users/{user_id}/data_retention/channel_policies`` + +### Go Version + - v5.36 is built with Go ``1.15.5``. + +### Open Source Components + - Added ``lodash``, ``memoize-one``, and ``sass`` to https://github.com/mattermost/mattermost-webapp. + - Added ``react-native-startup-time`` and removed ``react-native-status-bar-size`` from https://github.com/mattermost/mattermost-mobile. + +### Upcoming Deprecations in Mattermost v6.0 + +The following deprecations are planned for the Mattermost v6.0 release, which is scheduled for 2021/10/15. This list is subject to change prior to the release. + +1. [Legacy Command Line Tools](https://docs.mattermost.com/administration/command-line-tools.html). All commands have been fully replaced by [mmctl](https://docs.mattermost.com/administration/mmctl-cli-tool.html) and new commands have been added over the last few months, making this tool a full and robust replacement. + +2. [Slack Import via the web app](https://docs.mattermost.com/administration/migrating.html?highlight=mmetl#migrating-from-slack-using-the-mattermost-web-app). The Slack import tool accessible via the Team Setting menu is being replaced by the [mmetl](https://docs.mattermost.com/administration/migrating.html#migrating-from-slack-using-the-mattermost-mmetl-tool-and-bulk-import) tool that is much more comprehensive for the types of data it can assist in uploading. + +3. MySQL versions below 5.7.7. Minimum support will now be for 5.7.12. This version introduced a native JSON data type that lets us improve performance and scalability of several database fields (most notably Users and Posts props). Additionally, version 5.6 (our current minimum version) reached [EOL in February 2021](https://www.mysql.com/support/eol-notice.html). + +4. Elasticsearch 5 and 6 - [versions 5.x reached EOL in March of 2019, and versions 6.x reached EOL in November 2020](https://www.elastic.co/support/eol). Our minimal supported version with Mattermost v6.0 will be Elasticsearch version 7.0. + +5. Windows 7 reached [EOL in January 2020](https://support.microsoft.com/en-us/windows/what-does-it-mean-if-windows-isn-t-supported-08f3b92d-7539-671e-1452-2e71cdad18b5). We will no longer provide support for the Desktop App issues on Windows 7. + +6. [DisableLegacyMFA](https://docs.mattermost.com/configure/configuration-settings.html#disable-legacy-mfa-api-endpoint) configuration setting. + +7. [ExperimentalTimezone](https://docs.mattermost.com/configure/configuration-settings.html#timezone) configuration setting. + +8. All legacy channel sidebar experimental configuration settings. We encourage customers using these settings to upgrade to v5.32 or later to access [custom, collapsible channel categories](https://mattermost.com/blog/custom-collapsible-channel-categories/) among many other channel organization features. The settings being deprecated include: + + - [EnableLegacySidebar](https://docs.mattermost.com/administration/config-settings.html#enable-legacy-sidebar) + - [ExperimentalTownSquareIsReadOnly](https://docs.mattermost.com/administration/config-settings.html#town-square-is-read-only-experimental) + - [ExperimentalHideTownSquareinLHS](https://docs.mattermost.com/administration/config-settings.html#town-square-is-hidden-in-left-hand-sidebar-experimental) + - [EnableXToLeaveChannelsFromLHS](https://docs.mattermost.com/administration/config-settings.html#enable-x-to-leave-channels-from-left-hand-sidebar-experimental) + - [CloseUnusedDirectMessages](https://docs.mattermost.com/administration/config-settings.html#autoclose-direct-messages-in-sidebar-experimental) + - [ExperimentalChannelOrganization](https://docs.mattermost.com/administration/config-settings.html#sidebar-organization) + - [ExperimentalChannelSidebarOrganization](https://docs.mattermost.com/administration/config-settings.html#experimental-sidebar-features) + +9. [All configuration settings previously marked as “Deprecated”](https://docs.mattermost.com/administration/config-settings.html#deprecated-configuration-settings). + +10. Changes to ``mattermost-server/model`` for naming consistency. + +### Known Issues + - Batched email notifications from a single post have incorrect title text [MM-36559](https://mattermost.atlassian.net/browse/MM-36559). + - ``config.json`` can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Pinned posts are no longer highlighted. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [abdulsmapara](https://github.com/abdulsmapara), [adamjclarkson](https://github.com/adamjclarkson), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [avasconcelos114](https://github.com/avasconcelos114), [avddvd](https://github.com/avddvd), [awerries](https://github.com/awerries), [bbodenmiller](https://github.com/bbodenmiller), [bbuehrle](https://github.com/bbuehrle), [bradjcoughlin](https://github.com/bradjcoughlin), [cadavre](https://github.com/cadavre), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [CEOehis](https://github.com/CEOehis), [chenilim](https://github.com/chenilim), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [craigwillis-mm](https://github.com/craigwillis-mm), [craph](https://github.com/craph), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [dantepippi](https://github.com/dantepippi), [dbejanishvili](https://github.com/dbejanishvili), [devinbinnie](https://github.com/devinbinnie), [ejose19](https://github.com/ejose19), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [ewwollesen](https://github.com/ewwollesen), [faase](https://github.com/faase), [fakela](https://github.com/fakela), [FlaviaBastos](https://github.com/FlaviaBastos), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [Francois-D](https://github.com/Francois-D), [funkytwig](https://github.com/funkytwig), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gnello](https://github.com/gnello), [GrigalashviliT](https://github.com/GrigalashviliT), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [hzeroo](https://github.com/hzeroo), [ialorro](https://github.com/ialorro), [iamsayantan](https://github.com/iamsayantan), [ikeohachidi](https://github.com/ikeohachidi), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jprusch](https://github.com/jprusch), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [kosgrz](https://github.com/kosgrz), [l0r3zz](https://github.com/l0r3zz), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [liusy182](https://github.com/liusy182), [lynn915](https://github.com/lynn915), [maciejnems](https://github.com/maciejnems), [marianunez](https://github.com/marianunez), [mbecca](https://github.com/mbecca), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mterhar](https://github.com/mterhar), [nadalfederer](https://github.com/nadalfederer), [NassimBounouas](https://github.com/NassimBounouas), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [pankajhirway](https://github.com/pankajhirway), [petya-v](https://github.com/petya-v), [pradeepmurugesan](https://github.com/pradeepmurugesan), [prapti](https://github.com/prapti), [psy-q](https://github.com/psy-q), [Qujja](https://github.com/Qujja), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [sakaitsu](https://github.com/sakaitsu), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shibasisp](https://github.com/shibasisp), [Shivam010](https://github.com/Shivam010), [shred86](https://github.com/shred86), [spirosoik](https://github.com/spirosoik), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [thefactremains](https://github.com/thefactremains), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [ThiefMaster](https://github.com/ThiefMaster), [tomasmik](https://github.com/tomasmik), [tsabi](https://translate.mattermost.com/user/tsabi), [uhlhosting](https://github.com/uhlhosting), [vesari](https://github.com/vesari), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.35 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.35.5, released 2021-08-04** + - Mattermost v5.35.5 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). +- **v5.35.4, released 2021-06-21** + - Mattermost v5.35.4 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). +- **v5.35.3, released 2021-06-11** + - Mattermost v5.35.3 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). + - Fixed an issue where missing query parameters in the datasource could cause MySQL servers to crash on startup. [MM-36236](https://mattermost.atlassian.net/browse/MM-36236) + - Added performance improvements to the emoji picker overlay to improve typing performance and reduced the time taken to re-render when a post is received. +- **v5.35.2, released 2021-06-03** + - Fixed an issue where subsequent migrations failed to run after running a dot release on new installations. [MM-35931](https://mattermost.atlassian.net/browse/MM-35931) + - Fixed an issue where the server would crash if content extractor dependencies for PDFs were not present. [MM-35990](https://mattermost.atlassian.net/browse/MM-35990) + - Fixed an issue where the setting to allow disabling link previews from certain domains was grayed out in the System Console. [MM-35796](https://mattermost.atlassian.net/browse/MM-35796) + - Fixed an issue where SMTP showed a permission error when upgrading from version < 5.35 to 5.35 or greater. [MM-35861](https://mattermost.atlassian.net/browse/MM-35861) + - Fixed an issue with extracting OpenDocument Text files as part of content extraction. [MM-36103](https://mattermost.atlassian.net/browse/MM-36103) +- **v5.35.1, released 2021-05-18** + - Fixed an issue where 5.35.0 migration failed on MySQL installations with an "invalid connection" error due to an issue with the ``readTimeout`` parameter in ``SqlSettings.DataSource`` (default is 30 seconds). The ``readTimeout`` datasource query parameter is now being ignored and the application provided ``SqlSettings.QueryTimeout`` should be used instead. [MM-35767](https://mattermost.atlassian.net/browse/MM-35767) +- **v5.35.0, released 2021-05-16** + - Original 5.35.0 release + +Mattermost v5.35.0 contains low and medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org). + +### Important Upgrade Notes + +- Due to the introduction of backend database architecture required for upcoming new features, including Shared Channels and Collapsed Reply Threads, the performance of the migration process for the v5.35 release (May 16, 2021) has been noticeably affected. Depending on the size, type, and version of the database, longer than usual upgrade times should be expected. This can vary from a couple of minutes (average case) to hours (worst case, MySQL 5.x only). A moderate to significant spike in database CPU usage should also be expected during this process. [More details on the performance impact of the migration and possible mitigation strategies are provided here](https://gist.github.com/streamer45/9aee4906639a49ebde68b2f3c0f924c1). +- v5.35.0 introduces a new feature to search for files. Search results for files shared in the past may be incomplete until a [content extraction command](https://docs.mattermost.com/administration/command-line-tools.html#mattermost-extract-documents-content) is executed to extract and index the content of files already in the database. Instances running Elasticsearch or Bleve search backends will also need to execute a Bulk Indexing after the content extraction is complete. Please see more details in [this blog post](https://mattermost.com/blog/file-search/). +- The existing password generation logic used during the bulk user import process was comparatively weak. Hence it's advised for admins to immediately reset the passwords for all the users who were generated during the bulk import process and whose password has not been changed even once. +- In the v5.38 release (August 16, 2021), we will deprecate "config watcher" (the mechanism that automatically reloads the ``config.json file``), in favor of an mmctl command that will need to be run to apply configuration changes after they are made. This change will improve configuration performance and robustness. + +```{Important} +If you upgrade from a release earlier than v5.34, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Apps Framework (Developer Preview) + +- Apps Framework is a new way to integrate with external tools, and allows developers to create interactive apps in Mattermost, using any development language they're comfortable with. The new apps work seamlessly across mobile and desktop clients. This is a developer preview and is not intended for production instances of Mattermost yet. This feature is available for self-managed customers with v5.35 when the Apps Framework Plugin is loaded on an instance. + +#### Search for files and document contents + +- Searching in Mattermost now finds both relevant messages and files in your team’s conversation history. Search will return results for attachments that match the file name or contain matching text content within supported document types. [Learn more](https://mattermost.com/blog/file-search/). + +#### Granular Access to System Console Pages (Enterprise E20 Edition) + +- Migrated **Experimental**, **About**, **Reporting**, **Environment**, **Site Configuration**, **Authentication**, **Integrations**, and **Compliance** sections to their respective sub-section permissions. + +#### Shared Channels (Experimental, Enterprise Edition E20) + +- Experimental support added for sharing channels between Mattermost clusters. Requires an Enterprise Edition E20 license. The Shared Channels feature is disabled by default. + +#### Enterprise Trial Enhancements (Enterprise E20 Edition) + +- Added banners to alert System Admins when an Enterprise Edition E20 trial has started, when there are three days left of the trial, and when the trial is on the last day. + +#### Incident Collaboration (Enterprise Edition E20) + +- Updated prepackaged Incident Collaboration plugin with to include ad hoc tasks, stakeholder overview, and more. + +### Improvements + +#### User Interface (UI) + +- Added support to collapse in-line images over 100px in height. +- Implemented maximum length validation on the status modal for custom statuses. +- Synchronized collapsed channel sidebar categories on the server to keep category collapse states in-sync across devices. +- Empty state is no longer off-centered in the **Channel Switcher**. +- Ephemeral message created from call response ``markdown`` field is now posted by bot. +- Added various enhancements to custom status to allow users to switch to recent statuses with less clicks. +- Users can now see online status on user profile images in the channel switcher. +- Added a string field to restricted domains configuration with the key ``RestrictLinkPreviews``, and added a UI field for restricted domains under **System Console > Site Configuration > Posts**. Also expanded the logic that determines whether a post has a preview or not. +- Added an unread badge to the **Main Menu** icon and the **Plugin Marketplace** menu that displays until a System Admin visits the **Plugin Marketplace** for the first time. +- Profile images are now visible on **Direct Messages** in the channel sidebar. +- Added channel icons for email notifications as part of email notification redesigns. +- Direct Messages **More...** modal is now sorted by recent conversations when the modal is opened.- Removed legacy Open-Sans fonts and upgraded Open-Sans to v18. + +### Administration + + - Paused Admin Advisor notifications from triggering. + - Added a command line document extraction command that allows indexing documents by content. + - Removed the utility function ``model.GeneratePassword()`` for security reasons. An improved version is now being used internally to generate passwords for bulk-imported users. + - Only the System Admin is allowed to have the ability to assign system roles. + - Two new gauge metrics were added: ``mattermost_db_replica_lag_abs`` and ``mattermost_db_replica_lag_time``, both containing a label of "node", signifying which database host is the metric from. + - These metrics signify the replica lag in absolute terms and in the time dimension capturing the whole picture of replica lag. To use these metrics, a separate config section ``ReplicaLagSettings`` was added under ``SqlSettings``. This is an array of maps which contain three keys: ``DataSource``, ``QueryAbsoluteLag``, and ``QueryTimeLag``. Each map entry is for a single replica instance. ``DataSource`` contains the database credentials to connect to the replica instance. ``QueryAbsoluteLag`` is a plain SQL query that must return a single row of which the first column must be the node value of the Prometheus metric, and the second column must be the value of the lag. ``QueryTimeLag`` is the same as above, but used to measure the time lag. + - As an example, for AWS Aurora instances, the ``QueryAbsoluteLag`` can be: ``select server_id highest_lsn_rcvd-durable_lsn as bindiff from aurora_global_db_instance_status()`` where ``server_id=<>`` and ``QueryTimeLag`` can be: ``select server_id, visibility_lag_in_msec aurora_global_db_instance_status()`` where ``server_id=<>``. For MySQL Group Replication, the absolute lag can be measured from the number of pending transactions in the applier queue: ``select member_id, count_transactions_remote_in_applier_queue FROM performance_schema.replication_group_member_stats`` where ``member_id=<>``. Overall, what query to choose is left to the administrator, and depending on the database and need, an appropriate query can be chosen. + +### Bug Fixes + - Fixed link previews on a number of websites, including Reddit. + - Fixed an issue where SAML assigned Mattermost ``UserID`` as username if the value was invalid and did not log this. + - Fixed an issue where hover effects for category sorting and **Direct Messages** category limit submenus were too dark on a dark theme. + - Fixed an issue where users were unable to drag the vertical scroll bar on a PDF preview. + - Fixed an issue with animations on long posts when highlighted as a permalink. + - Fixed an issue where the user's nickname was not shown on channel switch. + - Fixed an issue where deactivated users were not marked as **Deactivated** in the channel switcher. + - Fixed an issue where queries executed during the upgrade process would pre-emptively time out on the application side. + - Fixed an issue where users were unable to deactivate MFA for their accounts even if MFA was disabled on the server. + - Fixed an issue where user settings on API could be set if LDAP Sync was on. For LDAP and SAML users, the following fields cannot be changed via the API if the corresponding LDAP/SAML attributes have been set: first name, last name, position, nickname, email, profile picture. For OAuth users (i.e., GitLab, Google, Office365, and OpenID), the following fields cannot be changed via the API: first name, last name. All users who authenticate via a method other than email cannot change their username via the API. + - Fixed a possible panic on post creation when the collapsed threads feature was enabled. + - Fixed a database deadlock that could happen if a sidebar category was updated and deleted at the same time. + - Fixed an issue where the sidebar **Text Hover BG Theme** color didn’t work on the left-hand side. + - Fixed an issue where the Team Admin’s current role was presented inconsistently in the different areas of the System Console. + - Fixed an issue where the **Show more** background color on long posts was broken for permalinks. + - Fixed an issue where redirecting with JS failed when Content Security Policy was enabled and restricted with ``unsafe-inline``. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableFileSearch`` for file search feature. + - Added ``RestrictLinkPreviews`` setting to allow disabling link previews from certain domains. + - Under ``FileSettings`` in ``config.json``: + - Added ``ExtractContent`` and ``ArchiveRecursion`` for file search feature. + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``EnableRemoteClusterService`` for experimental Shared Channels feature. + - Under ``SqlSettings`` in ``config.json``: + - Added ``ReplicaLagSettings``. This is an array of maps which contain three keys: ``DataSource``, ``QueryAbsoluteLag``, and ``QueryTimeLag``. + +### Database Changes + - Added new column in ``ChannelMembers`` table called ``MentionCountRoot``. Please note that the migration can take up to a few minutes on installations with large numbers of channels/users. + - Added ``TotalMsgCountRoot`` to ``Channels`` table and ``MsgCountRoot`` column to ``ChannelMembers`` table. Please note that the migration can take several minutes to complete on large MySQL instances. + +### API Changes + - Added ``/teams/{team_id}/files/search`` API endpoint for files search. + - For LDAP and SAML users, the following fields cannot be changed via the API if the corresponding LDAP/SAML attributes have been set: first name, last name, position, nickname, email, profile picture. For OAuth users (i.e., GitLab, Google, Office365, and OpenID), the following fields cannot be changed via the API: first name, last name. All users who authenticate via a method other than email cannot change their username via the API. + +### Go Version + - v5.35 is built with Go ``1.15.5``. + +### Open Source Components + - Added ``country-list``, ``form-data``, ``gfycat-sdk``, ``redux-thunk``, ``rudder-sdk-js``, ``serialize-error`` and ``shallow-equals``, and removed ``mattermost-redux`` from https://github.com/mattermost/mattermost-webapp. + +### Known Issues + - A persistent unread badge on sidebar hamburger menu may show if **Enable Marketplace** or **Enable Plugins** is disabled in the System Console [MM-36160](https://mattermost.atlassian.net/browse/MM-36160). + - ``config.json`` can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page [MM-30980](https://mattermost.atlassian.net/browse/MM-30980). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Fields on the right column in a message attachment render unevenly [MM-36943](https://mattermost.atlassian.net/browse/MM-36943). + - Pinned posts are no longer highlighted. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [Adovenmuehle](https://github.com/Adovenmuehle), [aedott](https://github.com/aedott), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [albatrosef](https://github.com/albatrosef), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [arvinDarmawan](https://github.com/arvinDarmawan), [asaadmahmood](https://github.com/asaadmahmood), [avinashdhinwa](https://github.com/avinashdhinwa), [bbodenmiller](https://github.com/bbodenmiller), [benarent](https://github.com/benarent), [BenCookie95](https://github.com/BenCookie95), [BharatKalluri](https://github.com/BharatKalluri), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chenilim](https://github.com/chenilim), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [chrisfromredfin](https://github.com/chrisfromredfin), [codingthat](https://github.com/codingthat), [coltoneshaw](https://github.com/coltoneshaw), [courtneypattison](https://github.com/courtneypattison), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkLord19](https://github.com/darkLord19), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [elyscape](https://github.com/elyscape), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [EricMontague](https://github.com/EricMontague), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gea-ecobricks](https://github.com/gea-ecobricks), [gigawhitlocks](https://github.com/gigawhitlocks), [girish17](https://github.com/girish17), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [Hampusholmstrom](https://github.com/Hampusholmstrom), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hastadhana](https://github.com/hastadhana), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [icelander](https://github.com/icelander), [IndushaS](https://github.com/IndushaS), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jecepeda](https://github.com/jecepeda), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [JoelRummel](https://github.com/JoelRummel), [Johennes](https://github.com/Johennes), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [komik966](https://github.com/komik966), [larkox](https://github.com/larkox), [leblanc-simon](https://github.com/leblanc-simon), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [majidsajadi](https://github.com/majidsajadi), [manojmalik20](https://github.com/manojmalik20), [marianunez](https://github.com/marianunez), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [maxerenberg](https://github.com/maxerenberg), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [microolapshare](https://github.com/microolapshare), [migbot](https://github.com/migbot), [mjnagel](https://github.com/mjnagel), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mrckndt](https://github.com/mrckndt), [muratbayan](https://github.com/muratbayan), [natalie-hub](https://github.com/natalie-hub), [Ndawakh](https://github.com/Ndawakh), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [ogi-m](https://github.com/ogi-m), [pablovelezvidal](https://github.com/pablovelezvidal), [prapti](https://github.com/prapti), [qunabu](https://github.com/qunabu), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [sakaitsu](https://github.com/sakaitsu), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shazm](https://github.com/shazm), [signalwerk](https://github.com/signalwerk), [spirosoik](https://github.com/spirosoik), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [Szymongib](https://github.com/Szymongib), [teresa-novoa](https://github.com/teresa-novoa), [thebestwj](https://github.com/thebestwj), [TheDarkestDay](https://github.com/TheDarkestDay), [thePanz](https://github.com/thePanz), [uhlhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xlanor](https://github.com/xlanor), [yashjohar](https://github.com/yashjohar), [YJSoft](https://github.com/YJSoft), [YoheiZuho](https://github.com/YoheiZuho), [zefhemel](https://github.com/zefhemel), [ziprandom](https://github.com/ziprandom), [Zukerherr](https://github.com/Zukerherr) + +---- + +## Release v5.34 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.34.5, released 2021-06-21** + - Mattermost v5.34.5 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.34.4, released 2021-06-11** + - Mattermost v5.34.4 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where missing query parameters in the datasource could cause MySQL servers to crash on startup. [MM-36236](https://mattermost.atlassian.net/browse/MM-36236) + - Fixed an issue where plugin icons were displaying as a column instead of as a row on the left-hand side. [MM-36199](https://mattermost.atlassian.net/browse/MM-36199) +- **v5.34.3, released 2021-06-03** + - Fixed an issue where subsequent migrations failed to run after running a dot release on new installations. [MM-35931](https://mattermost.atlassian.net/browse/MM-35931) +- **v5.34.2, released 2021-04-17** + - Fixed an issue where installs with some special characters in the MySQL password would break and fail to start. +- **v5.34.1, released 2021-04-15** + - Fixed an issue where upgrading to v5.34.0 runs a migration that could cause timeouts on MySQL installations. Upgrading to v5.34.1 may also execute missing migrations that were scheduled for v5.32.0. These additions can be lengthy on very big MySQL (version 5.x) installations. + - Altering of ``Posts.FileIds`` type (PostgreSQL only) + - Added new column ``ThreadMemberships.UnreadMentions`` + - Added new column ``Channels.Shared`` + - Added new column ``Reactions.UpdateAt`` + - Added new column ``Reactions.DeleteAt`` +- **v5.34.0, released 2021-04-15** + - Original 5.34.0 release + +### Highlights + +#### Incident Collaboration: Automated actions on incident start (E20 Edition) + - Users can now configure playbooks to automatically execute key actions when an incident is created to save time and reduce the chance of manual error. + +#### Bulgarian and Swedish language support + - Removed Beta tags from Swedish and Bulgarian languages. Mattermost is now available in 18 languages. + +### Improvements + +#### User Interface (UI) + - System Admins now see a prompt to join private channel when joining a private channel via a permalink. + - Added support for adding in-product notices for external dependency deprecation details. + - Improved the timezone selector component. + - Introduced a new theme variable for the team sidebar. + - Added support for automatic right-to-left (RTL) detection in browsers. + - Updated the font size for the **Add People** channel modal. + - Online status is now shown in the channel switcher. + - Improved the design and layout of email notifications for password resets, member invites, member welcomes, and verifications. + +#### Administration + - Added mmctl commands to create, list, download, and delete export files. + - Added schema migrations phase 0 (``Teams``, ``TeamMembers``). + - Removed references to ``SqlLite3`` from the code. + - Bleve updates are now logged in the config only when there is an actual change in the ``BleveSettings`` instead of on every config update. + - Profiling the Mattermost server with pprof is now available for Team Edition. + - Added attributes to split.io feature flags. + +### Bug Fixes + - Fixed unsafe access of properties of the plugin environment during ``ServePluginPublicRequest``. + - Fixed an issue where the Admin Console > Server Logs did not focus to the sidebar filter upon reload. + - Fixed an issue where the GIF picker appeared empty instead of showing a “No results” modal when no results were displayed. + - Fixed an issue where the keyboard accessibility controller was not allowed to resume left-hand side scroll after drag and drop. + - Fixed an issue where markdown links rendered incorrectly. + - Fixed an issue where the Slack theme import failed due to changes in formatting of Slack export color schemes. + - Fixed an issue where tooltips were missing for channels with a long name. + - Fixed a race condition which would crash the app server due to improper handling of WebSocket closing. + - Fixed an issue where the PDF zoom failed to respond to zoom in/out/reset actions until the user scrolled. + - Fixed an issue where, in a reply thread with the right-hand side expanded, attachments in a post draft were hidden behind the center channel text box. + - Fixed bugs related to replication lag for Enterprise Edition instances configured to use read replicas. + - Fixed an issue where Compliance Report field headers were not correctly aligned. + - Fixed an issue where the ``/join`` command was case-sensitive. + - Fixed an issue where one-character sidebar category names were not displayed. + - Fixed an issue with a theme discrepancy on Close buttons on some modals in the System Console (when using a custom team theme). + - Fixed an issue where long text input in the right-hand pane was jumpy when selected. + - Fixed an issue where the zoom level persisted across multi-attachment PDF previews. + - Fixed an issue where long image names pushed the show/hide control off the right side of the window. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Added ``ExportSettings`` to add support for compressed export files with attachments. + +### Go Version + - v5.34 is built with Go ``1.15.5``. + +### Open Source Components + - Removed ``core-js`` from https://github.com/mattermost/mattermost-mobile. + +### Known Issues + - Text alignment in right-to-left support does not work correctly in v5.34. This issue is fixed in the latest version of the [mattermost-rtl plugin](https://github.com/QueraTeam/mattermost-rtl). + - Deactivated users are not marked as "Deactivated" in the channel switcher [MM-33910](https://mattermost.atlassian.net/browse/MM-33910). + - User nickname is not shown on channel switch [MM-33897](https://mattermost.atlassian.net/browse/MM-33897). + - ``Config.json`` can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - The server tries to install E20-required plugins on non-E20 installations [MM-32387](https://mattermost.atlassian.net/browse/MM-32387). + - Adding an at-mention at the start of a post draft and pressing the leftwards or rightwards arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page [MM-30980](https://mattermost.atlassian.net/browse/MM-30980). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Reddit link previews no longer work in Mattermost. This affects older versions too [MM-31899](https://mattermost.atlassian.net/browse/MM-31899). + - Fields on the right column in a message attachment render unevenly [MM-36943](https://mattermost.atlassian.net/browse/MM-36943). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[abdullahceylan](https://github.com/abdullahceylan), [aconitumnapellus](https://github.com/aconitumnapellus), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [aggmoulik](https://github.com/aggmoulik), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [appleboy](https://github.com/appleboy), [asaadmahmood](https://github.com/asaadmahmood), [asimsedhain](https://github.com/asimsedhain), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [berkeka](https://github.com/berkeka), [BharatKalluri](https://github.com/BharatKalluri), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chenilim](https://github.com/chenilim), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [christian-lim](https://github.com/christian-lim), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [Crimson-riot](https://github.com/Crimson-riot), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [CyrilLD](https://github.com/CyrilLD), [danielsischy](https://github.com/danielsischy), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [ebati](https://github.com/ebati), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [firasm](https://github.com/firasm), [flexo3001](https://github.com/flexo3001), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [haonm](https://github.com/haonm), [hastadhana](https://github.com/hastadhana), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ianatha](https://github.com/ianatha), [icelander](https://github.com/icelander), [IndushaS](https://github.com/IndushaS), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jamiehurewitz](https://github.com/jamiehurewitz), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jbutler992](https://github.com/jbutler992), [jbutlerdev](https://github.com/jbutlerdev), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jials](https://github.com/jials), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jp0707](https://github.com/jp0707), [JtheBAB](https://github.com/JtheBAB), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [larkox](https://github.com/larkox), [lawrencejohnson](https://github.com/lawrencejohnson), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lucievr](https://github.com/lucievr), [lutfuahmet](https://github.com/lutfuahmet), [Maekes](https://github.com/Maekes), [mahmud2011](https://github.com/mahmud2011), [mantlecurve](https://github.com/mantlecurve), [matt-w99](https://github.com/matt-w99), [matthewbirtch](https://github.com/matthewbirtch), [maxerenberg](https://github.com/maxerenberg), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [microolapshare](https://github.com/microolapshare), [migbot](https://github.com/migbot), [minecraftchest1](https://github.com/minecraftchest1), [mistikel](https://github.com/mistikel), [mkdbns](https://github.com/mkdbns), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mrtpcet](https://github.com/mrtpcet), [msal4](https://github.com/msal4), [Mshahidtaj](https://github.com/Mshahidtaj), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nronas](https://github.com/nronas), [ogi-m](https://github.com/ogi-m), [opr77](https://github.com/opr77), [pablovelezvidal](https://github.com/pablovelezvidal), [pat-s](https://github.com/pat-s), [phntom](https://github.com/phntom), [pidgelar](https://github.com/pidgelar), [potatogim](https://github.com/potatogim), [prapti](https://github.com/prapti), [Prescise](https://github.com/Prescise), [proffalken](https://github.com/proffalken), [r-52](https://github.com/r-52), [rakhi2104](https://github.com/rakhi2104), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [renjithgr](https://github.com/renjithgr), [rodcorsi](https://github.com/rodcorsi), [saf6260](https://github.com/saf6260), [sakaitsu](https://github.com/sakaitsu), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shazm](https://github.com/shazm), [spirosoik](https://github.com/spirosoik), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [thePanz](https://github.com/thePanz), [toto6038](https://github.com/toto6038), [tsabi](https://github.com/tsabi), [uhlhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xlanor](https://github.com/xlanor), [YoheiZuho](https://github.com/YoheiZuho), [youtsumi](https://github.com/youtsumi), [zefhemel](https://github.com/zefhemel), [Zukerherr](https://github.com/Zukerherr) + +---- + +## Release v5.33 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.33.5, released 2021-06-11** + - Mattermost v5.33.5 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.33.4, released 2021-06-03** + - Fixed an issue where subsequent migrations failed to run after running a dot release on new installations. [MM-35931](https://mattermost.atlassian.net/browse/MM-35931) + - Added a performance improvement to the emoji picker overlay to improve typing performance. +- **v5.33.3, released 2021-03-31** + - Fixed an issue where, after migrating to OpenID, Office 365 returned different ID attributes based on user type, causing an error for users with expired sessions when they tried to sign in to Mattermost. [MM-34356](https://mattermost.atlassian.net/browse/MM-34356) +- **v5.33.2, released 2021-03-25** + - Improved typing performance on busy servers with lots of active users and with the new sidebar enabled. [MM-30407](https://mattermost.atlassian.net/browse/MM-30407) + - Reverted the WebSocket improvement added in v5.33.0 where epoll was used to manually read from a WebSocket connection. It was reverted because unofficial Mattermost builds in several different platforms broke due to the WebSocket changes. [MM-34158](https://mattermost.atlassian.net/browse/MM-34158) +- **v5.33.1, released 2021-03-22** + - Fixed an issue where WebSockets failed with TLS connections. [MM-34000](https://mattermost.atlassian.net/browse/MM-34000) + - Fixed a race condition which would crash the app server due to improper handling of WebSocket closing. [MM-33233](https://mattermost.atlassian.net/browse/MM-33233) + - Fixed an issue where the ``mmctl config`` command didn't recognize newer settings (e.g. ``ClusterSettings.EnableGossipCompression``) that were introduced in v5.33.0. [MM-34046](https://mattermost.atlassian.net/browse/MM-34046) +- **v5.33.0, released 2021-03-17** + - Original 5.33.0 release + +Mattermost v5.33.0 contains low-level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Important Upgrade Notes + - Deleting a reaction is now a soft delete in the ``Reactions`` table. A schema update is required and may take up to 15 seconds on first run with large data sets. + - WebSocket handshakes done with an HTTP version lower than 1.1 will result in a warning, and the server will transparently upgrade the version to 1.1 to comply with the WebSocket RFC. This is done to work around incorrect Nginx (and other proxy) configs that do not set the ``proxy_http_version`` directive to 1.1. This facility will be removed in a future Mattermost version. It is strongly recommended to fix the proxy configuration to correctly use the WebSocket protocol. + +```{Important} +If you upgrade from a release earlier than v5.32, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### OpenID Connect for OAuth 2.0 Authentication (E20 Edition) + - OpenID Connect enables authentication to Mattermost using any OAuth 2.0 provider that adheres to the OpenID Connect specification. This feature is available for Mobile Apps in the v1.40 release. + +#### Support Packet Generation (E10 & E20 Editions) + - Mattermost provides the ability to download configuration details, logs, and other deployment information when requesting commercial support for Mattermost self-managed E10 or E20 Enterprise editions, or Mattermost Cloud editions. + +#### Updated Incident Collaboration Plugin to 1.4.0 (E20 Edition) + - Added an Incident Timeline to support status updates and other key events shown chronologically in the right-hand sidebar. The timeline enables users to easily gather information for post-incident reports. + +#### Custom Statuses + - Users now gain the flexibility to express their current status in any way they prefer. Set a custom status to add a descriptive status message and emoji that’s visible to everyone throughout the app. + +### Improvements + +#### User Interface (UI) + - Improved the **Add Members** to channel modal. + - Added **Formatting** shortcut keys to the **Shortcut** modal. + - Added localization to the date picker used when searching for posts around a given date. + - The autocomplete popover is now positioned relative to the @, ~, or / trigger in the post draft. + - Removed the 5-page limit on previewing PDFs. + - Added ``files`` as a reserved team name. + - Searching for a channel by URL now returns the channel. + - Users are now provided with feedback when creating a custom category name that exceeds the character limit. + +#### Notifications + - Posts from OAuth 2.0 bots no longer trigger mentions for the user. + +#### Administration + - Added an ``ImportDelete`` job to periodically delete unused import files after a configurable retention period has passed. + - Introduced new ``mattermost_system_server_start_time`` and ``mattermost_jobs_active`` metrics for improved debugging with Grafana dashboards. + - Deleting a reaction is now a soft delete in the ``Reactions`` table. A schema update is required and may take up to 15 seconds on first run with large data sets. + - Changed default ``MaxFileSize`` from 50MB to 100MB. + - Updated Go dependencies to their latest minor version. + - Added support for compressed export files with attachments. + - Server crashes due to runtime panics are now captured as a log line. + - Optimized **Direct Message** creation by fetching all users involved in a single database call. + - During the user import process, a change in a user's ``NotifyProps`` will not send an email notification. This is done to make it consistent with other parts of the import process where a change in user's attributes would also not send any notifications. + - Implemented a job to delete unused export files. + +### Bug Fixes + - Fixed an issue where the Database Schema upgrade step for v5.29.1 was not taken into account in releases v5.30 and later. + - Fixed an issue where ``mmctl channel move`` did not allow moving private channels. + - Fixed an issue where ``mmctl config set PluginSettings.EnableUploads`` to change a configuration value did not return an error. + - Fixed an issue where the instructions to search for users in **System Console > Reporting > Server Logs** were not up-to-date. + - Fixed an issue where no error message was displayed when adding an LDAP Group Synchronized Team in **System Console > User Management > Users**. + - Fixed an issue where markdown tables did not wrap correctly. + - Fixed an issue where the search bar styling on dark themes was incorrect on mobile web view. + - Fixed an issue where the **Main Menu** on webapp appeared more left-aligned than previous releases. + - Fixed an issue where sticky sidebar headings appeared under **More Unreads**. + - Fixed an issue where the group channel icon was misaligned in the channel switcher. + - Fixed an issue where line breaks were ignored when used with inline images. + - Fixed an issue where the channel switcher did not focus on the first list result after a backspace. + - Fixed an issue where demoting a user to a guest would not take effect in an environment with read replicas. + - Fixed a bug with in-product notices where a date constraint might fail to match, which would lead to the notice not being fetched. + - Fixed an issue where creation of a bot would fail due to replica lag. + - The ``DownloadComplianceReport`` function in the Golang driver has been fixed to download a full report as a zip archive. + - Fixed Cache-Control headers to instruct that responses may only be cached on browsers. + - Fixed a panic when the OAuth discovery endpoint would not return a Cache-Control header. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ClusterSettings`` in ``config.json``: + - Added ``EnableGossipCompression``, to disable compression in the Gossip protocol. By default the value of the setting is ``true``. This is done to maintain compatibility with old servers in a cluster. Once all servers in a cluster are upgraded, it is recommended to disable this setting for better performance. + - Under ``SqlSettings`` in ``config.json``: + - Added ``ConnMaxIdleTimeMilliseconds``, to allow System Admins to control the maximum time a database connection can remain idle. The default value is set to 5 minutes. + - Under ``TeamSettings`` in ``config.json``: + - Added ``EnableCustomUserStatuses``, to allow users to set descriptive status messages and optional status emoji that are visible to all users. + +### Go Version + - v5.33 is built with Go ``1.15.5``. + +### Open Source Components + - Added ``types/react-overlays``, ``crypto-browserify``, ``process`` and ``stream-browserify``, and removed ``node-semver`` from https://github.com/mattermost/mattermost-webapp. + - Removed ``isomorphic-fetch`` from https://github.com/mattermost/mattermost-redux. + +### API Changes + - Added a new ``GET /{team_id}/threads/{thread_id}`` API method for retrieving single threads. + - Added a new ``/exports`` API endpoint to generate and manage export files. + - Added a new ``/users/{user_id}/teams/{team_id}/threads/mention_counts`` API endpoint. + - Added a new ``GET /api/v4/cloud/subscription/stats`` API endpoint. + - Added a new ``GET /api/v4/cloud/subscription/limitreached/invite`` API endpoint. + - Added new ``PUT /api/v4/users/<id>/status/custom``, ``DELETE /api/v4/users/<id>/status/custom``, and ``DELETE /api/v4/users/<id>/status/custom/recent`` API endpoints. + - The ``/api/v4/users/me/auth`` API endpoint can no longer be used to change passwords. This was a hidden feature that was not documented, but was nevertheless possible. We have removed this hidden feature. + - Updated ``/users/{user_id}/teams/{team_id}/threads`` API to support the ``unread=true`` query parameter. + - The ``/api/v4/users/{user_id}/teams/{team_id}/threads`` API endpoint now accepts "before" and "after" parameters instead of a page index. + - Removed the session required restriction from the ``GET api/v4/subscription/stats`` API endpoint. + +### Websocket Event Changes + - Improved the WebSocket implementation by using epoll to manually read from a WebSocket connection. As a result, the number of goroutines is expected to go down by half. This implementation is only available on Linux and FreeBSD-based distributions. + - The ``UserUpdate`` WebSocket Event is now broadcast by two more APIs, ``plugin.UpdateUser`` and ``ConvertBotToUser``. + +### Known Issues + - Config.json can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - The server tries to install E20-required plugins on non-E20 installations [MM-32387](https://mattermost.atlassian.net/browse/MM-32387). + - Adding an at-mention at the start of a post draft, then pressing the left or right arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - In some cases, the **New messages** toast appears without replacing variables with text. [MM-33829](https://mattermost.atlassian.net/browse/MM-33829) + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page [MM-30980](https://mattermost.atlassian.net/browse/MM-30980). + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side [MM-31994](https://mattermost.atlassian.net/browse/MM-31994). + - Reddit link previews no longer work in Mattermost. This affects older versions too [MM-31899](https://mattermost.atlassian.net/browse/MM-31899). + - Slack theme import fails due to changes in formatting of Slack export color schemes [MM-30531](https://mattermost.atlassian.net/browse/MM-30531). + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[a-c-sreedhar-reddy](https://github.com/a-c-sreedhar-reddy), [aaronrothschild](https://github.com/aaronrothschild), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [Ampit](https://github.com/Ampit), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [anurag6713](https://github.com/anurag6713), [arjunagl](https://github.com/arjunagl), [ashishbhate](https://github.com/ashishbhate), [aspleenic](https://github.com/aspleenic), [BenCookie95](https://github.com/BenCookie95), [berkeka](https://github.com/berkeka), [bjorge82](https://github.com/bjorge82), [calebroseland](https://github.com/calebroseland), [carantunes](https://github.com/carantunes), [catalintomai](https://github.com/catalintomai), [chenilim](https://github.com/chenilim), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cupakob](https://github.com/cupakob), [cwarnermm](https://github.com/cwarnermm), [daniron26](https://github.com/daniron26), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [DSchalla](https://github.com/DSchalla), [elyscape](https://github.com/elyscape), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harryfromwork](https://github.com/harryfromwork), [hectorskypl](https://github.com/hectorskypl), [helios1101](https://github.com/helios1101), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [IndushaS](https://github.com/IndushaS), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jatinjtg](https://github.com/jatinjtg), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [jomaxro](https://github.com/jomaxro), [josephbaylon](https://github.com/josephbaylon), [jp0707](https://github.com/jp0707), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kashifsoofi](https://github.com/kashifsoofi), [kayazeren](https://github.com/kayazeren), [kojiGit55](https://github.com/kojiGit55), [komik966](https://github.com/komik966), [koox00](https://github.com/koox00), [kristinakvn](https://github.com/kristinakvn), [larkox](https://github.com/larkox), [LauSam09](https://github.com/LauSam09), [lawrencejohnson](https://github.com/lawrencejohnson), [Leats](https://github.com/Leats), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lucievr](https://github.com/lucievr), [lynn915](https://github.com/lynn915), [mahmud2011](https://github.com/mahmud2011), [matthewbirtch](https://github.com/matthewbirtch), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [natalie-hub](https://github.com/natalie-hub), [neilharris123](https://github.com/neilharris123), [nevyangelova](https://github.com/nevyangelova), [nronas](https://github.com/nronas), [nurefexc](https://github.com/nurefexc), [ogi-m](https://github.com/ogi-m), [onoklin](https://github.com/onoklin), [pablovelezvidal](https://github.com/pablovelezvidal), [petermcj](https://github.com/petermcj), [Quaqmre](https://github.com/Quaqmre), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [saf6260](https://github.com/saf6260), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [SezalAgrawal](https://github.com/SezalAgrawal), [SimonSimonB](https://github.com/SimonSimonB), [Soriyyx](https://github.com/Soriyyx), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [Szymongib](https://github.com/Szymongib), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [ultra1394](https://github.com/ultra1394), [vpecinka](https://github.com/vpecinka), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak) + +---- + +## Release v5.32 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.32.1, released 2021-02-17** + - Fixed an issue where any search containing an underscore failed on PostgreSQL databases. This was fixed by reverting a v5.32.0 feature that added support for searching for terms on PostgreSQL that contain underscores. +- **v5.32.0, released 2021-02-16** + - Original 5.32.0 release + +Mattermost v5.32.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + - TLS versions 1.0 and 1.1 have been deprecated by browser vendors. Starting in Mattermost Server v5.32 (February 16), mmctl returns an error when connected to Mattermost servers deployed with these TLS versions and System Admins will need to explicitly add a flag in their commands to continue to use them. We recommend upgrading to TLS version 1.2 or higher. + - PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). From v5.26 Mattermost officially supports PostgreSQL version 10 as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions will continue to be compatible with PostgreSQL 9.4. PostgreSQL 9.4 and all 9.x versions are now fully deprecated in our v5.30 release (December 16, 2020). Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). Mattermost will now fail to start if the Postgres version is below that. + +### Breaking Changes + - ``ExperimentalChannelOrganization``, ``EnableXToLeaveChannelsFromLHS``, ``CloseUnusedDirectMessages``, and ``ExperimentalHideTownSquareinLHS`` settings are only functional if the Legacy Sidebar (``EnableLegacySidebar``) is enabled since they are not compatible with the new sidebar experience. ``ExperimentalChannelSidebarOrganization`` has been deprecated, since the [new sidebar is now enabled for all users](https://mattermost.com/blog/custom-collapsible-channel-categories/). + - Breaking changes to the Golang client API were introduced: ``GetPostThread``, ``GetPostsForChannel``, ``GetPostsSince``, ``GetPostsAfter``, ``GetPostsBefore``, and ``GetPostsAroundLastUnread`` now require an additional collapsedThreads parameter to be passed. Any client making use of these functions will need to update them when upgrading its dependencies. + - [A breaking change was introduced when upgrading the Go version to v1.15.5](https://go.dev/doc/go1.15) where user logins fail with AD/LDAP Sync when the certificate of the LDAP Server has no Subject Alternative Name (SAN) in it. Creating a new certificate on the AD/LDAP Server with the SAN inside fixes this. + +```{Important} +If you upgrade from a release earlier than v5.31, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### General availability of custom, collapsible channel categories + - Mattermost now gives users flexibility to organize channels and direct messages into custom, collapsible sidebar categories. Users gain full personalization of their sidebar to improve productivity, reduce clutter and focus on what matters. Learn more about [the new channel sidebar enhancements](https://mattermost.com/blog/custom-collapsible-channel-categories/). + +#### Self-serve renewals (E10 & E20 Editions) + - Mattermost is introducing the ability to renew your self-managed E10 or E20 license subscription online with a credit card. This feature creates a frictionless experience for System Administrators to renew their license without the need to contact sales. + +#### Incident Collaboration v1.3.2 (E20 Edition) + - Pre-packaged Incident Collaboration v1.3.2 offers a more specific incident status and centralized task list. + +### Improvements + +#### User Interface (UI) + - Added new languages, Bulgarian and Swedish. + - Added team sidebar user interface and animation enhancements. + - Moved the header icons to the left of the header beside the channel description. + - Added support to move multi-selected groups of channels to another category via the **More options** menu. + +#### Plugins + - Updated bundled plugin packages, including GitHub and Jenkins plugins. + - Enabled experimental support for ARM64 plugins by allowing any matching ``GOOS-GOOARCH`` combination in the plugin manifest. + +#### Administration + - ``AnalyticsPostCount`` now avoids unnecessary table scans during various background jobs. + - The Help text for the Rate Limiting setting was updated to explain the purpose of rate limiting. + - Removed the word "experimental" from the Gossip setting in the System Console. + - Updated the Go version to v1.15.5. + - Added support for automatic installation and enablement of plugins using feature flags. + - Added ``webhook create`` endpoints to local mode and the ability to create webhooks for other users. + - Added a Mattermost CLI command to initialize the database. + - Added support for processing import files through the API. + - Added support for protocol-relative URLs while using the Image Proxy. + - A Striped LRU cache is now used by default. + - Added shared channels and ``remote_cluster_service`` under a license check. + +### Bug Fixes + - Fixed an issue where the Admin Filter option was not disabled in the AD/LDAP page for Admin roles with a ``sysconsole_write_authentication`` permission. + - Fixed an issue where channels would sometimes be removed from custom categories when a user left a team. + - Fixed an issue where the error text was missing when the team name was left blank on the Team Create page. + - Fixed an issue where the System Manager was able to download the Compliance Export files. + - Fixed an issue where themed button colours in interactive message attachments in Mattermost’s default dark theme were mismatched. + - Fixed an issue where bold and italics shortcuts triggered with CTRL+B on Mac. + - Fixed an issue where a "Your license does not support cloud requests” log error appeared on self-hosted servers. + - Fixed an issue where the permissions of a System Admin role got deleted when changing the access level to any permission. + - Fixed an issue where editing a ``/me`` post behaved differently within the Mattermost Web App and the Mobile App. + - Fixed an issue where the hover state on category headers did not span the whole width of the left-hand navigation. + - Fixed an issue where plugins on the left-hand side of the System Console were sorted differently than the ones in the Plugin Management page. + - Fixed an issue where 15-character team names were truncated when the experimental channel sidebar was enabled. + - Fixed an issue where the sidebar menus weren't styled correctly in mobile browser view. + - Fixed an issue where jumping into an archive channel and clicking the link to jump to recent messages sent the user out of the archived channel. + - Fixed an issue where the tooltip text for copying an incoming webhook URL was unclear. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Deprecated the ``ExperimentalChannelSidebarOrganization`` setting and added a new ``EnableLegacySidebar`` setting. The new channel sidebar will be enabled system-wide by default. + - The ``UseExperimentalGossip`` field under ClusterSettings is now ``true`` by default. This means that new installations will use the Gossip protocol for cluster communication. There will be no changes to existing installations. The Gossip protocol is now considered to be in General Availability and is the recommended clustering mode. + - Enabled ``ExperimentalDataPrefetch`` for all servers and removed the corresponding setting. + - Under ``NativeAppSettings`` in ``config.json``: + - Added a ``AppCustomURLSchemes`` setting to add the ability to redirect to the mobile app after OAuth & SAML auth completion. + +### Go Version + - 5.32 is built with Go ``1.15.5``. + +### API Changes + - Thread related API routes now include ``teamId`` path parameter. + - Changed output of ``Get Threads API`` to include ``total_unread_threads`` instead of ``total_unread_replies``. + - Added ``collapsedThreads`` and ``collapsedThreadsExtended`` query parameters to: + - ``api/v4/channels/{channel_id:[A-Za-z0-9]+}/posts`` + - ``api/v4/users/{user_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}/posts/unread`` + - ``api/v4/posts/{post_id:[A-Za-z0-9]+}/thread`` + +### Database Changes + - Added a new ``Shared`` column to the ``Channels`` table. + +### Known Issues + - Config.json can reset when running the command ``systemctl restart mattermost``, and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - The server tries to install E20 required plugins on non-E20 installations. [MM-32387](https://mattermost.atlassian.net/browse/MM-32387) + - Some known issues related to the new channel sidebar, such as that the team icon on-click animation is laggy. [MM-32198](https://mattermost.atlassian.net/browse/MM-11820) + - Adding an at-mention at the start of a post draft, then pressing the left or right arrow can clear the post draft and the undo history [MM-33823](https://mattermost.atlassian.net/browse/MM-33823). + - Reddit link previews no longer work in Mattermost. [MM-31899](https://mattermost.atlassian.net/browse/MM-31899) + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page. [MM-30980](https://mattermost.atlassian.net/browse/MM-30980) + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side. [MM-31994](https://mattermost.atlassian.net/browse/MM-31994) + - Slow typing has been experienced when the channel sidebar has many channels. [MM-30407](https://mattermost.atlassian.net/browse/MM-30407) + - Slack theme import fails due to changes in formatting of Slack export color schemes. [MM-30531](https://mattermost.atlassian.net/browse/MM-30531) + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[aaronrothschild](https://github.com/aaronrothschild), [Aeiyko](https://github.com/Aeiyko), [aeomin](https://github.com/aeomin), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [Ampit](https://github.com/Ampit), [amwolff](https://github.com/amwolff), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [antwigambrah](https://github.com/antwigambrah), [anurag6713](https://github.com/anurag6713), [arjunagl](https://github.com/arjunagl), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [aspleenic](https://github.com/aspleenic), [Ayanrocks](https://github.com/Ayanrocks), [balan2010](https://github.com/balan2010), [bbodenmiller](https://github.com/bbodenmiller), [BenCookie95](https://github.com/BenCookie95), [ByeongsuPark](https://github.com/ByeongsuPark), [camgraff](https://github.com/camgraff), [chenilim](https://github.com/chenilim), [chikei](https://github.com/chikei), [chrisfromredfin](https://github.com/chrisfromredfin), [coltoneshaw](https://github.com/coltoneshaw), [compiledsound](https://github.com/compiledsound), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [darkLord19](https://github.com/darkLord19), [deanwhillier](https://github.com/deanwhillier), [devinbinnie](https://github.com/devinbinnie), [dmpichugin](https://github.com/dmpichugin), [ebroda](https://github.com/ebroda), [emilyhollinger](https://github.com/emilyhollinger), [emskaplann](https://github.com/emskaplann), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [FlipEnergy](https://github.com/FlipEnergy), [flynbit](https://github.com/flynbit), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [Hassall](https://github.com/Hassall), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [jp0707](https://github.com/jp0707), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kashifsoofi](https://github.com/kashifsoofi), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [koox00](https://github.com/koox00), [kristinakvn](https://github.com/kristinakvn), [larkox](https://github.com/larkox), [lawrencejohnson](https://github.com/lawrencejohnson), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lmammino](https://github.com/lmammino), [lucievr](https://github.com/lucievr), [lynn915](https://github.com/lynn915), [madhavhugar](https://github.com/madhavhugar), [marianunez](https://github.com/marianunez), [maxerenberg](https://github.com/maxerenberg), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mlongo4290](https://github.com/mlongo4290), [moschlar](https://github.com/moschlar), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikkinagar](https://github.com/nikkinagar), [nronas](https://github.com/nronas), [ogi-m](https://github.com/ogi-m), [onoklin](https://github.com/onoklin), [pablovelezvidal](https://github.com/pablovelezvidal), [prapti](https://github.com/prapti), [R8s6](https://github.com/R8s6), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [rolwin100](https://github.com/rolwin100), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [schunka](https://github.com/schunka), [shazm](https://github.com/shazm), [shuang2411](https://github.com/shuang2411), [SimonSimonB](https://github.com/SimonSimonB), [srkgupta](https://github.com/srkgupta), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [svenseeberg](https://github.com/svenseeberg), [Szymongib](https://github.com/Szymongib), [thePanz](https://github.com/thePanz), [uhlhosting](https://github.com/uhlhosting), [vpecinka](https://github.com/vpecinka), [vraravam](https://github.com/vraravam), [wf6DJd8a3xSSCZbn](https://github.com/wf6DJd8a3xSSCZbn), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [yukiisbored](https://github.com/yukiisbored) + +---- + +## Release v5.31 - [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) + +- **v5.31.9, released 2021-08-04** + - Mattermost v5.31.9 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) to this release is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Improved typing performance in affected environments by reducing the frequency at which drafts are saved. +- **v5.31.8, released 2021-07-21** + - Fixed an issue in clustering where a mutex would fail to be unlocked when a timeout happened. [MM-37246](https://mattermost.atlassian.net/browse/MM-37246) +- **v5.31.7, released 2021-06-21** + - Fixed an issue with an infinite recursion during message export for Hitachi HCP file backends. [MM-36440](https://mattermost.atlassian.net/browse/MM-36440) +- **v5.31.6, released 2021-06-11** + - Fixed an issue where subsequent migrations failed to run after running a dot release on new installations. [MM-35931](https://mattermost.atlassian.net/browse/MM-35931) + - Fixed an issue where messages with fallback text were repeated. [MM-30980](https://mattermost.atlassian.net/browse/MM-30980) +- **v5.31.5, released 2021-05-12** + - Fixed an issue where ``mmctl channel move`` did not allow moving private channels. [MM-32746](https://mattermost.atlassian.net/browse/MM-32746) +- **v5.31.4, released 2021-04-23** + - Fixed an issue with client-side slash commands being processed by multiple plugins. [MM-35074](https://mattermost.atlassian.net/browse/MM-35074) +- **v5.31.3, released 2021-04-07** + - Fixed an issue where cluster handlers were not immediately registered after starting the server. This led to issues where jobs were not scheduled until a request hit the cluster. [MM-34179](https://mattermost.atlassian.net/browse/MM-34179) + - Fixed an issue where the server version was reported as v5.30.0. +- **v5.31.2, released 2021-03-29** + - Improved typing performance on busy servers with lots of active users and with the new sidebar enabled. [MM-30407](https://mattermost.atlassian.net/browse/MM-30407) + - Fixed bugs related to replication lag for Enterprise Edition instances configured to use read replicas. [MM-31094](https://mattermost.atlassian.net/browse/MM-31094) +- **v5.31.1, released 2021-02-05** + - Fixed an issue where the ``config.json`` was sporadically getting reset upon CLI command execution. [MM-32234](https://mattermost.atlassian.net/browse/MM-32234) + - Fixed an issue where ``FeatureFlags`` section was getting erroneously written to ``config.json``. [MM-32389](https://mattermost.atlassian.net/browse/MM-32389) + - Fixed an issue where channels were sometimes removed from custom categories when a user left a team. [MM-30314](https://mattermost.atlassian.net/browse/MM-30314) + - Fixed an issue where users were unable to mark Direct Messages in a thread as unread. [MM-32253](https://mattermost.atlassian.net/browse/MM-32253) + - Fixed an issue where ``PermanentDeleteChannel`` failed with "failed to get a thread" error. [MM-31731](https://mattermost.atlassian.net/browse/MM-31731) +- **v5.31.0, released 2021-01-16** + - Original 5.31.0 release + +Mattermost v5.31.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + + - Support for Mattermost Server v5.25 [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) is coming to the end of its life cycle on April 16, 2021. Upgrading to Mattermost Server v5.31 [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) or later is highly recommended. + +### Highlights + +#### Improved status updates for [Incident Management (E20 Edition)](https://mattermost.com/playbooks/) + - Pre-packaged and pre-installed the Mattermost Incident Management v1.2.0, which enables incident responders to easily inform stakeholders of incident status updates. + +### Improvements + +#### User Interface (UI) + - Added the ability to mute categories with the experimental channel sidebar feature. + - Added support for multi-selection of channels when dragging and dropping between channels in the experimental sidebar feature. + - Group messages are now returned in the channel switcher when only first names are typed. + - Issuing ``/dnd`` consecutively no longer unexpectedly toggles the user's status between "Do Not Disturb" and "Online", and will only set the user’s status to "Do Not Disturb". + +#### Administration + - Added a new ``manage_remote_clusters`` permission. + +### Bug Fixes + - Fixed an issue where the ``UnreadMentions`` column was missing in the ``ThreadMemberships`` table for servers upgrading from v5.29.0. Admins planning to enable [Collapsed Reply Threads](https://mattermost.com/blog/dev-sneak-peek-collapsed-reply-threads/) (available in beta in Q1 2021) are recommended to upgrade to v5.31.0 or later. + - Cleaned up the config store on server initialization errors. + - Fixed an issue where permissions did not grant read and/or write access to the Global Relay configuration settings. + - Fixed an issue where the site configuration "Read only" permission did not make the "Notice" section read-only for the System Manager. + - Fixed an issue where importing Client4 in a node server caused an exception due to rudder modules. + - Fixed an issue where LDAP ``FirstLoginSync`` didn't close the LDAP session. + - Fixed an issue where line numbers did not line up with the text on code file previews. + - Fixed an issue where the threshold from the bottom of the screen was sometimes not respected for received messages. + - Fixed an issue where desktop notifications got sent for every message posted in a Direct Message channel. + +### Go Version + - 5.31 is built with Go ``1.14.6``. + +### API Changes + - Added a new ``POST /api/v4/cloud/webhook`` endpoint. + +### Websocket Event Changes + - Added new websocket events ``thread_updated``, ``thread_follow_changed``, and ``thread_read_changed``. + +### Known Issues + - The Database Schema Version is displayed as 5.30.0 in the About Mattermost modal. + - Config.json can reset when running the command ``systemctl restart mattermost`` and when running any commands that write to the config (e.g. ``config`` or ``plugin``) [MM-33752](https://mattermost.atlassian.net/browse/MM-33752), [MM-32390](https://mattermost.atlassian.net/browse/MM-32390). + - Reddit link previews no longer work in Mattermost. [MM-31899](https://mattermost.atlassian.net/browse/MM-31899) + - **Discard Changes** confirmation is not displayed when a System Admin adds people on the **System Roles** System Console page and clicks elsewhere before saving the changes. [MM-29927](https://mattermost.atlassian.net/browse/MM-29927) + - Error text is missing when the team name is left blank on the team creation page. [MM-31361](https://mattermost.atlassian.net/browse/MM-31361) + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page. [MM-30980](https://mattermost.atlassian.net/browse/MM-30980) + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side. [MM-31994](https://mattermost.atlassian.net/browse/MM-31994) + - Slow typing has been experienced when the channel sidebar has many channels. [MM-30407](https://mattermost.atlassian.net/browse/MM-30407) + - Slack theme import fails due to changes in formatting of Slack export color schemes. [MM-30531](https://mattermost.atlassian.net/browse/MM-30531) + - A JavaScript error may appear in some cases when dismissing the new messages toast while scrolled up in the right-hand side. [MM-30446](https://mattermost.atlassian.net/browse/MM-30446) + - The **Admin Filter** option is not disabled on the AD/LDAP page for Admin roles with the ``sysconsole_write_authentication`` permission. [MM-29089](https://mattermost.atlassian.net/browse/MM-29089) + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotation marks with Elasticsearch enabled returns more than just the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [a-c-sreedhar-reddy](https://github.com/a-c-sreedhar-reddy), [aeomin](https://github.com/aeomin), [agnivade](https://github.com/agnivade), [akshaychhajed](https://github.com/akshaychhajed), [amwsis](https://github.com/amwsis), [amyblais](https://github.com/amyblais), [anurag6713](https://github.com/anurag6713), [ashishbhate](https://github.com/ashishbhate), [avinashlng1080](https://github.com/avinashlng1080), [Ayanrocks](https://github.com/Ayanrocks), [calebroseland](https://github.com/calebroseland), [CandyZack](https://github.com/CandyZack), [catalintomai](https://github.com/catalintomai), [chikei](https://github.com/chikei), [cinlloc](https://github.com/cinlloc), [cpanato](https://github.com/cpanato), [CrHasher](https://github.com/CrHasher), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [daniel-shuy](https://github.com/daniel-shuy), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DigasNikas](https://github.com/DigasNikas), [edtrist](https://github.com/edtrist), [enahum](https://github.com/enahum), [ethervoid](https://github.com/ethervoid), [flynbit](https://github.com/flynbit), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [girish17](https://github.com/girish17), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [HeroicHitesh](https://github.com/HeroicHitesh), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jakaya123](https://github.com/jakaya123), [jakubnovak998](https://github.com/jakubnovak998), [jasonblais](https://github.com/jasonblais), [JeremyShih](https://github.com/JeremyShih), [jespino](https://github.com/jespino), [josephbaylon](https://github.com/josephbaylon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kcc343](https://github.com/kcc343), [KevinMarioGerard](https://github.com/KevinMarioGerard), [larkox](https://github.com/larkox), [lawrencejohnson](https://github.com/lawrencejohnson), [Leryan](https://github.com/Leryan), [lieut-data](https://github.com/lieut-data), [marianunez](https://github.com/marianunez), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [MikeworX](https://github.com/MikeworX), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [msal4](https://github.com/msal4), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nronas](https://github.com/nronas), [pablovelezvidal](https://github.com/pablovelezvidal), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [SBagaria2710](https://github.com/SBagaria2710), [sbishel](https://github.com/sbishel), [sbley](https://github.com/sbley), [snhardin](https://github.com/snhardin), [streamer45](https://github.com/streamer45), [sudheerDev](https://github.com/sudheerDev), [thePanz](https://github.com/thePanz), [tweichart](https://github.com/tweichart), [Tzunhei](https://github.com/Tzunhei), [uhlhosting](https://github.com/uhlhosting), [vraravam](https://github.com/vraravam), [wget](https://github.com/wget), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.30 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.30.3, released 2021-02-02** + - Fixed an issue where the **Edition** diagnostics field was reporting as "null" for Team Edition servers on 5.30. +- **v5.30.2, released 2021-01-18** + - Fixed an issue where the ``UnreadMentions`` column was missing in the ``ThreadMemberships`` table for servers upgrading from v5.29.0. Admins planning to enable [Collapsed Reply Threads](https://mattermost.com/blog/dev-sneak-peek-collapsed-reply-threads/) (available in beta in Q1 2021) are recommended to upgrade to v5.30.2 or later. +- **v5.30.1, released 2020-12-18** + - Fixed the displayed modal Build Number version to standard semver. +- **v5.30.0, released 2020-12-16** + - Original 5.30.0 release + +### Compatibility + - PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). From v5.26 Mattermost officially supports PostgreSQL version 10 as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL 9.4. PostgreSQL 9.4 and all 9.x versions are now fully deprecated in our v5.30 release (December 16, 2020). Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). + +### Highlights + +#### Incident Management provided out-of-the-box (E20) + - Pre-packaged and pre-installed the Incident Management as well as Channel Export plugins for enterprise-ready builds. + +#### Configure New Admin Roles Permissions in the System Console (E20, Beta) + - Mattermost [recently released three new pre-built granular administrator roles](https://mattermost.com/blog/mattermost-release-v5-28/) to enable you to selectively delegate administrative tasks to other members of your organization. The three new roles are System Manager, User Manager, and Read-only Admin. Now you can configure specific permissions for these roles directly from the System Console. + +### Improvements + +#### User Interface + - @-autocomplete results are now prioritized based on recency and thread activity. + - File attachments below the size of 10 (KB, MB, GB, TB, etc.) now allow showing fractions. + - The formatting of the channel header change message was improved. + - Team invite workflow now shows BOT tags when the search returns bot users. + - Added the ability to zoom in and out of PDF files. + - Added support for 16x16 base64 encoded mini images to use with progressive rendering. + +#### Notifications + - Channel-wide mentions are now automatically disabled when a user mutes a channel. + +#### Command Line Interface (CLI) + - Added new local API endpoints for getting, updating, and deleting incoming and outgoing webhooks. + - Added ``mmctl system version`` endpoint to print the remote server version. + - Improved the ``mmctl system status`` command output to include all the reported values. + +#### Integrations + - Updated ``icon_emoji`` field in incoming webhooks to allow emojis to be specified with surrounding colons. + - Dynamic auto-completion is now supported for built-in slash commands. + - Added plugin hooks for ``ReactionHasBeenAdded`` and ``ReactionHasBeenRemoved``. + +#### Administration + - Added the ability to load a set of custom configuration defaults from a ``MM_CUSTOM_DEFAULTS_PATH`` environment variable. + - Added AWS metering service support. + +#### Enterprise Edition (EE) + - Added the ability to retrieve compliance files from the System Console. + +### Bug Fixes + - Fixed a performance issue related to typing lag. + - Fixed an issue where YouTube previews did not display sometimes. + - Fixed an issue with broken link previews for Twitter links. + - Fixed an issue where editing a post did not submit with CMD+ENTER. + - Fixed an issue where users were able to create or edit slash commands to contain more than two slashes in the URL. + - Fixed an issue where resized emojis were being overwritten with original data. + - Fixed an issue where the sidebar category **More** menu was not shown when hovering over a long category name. + - Fixed an issue where a received direct message notification did not show up on the sidebar if the Direct Message channel was newly created. + - Fixed an issue where a search using **from:** failed to auto-load more results on the right-hand side when Elasticsearch was enabled. + - Fixed an issue where an s3 file backend ``TestFileConnection`` failed due to permissions if ``S3PathPrefix`` was in use. + - Fixed an issue where an ID was missing for a Tooltip in ``PostInfo``. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in ``config.json``, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ExperimentalSettings`` in ``config.json``: + - Added ``EnableSharedChannels``, to support managing shared channels feature. + - Under ``SamlSettings`` in ``config.json``: + - Added ``IgnoreGuestsLdapSync``, to ignore guests when using SAML and synchronizing with LDAP. + +### Go Version + - 5.30 is built with Go ``1.14.6``. + +### Open Source Components + - Added ``@stripe/react-stripe-js``, ``@stripe/stripe-js``, and ``@types/country-list`` to https://github.com/mattermost/mattermost-webapp. + - Removed ``react-native-image-gallery`` from https://github.com/mattermost/mattermost-mobile. + - Added ``react-native-redash`` and ``react-native-share`` to https://github.com/mattermost/mattermost-mobile. + +### Database Changes + - Added a new column ``minipreview`` to ``FileInfo`` table. + +### Websocket Event Changes + - In ``post_deleted`` websocket event, System Admins are now notified when a user initiates a post deletion. + +### API Changes + - Added new local API endpoints for getting, updating, and deleting incoming and outgoing webhooks. + - Added new API endpoints to work with experimental collapsed threads. + +### Known Issues + - The ``config.json`` may reset itself to default values if the binary is run with the root user. + - Reddit link previews no longer work in Mattermost. This affects older versions too. + - **Discard Changes** confirmation is not displayed when an admin adds people in the **System Roles** System Console page, then clicks elsewhere before saving the changes. + - Slow typing has been experienced when the channel sidebar has many channels. This has been reported in older versions too. + - Slack theme import fails due to changes in formatting of Slack export color schemes. + - Error text is missing when the team name is left blank on the team creation page. + - Line numbers do not line up with the text on code file previews. + - In some cases reply posts cannot be marked as unread. + - The threshold from the bottom of the screen is sometimes not respected for received messages. + - Posts created by bots containing attachments sometimes appear as repeated until the user refreshes the page. + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side. + - A JavaScript error may appear in some cases when dismissing the new messages toast while scrolled up in the right-hand side. + - The Admin Filter option is not disabled in AD/LDAP page for admin roles with ``sysconsole_write_authentication`` permission. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console. To fix this, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as **Away** or **Offline** in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - The team sidebar on the desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [adamjclarkson](https://github.com/adamjclarkson), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akshaychhajed](https://github.com/akshaychhajed), [Ampit](https://github.com/Ampit), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Ant0wan](https://github.com/Ant0wan), [antifarben](https://github.com/antifarben), [anurag6713](https://github.com/anurag6713), [ashishbhate](https://github.com/ashishbhate), [AugustasV](https://github.com/AugustasV), [avasconcelos114](https://github.com/avasconcelos114), [BenCookie95](https://github.com/BenCookie95), [bhargav50](https://github.com/bhargav50), [ByeongsuPark](https://github.com/ByeongsuPark), [calebroseland](https://github.com/calebroseland), [CandyZack](https://github.com/CandyZack), [catalintomai](https://github.com/catalintomai), [chikei](https://github.com/chikei), [cinlloc](https://github.com/cinlloc), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [cwarnermm](https://github.com/cwarnermm), [dalcde](https://github.com/dalcde), [daniel-shuy](https://github.com/daniel-shuy), [danielsischy](https://github.com/danielsischy), [darkLord19](https://github.com/darkLord19), [DavidePrincipi](https://github.com/DavidePrincipi), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [dizkek](https://github.com/dizkek), [drraghavendra](https://github.com/drraghavendra), [egrinberg](https://github.com/egrinberg), [eltociear](https://github.com/eltociear), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [erezo9](https://github.com/erezo9), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [fagunbhavsar](https://github.com/fagunbhavsar), [FalseHonesty](https://github.com/FalseHonesty), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [GodlikePenguin](https://github.com/GodlikePenguin), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [haardikdharma10](https://github.com/haardikdharma10), [hack3r-0m](https://github.com/hack3r-0m), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harryfromwork](https://github.com/harryfromwork), [hectorgabucio](https://github.com/hectorgabucio), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [icy-meteor](https://github.com/icy-meteor), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jecepeda](https://github.com/jecepeda), [JeremyShih](https://github.com/JeremyShih), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jials](https://github.com/jials), [johnsonbrothers](https://github.com/johnsonbrothers), [jomaxro](https://github.com/jomaxro), [josephbaylon](https://github.com/josephbaylon), [jrepe](https://github.com/jrepe), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kaiwalyakoparkar](https://github.com/kaiwalyakoparkar), [kayazeren](https://github.com/kayazeren), [kichloo](https://github.com/kichloo), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [lawrencejohnson](https://github.com/lawrencejohnson), [lestgabo](https://github.com/lestgabo), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lucianomagrao](https://github.com/lucianomagrao), [lynn915](https://github.com/lynn915), [Manimaran11](https://github.com/Manimaran11), [marianunez](https://github.com/marianunez), [maticbasle](https://github.com/maticbasle), [mbouzada](https://github.com/mbouzada), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [MikeworX](https://github.com/MikeworX), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [morganrconnolly](https://github.com/morganrconnolly), [msal4](https://github.com/msal4), [muety](https://github.com/muety), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [nronas](https://github.com/nronas), [ogi-m](https://github.com/ogi-m), [OgmaJ](https://github.com/OgmaJ), [pablovelezvidal](https://github.com/pablovelezvidal), [persianopencart](https://github.com/persianopencart), [phntom](https://github.com/phntom), [pikami](https://github.com/pikami), [prithvijit-dasgupta](https://github.com/prithvijit-dasgupta), [promulo](https://github.com/promulo), [razum2um](https://github.com/razum2um), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [Remakh](https://github.com/Remakh), [Revanth47](https://github.com/Revanth47), [rishabh710](https://github.com/rishabh710), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [Saucistophe](https://github.com/Saucistophe), [sbishel](https://github.com/sbishel), [seongwon-kang](https://github.com/seongwon-kang), [SezalAgrawal](https://github.com/SezalAgrawal), [shazm](https://github.com/shazm), [shinnlok](https://github.com/shinnlok), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [Spotts9](https://github.com/Spotts9), [sridhar02](https://github.com/sridhar02), [sstaszkiewicz-copperleaf](https://github.com/sstaszkiewicz-copperleaf), [stafot](https://github.com/stafot), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [tacoelho](https://github.com/tacoelho), [Tak-Iwamoto](https://github.com/Tak-Iwamoto), [tasdomas](https://github.com/tasdomas), [thefactremains](https://github.com/thefactremains), [thePanz](https://github.com/thePanz), [tianlangwu](https://github.com/tianlangwu), [tohn](https://github.com/tohn), [TQuock](https://github.com/TQuock), [trishitapingolia](https://github.com/trishitapingolia), [tw-ayush](https://github.com/tw-ayush), [tweichart](https://github.com/tweichart), [uhlhosting](https://github.com/uhlhosting), [vanya829](https://github.com/vanya829), [VolatianaYuliana](https://github.com/VolatianaYuliana), [vraravam](https://github.com/vraravam), [weblate](https://github.com/weblate), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [wijayaerick](https://github.com/wijayaerick), [zarej](https://github.com/zarej), [ZombiMigz](https://github.com/ZombiMigz) + +---- + +## Release v5.29 - [Quality Release](https://handbook.mattermost.com/operations/research-and-development/product/release-process/release-overview) + +- **v5.29.2, released 2021-01-18** + - Fixed an issue where the ``UnreadMentions`` column was missing in the ``ThreadMemberships`` table for servers upgrading from v5.29.0. Admins planning to enable [Collapsed Reply Threads](https://mattermost.com/blog/dev-sneak-peek-collapsed-reply-threads/) (available in beta in Q1 2021) are recommended to upgrade to v5.29.2 or later. +- **v5.29.1, released 2020-12-03** + - Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library. + - Added ``UnreadMentions`` column to ``ThreadMemberships`` table, and fixed server log warnings related to ``ThreadMemberships``. Admins planning to enable [Collapsed Reply Threads](https://mattermost.com/blog/dev-sneak-peek-collapsed-reply-threads/) (available in beta in Q1 2021) are recommended to upgrade to v5.29.1 or later. +- **v5.29.0, released 2020-11-16** + - Original 5.29.0 release + +### Compatibility + - A new configuration setting ``ThreadAutoFollow`` has been added to support [Collapsed Reply Threads](https://docs.google.com/presentation/d/1QSrPws3N8AMSjVyOKp15FKT7O0fGMSx8YidjSDS4Wng/edit#slide=id.g2f0aecc189_0_245) releasing in beta in Q1 2021. This setting is enabled by default and may affect server performance. It is recommended to review our [documentation on hardware requirements](https://docs.mattermost.com/install/requirements.html#hardware-requirements) to ensure your servers are appropriately scaled for the size of your user base. + +```{Important} +If you upgrade from a release earlier than v5.28, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Channel Moderation Settings now generally available (E20) + - [Channel moderation](https://docs.mattermost.com/deployment/team-channel-management.html#channels) feature was moved out of beta to general availability. + +#### Mattermost Omnibus now generally available + - [Mattermost Omnibus](https://docs.mattermost.com/help/getting-started/light-install.html) feature was moved out of beta to general availability. + +### Improvements + +#### User Interface (UI) + - Added a new browser favicon state for when there are new messages but no mentions. + - Improved sort order of the channel switcher to prioritize recently viewed channels. + - Improved filter control for the new channel sidebar to show unread channels without categories. + - The 'More unreads' banner in the new channel sidebar was updated to match the new mobile app styling. + - A threshold was added from the bottom of the screen for the new messages toast. + +### Bug Fixes + - Fixed an issue where Enterprise CLI commands would not run. + - Fixed an issue where the right-hand side comment box got pushed out of the view when a new message was posted in the message thread. + - Fixed an issue where the color picker colors were missing from the Announcement Banner page in the System Console. + - Fixed an issue where links in channels headers overlapped in some cases. + - Fixed an issue where a plugin could create a blank ephymeral post, leading to a white screen. + - Fixed an issue where the channel switcher dialog was not accessible with a screen reader. + - Fixed an issue where email addresses were not auto-detected on invites. + - Fixed an issue where duplicate sidebar categories could be created on first use of the new experimental sidebar. + - Fixed an issue where installing plugins on a server using ``FileSettings.PathPrefix`` caused issues. + - Fixed an issue where the error message was unclear when a plugin crashed during a slash command execution. + - Fixed an issue where bot icon images had too much height. + - Fixed an issue where tags where nested in Plugin Marketplace labels. + - Fixed an issue with inconsistent behaviour in channel mentions in message attachments. + - Fixed an issue where ephemeral posts posted by bot accounts showed a wrong username on the right-hand side. + - Fixed an issue where the category headings in the experimental sidebar were not sticky and overlapped the More Unreads indicators. + - Fixed an issue where Automatic Direct Message Replies were not shown on the right-hand side. + - Fixed an issue where Automatic Direct Message Replies were still showing after the root post was deleted. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``ThreadAutoFollow``, to add support for collapsed reply threads. + - Added ``ManagedResourcePaths``, to add support for a setting to use with the Desktop Managed Resources feature. + +### Go Version + - 5.29 is built with Go ``1.14.6``. + +### Open Source Components + - Removed ``@types/react-custom-scrollbars`` from https://github.com/mattermost/mattermost-webapp. + +### Database Changes + - Altered some types and defaults in ``SidebarCategories`` table. + - Added a new column ``Threads.ChannelId``. + - Added ``UnreadMentions`` column to ``ThreadMembership`` table. + +### Known Issues + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side. + - A JavaScript error may appear in some cases when dismissing the new messages toast while scrolled up in the right-hand side. + - Slow typing has been experienced when the channel sidebar has many channels. This has been reported in older versions too. + - Slack theme import fails due to changes in formatting of Slack export color schemes. + - Pressing ENTER closes the Account Settings Edit modal when adjusting the settings for desktop notification sound. + - Admin Filter option is not disabled in AD/LDAP page for admin roles with ``sysconsole_write_authentication`` permission. + - Twitter link previews no longer work in Mattermost as Twitter has removed OpenGraph data from its pages. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console. To fix this, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as Away or Offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [7quantumphysics](https://github.com/7quantumphysics), [93lykevin](https://github.com/93lykevin), [abdusabri](https://github.com/abdusabri), [Adovenmuehle](https://github.com/Adovenmuehle), [aedott](https://github.com/aedott), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [akshaychhajed](https://github.com/akshaychhajed), [akwanmaroso](https://github.com/akwanmaroso), [alexpjohnson](https://github.com/alexpjohnson), [ali-farooq0](https://github.com/ali-farooq0), [altmas5](https://github.com/altmas5), [amsjavan](https://github.com/amsjavan), [amwolff](https://github.com/amwolff), [amyblais](https://github.com/amyblais), [anchepiece](https://github.com/anchepiece), [angeloskyratzakos](https://github.com/angeloskyratzakos), [Ant0wan](https://github.com/Ant0wan), [arc9693](https://github.com/arc9693), [ArcaneDiver](https://github.com/ArcaneDiver), [ArturBa](https://github.com/ArturBa), [ashishbhate](https://github.com/ashishbhate), [AshishMhrzn10](https://github.com/AshishMhrzn10), [asimsedhain](https://github.com/asimsedhain), [aspleenic](https://github.com/aspleenic), [ataboo](https://github.com/ataboo), [attiss](https://github.com/attiss), [AugustasV](https://github.com/AugustasV), [AugustinJose1221](https://github.com/AugustinJose1221), [avasconcelos114](https://github.com/avasconcelos114), [avinashdhinwa](https://github.com/avinashdhinwa), [Ayanrocks](https://github.com/Ayanrocks), [bhargav50](https://github.com/bhargav50), [ByeongsuPark](https://github.com/ByeongsuPark), [calebroseland](https://github.com/calebroseland), [camgraff](https://github.com/camgraff), [carantunes](https://github.com/carantunes), [catalintomai](https://github.com/catalintomai), [CEOehis](https://github.com/CEOehis), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [chrisfromredfin](https://github.com/chrisfromredfin), [cinlloc](https://github.com/cinlloc), [cjmartian](https://github.com/cjmartian), [clarmso](https://github.com/clarmso), [coltoneshaw](https://github.com/coltoneshaw), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [daniloff200](https://github.com/daniloff200), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [devius](https://github.com/devius), [didithilmy](https://github.com/didithilmy), [DigasNikas](https://github.com/DigasNikas), [diode](https://github.com/diode), [dudupopkhadze](https://github.com/dudupopkhadze), [edtrist](https://github.com/edtrist), [emilyacook](https://github.com/emilyacook), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [EnzoBtv](https://github.com/EnzoBtv), [erezo9](https://github.com/erezo9), [ericjaystevens](https://github.com/ericjaystevens), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [evilghostgirl](https://github.com/evilghostgirl), [fakela](https://github.com/fakela), [filipghorbani](https://github.com/filipghorbani), [fireynis](https://github.com/fireynis), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [gabrieljackson](https://github.com/gabrieljackson), [Ganzabahl](https://github.com/Ganzabahl), [GodlikePenguin](https://github.com/GodlikePenguin), [goldsziggy](https://github.com/goldsziggy), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [haardikdharma10](https://github.com/haardikdharma10), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hardikmodi1](https://github.com/hardikmodi1), [hectorgabucio](https://github.com/hectorgabucio), [hectorskypl](https://github.com/hectorskypl), [hiendinhngoc](https://github.com/hiendinhngoc), [hirenchauhan2](https://github.com/hirenchauhan2), [hmhealey](https://github.com/hmhealey), [icy-meteor](https://github.com/icy-meteor), [imakish](https://github.com/imakish), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasimmons](https://github.com/jasimmons), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jaypitroda12](https://github.com/jaypitroda12), [jecepeda](https://github.com/jecepeda), [jekill](https://github.com/jekill), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [jmakhack](https://github.com/jmakhack), [johnsonbrothers](https://github.com/johnsonbrothers), [Jonany](https://github.com/Jonany), [josephbaylon](https://github.com/josephbaylon), [joshuabezaleel](https://github.com/joshuabezaleel), [jufab](https://github.com/jufab), [justinegeffen](https://github.com/justinegeffen), [kaakaa](https://github.com/kaakaa), [kashifsoofi](https://github.com/kashifsoofi), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [khushijindal](https://github.com/khushijindal), [KrishnaSindhur](https://github.com/KrishnaSindhur), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [Leryan](https://github.com/Leryan), [lestgabo](https://github.com/lestgabo), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lipmem](https://github.com/lipmem), [lucianomagrao](https://github.com/lucianomagrao), [lushan01](https://github.com/lushan01), [lynn915](https://github.com/lynn915), [M-Buntoro](https://github.com/M-Buntoro), [Manimaran11](https://github.com/Manimaran11), [marcelo-cardozo](https://github.com/marcelo-cardozo), [marianunez](https://github.com/marianunez), [mathiasvr](https://github.com/mathiasvr), [maticbasle](https://github.com/maticbasle), [mattermod](https://github.com/mattermod), [mbouzada](https://github.com/mbouzada), [mdabydeen](https://github.com/mdabydeen), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michelengelen](https://github.com/michelengelen), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [MikeworX](https://github.com/MikeworX), [mishkaowner](https://github.com/mishkaowner), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [MohanSha](https://github.com/MohanSha), [moussetc](https://github.com/moussetc), [n-thumann](https://github.com/n-thumann), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nbolender](https://github.com/nbolender), [NCC-1031](https://github.com/NCC-1031), [nevyangelova](https://github.com/nevyangelova), [NexWeb](https://github.com/NexWeb), [ng29](https://github.com/ng29), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [nizarmah](https://github.com/nizarmah), [ogi-m](https://github.com/ogi-m), [Oppodelldog](https://github.com/Oppodelldog), [outofgamut](https://github.com/outofgamut), [ozdemirburak](https://github.com/ozdemirburak), [palcodes](https://github.com/palcodes), [paulussujono](https://github.com/paulussujono), [Phizzard](https://github.com/Phizzard), [pikami](https://github.com/pikami), [Poussinette](https://github.com/Poussinette), [pranavtharoor](https://github.com/pranavtharoor), [prapti](https://github.com/prapti), [prazolpp](https://github.com/prazolpp), [promulo](https://github.com/promulo), [radoslavius](https://github.com/radoslavius), [Raj-Datta-Manohar](https://github.com/Raj-Datta-Manohar), [RanadeepPolavarapu](https://github.com/RanadeepPolavarapu), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [Revanth47](https://github.com/Revanth47), [rishabh710](https://github.com/rishabh710), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [sakaitsu](https://github.com/sakaitsu), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [seongwon-kang](https://github.com/seongwon-kang), [SezalAgrawal](https://github.com/SezalAgrawal), [ShajithaMohammed](https://github.com/ShajithaMohammed), [shazm](https://github.com/shazm), [shieldsjared](https://github.com/shieldsjared), [shihanng](https://github.com/shihanng), [Shivam7-1](https://github.com/Shivam7-1), [shred86](https://github.com/shred86), [shtelzerartem](https://github.com/shtelzerartem), [sikloidz](https://github.com/sikloidz), [simross](https://github.com/simross), [singh-sarabjeet](https://github.com/singh-sarabjeet), [SinithH](https://github.com/SinithH), [sirMackk](https://github.com/sirMackk), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [spielers](https://github.com/spielers), [spiritbro1](https://github.com/spiritbro1), [sridhar02](https://github.com/sridhar02), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [sudiptog81](https://github.com/sudiptog81), [Sumindar](https://github.com/Sumindar), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [Tak-Iwamoto](https://github.com/Tak-Iwamoto), [talentedunicorn](https://github.com/talentedunicorn), [tasdomas](https://github.com/tasdomas), [tellustheguru](https://github.com/tellustheguru), [teresa-novoa](https://github.com/teresa-novoa), [thefactremains](https://github.com/thefactremains), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [tsabi](https://github.com/tsabi), [tw-ayush](https://github.com/tw-ayush), [uhlhosting](https://github.com/uhlhosting), [utkuufuk](https://github.com/utkuufuk), [vaibhav111tandon](https://github.com/vaibhav111tandon), [vanya829](https://github.com/vanya829), [varunks99](https://github.com/varunks99), [vipul08](https://github.com/vipul08), [vladimirdotk](https://github.com/vladimirdotk), [VolatianaYuliana](https://github.com/VolatianaYuliana), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wijayaerick](https://github.com/wijayaerick), [Willyfrog](https://github.com/Willyfrog), [yash2189](https://github.com/yash2189) + +---- + +## Release v5.28 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.28.2, released 2020-12-03** + - Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library. +- **v5.28.1, released 2020-10-19** + - Fixed an issue where mmctl Command Line Tool (Beta) was broken on Mattermost server v5.28.0. [MM-29740](https://mattermost.atlassian.net/browse/MM-29740) + - Fixed an issue where the Compliance Exports were taking too long on large deployments. This was fixed with a performance optimization of the message export query. +- **v5.28.0, released 2020-10-16** + - Original 5.28.0 release + +### Compatibility + - PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). Mattermost is officially supporting PostgreSQL version 10 with v5.26 release as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL 9.4. We plan on fully deprecating PostgreSQL 9.4 and all 9.x versions in our v5.30 release (December 16, 2020). Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). + - Support for Mattermost Server [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) (ESR) 5.19 has come to the end of its life cycle. Upgrading to Mattermost Server v5.25 or later is required. + - TLS versions 1.0 and 1.1 have been deprecated by browser vendors. Starting in v5.31 (January 16, 2021) mmctl will return an error when connected to Mattermost servers deployed with these TLS versions and System Admins will need to explicitly add a flag in their commands to continue to use them. We recommend upgrading to TLS version 1.2 or higher. + +### Breaking Changes + - Now when the service crashes, it will generate a coredump instead of just dumping the stack trace to the console. This allows us to preserve the full information of the crash to help with debugging it. For more information about coredumps, please see: https://man7.org/linux/man-pages/man5/core.5.html. + +```{Important} +If you upgrade from a release earlier than v5.27, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### New admin roles to delegate administration tasks to other types of administrators (E20) + - New admin roles are additional system roles that have access to designated areas of the System Console. This enables you to delegate certain administrative tasks to other members of your organization. + +#### Certificate-based authentication with AD/LDAP (E10) + - You can now improve the security of your AD/LDAP authentication with certificate-based AD/LDAP authentication. + +#### Stay current with in-product notices + - With in-product notices, users and Admins will be made aware of the newest product enhancements from within Mattermost. [Learn more about in-product notices here](https://docs.mattermost.com/administration/notices.html). + +### Improvements + +#### User Interface (UI) + - Improved the readability of the toast banner message timestamp, post timestamp, and date separators. + - Added animation for emoji reactions on webapp. + - Added the ability to use CTRL+B and CTRL+I to add bold and italics markdown formatting to selected text. + - Clicking on original message creator's username in discontinuing posts now opens the user's profile popover. + - Added support for PSD file preview. + - When the **Enable Latex Rendering** option is set to ``true``, the current code now doesn't highlight. + - Updated the UX of the **More unreads** indicator in the channel sidebar. + - **Select Team** list container now scales in width based on browser window width. + - Added support for signaling login to other tabs (Windows, macOS and Linux browsers). + +#### Search + - Added wildcard support to Bleve. + - Search terms including stopwords now return matching stopwords instead of an empty result. + - Removed duplication in ``is_or_search`` and ``IncludeDeletedChannels`` parameters for search. + - ``*`` characters are now filtered from the search terms in the database. + - Fixed inconsistencies across product when using ``in:@` / `in:``, such as displaying Direct and Group Messages in ``in:@`` search suggestions. + +#### Notifications + - Added an option in the **Account Settings** to select different desktop notification sounds. This setting is available in supported browsers and in the Desktop app v4.6 and later. + +#### Command Line Interface (CLI) + - Added ``config migrate``, ``config subpath``, ``user delete``, ``integrity``, ``user migrate_auth``, ``moveChannel``, ``updateChannelPrivacy``, ``restoreTeam``, ``channel delete``, and plugin marketplace commands to mmctl. + +#### Plugins + - Plugins now start concurrently on server startup. + - Plugin tooltips are now only rendered when user hovers over a link. + - Added a ``CreateCommand`` plugin API that creates a slash command that is not handled by the plugin itself. + +#### Administration + - Added the ability to upload and remove private and public certificates for LDAP authentication. + - Added support for resumable file uploads. + - Added the ability to convert a public channel to private and vice versa via Advanced Permissions. + - Added filters to search teams in Teams page. + - Improved logging related to sessions that are not found. + - Created Grafana enterprise metrics for logging, such as for current queue level(s), rate of logging records emitted, and rate of logging errors. + - Improved logging when ``GetUser`` fails during MFA Authentication. + - Added support for sending telemetry via an environment variable set by packages to identify type of deployment (e.g. Docker, Mattermost Omnibus). + +### Bug Fixes + - Fixed an issue where a large number of archived channels caused performance degradation. + - Fixed an issue where ``group list-ldap`` mmctl command didn't return any results. + - Fixed an issue where user were allowed to update their profile picture on ADFS setup with SAML and LDAP configured and AD/LDAP Sync enabled. + - Fixed an issue where patching the config with ``DataSourceReplicas`` caused a panic. + - Fixed an issue where API invites by email were silently rate-limited. + - Fixed an issue where deactivated users broke pagination in Manage Members modal. + - Fixed an issue where an error occurred while inviting more than 20 users to a team via **Invite People**. + - Fixed an issue where a ``PostUtils.formatText`` crashed when formatting text with unicode emoji. + - Fixed an issue where a white screen occurred when editing a post and sending the post from a preview mode. + - Fixed an issue on Microsoft Edge (non-Chromium) where logging out caused the user to get stuck at a loading screen. + - Fixed an issue where a selected item in the Direct Messages **More** menu didn’t scroll into view when using keyboard navigation. + - Fixed an issue where users received ghost notifications when the "First name trigger mention" setting was set but the "First Name" was not set. + - Fixed an issue where post text was partially hidden by the post hover menu. + - Fixed an issue where users were unable to type color hex value into custom theme color input box. + - Fixed an issue where the badge with a mention count on the team sidebar did not increment when user was added to a channel. + - Fixed an issue where Group Message results were prioritized over Direct Message results for Full Name in the user autocomplete. + - Fixed an issue where the New Message indicator was broken when a webhook owned by the user posted to a channel. + - Fixed an issue where the active search bar was not vertically aligned with left edge of the right-hand side in tablet view. + - Fixed an issue where there were two scrollbars showing in the channel switcher. + - Fixed an issue where the "Start trial" message was unreadable in the System Console on dark theme on first load. + - Fixed an issue on Firefox where pasting an image also added the file as text. + - Fixed an issue where Python syntax highlighting handled ``"""`` strangely. + - Fixed an issue where formatting around inline codes was missing. + - Fixed an issue where ``GetPluginStatus`` didn't work in a non-cluster environment. + +### config.json +Multiple setting options were added to ``config.json``. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``LdapSettings`` in ``config.json``: + - Added ``PublicCertificateFile``, to be able to upload the public certificate to be used for encryption with SAML configuration. + - Added ``PrivateKeyFile``, to be able to upload the private key to be used for encryption with SAML configuration. + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableAPIChannelDeletion``, to permanently delete channels for compliance reasons. + - Added ``EnableAPIUserDeletion``, to permanently delete users for compliance reasons. + - Under ``NotificationLogSettings`` and ``ExperimentalAuditSettings`` in ``config.json``: + - Added ``AdvancedLoggingConfig``, to enable configuration options for setting audit targets. + - Under ``AnnouncementSettings`` in ``config.json``: + - Added ``AdminNoticesEnabled`` and ``UserNoticesEnabled``, to enable in-product notices to make users and Admins aware of the newest product enhancements from within Mattermost. + - ``EnableCustomEmoji``, ``EnableGifPicker``, ``ExperimentalViewArchivedChannels`` and ``ExperimentalTimezone`` are now enabled by default for new installs. + +### Open Source Components + - Added ``react-is`` and ``tinycolor2`` to https://github.com/mattermost/mattermost-webapp. + - Removed ``@types/highlight.js``, ``@typescript-eslint/parser``, ``bootstrap-colorpicker``, and ``intl`` from https://github.com/mattermost/mattermost-webapp. + - Removed ``react-native-v8`` from https://github.com/mattermost/mattermost-mobile. + +### Database Changes + - Added a new column ``Commands.PluginId``. + - Changed to data type of ``Teams.Type to varchar(255)``. + - Changed to data type of ``Teams.SchemeId to varchar(26)``. + - Changed to data type of ``IncomingWebhooks.Username to varchar(255)``. + - Changes to data type of ``IncomingWebhooks.IconURL to text",``. + +### API Changes + - Added ``POST /upgrade_to_enterprise`` API endpoint. + - Added ``GET /upgrade_to_enterprise/status`` API endpoint. + - Added ``POST /restart`` API endpoint. + - Added ``GET /warn_metrics/status`` API endpoint. + - Added ``POST /warn_metrics/ack/:warn_metric_id`` API endpoint. + +### Known Issues + - Emoji counter in the center channel doesn't always update immediately when a reaction is added in the right-hand side. + - Pressing ENTER closes the Account Settings Edit modal when adjusting the settings for desktop notification sound. + - Admin Filter option is not disabled in AD/LDAP page for admin roles with ``sysconsole_write_authentication`` permission. + - Twitter link previews no longer work in Mattermost as Twitter has removed OpenGraph data from its pages. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console. To fix this, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as Away or Offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [aedott](https://github.com/aedott), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [ali-farooq0](https://github.com/ali-farooq0), [amwolff](https://github.com/amwolff), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [apollo13](https://github.com/apollo13), [archit-p](https://github.com/archit-p), [arshchimni](https://github.com/arshchimni), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [asimsedhain](https://github.com/asimsedhain), [avasconcelos114](https://github.com/avasconcelos114), [Ayanrocks](https://github.com/Ayanrocks), [bbodenmiller](https://github.com/bbodenmiller), [bhargav50](https://github.com/bhargav50), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chikei](https://github.com/chikei), [clarmso](https://github.com/clarmso), [colorfusion](https://github.com/colorfusion), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [devius](https://github.com/devius), [DylanWard14](https://github.com/DylanWard14), [elaine-mattermost](https://github.com/elaine-mattermost), [elyscape](https://github.com/elyscape), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [fakoor](https://github.com/fakoor), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [furqanmlk](https://github.com/furqanmlk), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gracion](https://github.com/gracion), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jakubnovak998](https://github.com/jakubnovak998), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jecepeda](https://github.com/jecepeda), [JeremyShih](https://github.com/JeremyShih), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgilliam17](https://github.com/jgilliam17), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [josephk96](https://github.com/josephk96), [jp0707](https://github.com/jp0707), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kashifsoofi](https://github.com/kashifsoofi), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [kosgrz](https://github.com/kosgrz), [lanjp](https://github.com/lanjp), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [Lumexralph](https://github.com/Lumexralph), [luryus](https://github.com/luryus), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [marianunez](https://github.com/marianunez), [MathewtheCoder](https://github.com/MathewtheCoder), [mathiusjohnson](https://github.com/mathiusjohnson), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mozkomor05](https://github.com/mozkomor05), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nikolaizah](https://github.com/nikolaizah), [ogi-m](https://github.com/ogi-m), [openmohan](https://github.com/openmohan), [prapti](https://github.com/prapti), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [RohitJain13](https://github.com/RohitJain13), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shieldsjared](https://github.com/shieldsjared), [sridhar02](https://github.com/sridhar02), [srkgupta](https://github.com/srkgupta), [StevenPhan](https://github.com/StevenPhan), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [Tak-Iwamoto](https://github.com/Tak-Iwamoto), [tasdomas](https://github.com/tasdomas), [teresa-novoa](https://github.com/teresa-novoa), [thefactremains](https://github.com/thefactremains), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [txeli](https://github.com/txeli), [uhlhosting](https://github.com/uhlhosting), [vladimirdotk](https://github.com/vladimirdotk), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.27 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.27.2, released 2020-12-03** + - Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library. +- **v5.27.1, released 2020-10-19** + - Fixed an issue where the Compliance Exports were taking too long on large deployments. This was fixed with a performance optimization of the message export query. +- **v5.27.0, released 2020-09-16** + - Original 5.27.0 release + +Mattermost v5.27.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Improvements + - Added the ability to upgrade Mattermost from Team Edition to Enterprise Edition directly from the System Console. + - Added various improvements for Admin Advisor feature (Team Edition), including that the bot messages now appear only once for the 500-user advisory and the banner notification interval is reduced from daily to weekly. + - Changed the Default Theme setting in the System Console to a drop-down field. + +### Bug Fixes + - Fixed an issue where the server crashed when a Compliance Export job was run for Global Relay EML. + - Fixed an issue where Compliance Jobs did not restart correctly after a `Warning` status. + - Fixed an issue where users were not matching on mixed-case SAML assertions. + - Fixed an issue where Channel Admin was not able to make the default role as Channel Admin for AD/LDAP Groups. + - Fixed an issue where user role was not added correctly in the Members block in **System Console > Teams**. + - Fixed an issue where a team stopped loading in the System Console **Filter By**-dropdown when a search was performed and then cleared. + - Fixed an issue where the ability to demote Admins to members and to deactivate accounts from **System Console > Users** was not available. + - Fixed an issue where a false message "Group Mentions is already taken" was shown when a System Admin tried to add a channel to an AD/LDAP Group. + - Fixed an issue where a AD/LDAP group mention of an outsider group was highlighted in a Group Synced channel. + - Fixed an issue where incoming webhooks owned by a bot did not consistently allow a username override. + - Fixed an issue where the emoji picker in the Edit Post modal was misaligned. + - Fixed an issue where pasted unicode emojis failed to appear once posted. + - Fixed an issue where long text in message edit modal did not scroll with a scroll bar. + - Fixed an issue with Accessibility where user's name was not displayed in alt text on some images. + - Fixed an issue where dates on **System Console > Site Statistics - Dates** were displayed out of order on days when there were no posts. + - Fixed an issue where the Admin Advisor bot was unexpectedly displayed in the **Integrations > Bot Accounts** page. + - Fixed an issue where a new badge in the channel sidebar category header reappeard after a channel was removed from the category. + - Fixed an issue where the theme color for **Sidebar Text Active Border** was not currently being used in the active border in the sidebar. + - Fixed an issue where users saw an incorrect mention count when added to a channel by another user. + - Fixed an issue where channels created from another browser tab did not immediately appear in the channel sidebar. + - Fixed an issue where a console error showed when creating a new custom category in the channel sidebar. + - Fixed an issue where enabling the new channel sidebar created invalid channel links. + - Fixed an issue where a channel state got broken after an "unallowed" deletion. + - Fixed an issue where dynamic slash command autocomplete options did not update between requests. + - Fixed an issue where an incorrect callback URL with OAuth 2.0 allowed users to click **Back to Mattermost** in the authentication window. + - Fixed an issue where editing "Full Name" got overwritten by Single Sign-On settings. + - Fixed an issue where "You do not have the appropriate permissions" error was shown for ``warn_metrics`` call for non-admin users. + - Fixed an issue where the channel switcher sometimes showed a wrong empty state with network API. + - Fixed an issue where the loader was not hidden when posts were not loading which affected the performance of some Linux distros. + - Fixed an issue where ``PatchConfig`` caused a panic if ``SiteURL`` was not set. + - Fixed an issue where a panic occurred when the server was getting a shutdown before ``InitPlugins()`` was able to complete. + - Fixed an issue where a panic was caused when a user joined a team with default channels archived. + - Fixed an issue where ``App.GetSidebarCategories()`` panicked on nil returned value. + - Fixed an issue where the ``SendEmailNotifications`` setting blocked testing the SMTP connection. + +### Open Source Components + - Removed ``@types/redux-mock-store`` and ``tinycolor2`` from https://github.com/mattermost/mattermost-webapp. + - Added ``bootstrap-colorpicker`` in https://github.com/mattermost/mattermost-webapp. + - Added ``@react-native-community/clipboard`` in https://github.com/mattermost/mattermost-mobile. + +### API Changes + - Added ``POST api/v4/upgrade_to_enterprise`` API endpoint to be able to execute an inplace upgrade from Team Edition to Enterprise Edition. + - Added ``GET api/v4/upgrade_to_enterprise/status`` API endpoint to get the current status for the inplace upgrade from Team Edition to Enterprise Edition. + - Added ``POST api/v4/restart`` API endpoint to restart the system after an upgrade from Team Edition to Enterprise Edition. + +### Known Issues + - A blank screen occurs when user edits a post and submits or cancels the edits while on Preview mode. + - Twitter link previews do not work in Mattermost. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console. To fix this, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as Away or Offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [abdulsmapara](https://github.com/abdulsmapara), [abdusabri](https://github.com/abdusabri), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [aidapira](https://github.com/aidapira), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [ankallio](https://github.com/ankallio), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AugustasV](https://github.com/AugustasV), [avasconcelos114](https://github.com/avasconcelos114), [BaaaZen](https://github.com/BaaaZen), [bbodenmiller](https://github.com/bbodenmiller), [bill2004158](https://github.com/bill2004158), [bradjcoughlin](https://github.com/bradjcoughlin), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chakatz](https://github.com/chakatz), [chikei](https://github.com/chikei), [corey-robinson](https://github.com/corey-robinson), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [danielhelfand](https://github.com/danielhelfand), [DanielSz50](https://github.com/DanielSz50), [dantepippi](https://github.com/dantepippi), [Dartui](https://github.com/Dartui), [dbejanishvili](https://github.com/dbejanishvili), [deanwhillier](https://github.com/deanwhillier), [denniskamp](https://github.com/denniskamp), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [dpanic](https://github.com/dpanic), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [ericjaystevens](https://github.com/ericjaystevens), [esadur](https://github.com/esadur), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [fakela](https://github.com/fakela), [flexo3001](https://github.com/flexo3001), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [Francois-D](https://github.com/Francois-D), [gabrieljackson](https://github.com/gabrieljackson), [ghasrfakhri](https://github.com/ghasrfakhri), [gigawhitlocks](https://github.com/gigawhitlocks), [grubbins](https://github.com/grubbins), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hhhhugi](https://github.com/hhhhugi), [hmhealey](https://github.com/hmhealey), [hryuk](https://github.com/hryuk), [ialorro](https://github.com/ialorro), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jakubnovak998](https://github.com/jakubnovak998), [jasonblais](https://github.com/jasonblais), [javimox](https://github.com/javimox), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [joshuabezaleel](https://github.com/joshuabezaleel), [jseiser](https://github.com/jseiser), [JtheBAB](https://github.com/JtheBAB), [Jukie](https://github.com/Jukie), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kayron8](https://github.com/kayron8), [khos2ow](https://github.com/khos2ow), [kirkjaa](https://github.com/kirkjaa), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [liusy182](https://github.com/liusy182), [Lyimmi](https://github.com/Lyimmi), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [marianunez](https://github.com/marianunez), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mlongo4290](https://github.com/mlongo4290), [moussetc](https://github.com/moussetc), [mustafayildirim](https://github.com/mustafayildirim), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nicolailang](https://github.com/nicolailang), [nikolaizah](https://github.com/nikolaizah), [nperera](https://github.com/nperera), [ofpiyush](https://github.com/ofpiyush), [openmohan](https://github.com/openmohan), [phommasy](https://github.com/phommasy), [prapti](https://github.com/prapti), [qerosi](https://github.com/qerosi), [rahulchheda](https://github.com/rahulchheda), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rmatev](https://github.com/rmatev), [rodcorsi](https://github.com/rodcorsi), [ruzaq](https://github.com/ruzaq), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottjr632](https://github.com/scottjr632), [ShehryarShoukat96](https://github.com/ShehryarShoukat96), [shred86](https://github.com/shred86), [skaramanlis](https://github.com/skaramanlis), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [sridhar02](https://github.com/sridhar02), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [TRUNGTar](https://github.com/TRUNGTar), [uhlhosting](https://github.com/uhlhosting), [utkuufuk](https://github.com/utkuufuk), [Vars-07](https://github.com/Vars-07), [Venhaus](https://github.com/Venhaus), [vijaynag-bs](https://github.com/vijaynag-bs), [webchick](https://github.com/webchick), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [Yohannesseifu](https://github.com/Yohannesseifu), [YushiOMOTE](https://github.com/YushiOMOTE) + +---- + +## Release v5.26 - [Feature Release](https://docs.mattermost.com/administration/release-definitions.html#feature-release) + +- **v5.26.2, released 2020-09-03** + - Forcefully disabled the SAML Setting "Use Improved SAML Library (Beta)", as we have identified some issues in this feature. Please follow instructions at https://docs.mattermost.com/deployment/sso-saml-before-you-begin.html for enabling SAML using the feature-equivalent ``xmlsec1`` utility. +- **v5.26.1, released 2020-08-25** + - Fixed an issue where users were unable to use the [``PictureAttribute`` setting](https://docs.mattermost.com/administration/config-settings.html#profile-picture-attribute) with SAML authentication. [MM-27852](https://mattermost.atlassian.net/browse/MM-27852) + - Fixed an issue where users got unexpectedly logged out from the mobile app when ``ExtendSessionLengthWithActivity`` was enabled as opening the mobile app called an API that overrode session extension triggers of typing, channel change, and posts. [MM-27184](https://mattermost.atlassian.net/browse/MM-27184) + - Fixed an issue where users experienced a kernel panic during LDAP sync when AuthData value was null. [MM-27965](https://mattermost.atlassian.net/browse/MM-27965) +- **v5.26.0, released 2020-08-16** + - Original 5.26.0 release + +### Compatibility + - PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). Mattermost is officially supporting PostgreSQL version 10 with v5.26 release as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL 10+. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL 9.4. In our 6.0 release (date to be announced), we plan on fully deprecating PostgreSQL 9.4. Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). + +### Breaking Changes + - In v5.26, Elasticsearch indexes needed to be recreated. Admins should re-index Elasticsearch using the **Purge index** and then **Index now** button so that all the changes will be included in the index. Systems may be left with a limited search during the indexing, so it should be done during a time when there is little to no activity because it may take several hours. + - An ``EnableExperimentalGossipEncryption`` option was added under ``ClusterSettings``. If this is set to ``true``, and ``UseExperimentalGossip`` is also ``true``, all communication through the cluster using the gossip protocol will be encrypted. The encryption uses ``AES-256`` by default, and it is not kept configurable by design. However, if one wishes, they can set the value in Systems table manually for the ``ClusterEncryptionKey`` row. A key is a byte array converted to base64. It should be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. To update the key, one can execute ``UPDATE Systems SET Value='<value>' WHERE Name='ClusterEncryptionKey';`` in MySQL and ``UPDATE systems SET value='<value>' WHERE name='ClusterEncryptionKey'`` for PostgreSQL. For any change in this config setting to take effect, the whole cluster must be shutdown first. Then the config change made, and then restarted. In a cluster, all servers either will completely use encryption or not. There cannot be any partial usage. + +```{Important} +If you upgrade from a release earlier than 5.25, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Archive & unarchive channels from the System Console (E20 Edition) + - Channels can now be archived and unarchived with ease from the System Console. + +#### Manage members and channels in System Console using search filters (E20 Edition) + - Managing members & channels is now lot easier with new search filters. + +#### Customize log configuration and output targets (E20 Edition) + - Customize log level records beyond the standard levels of trace, debug, info, and panic, as well as configure different destinations based on discrete log levels. + +#### Get help from the Mattermost community via ‘Ask the community’ link + - You can access the community from a new “Help” menu in the channel header, after which you will create an account on our public [Mattermost Community server](https://community.mattermost.com/) to join a vibrant user community to ask questions and help your peers to troubleshoot issues. + +#### Categorize and reorder channels with channel sidebar enhancements (Experimental) + - Users now have the ability to create custom categories in the sidebar to group channels together for easier navigation, drag channels between or within categories to prioritize conversations most important to you, and much more. + +### Improvements + +#### User Interface (UI) + - Improved the styling of a deactivated user's Direct Message channel footer. + - All emoji aliases are now shown on the emoji picker. + - Added support for allowing copying and pasting of emoji shortcodes. + - Added Online, Away, Do Not Disturb, and Offline icons to the status menu for quicker recognition. + - Increased visibility of user and channel autocomplete suggestions when editing a long post. + - Added a flag icon to the post hover menu and updated pinned and flagged post styling in the channel. + - Added support for PostgreSQL & PL/pgSQL syntax highlighting. + - Expanded the width of server logs page in System Console UI to full screen width. + +#### Localization + - Promoted Russian and Dutch languages to “official”. + +#### Command Line Interface (CLI) + - Added new mmctl CLI commands, such as ``ldap idmigrate``, ``user convert``, ``channel move``, and ``user deleteall``. + +#### Search + - Added ability for Elasticsearch to search terms inside links. + - Searching for a user with a leading "@" in the search term with Elasticsearch now returns results for those users. + - Added ability to include filtering search/autocompletion by roles. + - Added ability to search/autocomplete deactivated users from Elasticsearch. + - Added missing methods such as ``PermanenteDeleteByUser`` and ``PermanenteDeleteByChannel`` that update and/or delete entities in the searchlayer. + - Implemented prefix/suffix search on Teams and Channel pages in System Console. + +#### Integrations + - Added slash command autocomplete functionality to enable commands to be executed on selection (mouse click, tab or enter). + - Added plugin API endpoint to run a slash command. + - Implemented ``http.Hijacker`` for plugins' ``ServeHTTP`` to make it possible to upgrade the ``ServeHTTP`` hook to expose a websocket connection. + +#### Command Line Interface (CLI) + - Added the ability to remove non-members of the target team if ``channel move`` fails. + +#### Administration + - Added support for a System Admin warning system that displays warnings in the announcement bar and sends Direct Messages to admins if one or more metric fulfills a certain condition. + - **System Console > Plugins** section now lists all the installed plugins regardless of the number of configurable settings associated with each plugin. + - Servers now send a push notification to mobile clients when a user's session expires. + - Clearing the Site URL in the System Console is no longer allowed. + - Changed the patch post API endpoint authorization logic to allow the ``edit_others_posts`` permission to function independently from ``edit_own_posts``. + - Included a response code in the "Received HTTP Request" log line. + - Added support for a new environment variable ``MM_LICENSE`` which can contain the contents of a license file. When set, this license takes priority over all other license sources. + - Added support for encryption for gossip protocol. + - Move gossip protocol to use only gossip. + +### Bug Fixes + - Fixed an issue where an empty outgoing webhook response generated a spurious ERROR. + - Fixed an issue where quick switch user search was always falling back to the database. + - Fixed an issue where a user's status was displayed as online while the database status was displayed as offline. + - Fixed an issue where Elasticsearch indexing job did not index users and/or channels older than the first post. + - Fixed an issue where Global Relay SMTP connection timeout was not independent of the regular SMTP email settings timeout. + - Fixed an issue with a poor performance when opening More Direct Messages modal. + - Fixed an issue where bot username validation message was unclear as it did not mention which value was invalid. + - Fixed an issue where Command+K input field lost focus when the window lost focus, causing search results to disappear. + - Fixed an issue where a highlight was missing when users at-mentioned themselves, followed by period, underscore, or hyphen. + - Fixed an issue where a 500 error was returned by the ``/posts/unread`` endpoint caused by an [integer overflow](https://en.wikipedia.org/wiki/Integer_overflow) when ``limit_after`` was set to 0. + - Fixed an issue where the footer text in invitation emails was not translated. + - Fixed an issue where ``PermanentDeleteTeam`` did not return an error but did a soft deletion if ``EnableAPITeamDeletion`` was not set. + - Fixed an issue on PostgreSQL where logging in using MFA did not respect the uppercase of the email address. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``ExperimentalDataPrefetch``, to enable messages in all unread channels to be pre-loaded from the server whenever the client reconnects to the network to eliminate loading time when users switch to unread channels. + - Under ``ClusterSettings`` in ``config.json``: + - Added ``EnableExperimentalGossipEncryption``, to enable all communication through the cluster using the gossip protocol to be encrypted. + - Under ``LogSettings`` in ``config.json``: + - Added ``EnableSentry``, to enable sentry reporting. + - Added ``AdvancedLoggingConfig``, to enable optional logging capability to allow sending log records to a number of destinations. + - Under ``FileSettings`` in ``config.json``: + - Added ``AmazonS3PathPrefix``, to allow using the same S3 bucket for multiple deployments. + - Under ``EmailSettings`` in ``config.json``: + - Added ``PushNotificationBuffer``, to remove hardcoded goroutine workers from push notifications to improve notifications arriving in order. + - Under ``SupportSettings`` in ``config.json``: + - Added ``EnableAskCommunityLink``, to enable showing a link in the Mattermost channel header under the **Help** menu. When clicked, users are redirected to https://mattermost.com/community/, where they can join the Mattermost Community to ask questions and help others troubleshoot issues. This option is not available on the mobile apps. + - Under ``GlobalRelayMessageExportSettings`` in ``config.json``: + - Added ``SMTPServerTimeout``, to ensure Global Relay SMTP connection timeout is independent of regular email settings timeout. + +### Open Source Components + - Added ``react-native-cookies`` and ``react-native-keyboard-aware-scroll-view``, and removed ``@react-native-community/cookies`` in https://github.com/mattermost/mattermost-mobile. + - Added ``dynamic-virtualized-list`` and ``prettier`` in https://github.com/mattermost/mattermost-webapp. + - Added ``rudder-sdk-js`` in https://github.com/mattermost/mattermost-redux. + +### Database Changes + - Added a new column ``Sessions.ExpiredNotify``. + +### API Changes + - Added ``POST api/v4/bots/:bot_id/convert_to_user`` API endpoint to add the ability to convert a bot into a user. + - Added ``POST api/v4/users/:user_id/convert_to_bot`` API endpoint to add the ability to convert a user into a bot. + - Added ``GET api/v4/users/:user_id/teams/:team_id/channels/categories`` API endpoint to get a list of sidebar categories that will appear in the user's sidebar on the given team, including a list of channel IDs in each category. + - Added ``POST api/v4/users/:user_id/teams/:team_id/channels/categories`` API endpoint to create a custom sidebar category for the user on the given team. + - Added ``PUT api/v4/users/:user_id/teams/:team_id/channels/categories`` API endpoint to update any number of sidebar categories for the user on the given team. + - Added ``GET api/v4/users/:user_id/teams/:team_id/channels/categories/order`` API endpoint to get the order of the sidebar categories for a user on the given team as an array of IDs. + - Added ``PUT api/v4/users/:user_id/teams/:team_id/channels/categories/order`` API endpoint to update the order of the sidebar categories for a user on the given team. + - Added ``GET api/v4/users/:user_id/teams/:team_id/channels/categories/:category_id`` API endpoint to get a single sidebar category for the user on the given team. + - Added ``PUT api/v4/users/:user_id/teams/:team_id/channels/categories/:category_id`` API endpoint to update a single sidebar category for the user on the given team. + - Added ``DELETE api/v4/users/:user_id/teams/:team_id/channels/categories/:category_id`` API endpoint to delete a single custom sidebar category for the user on the given team. + - Added ``POST api/v4/ldap/migrateid`` API endpoint to migrate LDAP IdAttribute to a new value. + - Added ``GET api/v4/warn_metrics/status`` API endpoint to get the status of a set of metrics (enabled or disabled) from the Systems table. + - Added ``POST api/v4/warn_metrics/ack/:warn_metric_id`` API endpoint to acknowldge a warning for the ``warn_metric_id`` metric crossing a threshold (or some similar condition being fulfilled). + - Added ``GET api/v4/groups/:group_id/stats`` API endpoint to retrieve the stats of a given group. + - Added ``GET api/v4/teams/:team_id/channels/private`` API endpoint to get a list of private channels on a team based on query string parameters. + - Added ``GET api/v4/users/stats/filtered`` API endpoint to get a count of users in the system matching the specified filters. + - Added ``POST api/v4/users/:user_id/email/verify/member`` API endpoint to verify the email used by a user without a token. + - Added ``POST api/v4/users/:user_id/typing`` API endpoint to notify users in the given channel via websocket that the given user is typing. + - Added Get/Update/Delete user preferences to Plugin API. + - Added channel ID check for Plugin API ``UploadFile`` to specify the ID of the channel a file will be uploaded to. + +### Websocket Event Changes + - Added ``sidebar_category_created`` Websocket Event. + - Added ``sidebar_category_updated`` Websocket Event. + - Added ``sidebar_category_deleted`` Websocket Event. + - Added ``sidebar_category_order_updated`` Websocket Event. + - Added ``warn_metric_status_received`` Websocket Event. + - Added ``warn_metric_status_removed`` Websocket Event. + +### Known Issues + - Twitter link previews do not work in Mattermost. + - Pasted unicode emojis fail to appear once posted. + - ``CMD+SHIFT+V`` does not paste copied text on MacOS on Safari 12 (Catalina) and Firefox. + - Enabling Bleve search engine makes the Command Line Interface (CLI) mutually exclusive with the running server. This issue does not apply when using [mmctl Command Line Tool](https://docs.mattermost.com/administration/mmctl-cli-tool.html). + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [abdulsmapara](https://github.com/abdulsmapara), [abdusabri](https://github.com/abdusabri), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [aidapira](https://github.com/aidapira), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [ankallio](https://github.com/ankallio), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [AugustasV](https://github.com/AugustasV), [avasconcelos114](https://github.com/avasconcelos114), [BaaaZen](https://github.com/BaaaZen), [bbodenmiller](https://github.com/bbodenmiller), [bill2004158](https://github.com/bill2004158), [bradjcoughlin](https://github.com/bradjcoughlin), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chakatz](https://github.com/chakatz), [chikei](https://github.com/chikei), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [danielhelfand](https://github.com/danielhelfand), [DanielSz50](https://github.com/DanielSz50), [dantepippi](https://github.com/dantepippi), [Dartui](https://github.com/Dartui), [dbejanishvili](https://github.com/dbejanishvili), [deanwhillier](https://github.com/deanwhillier), [denniskamp](https://github.com/denniskamp), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [djanda97](https://github.com/djanda97), [dpanic](https://github.com/dpanic), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [ericjaystevens](https://github.com/ericjaystevens), [esadur](https://github.com/esadur), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [fakela](https://github.com/fakela), [flexo3001](https://github.com/flexo3001), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [Francois-D](https://github.com/Francois-D), [gabrieljackson](https://github.com/gabrieljackson), [ghasrfakhri](https://github.com/ghasrfakhri), [gigawhitlocks](https://github.com/gigawhitlocks), [grubbins](https://github.com/grubbins), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hhhhugi](https://github.com/hhhhugi), [hmhealey](https://github.com/hmhealey), [hryuk](https://github.com/hryuk), [ialorro](https://github.com/ialorro), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jakubnovak998](https://github.com/jakubnovak998), [jasonblais](https://github.com/jasonblais), [javimox](https://github.com/javimox), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnsonbrothers](https://github.com/johnsonbrothers), [josephbaylon](https://github.com/josephbaylon), [joshuabezaleel](https://github.com/joshuabezaleel), [jseiser](https://github.com/jseiser), [JtheBAB](https://github.com/JtheBAB), [Jukie](https://github.com/Jukie), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kayron8](https://github.com/kayron8), [khos2ow](https://github.com/khos2ow), [kirkjaa](https://github.com/kirkjaa), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [liusy182](https://github.com/liusy182), [Lyimmi](https://github.com/Lyimmi), [lynn915](https://github.com/lynn915), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mlongo4290](https://github.com/mlongo4290), [mustafayildirim](https://github.com/mustafayildirim), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nicolailang](https://github.com/nicolailang), [nikolaizah](https://github.com/nikolaizah), [ofpiyush](https://github.com/ofpiyush), [openmohan](https://github.com/openmohan), [phommasy](https://github.com/phommasy), [prapti](https://github.com/prapti), [qerosi](https://github.com/qerosi), [rahulchheda](https://github.com/rahulchheda), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rmatev](https://github.com/rmatev), [rodcorsi](https://github.com/rodcorsi), [ruzaq](https://github.com/ruzaq), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottjr632](https://github.com/scottjr632), [ShehryarShoukat96](https://github.com/ShehryarShoukat96), [shred86](https://github.com/shred86), [skaramanlis](https://github.com/skaramanlis), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [sridhar02](https://github.com/sridhar02), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [Szymongib](https://github.com/Szymongib), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [TRUNGTar](https://github.com/TRUNGTar), [uhlhosting](https://github.com/uhlhosting), [utkuufuk](https://github.com/utkuufuk), [Vars-07](https://github.com/Vars-07), [Venhaus](https://github.com/Venhaus), [vijaynag-bs](https://github.com/vijaynag-bs), [webchick](https://github.com/webchick), [weblate](https://github.com/weblate), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [Yohannesseifu](https://github.com/Yohannesseifu), [YushiOMOTE](https://github.com/YushiOMOTE) + +---- + +## Release v5.25 - [Extended Support Release](https://docs.mattermost.com/administration/release-definitions.html#extended-support-release-esr) + +- **v5.25.7, released 2020-12-03** + - Disabled the xmlsec1-based SAML library in favor of the re-enabled and improved SAML library. +- **v5.25.6, released 2020-11-10** + - Fixed an issue where the Compliance Exports were taking too long on large deployments. This was fixed with a performance optimization of the message export query. + - Bumped up Go patch version to 1.14.6 to fix an issue where a potential livelock was detected in the app server under heavy load. [MM-26584](https://mattermost.atlassian.net/browse/MM-26584) +- **v5.25.5, released 2020-09-03** + - Forcefully disabled the SAML Setting "Use Improved SAML Library (Beta)", as we have identified some issues in this feature. Please follow instructions at https://docs.mattermost.com/deployment/sso-saml-before-you-begin.html for enabling SAML using the feature-equivalent ``xmlsec1`` utility. +- **v5.25.4, released 2020-08-25** + - Fixed an issue where users were unable to use the [``PictureAttribute`` setting](https://docs.mattermost.com/administration/config-settings.html#profile-picture-attribute) with SAML authentication. [MM-27852](https://mattermost.atlassian.net/browse/MM-27852) + - Fixed an issue where users got unexpectedly logged out from the mobile app when ``ExtendSessionLengthWithActivity`` was enabled as opening the mobile app called an API that overrode session extension triggers of typing, channel change, and posts. [MM-27184](https://mattermost.atlassian.net/browse/MM-27184) + - Fixed an issue where users experienced a kernel panic during LDAP sync when AuthData value was null. [MM-27965](https://mattermost.atlassian.net/browse/MM-27965) + - Fixed an issue where users experienced the Mattermost server crashing on ``(Status).ToClusterJson`` calls. [MM-24544](https://mattermost.atlassian.net/browse/MM-24544) +- **v5.25.3, released 2020-08-12** + - Fixed an issue where the permission to create user access tokens on environments with OpenID Connect login providers such as GitLab was denied for System Admins. [MM-27623](https://mattermost.atlassian.net/browse/MM-27623) + - Fixed an issue where deactivated users were included in compliance exports. [MM-27194](https://mattermost.atlassian.net/browse/MM-27194) + - Fixed an issue where guest user invites did not work in a SAML environment. [MM-27519](https://mattermost.atlassian.net/browse/MM-27519) + - Fixed an issue where the bulk export didn't finish if a custom data directory was set. [MM-27550](https://mattermost.atlassian.net/browse/MM-27550) + - Fixed an issue with a performance degradation after upgrading to 5.25.0. [MM-27575](https://mattermost.atlassian.net/browse/MM-27575) + - Fixed an issue where attempting to pin a post failed if a user did not have the ``channel_mention`` permission on a channel. [MM-26346](https://mattermost.atlassian.net/browse/MM-26346) +- **v5.25.2, released 2020-07-31** + - Fixed an issue where pages in the System Console didn't scroll up or down in some browser versions. [MM-27168](https://mattermost.atlassian.net/browse/MM-27168) +- **v5.25.1, released 2020-07-23** + - Smoothed the database query load while syncing teams and channel roles by fetching data in batches. [MM-27114](https://mattermost.atlassian.net/browse/MM-27114) + - Fixed a bug in pagination which queried more data redundantly. [MM-27187](https://mattermost.atlassian.net/browse/MM-27187) + - Throttled network traffic by implementing bounded concurrency. +- **v5.25.0, released 2020-07-16** + - Original 5.25.0 release + +Mattermost v5.25.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Breaking Changes + - Some incorrect instructions regarding SAML setup with Active Directory ADFS for setting the “Relying party trust identifier” were corrected. Although the settings will continue to work, it is encouraged to [modify those settings](https://docs.mattermost.com/deployment/sso-saml-adfs-msws2016.html#add-a-relying-party-trust). + +```{Important} +If you upgrade from a release earlier than 5.24, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Improvements + - Added the ability for admins to request a 30-day E20 trial license directly in the System Console. + - [AD/LDAP Group Sync (E20)](https://docs.mattermost.com/deployment/ldap-group-sync.html) feature was moved out of Beta to General Availability. + +### Bug Fixes + - Fixed an issue where the ability to run a command to export data was erroneously available in Team Edition. + - Fixed an issue where a user lost access to the current channel and other channels in a team when Team Override Scheme was deleted. + - Fixed an issue where ADFS for SAML and AD/LDAP using ObjectGUID did not sync correctly. + - Fixed an issue where LDAP Sync job failed when one of the teams had email restrictions. + - Fixed an issue where an incorrect session length for SSO login was initiated from the mobile app. + - Fixed an issue on web mobile narrow view where clicking a hashtag in a channel header did not open the hashtag search. + - Fixed an issue where license ID was not populated correctly in the license renewal banner. + - Fixed an issue where an archived team could be fully accessed with the archived team's URL. + - Fixed an issue where leaving an archived channel did not return user to the last viewed channel. + - Fixed an issue where bulk import rejected team names prefixed with reserved keywords, even with additional text appended. + - Fixed an issue where System Admin could no longer manage custom emoji after running ``bin/mattermost permissions reset``. + - Fixed an issue where a user's role in Team Members dialog did not update when a user was searching for the user. + - Fixed an issue where Bleve was not correctly setting the query size, missing search results. + - Fixed an issue where the timezone count was not displayed correctly when a user set a new timezone and then changed it to set automatically. + - Fixed an issue where existing users were not shown in the Invite Members flow. + - Fixed an issue where the **System Console > User Management > Users** page was too tall and the **Revoke All Sessions** button was cut off when a license banner was present. + - Fixed an issue where the **Email verified** banner was red instead of green. + - Fixed an issue where **Copy Theme Colors** button in **Account Settings > Display > Theme** was not themed correctly. + - Fixed an issue where archived channel icons were too dark in the Channel Info modal with the Dark Theme. + - Fixed an issue where the **Save** button was not visible in browser for Safari on iPad device. + - Fixed an issue where the thumbnail of a user was not displayed correctly when searching for a Direct Message channel. + - Fixed an issue where text flowed outside the "Invite Members" button in "Invite People" page for some languages. + - Fixed an issue where the **Next** button in **Main Menu > Manage Members** was not visible to be able to see the last few members of the team. + - Fixed an issue where a different behavior was seen when pasting a table into message compose and to message edit box. + - Fixed an issue where one-byte unicode emoji did not support skin tones. + - Fixed an issue where no error was reported in server logs if a plugin icon was invalid. + - Fixed an issue where providing AutocompleteData did not log a proper error in the System Console. + - Fixed an issue where signup password minimum length error messages were inconsistent. + - Fixed an issue where the right-hand side overlapped the GitHub Plugin tooltip. + - Fixed an issue where the plugin right-hand side did not show tooltips when a user hovered over the Close or Expand/Shrink icons. + - Fixed an issue where query string parameters were omitted from interactive dialog request urls. + - Fixed an issue where ``store.GetPostsSince()`` did not sanitise deleted posts. + - Fixed an issue with a panic caused by nil pointer dereference in ``importTeam``. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``SamlSettings`` in ``config.json``: + - Added ``ServiceProviderIdentifier``, as the unique identifier for the Service Provider, usually the same as Service Provider Login Url. In ADFS, this must match the Relying Party Identifier. + +### Known Issues + - Twitter link previews do not work in Mattermost. + - Highlight is missing when at-mentioning yourself, followed by period, underscore, or hyphen. + - Ctrl+Enter doesn't post an edited message with "Send messages on Ctrl+Enter" enabled for all messages. + - Enabling Bleve search engine makes the Command Line Interface (CLI) mutually exclusive with the running server. This issue does not apply when using [mmctl Command Line Tool](https://docs.mattermost.com/administration/mmctl-cli-tool.html). + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://github.com/aeomin), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [Ashniu123](https://github.com/Ashniu123), [attilamolnar](https://github.com/attilamolnar), [avasconcelos114](https://github.com/avasconcelos114), [bbodenmiller](https://github.com/bbodenmiller), [bradjcoughlin](https://github.com/bradjcoughlin), [brunoro](https://github.com/brunoro), [CEOehis](https://github.com/CEOehis), [checkaayush](https://github.com/checkaayush), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [clarmso](https://github.com/clarmso), [corey-robinson](https://github.com/corey-robinson), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [craigwillis-mm](https://github.com/craigwillis-mm), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [danger89](https://github.com/danger89), [DanielSz50](https://github.com/DanielSz50), [dantepippi](https://github.com/dantepippi), [davebarkerxyz](https://github.com/davebarkerxyz), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [dpanic](https://github.com/dpanic), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [ericjaystevens](https://github.com/ericjaystevens), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [Extazx2](https://github.com/Extazx2), [faase](https://github.com/faase), [fakela](https://github.com/fakela), [farah](https://github.com/farah), [fedealconada](https://github.com/fedealconada), [FlaviaBastos](https://github.com/FlaviaBastos), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [GrigalashviliT](https://github.com/GrigalashviliT), [GrSto](https://github.com/GrSto), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gsagula](https://github.com/gsagula), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorgabucio](https://github.com/hectorgabucio), [hectorskypl](https://github.com/hectorskypl), [HilaryClarke](https://github.com/HilaryClarke), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnthompson365](https://github.com/johnthompson365), [josephbaylon](https://github.com/josephbaylon), [jseiser](https://github.com/jseiser), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kadir96](https://github.com/kadir96), [kayazeren](https://github.com/kayazeren), [khos2ow](https://github.com/khos2ow), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [liusy182](https://github.com/liusy182), [lynn915](https://github.com/lynn915), [marianunez](https://github.com/marianunez), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mitchellroe](https://github.com/mitchellroe), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nickmisasi](https://github.com/nickmisasi), [nperera](https://github.com/nperera), [octoquad](https://github.com/octoquad), [prapti](https://github.com/prapti), [promehul](https://github.com/promehul), [Qovaros](https://github.com/Qovaros), [rahimrahman](https://github.com/rahimrahman), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [TheDarkestDay](https://github.com/TheDarkestDay), [thefactremains](https://github.com/thefactremains), [thePanz](https://github.com/thePanz), [uhlhosting](https://github.com/uhlhosting), [waqasraz](https://github.com/waqasraz), [weblate](https://github.com/weblate), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [will7200](https://github.com/will7200), [Willyfrog](https://github.com/Willyfrog), [ztrayner](https://github.com/ztrayner) + +---- + +## Release v5.24 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.24.3, released 2020-07-23** + - Smoothed the database query load while syncing teams and channel roles by fetching data in batches. [MM-27114](https://mattermost.atlassian.net/browse/MM-27114) + - Fixed a bug in pagination which queried more data redundantly. [MM-27187](https://mattermost.atlassian.net/browse/MM-27187) + - Throttled network traffic by implementing bounded concurrency. +- **v5.24.2, released 2020-06-26** + - Fixed an issue where changing primary keys during migration did not work with Postgres versions lower than 9.3. [MM-26514](https://mattermost.atlassian.net/browse/MM-26514) +- **v5.24.1, released 2020-06-19** + - Fixed an issue with a semantic versioning violation of the plugin API that broke plugins using the ``GetGroupByName`` method. [MM-26231](https://mattermost.atlassian.net/browse/MM-26231) + - Fixed an issue with the Plugin Tooltip implementation that caused links to be truncated when rendered. This issue occured if you are using the recent GitHub plugin v1.0.0 release. All links were affected, regardless if they were related to GitHub. [MM-25808](https://mattermost.atlassian.net/browse/MM-25808) +- **v5.24.0, released 2020-06-16** + - Original 5.24.0 release + +Mattermost v5.24.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Breaking Changes + - A new configuration setting, ``ExtendSessionLengthWithActivity`` automatically extends sessions to keep users logged in if they are active in their Mattermost apps. It is recommended to enable this setting to improve user experience if compliant with your organizations policies. [Learn more here](https://mattermost.com/blog/session-expiry-experience). + - The ``mattermost_http_request_duration_seconds`` histogram metric (in Enterprise Edition) has been removed. This information was already captured by ``mattermost_api_time``, which also contains the api handler name, HTTP method, and the response code. As an example, if you are using ``rate(mattermost_http_request_duration_seconds_sum{server=~"$var"}[5m]) / rate(mattermost_http_request_duration_seconds_count{server=~"$var"}[5m])`` to measure average call duration, it needs to be replaced with ``sum(rate(mattermost_api_time_sum{server=~"$var"}[5m])) by (instance) / sum(rate(mattermost_api_time_count{server=~"$var"}[5m])) by (instance)``. + - Due to fixing performance issues related to emoji reactions, the performance of the upgrade has been affected in that the schema upgrade now takes more time in environments with lots of reactions in their database. These environments are recommended to perform the schema migration during low usage times and potentially in advance of the upgrade. Since this migration happens before the Mattermost Server is fully launched, non-High Availability installs will be unreachable during this time. Please see the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for full details. + - On mobile apps, users will not be able to see LDAP group mentions (E20 feature) in the autocomplete dropdown. Users will still receive notifications if they are part of an LDAP group. However, the group mention keyword will not be highlighted. + +```{Important} +If you upgrade from a release earlier than 5.23, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Notify AD/LDAP Groups with a single @mention (Beta) (E20) + - Ability to enable mentions for LDAP-synced groups so users can notify the entire group at the same time. + +#### Manage users from the System Console (E20) + - Ability to view and manage members via each team or channel configuration page. + +#### Sync profile images from AD/LDAP (E10, E20) + - Ability to ensure compliance with corporate policies by automatically syncing profile images from AD/LDAP. + +#### Automatically extending user sessions + - Ability to enable a feature that automatically extends session lengths when users are active on Mattermost apps. + +#### Access CLI remotely + - Ability to manage Mattermost without having direct access to the server with a new Local Mode for mmctl. + +#### Improved search filters + - Ability to use the mouse or keyboard to select search filters instead of typing them manually. + +#### Slash command autocomplete framework (Beta) + - Ability to make slash commands easier to use and increase discoverability with a new slash command autocomplete framework for plugins. + +#### Full-text search and indexing (Experimental) + - Ability to use Bleve to execute search functionality instead of the database. + +### Improvements + +#### Enterprise Edition (EE) + - Grace period after Enterprise Edition subscription expires was reduced from 15 days to 10 days. Moreover, Enterprise features are now disabled immediately after the grace period is over, instead of only after a server restart. Please see https://mattermost.com/pricing/#faq for more details. + +#### User Interface (UI) + - Added a count for pinned posts header icon. + - Added the ability to view user profile pop-over when clicking the profile picture or username from the **View Members** and **Manage Members** modals. + - Improved keyboard usability in the emoji picker search bar. + - Improved profile popover for posts with overwritten username or icon. + - Added support for code highlighting of TypeScript files. + +#### Notifications + - Mention notification settings for "Case sensitive first name" and "Non-case sensitive username" are now disabled by default. + +#### Search + - Added support for searching by position in user lists such as the **Add Members** menu. + +#### Integrations + - Added support for different interactive message button styles. + +#### Administration + - Added the ability to bulk create, update, and delete team members and channel members in the store, as well as bulk import users belonging to different teams and channels. + - Added auditing support to all Comman Line Interface (CLI) API’s. + - Replaced "Back to Mattermost" button with a helpful error message in the OAuth 2.0 authentication window when an incorrect Client ID is typed during authentication. + - Centralized ID validation to a single function. + +### Bug Fixes + - Fixed an issue where database read and search replicas were available in Team Edition, leading to unsupported server configuration. + - Fixed an issue where Session Idle Timeout setting also unexpectedly affected the mobile app session expiry. + - Fixed an issue where an unread channel disappeared from a list of unread channels immediately. + - Fixed an issue where a user's role was not reflected correctly in the **Team Members** modal when the user's role was updated after the modal was opened. + - Fixed an issue where the autocomplete list of channels remained populated after a user cleared the search on **Add user to a channel** modal. + - Fixed an issue where Integrations menu was available for member and team admin roles only if with oAuth2 permission. + - Fixed an issue where empty strings for ``auth_data`` created invalid users for LDAP sync during bulk import. + - Fixed an issue where bulk import did not report errors when importing posts failed. + - Fixed an issue where Compliance Export reported "success" when failing to export a missing file. + - Fixed an issue where the user interface got stuck when leaving an archived channel. + - Fixed an issue where Unicode characters appeared in users' display names. + - Fixed an issue where a failed plugin installation from the plugin marketplace retried automatically. + - Fixed an issue where markdown images hosted by plugins did not appear if local image proxy was enabled. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``ExtendSessionLengthWithActivity`` to enable sessions to be automatically extended when the user is active in their Mattermost client. + - Added ``EnableLocalMode`` to enable local mode for mmctl. + - Added ``LocalModeSocketLocation`` to set the path for the socket that the server will create for mmctl to connect and communicate through local mode. + - Changed ``EnableLinkPreviews`` to default true for new installs. + - Changed ``SessionLengthWebInDays`` to default to 30 days for new installs. + - Under ``SqlSettings`` in ``config.json``: + - Added ``DisableDatabaseSearch`` to disable the use of the database to perform searches. + - Under ``LdapSettings`` in ``config.json``: + - Added ``PictureAttribute`` to configure the attribute in the AD/LDAP server used to synchronize (and lock) the profile picture used in Mattermost. + - Under ``BleveSettings`` in ``config.json``: + - Added ``IndexDir`` to set the directory path to use for storing bleve indexes. + - Added ``EnableIndexing`` to enable the indexing of new posts to occur automatically. + - Added ``EnableSearching`` to enable search queries to use bleve search. + - Added ``EnableAutocomplete`` to enable autocomplete queries to use bleve search. + - Added ``BulkIndexingTimeWindowSeconds`` to determine the maximum time window for a batch of posts being indexed by the Bulk Indexer. + - Under ``EmailSettings`` in ``config.json``: + - Changed ``PushNotificationContents`` to default ``full`` for new installs. + +### Open Source Components + - Added ``@types/react-custom-scrollbars`` in https://github.com/mattermost/mattermost-webapp + - Added ``p-queue`` in https://github.com/mattermost/mattermost-webapp + - Added ``@react-native-community/cookies`` in https://github.com/mattermost/mattermost-mobile + - Added ``@react-native-community/masked-view`` in https://github.com/mattermost/mattermost-mobile + - Added ``analytics-react-native`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-elements`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-file-viewer`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-localize`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-reanimated`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-safe-area-context`` in https://github.com/mattermost/mattermost-mobile + - Added ``react-native-screens`` in https://github.com/mattermost/mattermost-mobile + +### Database Changes + - Added a new column ``UserGroups.AllowReference``. + - Changed the primary key on the Reactions table. + +### API Changes + - Added a new route ``POST /api/v4/group/bleve/purge_indexes`` to delete all Bleve indexes and their contents. + - Added a new route ``GET /api/v4/channels/:channel_id/member_counts_by_group`` to get the channel members counts for each AD/LDAP group that has at least one member in the channel. + - Added a new route ``GET /api/v4/teams/:team_id/commands/autocomplete_suggestions`` to get a list of autocomplete suggestions. + - Added a new route ``GET api/v4/users/:user_id/groups`` to get all AD/LDAP groups for a user. + - Added a new route ``GET api/v4/teams/:team_id/groups_by_channels`` to get a set of AD/LDAP groups associated with the channels in the given team grouped by channel. + - Added several new APIs for use by mmctl local mode, such as the ability to modify and restore teams with mmctl. + +### Websocket Event Changes + - Added a new ``received_group`` Websocket Event. + - Added a new ``received_group_associated_to_team`` Websocket Event. + - Added a new ``received_group_not_associated_to_team`` Websocket Event. + - Added a new ``received_group_associated_to_channel`` Websocket Event. + - Added a new ``received_group_not_associated_to_channel`` Websocket Event. + +### Known Issues + - Profile image of a user is not displayed correctly when searching for Direct Message channels. + - "Email verified" banner is red instead of green. + - Command+K search results disappear when the input field loses focus when Mattermost window is made unfocused. + - Enabling Bleve search engine makes the Command Line Interface (CLI) mutually exclusive with the running server. This issue does not apply when using [mmctl Command Line Tool](https://docs.mattermost.com/administration/mmctl-cli-tool.html). + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [aaronrothschild](https://github.com/aaronrothschild), [abdulsmapara](https://github.com/abdulsmapara), [adamjclarkson](https://github.com/adamjclarkson), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://translate.mattermost.com/user/aeomin/), [agarciamontoro](https://github.com/agarciamontoro), [agnivade](https://github.com/agnivade), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [avasconcelos114](https://github.com/avasconcelos114), [avddvd](https://github.com/avddvd), [awerries](https://github.com/awerries), [bbodenmiller](https://github.com/bbodenmiller), [bbuehrle](https://github.com/bbuehrle), [bradjcoughlin](https://github.com/bradjcoughlin), [cadavre](https://github.com/cadavre), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [CEOehis](https://github.com/CEOehis), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [corey-robinson](https://github.com/corey-robinson), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [craigwillis-mm](https://github.com/craigwillis-mm), [craph](https://github.com/craph), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [dantepippi](https://github.com/dantepippi), [dbejanishvili](https://github.com/dbejanishvili), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DSchalla](https://github.com/DSchalla), [ejose19](https://github.com/ejose19), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [fakela](https://github.com/fakela), [fedealconada](https://github.com/fedealconada), [FlaviaBastos](https://github.com/FlaviaBastos), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [Francois-D](https://github.com/Francois-D), [funkytwig](https://github.com/funkytwig), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gnello](https://github.com/gnello), [GrigalashviliT](https://github.com/GrigalashviliT), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gsagula](https://github.com/gsagula), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [hzeroo](https://github.com/hzeroo), [ialorro](https://github.com/ialorro), [iamsayantan](https://github.com/iamsayantan), [ikeohachidi](https://github.com/ikeohachidi), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [josephbaylon](https://github.com/josephbaylon), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [khos2ow](https://github.com/khos2ow), [kosgrz](https://github.com/kosgrz), [l0r3zz](https://github.com/l0r3zz), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [liusy182](https://github.com/liusy182), [lynn915](https://github.com/lynn915), [marianunez](https://github.com/marianunez), [mbecca](https://github.com/mbecca), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mterhar](https://github.com/mterhar), [muratbayan](https://github.com/muratbayan), [nadalfederer](https://github.com/nadalfederer), [NassimBounouas](https://github.com/NassimBounouas), [natalie-hub](https://github.com/natalie-hub), [nathanaelhoun](https://github.com/nathanaelhoun), [nevyangelova](https://github.com/nevyangelova), [nperera](https://github.com/nperera), [octoquad](https://github.com/octoquad), [pankajhirway](https://github.com/pankajhirway), [petya-v](https://github.com/petya-v), [pradeepmurugesan](https://github.com/pradeepmurugesan), [prapti](https://github.com/prapti), [psy-q](https://github.com/psy-q), [Qovaros](https://github.com/Qovaros), [Qujja](https://github.com/Qujja), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shibasisp](https://github.com/shibasisp), [Shivam010](https://github.com/Shivam010), [shred86](https://github.com/shred86), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [thefactremains](https://github.com/thefactremains), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [ThiefMaster](https://github.com/ThiefMaster), [tomasmik](https://github.com/tomasmik), [uhlhosting](https://github.com/uhlhosting), [vesari](https://github.com/vesari), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [ztrayner](https://github.com/ztrayner) + +---- + +## Release v5.23 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.23.2, released 2020-07-23** + - Smoothed the database query load while syncing teams and channel roles by fetching data in batches. [MM-27114](https://mattermost.atlassian.net/browse/MM-27114) + - Fixed a bug in pagination which queried more data redundantly. [MM-27187](https://mattermost.atlassian.net/browse/MM-27187) + - Throttled network traffic by implementing bounded concurrency. +- **v5.23.1, released 2020-06-02** + - Fixed an issue where ``Content-Type`` was no longer optional in incoming webhook requests and led to errors. [MM-25677](https://mattermost.atlassian.net/browse/MM-25677) +- **v5.23.0, released 2020-05-16** + - Original 5.23.0 release + +Mattermost v5.23.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility +PostgreSQL ended long-term support for [version 9.4 in February 2020](https://www.postgresql.org/support/versioning). Mattermost will officially be supporting PostgreSQL version 10 with the Mattermost v5.26 release as PostgreSQL 9.4 is no longer supported. New installs will require PostgreSQL version 10. Previous Mattermost versions, including our current ESR, will continue to be compatible with PostgreSQL version 9.4. In our 6.0 release (date to be announced), we plan on fully deprecating PostgreSQL 9.4. + +We highly recommend upgrading to PostgreSQL version 10+. Please follow the instructions under the Upgrading Section within [the PostgreSQL documentation](https://www.postgresql.org/support/versioning/). + +### Bug Fixes + - Fixed an issue where using slash command ``/leave`` failed to leave the channel. + - Fixed an issue where clicking on a channel link from a Direct Message channel that linked to a different team resulted in a "Page not Found" error. + - Fixed an issue where reloading a channel caused the channel to be shown as read-only for a few seconds. + - Fixed an issue where the Channel Export plugin bot channel did not appear on the left-hand side channel sidebar until the user switched to a different channel. + - Fixed an issue where no channel suggestions were displayed for ``in:`` search modifier for Guest Accounts. + - Fixed an issue where ``Guest`` tags were not shown in Group Message channel header. + - Fixed an issue where guest permissions could not be set in Team Override Schemes. + - Fixed an issue where a "this user didn't get notified" system message was missing if an at-mention was followed by a period and the user was not in the channel. + - Fixed an issue where batched emails were still sent even if there was activity from the user. + - Fixed an issue where ``/me`` messages weren't formatted in the right-hand side. + - Fixed an issue where mentions in header-changed system messages weren't highlighted. + - Fixed an issue where a thread title was missing when initial message in a thread showed as "message deleted". + - Fixed an issue where there was no hover effect when mousing over options in Search. + - Fixed an issue on Firefox where using Alt+arrow stopped working on read-only channels. + - Fixed an issue where muted channels on another team appeared as unread in team sidebar and browser tab. + - Fixed an issue where the URL field on Rename Channel modal allowed more than two underscores. + - Fixed an issue where pasting text from a GitHub code block erased post textbox contents. + - Fixed an issue where keyboard shortcuts to move between teams conflicted with a native Linux OS shortcut for switching virtual desktops. + - Fixed an issue where incoming webhooks that contained certain sized attachments resulted in an infinite loop, causing a memory leak. + - Fixed an issue with errors appearing in logs when sending a direct message to your own account. + - Fixed an issue with a "Failed to get membership" log spam for bot posts. + +### Open Source Components + - Added ``react-native-mmkv-storage`` in https://github.com/mattermost/mattermost-mobile. + - Added ``redux-action-buffer`` in https://github.com/mattermost/mattermost-mobile. + - Added ``redux-reset`` in https://github.com/mattermost/mattermost-mobile. + - Added ``serialize-error`` in https://github.com/mattermost/mattermost-mobile. + +### API Changes + - Added a new API endpoint ``GET /api/v4/users/known`` to get the list of user IDs of users with any direct relationship with a user. That means any user sharing any channel, including direct and group channels. + - ``GET /api/v4/teams/:team_id/channels`` no longer requires the ``list_team_channels`` permission. + +### Websocket Event Changes + - Added a new ``update_team_scheme`` Websocket Event. + +### Known Issues + - **Copy Theme Colors** button on custom theme Display Settings modal is not themed correctly on Mattermost dark theme. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + + - [aaronrothschild](https://github.com/aaronrothschild), [adamjclarkson](https://github.com/adamjclarkson), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://translate.mattermost.com/user/aeomin/), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ahmaddanialmohd](https://github.com/ahmaddanialmohd), [akarikuu](https://github.com/akarikuu), [Akendo](https://github.com/Akendo), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [angeloskyratzakos](https://github.com/angeloskyratzakos), [AninditaBasu](https://github.com/AninditaBasu), [asaadmahmood](https://github.com/asaadmahmood), [attilamolnar](https://github.com/attilamolnar), [avasconcelos114](https://github.com/avasconcelos114), [avddvd](https://github.com/avddvd), [bakurits](https://github.com/bakurits), [bbodenmiller](https://github.com/bbodenmiller), [bolariin](https://github.com/bolariin), [bradjcoughlin](https://github.com/bradjcoughlin), [cadavre](https://github.com/cadavre), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [ckavili](https://github.com/ckavili), [clarmso](https://github.com/clarmso), [cpanato](https://github.com/cpanato), [cpurta](https://github.com/cpurta), [craigwillis-mm](https://github.com/craigwillis-mm), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [curiousercreative](https://github.com/curiousercreative), [danger89](https://github.com/danger89), [Danziger](https://github.com/Danziger), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [dhadiseputro](https://github.com/dhadiseputro), [DHaussermann](https://github.com/DHaussermann), [ebaker](https://github.com/ebaker), [emilyhollinger](https://github.com/emilyhollinger), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [fedealconada](https://github.com/fedealconada), [FlaviaBastos](https://github.com/FlaviaBastos), [flynbit](https://github.com/flynbit), [fmunshi](https://github.com/fmunshi), [Francois-D](https://github.com/Francois-D), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gnello](https://github.com/gnello), [gramakri](https://github.com/gramakri), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gsagula](https://github.com/gsagula), [hahmadia](https://github.com/hahmadia), [hajowieland](https://github.com/hajowieland), [hanzei](https://github.com/hanzei), [haydenhw](https://github.com/haydenhw), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ialorro](https://github.com/ialorro), [iamsayantan](https://github.com/iamsayantan), [icelander](https://github.com/icelander), [igor47](https://github.com/igor47), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnthompson365](https://github.com/johnthompson365), [josephbaylon](https://github.com/josephbaylon), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [justledbetter](https://github.com/justledbetter), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lynn915](https://github.com/lynn915), [marianunez](https://github.com/marianunez), [MatthewDorner](https://github.com/MatthewDorner), [mbecca](https://github.com/mbecca), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mo2menelzeiny](https://github.com/mo2menelzeiny), [moussetc](https://github.com/moussetc), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [Nirei](https://github.com/Nirei), [nvjacobo](https://github.com/nvjacobo), [oguera](https://github.com/oguera), [Pafzedog](https://github.com/Pafzedog), [popstr](https://github.com/popstr), [promulo](https://github.com/promulo), [Qovaros](https://github.com/Qovaros), [rahimrahman](https://github.com/rahimrahman), [rajeshkp](https://github.com/rajeshkp), [rakhi2104](https://github.com/rakhi2104), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [shred86](https://github.com/shred86), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [syuo7](https://github.com/syuo7), [T0biii](https://github.com/T0biii), [theo-o](https://github.com/theo-o), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [uhlhosting](https://github.com/uhlhosting), [vesari](https://github.com/vesari), [vespian](https://github.com/vespian), [VishalSwarnkar](https://github.com/VishalSwarnkar), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [ztrayner](https://github.com/ztrayner) + +---- + +## Release v5.22 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.22.3, released 2020-05-11** + - Fixed an issue where channels were shown as read-only when [Channel Moderation feature](https://docs.mattermost.com/deployment/advanced-permissions.html#channel-moderation-beta-e20) was used in High Availability environments. [MM-24987](https://mattermost.atlassian.net/browse/MM-24987) +- **v5.22.2, released 2020-05-05** + - Fixed an issue where message reply threads did not get correctly imported via [bulk loading tool](https://docs.mattermost.com/deployment/bulk-loading.html). [MM-24707](https://mattermost.atlassian.net/browse/MM-24707) +- **v5.22.1, released 2020-04-23** + - Fixed an issue where Amazon S3 file storage with IAM credentials failed due to a bug in the ``minio-go`` library. [MM-24388](https://mattermost.atlassian.net/browse/MM-24388) +- **v5.22.0, released 2020-04-16** + - Original 5.22.0 release + +**Release day: 2020-04-16** + +Mattermost v5.22.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + + - v5.9.0 as our Extended Support Release (ESR) is coming to the end of its life cycle and upgrading to 5.19.0 ESR or a later version is highly recommended. v5.19.0 will continue to be our current ESR until October 15, 2020. [Learn more in our forum post](https://forum.mattermost.com/t/upcoming-extended-support-release-updates/8526). + +### Breaking Changes + + - Due to fixing performance issues related to emoji reactions, the performance of the upgrade has been affected in that the schema upgrade now takes more time in environments with lots of reactions in their database. These environments are recommended to perform the schema migration during low usage times and potentially in advance of the upgrade. Since this migration happens before the Mattermost Server is fully launched, non-High Availability installs will be unreachable during this time. + - The Channel Moderation Settings feature is supported on mobile app versions v1.30 and later. In earlier versions of the mobile app, users who attempt to post or react to posts without proper permissions will see an error. + - Direct access to the ``Props`` field in the ``model.Post`` structure has been deprecated. The available ``GetProps()`` and ``SetProps()`` methods should now be used. Also, direct copy of the ``model.Post`` structure must be avoided in favor of the provided ``Clone()`` method. + +```{Important} +If you upgrade from a release earlier than 5.21, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Read-only channels and channel moderation settings (E20) (Beta) + - System admins can use new channel-specific permissions to create read-only channels, restrict who can post in certain channels, and more. This feature is in beta and ships with Enterprise Edition E20. + +#### Team switch shortcuts + - Added new keyboard shortcuts that allow users to switch to the next or previous team using ``Ctrl/⌘ + Alt + Up/Down`` and switch to a specific team using ``Ctrl/⌘ + Alt + #``. + - Also added the ability to reorder teams on the sidebar via drag-and-drop. + +#### Unarchive Channel option in the archived channels menu + - Added the ability for users to restore archived channels via the Mattermost interface. + +#### Channel sidebar reorganization features (Experimental) + - Added improvements to the channel sidebar, including the ability to collapse categories in the sidebar (e.g., favorites, public channels, private channels, and direct messages) to reduce unnecessary scrolling. + +### Improvements + +#### User Interface (UI) + - Added several UI improvements, such as added a "Close Group Message" option to Group Message menu. + - Added a keyboard shortcut to open/close the right-hand sidebar. + - Added a keyboard shortcut to add reactions to last message in a channel or a thread. + - Added infinite scroll to Select Teams screen. + - Updated the message permalink view. + +#### Localization + - Promoted Dutch and Russian languages to Beta. + +#### Notifications + - Added support for notification sounds in Firefox. + +#### Plugins + - Allow searching for files through the plugin API. + - Allowed prepackaged and local plugins to set ``ReleaseNotesURL``. + +#### Integrations + - In interactive dialogs, the autocomplete lists now render below the input field by default. + - Extended the payload of slash commands to include a map of the users and channels mentioned in the message to their corresponding identifiers. + - Added support for recognizing multi-line slash commands without requiring trailing space after the trigger word. + +#### Bulk Import + - Added support for exporting and importing the props of a post. + +### Bug Fixes + - Fixed an issue where a user's role was not reflected correctly in the Channel Members Modal when it was updated after the modal was opened. + - Fixed an issue where verification emails were still sent on servers with SMTP configured when`Enable Email Notifications` and `Require Email Verification` were disabled in the System Console. + - Fixed an issue where a user account was still created when inviting a new user to a team with an email address that didn't match the team's allowed domain. + - Fixed an issue where System Admins could not access the Teams menu of the System Console. + - Fixed an issue where an incorrect time was displayed at midnight when 24-hour clock display was enabled. + - Fixed an issue where a channel appeared twice on the channel sidebar if the channels were created with a certain arrangement of characters. + - Fixed an issue where pasting a custom theme caused a white screen. + - Fixed an issue where a modified Edit Post dialog silently closed on a mouse click outside it. + - Fixed an issue where users were unable to drag and drop files on Edge. + - Fixed an issue where the autoresponder responded to every bot post. + - Fixed an issue where Mattermost was unable to start if a configured mail server was listening but not responding. + - Fixed an issue where LDAP sync did not finish if read database replica was enabled. + - Fixed a SIGSEGV crash issue when exporting to CSV. + - Fixed an issue where Elasticsearch error was output when running unrelated commands. + - Fixed an issue where importing from slack crashed due to invalid memory access or nil pointer dereference. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableOpenTracing``, to enable a Jaeger client to be instantiated and used to trace each HTTP request as it goes through App and Store layers. + - Added ``IdleTimeout``, to set an explicit idle timeout in the HTTP server. + - Added ``ExperimentalChannelSidebarOrganization``, to enable accessing the experimental channel sidebar feature set. + - Under ``NotificationLogSettings`` in ``config.json``: + - Added ``SMTPServerTimeout``, to enable the maximum amount of time (in seconds) allowed for establishing a TCP connection between Mattermost and the SMTP server, to be idle before being terminated. + - Added ``DirectoryId`` object, to enable the ID of the application's AAD directory. + - Added ``ExperimentalAuditSettings`` object, to enable the audit settings to output audit records to syslog (local or remote server via TLS) and/or to a local file. + +### Open Source Components + - Added ``core-js`` in https://github.com/mattermost/mattermost-redux. + - Added ``@types/redux-mock-store`` in https://github.com/mattermost/mattermost-webapp. + - Added ``react-beautiful-dnd`` in https://github.com/mattermost/mattermost-webapp. + - Added ``react-native-hw-keyboard-event`` in https://github.com/mattermost/mattermost-mobile. + - Added ``react-native-v8`` in https://github.com/mattermost/mattermost-mobile. + - Removed ``jsc-android`` from https://github.com/mattermost/mattermost-mobile. + +### Database Changes + - Various indexes were added. + +### API Changes + - Added ``GET api/v4/channels/:channels/moderations`` and ``PUT api/v4/channels/:channels/moderations/patch`` to support channel moderation settings. + - Added a ``PUT api/v4/commands/move`` endpoint to move a command to another team. + - Added a ``GET api/v4/commands`` endpoint to retrieve a command by id. + +### Websocket Event Changes + - Added ``channel_scheme_updated`` Websocket Event. + +### Known Issues + - Batched emails are still sent even if any activity from the user is detected. + - Keyboard shortcut to move between teams conflicts with Linux native OS shortcut. + - Webapp crashes if the Direct Message modal is open when a guest is removed from a channel. + - Slash command ``/leave`` fails to leave channel on webapp and crashes the Android app. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + + - [abdulsmapara](https://github.com/abdulsmapara), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://translate.mattermost.com/user/aeomin/), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ali-farooq0](https://github.com/ali-farooq0), [allenlai18](https://github.com/allenlai18), [ami9000](https://github.com/ami9000), [amyblais](https://github.com/amyblais), [amynicol1985](https://github.com/amynicol1985), [angeloskyratzakos](https://github.com/angeloskyratzakos), [AninditaBasu](https://github.com/AninditaBasu), [apoxa](https://github.com/apoxa), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [ashwanisng](https://github.com/ashwanisng), [avasconcelos114](https://github.com/avasconcelos114), [bakurits](https://github.com/bakurits), [Better-Boy](https://github.com/Better-Boy), [bhuvana-guna](https://github.com/bhuvana-guna), [bolariin](https://github.com/bolariin), [bradjcoughlin](https://github.com/bradjcoughlin), [catalintomai](https://github.com/catalintomai), [caugner](https://github.com/caugner), [checkaayush](https://github.com/checkaayush), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [compiledsound](https://github.com/compiledsound), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://github.com/ctlaltdieliet), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [Durgaprasad-Budhwani](https://github.com/Durgaprasad-Budhwani), [ebiiim](https://github.com/ebiiim), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [ericjaystevens](https://github.com/ericjaystevens), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [fedealconada](https://github.com/fedealconada), [flynbit](https://github.com/flynbit), [fm2munsh](https://github.com/fm2munsh), [gabrieljackson](https://github.com/gabrieljackson), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gsagula](https://github.com/gsagula), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [haydenhw](https://github.com/haydenhw), [hectorskypl](https://github.com/hectorskypl), [hiendinhngoc](https://github.com/hiendinhngoc), [HilaryClarke](https://github.com/HilaryClarke), [hmhealey](https://github.com/hmhealey), [iamsayantan](https://github.com/iamsayantan), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [JanhaviC15](https://github.com/JanhaviC15), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [joewaitye](https://github.com/joewaitye), [johnthompson365](https://github.com/johnthompson365), [josephbaylon](https://github.com/josephbaylon), [josephk96](https://github.com/josephk96), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kajumito](https://github.com/kajumito), [Kaya_Zeren](https://x.com/kaya_zeren), [kosgrz](https://github.com/kosgrz), [larkox](https://github.com/larkox), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [Lumexralph](https://github.com/Lumexralph), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [MarcoAlejandro](https://github.com/MarcoAlejandro), [marianunez](https://github.com/marianunez), [MatthewDorner](https://github.com/MatthewDorner), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mo2menelzeiny](https://github.com/mo2menelzeiny), [msvbhat](https://github.com/msvbhat), [MuLx10](https://github.com/MuLx10), [nadalfederer](https://github.com/nadalfederer), [natalie-hub](https://github.com/natalie-hub), [NeroBurner](https://github.com/NeroBurner), [nevyangelova](https://github.com/nevyangelova), [phillipahereza](https://github.com/phillipahereza), [Pomyk](https://github.com/Pomyk), [potaito](https://github.com/potaito), [prasoonmayank](https://github.com/prasoonmayank), [promulo](https://github.com/promulo), [rakhi2104](https://github.com/rakhi2104), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [RohitJain13](https://github.com/RohitJain13), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [sbis04](https://github.com/sbis04), [sbishel](https://github.com/sbishel), [shadabk96](https://github.com/shadabk96), [shibasisp](https://github.com/shibasisp), [sibashisbishi](https://github.com/sibashisbishi), [someone-somenet-org](https://github.com/someone-somenet-org), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [teyotan](https://github.com/teyotan), [TheoVitkovskiy](https://github.com/TheoVitkovskiy), [thePanz](https://github.com/thePanz), [thnat1234](https://github.com/thnat1234), [Ths2-9Y-LqJt6](https://github.com/Ths2-9Y-LqJt6), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [upwell](https://github.com/upwell), [vespian](https://github.com/vespian), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.21 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +**Release day: 2020-03-16** + +Mattermost v5.21.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + - Honour key value expiry in KVCompareAndSet, KVCompareAndDelete and KVList. We also improved handling of plugin key value race conditions and deleted keys in Postgres. + +### Bug Fixes + - Fixed an issue where switching to an unread channel sometimes got stuck at "Loading..." on certain screen resolutions. + - Fixed an issue where bots could not be added to group-synced channels or teams. + - Fixed an issue where a user's authentication method in the System Console was shown as email if it was actually LDAP. + - Fixed an issue where lines in over 65536 characters caused bulk import to fail. + - Fixed an issue where code block line numbers were copied when pasting into certain applications. + - Fixed an issue where the right-hand side reply thread scrolled down after receiving a new message. + - Fixed an issue where the post menu opened up in the right-hand side made the menu options float off page if the parent post was short with no replies. + - Fixed an issue where enabling and disabling the demo plugin generated a "connection is shutdown" error. + - Fixed an issue where deactivated users with whom a user had never interacted in a private message before appeared in the New Direct Message menu. + - Fixed an issue where clicking on an image in external image preview opened the image within the desktop app. + - Fixed an issue where users were unable to open email links using View in Browsers option in incognito mode. + - Fixed an issue where **Invite Guests > Emails** containing upper case letters were rejected. + - Fixed an issue where a new user got a "No more channels to join" message while scrolling through the channel list. + - Fixed an issue where clicking on "Terms of Service" and "Privacy Policy" on account creation on the desktop app didn't do anything. + - Fixed an issue where gendered emojis were rendered with the wrong gender. + - Fixed an issue where large video file uploads failed on the right-hand side without an appropriate error. + +### Known Issues + - Verification emails are still sent on servers with SMTP configured when`Enable Email Notifications` and `Require Email Verification` are disabled in the System Console. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + - [adamjclarkson](https://github.com/adamjclarkson), [Adovenmuehle](https://github.com/Adovenmuehle), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ajh3](https://github.com/ajh3), [ali-farooq0](https://github.com/ali-farooq0), [allenlai18](https://github.com/allenlai18), [ami9000](https://github.com/ami9000), [amyblais](https://github.com/amyblais), [andreiavrammsd](https://github.com/andreiavrammsd), [AninditaBasu](https://github.com/AninditaBasu), [Apollo9999](https://github.com/Apollo9999), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [asutosh97](https://github.com/asutosh97), [avasconcelos114](https://github.com/avasconcelos114), [bbodenmiller](https://github.com/bbodenmiller), [bolariin](https://github.com/bolariin), [bradjcoughlin](https://github.com/bradjcoughlin), [catalintomai](https://github.com/catalintomai), [checkaayush](https://github.com/checkaayush), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [ctlaltdieliet](https://translate.mattermost.com/user/ctlaltdieliet/), [ctmusicnz](https://github.com/ctmusicnz), [darkdebo](https://github.com/darkdebo), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [dkbhadeshiya](https://github.com/dkbhadeshiya), [dlclark](https://github.com/dlclark), [DSchalla](https://github.com/DSchalla), [emilioicai](https://github.com/emilioicai), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [esethna](https://github.com/esethna), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [flynbit](https://translate.mattermost.com/user/flynbit/), [fm2munsh](https://github.com/fm2munsh), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [ikeohachidi](https://github.com/ikeohachidi), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [it33](https://github.com/it33), [J35u527](https://github.com/J35u527), [jasonblais](https://github.com/jasonblais), [jasonlanderson](https://github.com/jasonlanderson), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnthompson365](https://github.com/johnthompson365), [josephbaylon](https://github.com/josephbaylon), [joshuabezaleel](https://github.com/joshuabezaleel), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [khos2ow](https://github.com/khos2ow), [larkox](https://github.com/larkox), [lawikip](https://github.com/lawikip), Lena, [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [marianunez](https://github.com/marianunez), [matthewbirtch](https://github.com/matthewbirtch), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [nadalfederer](https://github.com/nadalfederer), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [njkevlani](https://github.com/njkevlani), [nmlc](https://github.com/nmlc), [opllama2](https://github.com/opllama2), [phillipahereza](https://github.com/phillipahereza), [promulo](https://github.com/promulo), [RajatVaryani](https://github.com/RajatVaryani), [ramkumarrn](https://github.com/ramkumarrn), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [Rulikkk](https://github.com/Rulikkk), [RyanCommits](https://github.com/RyanCommits), [s3than](https://github.com/s3than), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [strtw](https://github.com/strtw), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [thePanz](https://github.com/thePanz), [theriverman](https://github.com/theriverman), [Ths2-9Y-LqJt6](https://github.com/Ths2-9Y-LqJt6), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [Unkn0wnCat](https://github.com/Unkn0wnCat), [vesari](https://github.com/vesari), [vespian](https://github.com/vespian), [vovapi](https://github.com/vovapi), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.20 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.20.2, released 2020-03-12** + - Fixed an issue where Mattermost server crashed when running a compliance export. [MM-23157](https://mattermost.atlassian.net/browse/MM-23157) + - Fixed an issue where switching to an unread channel got stuck at "Loading..." in certain screen resolutions. [MM-22698](https://mattermost.atlassian.net/browse/MM-22698) +- **v5.20.1, released 2020-02-16** + - Fixed an issue where upgrading to v5.20 failed on servers running with ``PluginSettings.Enable = false``, and ``LogSettings.EnableDiagnostics = true``. +- **v5.20.0, released 2020-02-16** + - Original 5.20.0 release + +Mattermost v5.20.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + +### Breaking Changes + - Any [pre-packaged plugin](https://docs.mattermost.com/administration/plugins.html#pre-packaged-plugins) that is not enabled in the ``config.json`` will no longer install automatically, but can continue to be installed via the [plugin marketplace](https://docs.mattermost.com/administration/plugins.html#plugin-marketplace). + - Boolean elements from interactive dialogs are no longer serialized as strings. While we try to avoid breaking changes, this change was necessary to allow both the web and mobile apps to work with the boolean elements introduced with v5.16. + +```{Important} +If you upgrade from a release earlier than 5.19, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### A Banner to Jump to the Most Recent Posts + - Ability to jump to the most recent posts in a channel by clicking a banner that automatically appears in busy channels with unread messages. + +#### Open Email Notifications in the Desktop or Mobile App + - Ability to open messages from email notifications in the Mattermost desktop or mobile apps instead of being directed to open them in the browser. + +#### Ship MMCTL with Mattermost + - Manage servers remotely with `mmctl`, a CLI tool that mimics the Mattermost CLI tool and ships inside Mattermost. + +#### Reworked pre-packaged plugins + - Pre-packaged plugins are now “pre-downloaded” plugins that are available within the Plugin Marketplace, even if your server doesn’t have direct access to the internet. + +#### Plugin Marketplace Labels + - Plugins supported by Mattermost and community supported plugins will be visible, making it easier to select an appropriate plugin based on your organization’s security policies. + +#### Role mapping from LDAP and SAML (E20) + - Ability to assign and restrict users to roles within Mattermost from your single sign-on (SSO) system. + +#### Faster SAML install and configuration (E20) + - Ability to use SAML without installing a separate binary and pull configuration metadata directly from the Identity Provider using an account-specific URL. + +### Improvements + +#### User Interface (UI) + - Added support for mute option in Direct Message channel menus. + - Added a red dot to browser favicon when there are unread mentions. + - Added support for displaying a left-hand side bot icon in the webapp. + - User's own username with a suffix 'you' is now shown in the username autocomplete. + - Allowed user autocomplete to match on terms with spaces. + - Improved autocomplete highlighting when using mouse and keyboard together. + - Added support for showing single image thumbnails in compact view. + - Contents of View Members and Manage Members modals now refresh when a user's role has changed. + - Filtering search by channel now also shows the channel name and not only its ID. + - Users now cannot type account input fields longer than the maximum length for first name, last name and email fields. + +#### Plugins + - Added a way to show that a plugin requires a certain Mattermost configuration setting. + - Added support for plugins to add menu items to the Channel Menu. + +#### Command Line Interface (CLI) + - Added a CLI command ``webhook move`` for moving outgoing webhooks. + +#### Bulk Import + - When bulk import finds an already existing post, it now deletes existing files before importing new ones. + - Bulk export now includes direct messages from a user to themselves. + +#### Administration + - Added support for Elasticsearch v7. + - Added ability to inform System Admins when a user who managed bot accounts is deactivated, and enable them to take ownership of the bot. + - Added LDAP/Elasticsearch/SQL Trace to server logs to make it easier for admins to diagnose problems. + - Added ``plugins`` to the list of words that a team URL cannot start with. + - Removed 26 character requirement from post action IDs. + +### Bug Fixes + - Fixed an issue where guest account creation erroneously considered the global list of whitelisted domains. + - Fixed an issue where inviting multiple users with valid and invalid emails caused the invites for the valid users not to be sent. + - Fixed an issue where option to invite users by email was displayed even if email invitations were disabled. + - Fixed an issue where the channel drop-down **Leave Channel** failed to leave the channel on a server with a subpath. + - Fixed an issue where messages with 2-byte characters didn't get posted. + - Fixed an issue where links for recent mentions and flagged posts were doubled in smaller window widths. + - Fixed an issue where opening the right-hand sidebar placed focus in the Search box instead of the Text box. + - Fixed an issue where **Customization > Site Name** help text didn't match text field behavior. + - Fixed an issue where the option to mark posts as unread was unexpectedly available when viewing archived channels. + - Fixed an issue where emoji reactions shifted down a few pixels after clicking. + - Fixed an issue where pasting code from GitHub resulted in broken markup and loss of text. + - Fixed an issue where importing theme colours from Slack gave an error. + - Fixed an issue where navigating to a plugin configuration page in the System Console for a deleted plugin returned a `Not Found` error. + - Fixed an issue where scroll bar was missing on the welcome tutorial screen in web mobile view. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``SamlSettings`` in ``config.json``: + - Added ``IdpMetadataUrl``, to add the URL where Mattermost sends a request to obtain setup metadata from the provider. + - Added ``EnableAdminAttribute`` and ``AdminAttribute``, to add the attribute in the SAML Assertion for designating System Admins. + - Under ``LdapSettings`` in ``config.json``: + - Added ``EnableAdminFilter`` and ``AdminFilter``, to enter a filter to use for designating the System Admin role to users. + - Under ``PluginSettings`` in ``config.json``: + - Added ``EnableRemoteMarketplace``, to have the server attempt to connect to the configured Plugin Marketplace to show the latest plugins. + - Added ``AutomaticPrepackagedPlugins``, so that any pre-packaged plugins enabled in the configuration will be installed or upgraded automatically. + +### Open Source Components + - Added ``@formatjs/intl-pluralrules`` in https://github.com/mattermost/mattermost-webapp. + - Added ``@formatjs/intl-relativetimeformat`` in https://github.com/mattermost/mattermost-webapp. + - Added ``custom-protocol-detection`` in https://github.com/mattermost/mattermost-webapp. + - Added ``react-inlinesvg`` in https://github.com/mattermost/mattermost-webapp. + +### Database Changes + - Added ``Bots.LastIconUpdate`` column. + - Added ``GroupTeams.SchemeAdmin`` column. + - Added ``GroupChannels.SchemeAdmin`` column. + +### API Changes + - Added ``PUT /config/patch`` REST API endpoint that uses patch semantics to only update the fields of the config that are provided, while leaving the other fields unchanged. + - Added ``POST /server_busy``, ``GET /server_busy`` and ``DELETE /server_busy`` REST API endpoints to add the ability to turn off non-critical services when under load. + +### Websocket Event Changes + - Added ``channel_restored`` Websocket Event. + +### Known Issues + - Code block line numbers are copied when pasting into certain applications. + - Deactivated users with whom you never interacted in a private message before appear in New Direct Message menu. + - Verification emails are still sent on servers with SMTP configured when`Enable Email Notifications` and `Require Email Verification` are disabled in the System Console. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[abdusabri](https://github.com/abdusabri), [aeomin](https://translate.mattermost.com/user/aeomin/), [agarciamontoro](https://github.com/agarciamontoro), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ali-farooq0](https://github.com/ali-farooq0), [allenlai18](https://github.com/allenlai18), [amyblais](https://github.com/amyblais), [andylibrian](https://github.com/andylibrian), [anidok](https://github.com/anidok), [AninditaBasu](https://github.com/AninditaBasu), [anon6789](https://github.com/anon6789), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [atulya-pandey](https://github.com/atulya-pandey), [avasconcelos114](https://github.com/avasconcelos114), [bbodenmiller](https://github.com/bbodenmiller), [bolariin](https://github.com/bolariin), [bpietraga](https://github.com/bpietraga), [bradjcoughlin](https://github.com/bradjcoughlin), [c-yan](https://github.com/c-yan), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [CEOehis](https://github.com/CEOehis), [chikei](https://github.com/chikei), [ChrisDobby](https://github.com/ChrisDobby), [chuttam](https://github.com/chuttam), [cjohannsen81](https://github.com/cjohannsen81), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [ctmusicnz](https://github.com/ctmusicnz), [davidjwilkins](https://github.com/davidjwilkins), [DE-mbecker](https://github.com/DE-mbecker), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [dlclark](https://github.com/dlclark), [dra](https://github.com/dra), [DSchalla](https://github.com/DSchalla), [emilioicai](https://github.com/emilioicai), [enahum](https://github.com/enahum), [enelson720](https://github.com/enelson720), [enolal826](https://github.com/enolal826), [esdrasbeleza](https://github.com/esdrasbeleza), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [flexo3001](https://github.com/flexo3001), [fm2munsh](https://github.com/fm2munsh), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gopheros](https://github.com/gopheros), [grubbins](https://github.com/grubbins), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [gsagula](https://github.com/gsagula), [gupsho](https://github.com/gupsho), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hector2](https://github.com/hector2), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [hunterlester](https://github.com/hunterlester), [ikeohachidi](https://github.com/ikeohachidi), [imisshtml](https://github.com/imisshtml), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [itao](https://github.com/itao), [jasonblais](https://github.com/jasonblais), [jasonlanderson](https://github.com/jasonlanderson), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jomaxro](https://github.com/jomaxro), [josephbaylon](https://github.com/josephbaylon), [JtheBAB](https://github.com/JtheBAB), [jupenur](https://github.com/jupenur), [justinegeffen](https://github.com/justinegeffen), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [karlmarxlopez](https://github.com/karlmarxlopez), [Kaya_Zeren](https://x.com/kaya_zeren), [khos2ow](https://github.com/khos2ow), [kosgrz](https://github.com/kosgrz), [larkox](https://github.com/larkox), [lawikip](https://github.com/lawikip), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lukewest](https://github.com/lukewest), [lurcio](https://github.com/lurcio), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [marianunez](https://github.com/marianunez), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mitchellroe](https://github.com/mitchellroe), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [nadalfederer](https://github.com/nadalfederer), [natalie-hub](https://github.com/natalie-hub), [niklabh](https://github.com/niklabh), [NiroshaV](https://github.com/NiroshaV), [nmlc](https://github.com/nmlc), [opllama2](https://github.com/opllama2), [phillipahereza](https://github.com/phillipahereza), [Pomyk](https://github.com/Pomyk), [popstr](https://github.com/popstr), [RajatVaryani](https://github.com/RajatVaryani), [rajudev](https://github.com/rajudev), [rascasoft](https://github.com/rascasoft), [rbradleyhaas](https://github.com/rbradleyhaas), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [RyanCommits](https://github.com/RyanCommits), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottjr632](https://github.com/scottjr632), [sij507](https://github.com/sij507), [somenet](https://github.com/somenet), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tasdomas](https://github.com/tasdomas), [thapakazi](https://github.com/thapakazi), [thefactremains](https://github.com/thefactremains), [themaverikk](https://github.com/themaverikk), [thePanz](https://github.com/thePanz), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [vesari](https://github.com/vesari), [VishalSwarnkar](https://github.com/VishalSwarnkar), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [xalkan](https://github.com/xalkan) + +---- + +## Release v5.19 - [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) + +Mattermost v5.19.0 contains low to high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.19.3, released 2020-06-19** + - Fixed an issue with the Plugin Tooltip implementation that caused links to be truncated when rendered. This issue occured if you are using the recent GitHub plugin v1.0.0 release. All links were affected, regardless if they were related to GitHub. [MM-25808] +- **v5.19.2, released 2020-04-21** + - Fixed an issue with unexpected crashes related to any action taken to modify post properties such as push notifications. Note for developers: Direct access to the ``Props`` field in the ``model.Post`` structure has been deprecated. To avoid crash issues, the available ``GetProps()`` and ``SetProps()`` methods should now be used. Also, direct copy of the ``model.Post`` structure must be avoided in favor of the provided ``Clone()`` method. [MM-21378](https://mattermost.atlassian.net/browse/MM-21378) + - Fixed an issue where a public channel appears in the list of Direct Message channels in the channel sidebar if the channel name is 40 characters long. [MM-23427](https://mattermost.atlassian.net/browse/MM-23427) +- **v5.19.1, released 2020-01-21** + - Fixed a regression affecting v5.18 and v5.19 where some users were experiencing client-side performance issues. This was mainly affecting users with more than 100 channels listed in the channel sidebar and with channels sorted alphabetically. [MM-20349](https://mattermost.atlassian.net/browse/MM-20349) +- **v5.19.0, released 2020-01-16** + - Original 5.19.0 release + +### Compatibility + +#### Breaking Changes + - ``LockTeammateNameDisplay`` setting was moved to Enterprise Edition E20 as it was erroneously available in Team Edition and Enterprise Edition E10. + +```{Important} +If you upgrade from a release earlier than 5.18, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Bug Fixes + - Fixed an issue where email notifications were still sent in some cases while disabled in the user interface. + - Fixed an issue where **System Console > Site Configuration > Users & Teams > Lock Teammate Name Display** should only have been available on Enterprise Edition E20 but was erroneously available also on Team Edition and Enterprise Edition E10. + - Fixed an issue where the System Console left-hand side scrollbar was too dark to see. + - Fixed an issue where inline markdown image links did not open with preview modal. + - Fixed an issue on Edge where the "+" buttons in channel list were black on Mattermost default theme. + - Fixed an issue where users were unable to scroll through message textbox autocomplete results using arrow keys. + - Fixed an issue where clicking a line separator in the Main Menu closed the menu. + - Fixed an issue where date separator showed long-format timestamps. + - Fixed an issue where the Menu help text was truncated in English for Do Not Disturb status. + - Fixed an issue where the height and width parameters in inline images didn't work. + - Fixed an issue where the day picker in after/before search didn't honor the user's timezone override. + - Fixed an issue where editing a post and hitting ``<enter>`` in code block saved the post automatically instead of adding a newline. + - Fixed an issue where users were unable to close the Edit Channel Header modal when opened from the Intro Message. + - Fixed an issue where opening the channel picker using CTRL+K and then focusing on the message box using CTRL+SHIFT+L did not close the channel picker. + - Fixed an issue where the at-mention suggestions still highlighted the previous search but not the first suggestion in the list. + - Fixed an issue where the at-mention autocomplete always opened up in the right-hand side reply thread, sometimes cutting off users in the list. + - Fixed an issue with a notification badge count inconsistency when push notification setting was set to **All Activity**. + - Fixed an issue where timestamps on 12-hour format had a leading zero. + - Fixed an issue with an incorrect error message when attempting to add a bot to a channel if the bot was previously on the team. + - Fixed an issue where the client license API generated a different ETag for every response. + +### API Changes + - Etag header was added to the API endpoint to get the client license. + - Oath ``IsTrusted`` configuration can only be changed if the user has the ``manage_system`` permission. + +### Known Issues + - Client-side performance issues seen while typing. + - On a server with a subpath, channel drop-down **Leave Channel** fails to leave the channel. + - Importing theme colours from Slack gives an error. + - Inviting multiple users with valid/allowed and invalid emails causes the invites for the valid users not to be sent. + - Option to invite users by email is displayed even if email invitations are disabled. + - Users may need to reinstall and delete cache on Classic apps if launching and logging into the app get stuck. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[aaronrothschild](https://github.com/aaronrothschild), [abdusabri](https://github.com/abdusabri), [abhisek](https://github.com/abhisek), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [ali-farooq0](https://github.com/ali-farooq0), [allenlai18](https://github.com/allenlai18), [alxsah](https://github.com/alxsah), [amyblais](https://github.com/amyblais), [anidok](https://github.com/anidok), [AninditaBasu](https://github.com/AninditaBasu), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [avegrv](https://github.com/avegrv), [benbhall](https://github.com/benbhall), [bpietraga](https://github.com/bpietraga), [bradjcoughlin](https://github.com/bradjcoughlin), [calebroseland](https://github.com/calebroseland), [catalintomai](https://github.com/catalintomai), [chikei](https://github.com/chikei), [ChrisDobby](https://github.com/ChrisDobby), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [darkestofdans](https://github.com/darkestofdans), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [ethervoid](https://github.com/ethervoid), [faase](https://github.com/faase), [fm2munsh](https://github.com/fm2munsh), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gopheros](https://github.com/gopheros), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [gsagula](https://github.com/gsagula), [gupsho](https://github.com/gupsho), [hahmadia](https://github.com/hahmadia), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [igomonov88](https://github.com/igomonov88), [ilgooz](https://github.com/ilgooz), [imisshtml](https://github.com/imisshtml), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jimiolaniyan](https://github.com/jimiolaniyan), [JtheBAB](https://github.com/JtheBAB), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kop](https://github.com/kop), [kosgrz](https://github.com/kosgrz), [larkox](https://github.com/larkox), Lena, [lenucksi](https://github.com/lenucksi), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lurcio](https://github.com/lurcio), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [MariadeAnton](https://github.com/MariadeAnton), [marianunez](https://github.com/marianunez), [mavegaf](https://github.com/mavegaf), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [Mycobee](https://github.com/Mycobee), [nadalfederer](https://github.com/nadalfederer), [natalie-hub](https://github.com/natalie-hub), [nevyangelova](https://github.com/nevyangelova), [nick-brady](https://github.com/nick-brady), [phillipahereza](https://github.com/phillipahereza), [Pomyk](https://github.com/Pomyk), [RajatVaryani](https://github.com/RajatVaryani), [ramkumarvenkat](https://github.com/ramkumarvenkat), [reflog](https://github.com/reflog), [renilJoseph](https://github.com/renilJoseph), [rodcorsi](https://github.com/rodcorsi), [saneletm](https://github.com/saneletm), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [sij507](https://github.com/sij507), [smacgregor](https://github.com/smacgregor), [src-r-r](https://github.com/src-r-r), [srkgupta](https://github.com/srkgupta), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [sunsingerus](https://github.com/sunsingerus), [svelle](https://github.com/svelle), [themaverikk](https://github.com/themaverikk), [thePanz](https://github.com/thePanz), [tomasmik](https://github.com/tomasmik), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [valentijnnieman](https://github.com/valentijnnieman), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [zujko](https://github.com/zujko) + +---- + +## Release v5.18 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +Mattermost v5.18.0 contains low to high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.18.2, released 2020-01-16** + - Fixed an issue where server crashed when a user updated their Account Settings in a high availability cluster environment, and the corresponding ``user_updated`` event did not reach a guest user. [MM-21481](https://mattermost.atlassian.net/browse/MM-21481) +- **v5.18.1, released 2020-01-08** + - Mattermost v5.18.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where migrating accounts from email to SAML failed. [MM-21472](https://mattermost.atlassian.net/browse/MM-21472) +- **v5.18.0, released 2019-12-16** + - Original 5.18.0 release + +### Compatibility + +### Important Upgrade Notes +- Marking a post unread from the mobile app requires v1.26 or later. If using v5.18, but mobile is on v1.25 or earlier, marking a post unread from webapp/desktop will only be reflected on mobile the next time the app launches or is brought to the foreground. + +### Breaking Changes + - The Go module path of ``mattermost-server`` was changed to comply with the Go module version specification. Developers using Go modules with ``mattermost-server`` as a dependency must change the module and import paths to ``github.com/mattermost/mattermost-server/v5`` when upgrade this dependency to `v5.18`. See https://go.dev/blog/v2-go-modules for further information. + - Removed ``Team.InviteId`` from the related Websocket event and sanitized it on all team API endpoints for users without invite permissions. + - Removed the ability to change the type of a channel using the ``PUT /channels/{channel_id}`` API endpoint. The new ``PUT /channels/{channel_id}/privacy`` endpoint should be used for that purpose. + +```{Important} +If you upgrade from a release earlier than 5.17, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### ID Loaded push notifications (E20) + - Allows push notifications to be delivered showing the full message contents that are fetched from the server once the notification is delivered to the device. This means that Apple Push Notification Service (APNS) or Google Firebase Cloud Messaging (FCM) cannot read the message contents since only a unique message ID is sent in the notification payload. + +#### Allow Plugin Upgrades + - Added ability to upgrade plugins and prepackaged plugins via the marketplace. + +#### Mark Posts as Unread + - When marking a post as unread, the user will land on the unread post the next time they click on the relevant channel. + +#### mmctl remote CLI tool + - Allows a system admin to run commands when conventional access to the server via SSH isn't possible. + +#### View Archived Channels (Beta) + - View, share and search for content of archived channels. See more details [here](https://docs.mattermost.com/administration/config-settings.html#allow-users-to-view-archived-channels-beta). + +#### Guest Account SAML & LDAP Support (EE) + - Provision Guests directly from AD/LDAP or SAML upon login. Guests will have no access to any teams or channels until they are assigned. + +#### Actiance Improvements (E20) + - Added events (such as post/file deletion and edit events) to Actiance Export to improve tracking within the Vantage report interface. + +#### LDAP Group Sync upgraded to Beta phase (E20) + - Previously in “Experimental” phase, the linking of AD/LDAP groups to Mattermost groups is now officially in “Beta” phase. + +### Improvements + +#### User Interface (UI) + - Disabled email notifications in Do Not Disturb mode. + - Added support for showing a tooltip on public and private channel names that get truncated. + - Added support for allowing in-line markdown images to open a preview window. + - Added line numbers to code blocks that have syntax highlighting. + - Added support for trimming leading/trailing whitespace on a channel name when a channel is created. + +#### Command Line Interface (CLI) + - Updated CLI command "deleter user" to add ability to delete the given user's group memberships. + - Created CLI command "config reset" to allow resetting the value of a config setting to its default value. + +#### Integrations + - Added ability to disable attachment buttons and fields. + - Added user_name, team_domain and channel_name metadata when clicking an interactive button. + - Extended EnsureBot helper function to include bot images. + - Added support for a generic error message in interactive dialog responses. + +#### Plugins + - Added support for interplugin communication. + - Added support for server version and minimum server version checks in helper methods for plugins. + - Added support for returning results for individual plugins in **System Console > Search**. + - Added the ability to add submenus in post dropdowns for plugins. + +#### Administration + - Added support for System Administrators to control Teammate Name Display at the system level. + - Added support for revoking Guest User Sessions when the Guest Accounts feature is disabled. + - Added the ability to search in **System Console > Channels** and **System Console > Teams**. + - Added the ability to add users as another user to the plugin API. + - Restricted user access to ``/logs`` API endpoint. + - Added "Remove team" and "Change role" options in Team Membership panel. + - Added support for disabling channel settings for public and private toggle for default channels. + +#### Enterprise Edition (EE) + - Added SAML login events to the Audits Table. + - Added support for configuration of SAML crypto hashing algorithms. + - Added support for not allowing Guest invitations to teams that are managed by LDAP Group Sync. + - Added support for custom post types to Compliance exports. + +### Bug Fixes + - Fixed an issue where modifying config files caused compliance exports to run twice. + - Fixed an issue where admins were not able to create LDAP user via /api/v4/users. + - Fixed some bugs related to the [keyboard accessibility](https://docs.mattermost.com/help/getting-started/accessibility.html) feature. + - Fixed issues with Guest Accounts feature, such as an issue where the option to make guest users as team admins was erroneously provided in Manage Teams dialog on **System Console > Users**. + - Fixed an issue where an opened emoji picker floated while the user scrolled in the channel. + - Fixed an issue where "Your message is too long" warning on the right-hand side reply thread overlapped the Preview button. + - Fixed an issue where hitting escape to close autocomplete also closed channel header modal. + - Fixed an issue where negative search filter hypens and occasional random terms were highlighted in search results. + - Fixed an issue where deactivating a user increased Monthly Active Users and Daily Active Users count by 1 in **System Console > Site Statistics**. + - Fixed an issue where **Reporting > Statistics** showed 'Loading...' when the value for any of the statistics was zero. + - Fixed an issue where converting a user to a bot via the command line tool (CLI) did not create an access token and could not be deleted. + - Fixed an issue where archived channels displayed in **System Console -> Channels** page. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``TeamSettings``: + - Added ``LockTeammateNameDisplay`` to add support for System Administrators to control Teammate Name Display at the system level. + - Under ``LdapSettings``: + - Added ``GuestFilter`` to be able to enter an AD/LDAP Filter to use when searching for external users who have Guest Access to Mattermost. + - Under ``SamlSettings``: + - Added ``SignatureAlgorithm`` to be able to choose a signature algorithm used to sign the request. + - Added ``CanonicalAlgorithm`` to be able to choose the canonicalization algorithm. + - Added ``GuestAttribute`` to add support for entering the attribute in the SAML Assertion used to apply a guest role to users. + - Under ``PluginSettings``: + - Added ``RequirePluginSignature`` to add support for requiring valid plugin signatures before starting managed or unmanaged plugins. + - Added ``SignaturePublicKeyFiles`` to add support for specifying public keys to be trusted to validate plugin signatures in addition to the Mattermost plugin signing key built-into the server. + - Under Push Notification Contents: + - Added ``id_loaded`` to add an option for full message content being fetched from the server on receipt (*Available in Enterprise Edition E20*). + - Under ``ServiceSettings``: + - Removed ``ExperimentalLdapGroupSync`` setting. + +### Open Source Components + - Added ``@types/highlight`` in https://github.com/mattermost/mattermost-webapp. + - Added ``@typescript-eslint/parser`` in https://github.com/mattermost/mattermost-webapp. + - Added ``@react-native-community/cameraroll`` in https://github.com/mattermost/mattermost-mobile. + - Added ``@sentry/react-native`` in https://github.com/mattermost/mattermost-mobile. + - Added ``form-data`` in https://github.com/mattermost/mattermost-mobile. + - Added ``react-native-fast-image`` in https://github.com/mattermost/mattermost-mobile. + - Added ``react-navigation-stack`` in https://github.com/mattermost/mattermost-mobile. + - Added ``redux-offline`` in https://github.com/mattermost/mattermost-mobile. + +### API Changes + - Added POST handler for /plugins/marketplace to install marketplace plugins. + - Added a ``search_archived`` API endpoint to be able to search archived channels. + - Added a ``post_unread`` API endpoint to be able to set posts as unread. + +### Websocket Event Changes + - Added marked post as unread Websocket Event. + - Added guests deactivated Websocket Event. + +### Known Issues + - Client-side performance issues seen while typing. + - System Console left-hand side scrollbar may be too dark to see. + - Menu help text for Do Not Disturb is truncated in English. + - Inviting multiple users with valid/allowed and invalid emails causes the invites for the valid users not to be sent. + - Option to invite users by email is displayed even if email invitations are disabled. + - Option to mark posts as unread is unexpectedly available when viewing archived channels. + - Users may need to reinstall and delete cache on Classic apps if launching and logging into the app get stuck. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[3mard](https://github.com/3mard), [a8uhnf](https://github.com/a8uhnf), [aaronrothschild](https://github.com/aaronrothschild), [abdusabri](https://github.com/abdusabri), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [akshaychhajed](https://github.com/akshaychhajed), [ali-farooq0](https://github.com/ali-farooq0), [allenlai18](https://github.com/allenlai18), [alxsah](https://github.com/alxsah), [amyblais](https://github.com/amyblais), [andresoro](https://github.com/andresoro), [anindha](https://github.com/anindha), [AninditaBasu](https://github.com/AninditaBasu), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [ashishbhate](https://github.com/ashishbhate), [avasconcelos114](https://github.com/avasconcelos114), [bradjcoughlin](https://github.com/bradjcoughlin), [brewsterbhg](https://github.com/brewsterbhg), [bvineyar](https://github.com/bvineyar), [cardoso](https://github.com/cardoso), [catalintomai](https://github.com/catalintomai), [chapa](https://github.com/chapa), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [cinlloc](https://github.com/cinlloc), [cjohannsen81](https://github.com/cjohannsen81), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [cpurta](https://github.com/cpurta), [crspeller](https://github.com/crspeller), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [drekar](https://github.com/drekar), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [enolal826](https://github.com/enolal826), [ethervoid](https://github.com/ethervoid), [etoaster](https://github.com/etoaster), [FlaviaBastos](https://github.com/FlaviaBastos), [fm2munsh](https://github.com/fm2munsh), [focusonmx](https://github.com/focusonmx), [g3rv4](https://github.com/g3rv4), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [goku321](https://github.com/goku321), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [HilalNazli](https://github.com/HilalNazli), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [ilgooz](https://github.com/ilgooz), [imisshtml](https://github.com/imisshtml), [iomodo](https://github.com/iomodo), [ishanray](https://github.com/ishanray), [ivanvc](https://github.com/ivanvc), [jabshire](https://github.com/jabshire), [jasonblais](https://github.com/jasonblais), [jaydeland](https://github.com/jaydeland), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jgbaylon](https://github.com/jgbaylon), [jimiolaniyan](https://github.com/jimiolaniyan), [johnthompson365](https://github.com/johnthompson365), [joshuabezaleel](https://github.com/joshuabezaleel), [jozuenoon](https://github.com/jozuenoon), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kanozec](https://github.com/kanozec), [karlmarxlopez](https://github.com/karlmarxlopez), [Kaya_Zeren](https://x.com/kaya_zeren), [kdenz](https://github.com/kdenz), [kosgrz](https://github.com/kosgrz), [KuSh](https://github.com/KuSh), [larkox](https://github.com/larkox), [last-partizan](https://github.com/last-partizan), Lena, [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [M-ZubairAhmed](https://github.com/M-ZubairAhmed), [m4ver1k](https://github.com/m4ver1k), [malaDev](https://github.com/malaDev), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [MathewtheCoder](https://github.com/MathewtheCoder), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [michaelschiffmm](https://github.com/michaelschiffmm), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [natalie-hub](https://github.com/natalie-hub), [nathanmkaya](https://github.com/nathanmkaya), [niklabh](https://github.com/niklabh), [nrekretep](https://github.com/nrekretep), [Pomyk](https://github.com/Pomyk), [pqzx](https://github.com/pqzx), [pradeepmurugesan](https://github.com/pradeepmurugesan), [promulo](https://github.com/promulo), [PunitGr](https://github.com/PunitGr), [r4zorgeek](https://github.com/r4zorgeek), [RajatVaryani](https://github.com/RajatVaryani), [reflog](https://github.com/reflog), [rfoyard](https://github.com/rfoyard), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [SamWolfs](https://github.com/SamWolfs), [saneletm](https://github.com/saneletm), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottleedavis](https://github.com/scottleedavis), [Sheshagiri](https://github.com/Sheshagiri), [sij507](https://github.com/sij507), [sphr](https://github.com/sphr), [srkgupta](https://github.com/srkgupta), [sstaszkiewicz-copperleaf](https://github.com/sstaszkiewicz-copperleaf), [steevsachs](https://github.com/steevsachs), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [sunsingerus](https://github.com/sunsingerus), [svelle](https://github.com/svelle), [thePanz](https://github.com/thePanz), [TonPC64](https://github.com/TonPC64), [TQuock](https://github.com/TQuock), [uhlhosting](https://github.com/uhlhosting), [unlikelygeek](https://github.com/unlikelygeek), [valentijnnieman](https://github.com/valentijnnieman), [ventz](https://github.com/ventz), [vinicio](https://github.com/vinicio), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [wiggin77](https://github.com/wiggin77), [Willyfrog](https://github.com/Willyfrog), [wlsf82](https://github.com/wlsf82), [YuikoTakada](https://github.com/YuikoTakada) + +---- + +## Release v5.17 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +Mattermost v5.17.0 contains medium to high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.17.3, released 2020-01-08** + - Mattermost v5.17.3 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where migrating accounts from email to SAML failed. [MM-21472](https://mattermost.atlassian.net/browse/MM-21472) +- **v5.17.2, released 2019-12-18** + - Mattermost v5.17.2 contains high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.17.1, released 2019-11-25** + - Fixed an issue where leaving a channel does not work in some cases if the channel was open in another webapp or desktop client. [MM-20206](https://mattermost.atlassian.net/browse/MM-20206) +- **v5.17.0, released 2019-11-16** + - Original 5.17.0 release + +### Bug Fixes + - Fixed an issue where saving an empty string on Marketplace URL reset the URL instead of showing an error. + - Fixed an issue where the default permission was such that all users were allowed to invite a guest instead of only System Admins. + - Fixed an issue where Guest users were shown in the list when adding new members to a channel. + - Fixed an issue where attempting to configure uninstalled plugins got stuck at "Loading..." without timeout. + - Fixed an issue where clicking "Search" icon in narrow-width mode caused right-hand side to appear along with loading indicator "...". + - Fixed an issue where ``@all`` notification was still sent to all users when using TAB to press Cancel on the notification prompt. + - Fixed an issue where system messages could trigger mentions for username collisions. + - Fixed an issue where code syntax was not rendering or highlighting as expected in markdown. + - Fixed an issue where users were not able to attach a file from iPad using Safari. + - Fixed an issue where ``/code`` was rendering HTML incorrectly. + - Fixed an issue where clicking "Pinned" icon removed text in the search box. + - Fixed an issue where **Main Menu > Integrations > OAuth 2.0 Applications** page user interface broke when shrinking the window to a small size. + - Fixed an issue where no feedback was given on mobile view when the maximum post length had been exceeded. + - Fixed an issue where dragging or dropping a folder did not scroll the user to the right-hand side text box to make the error more visible. + - Fixed an issue on mobile browser view where the post menu was split in 2 and users were not able to scroll up to see "Add Reaction" option. + - Fixed an issue where pressing and holding on teams and channels in the left-hand side opened the context menu on the Desktop App. + - Fixed an issue where the user popover bled off screen when browser or Desktop App was set to full-screen mode. + - Fixed an issue where clicking locally installed plugins without a URL opened a new tab to the same page. + - Fixed an issue where interactive message buttons and menus were not vertically the same size. + - Fixed an issue where the first element was selected by default in radio elements in interactive buttons. + - Fixed an issue where search with quotation marks was not returning expected results. + - Fixed an issue where bulk importer generated invalid passwords for the user object with a missing password key. + - Fixed an issue where post metadata was returned for deleted posts. + - Fixed an issue where users were not able to use ``api/v4/websocket`` with a trailing slash. + - Fixed an issue with subpaths where in-app System Console links were missing in the ``/subpath`` and resulted in a 404 error. + - Fixed an issue where **Terms of Service** and **Privacy Policy** in **Main Menu > About Mattermost** did not permanently link to Mattermost's policies. + +### config.json + +A setting option was added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + - Under ``ServiceSettings`` in ``config.json``: + - Added ``EnableLatex`` to add an option to enable/disable rendering of latex code. + +### Known Issues + - Deactivating a user increases Monthly Active Users and Daily Active Users count by 1 in **System Console > Site Statistics**. + - Negative search filter hypens and occasional random terms are highlighted in search results. + - Hitting escape to close autocomplete also closes channel header modal. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[a-arias](https://github.com/a-arias), [A-Hilaly](https://github.com/A-Hilaly), [a8uhnf](https://github.com/a8uhnf), [aaronrothschild](https://github.com/aaronrothschild), [abadojack](https://github.com/abadojack), [abdusabri](https://github.com/abdusabri), [abelharisov](https://github.com/abelharisov), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [agnivade](https://github.com/agnivade), [agusl88](https://github.com/agusl88), [akantsevoi](https://github.com/akantsevoi), [akpark](https://github.com/akpark), [akshaychhajed](https://github.com/akshaychhajed), [aladhims](https://github.com/aladhims), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [ananichev](https://github.com/ananichev), [anchepiece](https://github.com/anchepiece), [andresoro](https://github.com/andresoro), [anindha](https://github.com/anindha), [aqche](https://github.com/aqche), [arjitc](https://github.com/arjitc), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [bensooraj](https://github.com/bensooraj), [boonwj](https://github.com/boonwj), [bradjcoughlin](https://github.com/bradjcoughlin), [brewsterbhg](https://github.com/brewsterbhg), [bryanculver](https://github.com/bryanculver), [catalintomai](https://github.com/catalintomai), [cedrickring](https://github.com/cedrickring), [chahat-arora](https://github.com/chahat-arora), [chikei](https://github.com/chikei), [ChrisDobby](https://github.com/ChrisDobby), [chuttam](https://github.com/chuttam), [cinlloc](https://github.com/cinlloc), [codevbus](https://github.com/codevbus), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [CSBatchelor](https://github.com/CSBatchelor), [dailos2coders](https://github.com/dailos2coders), [DaKeiser](https://github.com/DaKeiser), [deanwhillier](https://github.com/deanwhillier), [dedifferentiator](https://github.com/dedifferentiator), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [dnguy078](https://github.com/dnguy078), [drekar](https://github.com/drekar), [DropNib](https://github.com/DropNib), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [FlaviaBastos](https://github.com/FlaviaBastos), [gabrieljackson](https://github.com/gabrieljackson), [gfelixc](https://github.com/gfelixc), [gigawhitlocks](https://github.com/gigawhitlocks), [goku321](https://github.com/goku321), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [guigui64](https://github.com/guigui64), [gupsho](https://github.com/gupsho), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [hector2](https://github.com/hector2), [hectorskypl](https://github.com/hectorskypl), [HelioStrike](https://github.com/HelioStrike), [heowc](https://github.com/heowc), [hmhealey](https://github.com/hmhealey), [hypnoglow](https://github.com/hypnoglow), [iDevoid](https://github.com/iDevoid), [imavroukakis](https://github.com/imavroukakis), [imisshtml](https://github.com/imisshtml), [iomodo](https://github.com/iomodo), [isacikgoz](https://github.com/isacikgoz), [italolelis](https://github.com/italolelis), [iwataka](https://github.com/iwataka), [jairojj](https://github.com/jairojj), [jasminexie](https://github.com/jasminexie), [jasonblais](https://github.com/jasonblais), [jatinjtg](https://github.com/jatinjtg), [JeewhanR](https://github.com/JeewhanR), [jesperhansen17](https://github.com/jesperhansen17), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jkl5616](https://github.com/jkl5616), [joebordes](https://github.com/joebordes), [johnthompson365](https://github.com/johnthompson365), [jordeguevara](https://github.com/jordeguevara), [jorgeruvalcaba](https://github.com/jorgeruvalcaba), [josephk96](https://github.com/josephk96), [JosephSamela](https://github.com/JosephSamela), [joshuabezaleel](https://github.com/joshuabezaleel), [jozuenoon](https://github.com/jozuenoon), [JtheBAB](https://github.com/JtheBAB), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [karanrn](https://github.com/karanrn), [karlmarxlopez](https://github.com/karlmarxlopez), [kashifsoofi](https://github.com/kashifsoofi), [Kaya_Zeren](https://x.com/kaya_zeren), [kethinov](https://github.com/kethinov), [kgeorgiou](https://github.com/kgeorgiou), [larkox](https://github.com/larkox), [laurapareja](https://github.com/laurapareja), Lena, [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [LK4D4](https://github.com/LK4D4), [lucianomagrao](https://github.com/lucianomagrao), [Lumexralph](https://github.com/Lumexralph), [lurcio](https://github.com/lurcio), [malaDev](https://github.com/malaDev), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [mauricio](https://github.com/mauricio), [MayMeow](https://github.com/MayMeow), [mbluemer](https://github.com/mbluemer), [meilon](https://github.com/meilon), [Menelion](https://github.com/Menelion), [mgdelacroix](https://github.com/mgdelacroix), [mhartenbower](https://github.com/mhartenbower), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mistikel](https://github.com/mistikel), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [Mrigank11](https://github.com/Mrigank11), [Muscaw](https://github.com/Muscaw), [Mycobee](https://github.com/Mycobee), [nfriend](https://github.com/nfriend), [nicnicknicky](https://github.com/nicnicknicky), [niklabh](https://github.com/niklabh), [njkevlani](https://github.com/njkevlani), [octoquad](https://github.com/octoquad), [oksmelnik](https://github.com/oksmelnik), [pbitty](https://github.com/pbitty), [Pensu](https://github.com/Pensu), [phillipahereza](https://github.com/phillipahereza), [Phizzard](https://github.com/Phizzard), [pikami](https://github.com/pikami), [Pomyk](https://github.com/Pomyk), [pqzx](https://github.com/pqzx), [pradeepmurugesan](https://github.com/pradeepmurugesan), [ptisserand](https://github.com/ptisserand), [pushkyn](https://github.com/pushkyn), [raghuiamsingh](https://github.com/raghuiamsingh), [RajatVaryani](https://github.com/RajatVaryani), [reflog](https://github.com/reflog), [rfoyard](https://github.com/rfoyard), [rodcorsi](https://github.com/rodcorsi), [rohanjulka19](https://github.com/rohanjulka19), [rv404674](https://github.com/rv404674), [sahilsharma011](https://github.com/sahilsharma011), [SamWolfs](https://github.com/SamWolfs), [sascha-andres](https://github.com/sascha-andres), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottleedavis](https://github.com/scottleedavis), [sdesani](https://github.com/sdesani), [SezalAgrawal](https://github.com/SezalAgrawal), [shahbour](https://github.com/shahbour), [Sheshagiri](https://github.com/Sheshagiri), [simonfrey](https://github.com/simonfrey), [simross](https://github.com/simross), [sourabkumarkeshri](https://github.com/sourabkumarkeshri), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [srkgupta](https://github.com/srkgupta), [steevsachs](https://github.com/steevsachs), [stefan-malcek](https://github.com/stefan-malcek), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tgkouras](https://github.com/tgkouras), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [ThiefMaster](https://github.com/ThiefMaster), [tpaschalis](https://github.com/tpaschalis), [uhlhosting](https://github.com/uhlhosting), [Vaelor](https://github.com/Vaelor), [valentijnnieman](https://github.com/valentijnnieman), [vdepatla](https://github.com/vdepatla), [VictorAvelar](https://github.com/VictorAvelar), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [willdot](https://github.com/willdot), [Willyfrog](https://github.com/Willyfrog), [wyze](https://github.com/wyze), [xrav3nz](https://github.com/xrav3nz) + +---- + +## Release v5.16 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.16.5, released 2020-01-08** + - Mattermost v5.16.5 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where migrating accounts from email to SAML failed. [MM-21472](https://mattermost.atlassian.net/browse/MM-21472) +- **v5.16.4, released 2019-12-18** + - Mattermost v5.16.4 contains high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.16.3, released 2019-11-06** + - (Accessibility) Fixed an issue where keyboard navigation within the right-hand side did not navigate in expected order. [MM-19901](https://mattermost.atlassian.net/browse/MM-19901) +- **v5.16.2, released 2019-10-30** + - Fixed an issue where Permission Schemes was not working properly on an E10 license. [MM-19556](https://mattermost.atlassian.net/browse/MM-19556) + - Fixed an issue where switching to an unread channel sometimes got stuck at "Loading...". [MM-19091](https://mattermost.atlassian.net/browse/MM-19091) +- **v5.16.1, released 2019-10-24** + - Mattermost v5.16.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - (Accessibility) Fixed an issue where "Click here to jump to recent messages" was not accessible via keyboard. [MM-19498](https://mattermost.atlassian.net/browse/MM-19498) + - (Accessibility) Fixed an issue where post options were skipped when tabbing through a post in search results. [MM-19497](https://mattermost.atlassian.net/browse/MM-19497) + - (Accessibility) Fixed an issue where F6 did not allow navigating to the right-hand side when a thread wasn't open. [MM-18117](https://mattermost.atlassian.net/browse/MM-18117) + - Fixed an issue where a change to the production Plugin Marketplace URL wasn't backported to v5.16.0. [MM-19516](https://mattermost.atlassian.net/browse/MM-19516) +- **v5.16.0, released 2019-10-16** + - Original 5.16.0 release + +Mattermost v5.16.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + +#### Removed and Deprecated Features + + - Support for Internet Explorer (IE11) was removed. Learn more in our [forum post](https://forum.mattermost.com/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575). + +### Breaking Changes + - The Mattermost Desktop v4.3.0 release includes a change to how desktop notifications are sent from non-secure URLs (http://). Organizations using non-secure Mattermost Servers (http://) will need to update to Mattermost Server versions 5.16.0+, 5.15.1, 5.14.4 or 5.9.5 (ESR) to continue receiving desktop notifications when using Mattermost Desktop v4.3.0 or later. + - When enabling [Guest Accounts](https://docs.mattermost.com/deployment/guest-accounts.html), all users who have the ability to invite users will be able to invite guests by default. System admins will need to remove this permission on each role via **System Console > Permissions Schemes**. In Mattermost Server version 5.17, the System admin will be the only role to automatically get the invite guest permission, however the fix will not be applicable in 5.16 due to database migration processes. + +### Highlights + +#### Guest Accounts + - Provides a controlled and secure method for users outside of an organization to collaborate with their organization without allowing the guest to access proprietary or confidential information. + +#### Plugin Marketplace + - The integrations marketplace is built into the product and gives system administrators the ability to discover and install Mattermost plugins that are compatible with the server version you are running. + +#### Improved user management + - System Administrators can view a user's team memberships and add a user to additional teams from the System Console without having to be a member of the team. + +### Improvements + +#### User Interface (UI) + - Added support for showing TIF image thumbnail previews. + - Added the ability to remove the custom branding image. + - Added support for showing channel links as links in email notifications. + - Added support for direct message permalinks. + - Changed recent date separators to read Today/Yesterday. + +#### Import/Export + - Added support for including the Theme property on ``UserTeamMemberships`` in bulk exports. + +#### Search + - Added support for excluding results from search. + +#### Notifications + - Enabled account related emails when ``SendEmailNotifications`` is set to false. + +#### Command Line Interface (CLI) + - Added a ``integrity`` CLI command to verify database integrity. + +#### Plugins + - Added the ability for plugins to render custom embed views for posts. + - Added support for including custom System Console components for plugins. + - Added support for plugins to close the right-hand sidebar. + +#### Integrations + - Added support for introductory markdown paragraph in interactive dialogs. + - Added a password type for interactive dialogs. + - Added support for footer and footer_icon in attachments. + - Added support for boolean elements in interactive dialogs. + - Added support for a ``radio`` type in interactive dialogs. + +#### Performance + - Improved perceived performance of the emoji picker. + - Improved post list performance by making thread comments be loaded only when needed. + - Improved quick switcher experience to make the autocomplete feel more like a modal rather than a dropdown. + +#### Administration + - Added the ability for System Administrators to revoke all sessions from all users. + - Added support for System Administrators to make public channels private and private channels public within the **System Console > User Management > Channel Configuration** page when [Experimental Groups feature](https://docs.mattermost.com/administration/config-settings.html#groups-experimental) is enabled. + - Added user Id information in the **System Console > Users** page. + - Updated System Console plugin settings page to expose enable/disable setting. + - Added ability for System Administrators to view a user's team memberships and add users to additional teams within **System Console > User Management > User Configuration**. + +### Bug Fixes + - Fixed an issue where user count did not update if a user automatically joined a channel. + - Fixed an issue where using the channel autocomplete while editing posts caused the current channel to be unread. + - Fixed an issue where users were unable to type in any other channel after leaving a draft post in preview mode in one channel and then switching to another channel. + - Fixed an issue where a user didn't see any unreads when rejoining a team if they were in a Direct Message channel when they left the last team. + - Fixed an issue where some pre-packaged plugins showed as removable in the user interface. + - Fixed an issue where clicking "Edit" of another sub-section in Account Settings appeared to save the setting that was currently being edited in an open sub-section in the same modal. + - Fixed an issue where the System Console user menu did not show all inactive users. + - Fixed an issue where a JS console error appeared when uploading an image from the right-hand side. + - Fixed some bugs related to the new [keyboard accessibility](https://docs.mattermost.com/help/getting-started/accessibility.html) feature. + - Fixed an issue where the ``/leave`` slash command was not working on direct message channels. + - Fixed an issue where the quick channel switcher box opened behind the header attachment expansion. + - Fixed an issue on mobile web view where emoji reaction modal was cut off when adding a second reaction via "+" icon. + - Fixed an issue where the username was not shown in the left-hand side on mobile web view. + - Fixed an issue where "Thumbs up" emoji did not get added to "Recently Used" section. + - Fixed an issue where trailing white space was not ignored when saving a bot username. + - Fixed an issue where enabling channel group constraints turned the admin site blank. + - Fixed an issue where SQL connections closed prematurely for clusters. + - Fixed an issue where absolute paths were not honoured in SAML certificates. + +### config.json +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``PluginSettings``: + - Added ``EnableMarketplace`` (default to true) and ``MarketplaceUrl`` (default to ``https://marketplace.integrations.mattermost.com``), to enable Plugin Marketplace feature. + - Under ``GuestAccountsSettings``: + - Added ``Enable``, ``AllowEmailAccounts``, ``EnforceMultifactorAuthentication``, and ``RestrictCreationToDomains``, to enable Guest Accounts feature. + - Changed ``SqlSettings.DataSource``, ``ElasticsearchSettings.ConnectionUrl``, and ``EmailSettings.SMTPServer`` to default to using localhost (instead of dockerhost). + - Changed ``NativeAppSettings.AppDownloadLink`` to default to ``https://mattermost.com/download/#mattermostApps`` (instead of ``https://mattermost.com/download/``). + +### Open Source Components + - Added ``react-native-android-open-settings`` in https://github.com/mattermost/mattermost-mobile. + - Added ``react-native-haptic-feedback`` in https://github.com/mattermost/mattermost-mobile. + - Added ``DefinitelyTyped`` in https://github.com/mattermost/mattermost-webapp. + - Added ``node-semver`` in https://github.com/mattermost/mattermost-webapp. + - Added ``regenerator`` in https://github.com/mattermost/mattermost-webapp. + - Added ``typescript`` in https://github.com/mattermost/mattermost-webapp. + +### API Changes + - Added a new ``GET /plugins/marketplace`` API endpoint added to list marketplace plugins. + - Added a new ``PUT /channels/:channel_id/privacy`` API endpoint to update the privacy of a channel. + - Added a new ``POST /site_url/test to test`` API endpoint to test the configured site URL. + - Added a new ``POST /teams/:team_id/invite-guests/email`` API endpoint to invite guest users by email. + - Added new ``POST /users/:user_id/promote`` and ``POST /users/:user_id/demote`` API endpoints to promote and demote users to guest accounts. + - Updated the ``PUT /channels/:channel_id/patch`` API endpoint to ensure that the requestor user has permission to see each channel member. + - Updated the ``GET /channels/:channel_id/stats`` API endpoint to include the pinned post and guest counts. + - ``PUT /roles/:role_id/patch`` API endpoint now ensures that guest account roles are not updatable without the required license and feature SKU. + - Several OAuth API endpoints were removed. + +### Database Changes + - Added a change to the ``Tokens`` table ``Extra`` column's data type. + +### Known Issues + - Saving an empty string on Plugin Marketplace URL resets the URL instead of showing an error. + - Switching to an unread channel sometimes gets stuck at "Loading...". + - Attempting to configure uninstalled plugins get stuck at "Loading..." without timeout. + - Enabling/disabling guest access in System Console fails. + - Guest users are shown in the list when adding new members to a channel. + - Negative search filter hypens and occasional random terms are highlighted in search results. + - ``@all`` notification is still sent to all users when using TAB to press Cancel on the notification prompt. + - System messages may trigger mentions for name collisions. + - Hitting escape to close autocomplete also closes channel header modal. + - Pressing and holding on teams and channels in the left-hand side opens the context menu on desktop apps. + - Modifying config files causes compliance exports to run twice. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +[a-arias](https://github.com/a-arias), [aaronrothschild](https://github.com/aaronrothschild), [abdusabri](https://github.com/abdusabri), [adarj](https://github.com/adarj), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [agusl88](https://github.com/agusl88), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [aneeeshp](https://github.com/aneeeshp), [ankitrgadiya](https://github.com/ankitrgadiya), anuragbhd, [arjitc](https://github.com/arjitc), [arshchimni](https://github.com/arshchimni), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [bradjcoughlin](https://github.com/bradjcoughlin), [cardoso](https://github.com/cardoso), [carlosasj](https://github.com/carlosasj), [chikei](https://github.com/chikei), [chuttam](https://github.com/chuttam), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [DarrellRichards](https://github.com/DarrellRichards), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [dhadiseputro](https://github.com/dhadiseputro), [DHaussermann](https://github.com/DHaussermann), [enahum](https://github.com/enahum), [esdrasbeleza](https://github.com/esdrasbeleza), [esethna](https://github.com/esethna), [freerider7777](https://github.com/freerider7777), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [hector2](https://github.com/hector2), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [hvhallmann](https://github.com/hvhallmann), [imisshtml](https://github.com/imisshtml), [iomodo](https://github.com/iomodo), [it33](https://github.com/it33), [janvt](https://github.com/janvt), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jkl5616](https://github.com/jkl5616), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [liusy182](https://github.com/liusy182), [Lumexralph](https://github.com/Lumexralph), [lurcio](https://github.com/lurcio), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [MatthewDorner](https://github.com/MatthewDorner), [mcrwfrd](https://github.com/mcrwfrd), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [nfriend](https://github.com/nfriend), [niklabh](https://github.com/niklabh), [OCram85](https://github.com/OCram85), [paddatrapper](https://github.com/paddatrapper), [patrickkang](https://github.com/patrickkang), [pbitty](https://github.com/pbitty), [phillipahereza](https://github.com/phillipahereza), [QamarFarooq](https://github.com/QamarFarooq), [RajatVaryani](https://github.com/RajatVaryani), [reflog](https://github.com/reflog), [renilJoseph](https://github.com/renilJoseph), [rodcorsi](https://github.com/rodcorsi), [rohanjulka19](https://github.com/rohanjulka19), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [sbishel](https://github.com/sbishel), [scottleedavis](https://github.com/scottleedavis), [Selimix](https://github.com/Selimix), [sij507](https://github.com/sij507), [sowmiyamuthuraman](https://github.com/sowmiyamuthuraman), [srkgupta](https://github.com/srkgupta), [stoerchl](https://github.com/stoerchl), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [tejashreecd](https://github.com/tejashreecd), [tekminewe](https://github.com/tekminewe), [tgkouras](https://github.com/tgkouras), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [threepwood-mm](https://github.com/threepwood-mm), [tnir](https://github.com/tnir), [ulhosting](https://github.com/uhlhosting), [valentijnnieman](https://github.com/valentijnnieman), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [Willyfrog](https://github.com/Willyfrog), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.15 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.15.5, released 2020-01-08** + - Fixed an issue where migrating accounts from email to SAML failed. [MM-21472](https://mattermost.atlassian.net/browse/MM-21472) +- **v5.15.4, released 2019-12-18** + - Mattermost v5.15.4 contains high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.15.3, released 2019-11-06** + - (Accessibility) Fixed an issue where keyboard navigation within the right-hand side did not navigate in expected order. [MM-19901](https://mattermost.atlassian.net/browse/MM-19901) + - Fixed an issue where switching to an unread channel sometimes got stuck at "Loading...". [MM-19091](https://mattermost.atlassian.net/browse/MM-19091) +- **v5.15.2, released 2019-10-24** + - Mattermost v5.15.2 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - (Accessibility) Fixed an issue where "Click here to jump to recent messages" was not accessible via keyboard. [MM-19498](https://mattermost.atlassian.net/browse/MM-19498) + - (Accessibility) Fixed an issue where post options were skipped when tabbing through a post in search results. [MM-19497](https://mattermost.atlassian.net/browse/MM-19497) + - (Accessibility) Fixed an issue where F6 did not allow navigating to the right-hand side when a thread wasn't open. [MM-18117](https://mattermost.atlassian.net/browse/MM-18117) +- **v5.15.1, released 2019-10-11** + - Fixed an issue that will be introduced with a change in upcoming server v5.16 and desktop app v4.3 releases where desktop notifications will be broken as the desktop app will no longer be able to directly interact with the web app. [MM-18819](https://mattermost.atlassian.net/browse/MM-18819) + - Fixed an issue where server-side telemetry was not reporting back after 5.14 release. [MM-18115](https://mattermost.atlassian.net/browse/MM-18115) +- **v5.15.0, released 2019-09-16** + - Original 5.15.0 release + +Mattermost v5.15.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Bug Fixes + - Fixed an issue where an invalid locale caused a white screen. + - Fixed an issue where rate limited posts failed to load threads. + - Improved the group linking failure error message and logging to make it clear that the group id attribute is most likely misconfigured. + - Fixed an issue where the right-hand side did not fetch messages on socket reconnect when a different channel was in center. + - Fixed an issue where posting a message in an empty channel sometimes caused the channel to display a loading spinner. + - Fixed an issue where deleting the last post in a channel caused the channel to only display a loading spinner. + - Fixed an issue with an absence of unread badges on private channels on mobile apps. + - Fixed an issue where at-sign was missing in front of usernames in push notifications. + - Fixed some bugs related to the new [keyboard accessibility](https://docs.mattermost.com/help/getting-started/accessibility.html) feature. + - Fixed an issue where the "@" sign was replaced with keyboard accessibility feature on Italian keyboard. + - Fixed an issue where joining a new channel with few posts sometimes did not take the user to the bottom of the channel. + - Fixed an issue where scroll pop sometimes occured with embedded YouTube links. + - Fixed an issue with stuttery dropdowns in Safari. + - Fixed an issue where clicking on a post would highlight it after returning to the tab/window. + - Fixed an issue where SVG attachments bled over into subsequent posts. + - Fixed an issue where long posts were overlapping in compact view. + - Fixed an issue where the expand/collapse button in images were underlined. + - Fixed an issue where incoming webhook URL was clickable and shown as a link on the desktop app. + - Fixed an issue where the markdown helper text was missing on Edit Channel Header modal. + - Fixed an issue on mobile view where Edit/Delete/More options were not displayed on the right-hand side after a message was posted. + - Fixed an issue where the channel mute icon was displayed in the incorrect position when a channel was muted. + - Fixed an issue where there was an extra menu divider on Town Square channel menu. + - Fixed an issue on Firefox where post and comment boxes were expanding too early. + - Fixed an issue where focus was not automatically set on text input box after selecting an emoji from the emoji picker. + - Fixed an issue where channel changes were not updated for other users until refresh. + - Fixed an issue where changes to Account Settings were being saved even when the user did not click the **Save** button. + - Fixed an issue where some of the links in System Console opened the page on the same tab instead of opening it on a new browser/tab. + - Fixed an issue where installing a plugin via URL failed if the download took longer then 30 seconds. + - Fixed an issue where plugins did not get disabled when removing them. + - Fixed an issue where plugin translation files were not updated on web-clients when plugins were upgraded. + - Fixed an issue where bots could not be added to any team if server wide email domain restriction was enabled. + - Fixed an issue where pagination broke when adding users to a team. + - Fixed an issue where list of users were not paginated on warning modal for LDAP group sync team / channel removal. + - Fixed an issue where enabling LDAP Trace prevented login. + - Fixed an issue where Google User API Endpoint showed an outdated helper text. + - Fixed an issue where a markdown image with an SVG briefly displayed for sender with ``EnableSVGs`` set to false. + - Fixed an issue with an incorrect error message on Custom URL Schemes field. + +### Known Issues + - JS console error may appear when uploading an image from the right-hand side. + - Scroll pop may occur in channels with markdown images. + - Trailing white space is not ignored when saving bot user name. + - Clicking "Edit" of another sub-section in Account Settings appears to save the setting that is currently being edited in an open sub-section in the same modal. + - Some pre-packaged plugins show as removable in the User Interface. + - If ``ExperimentalStrictCSRFEnforcement`` is set to True, attempts to use ``/jira subscribe`` fail. + - Users are unable to type in any other channel after leaving a draft post in preview mode in one channel and then switching to another channel. + - User count in a channel does not update until after refresh if a user automatically joins a channel. + - Scrolling upwards while loading more posts sometimes causes you to jump upwards on Firefox. + - Modifying config files causes compliance exports to run twice. + - Using channel autocomplete while editing post causes current channel to be unread. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + + - [a-arias](https://github.com/a-arias), [aaronrothschild](https://github.com/aaronrothschild), [accxiagmbh](https://github.com/accxiagmbh), [aeomin](https://translate.mattermost.com/user/aeomin/), [Akito13](https://github.com/Akito13), [ali-farooq0](https://github.com/ali-farooq0), [Amonith](https://github.com/Amonith), [amyblais](https://github.com/amyblais), [angelbarrera92](https://github.com/angelbarrera92), [ankitrgadiya](https://github.com/ankitrgadiya), [asaadmahmood](https://github.com/asaadmahmood), [atpons](https://github.com/atpons), [bradjcoughlin](https://github.com/bradjcoughlin), [cardoso](https://github.com/cardoso), [cdncat](https://github.com/cdncat), [chikei](https://github.com/chikei), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [eilgin](https://github.com/eilgin), [ejachang](https://github.com/ejachang), [elyscape](https://github.com/elyscape), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [eshyong](https://github.com/eshyong), [ethervoid](https://github.com/ethervoid), [g3rv4](https://github.com/g3rv4), [gabrieljackson](https://github.com/gabrieljackson), [gigawhitlocks](https://github.com/gigawhitlocks), [goku321](https://github.com/goku321), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [hahmadia](https://github.com/hahmadia), [hanzei](https://github.com/hanzei), [healthchecks](https://github.com/healthchecks), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [iomodo](https://github.com/iomodo), [irbrad](https://github.com/irbrad), [it33](https://github.com/it33), [ivenk](https://github.com/ivenk), [janvt](https://github.com/janvt), [jasonblais](https://github.com/jasonblais), [jesperhansen17](https://github.com/jesperhansen17), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jozuenoon](https://github.com/jozuenoon), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kdenz](https://github.com/kdenz), [kosgrz](https://github.com/kosgrz), [krjn](https://github.com/krjn), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [Lisenish](https://github.com/Lisenish), [liusy182](https://github.com/liusy182), [lurcio](https://github.com/lurcio), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [MatthewDorner](https://github.com/MatthewDorner), [matthewshirley](https://github.com/matthewshirley), [meilon](https://github.com/meilon), [metanerd](https://github.com/metanerd), [mgdelacroix](https://github.com/mgdelacroix), [michaelgamble](https://github.com/michaelgamble), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [pichouk](https://github.com/pichouk), [Rajakavitha1](https://github.com/Rajakavitha1), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [sadohert](https://github.com/sadohert), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [sij507](https://github.com/sij507), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [threepwood-mm](https://github.com/threepwood-mm), [tnir](https://github.com/tnir), [ulhosting](https://github.com/uhlhosting), [uusijani](https://github.com/uusijani), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [Willyfrog](https://github.com/Willyfrog), [wyze](https://github.com/wyze) + +---- + +## Release v5.14 - [Feature Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +- **v5.14.5, released 2019-10-24** + - Mattermost v5.14.5 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.14.4, released 2019-10-11** + - Fixed an issue that will be introduced with a change in upcoming server v5.16 and desktop app v4.3 releases where desktop notifications will be broken as the desktop app will no longer be able to directly interact with the web app. [MM-18819](https://mattermost.atlassian.net/browse/MM-18819) + - Fixed an issue where server-side telemetry was not reporting back after 5.14 release. [MM-18115](https://mattermost.atlassian.net/browse/MM-18115) +- **v5.14.3, released 2019-09-16** + - Fixed an issue where edited posts were not included in Compliance Export (Beta). [MM-18522](https://mattermost.atlassian.net/browse/MM-18522) +- **v5.14.2, released 2019-08-30** + - Fixed an issue where Mattermost crashed when date-related search terms `on:` `before:` and `after:` were used in search. [MM-18143](https://mattermost.atlassian.net/browse/MM-18143) +- **v5.14.1, released 2019-08-28** + - Fixed issues with [keyboard accessibility](https://docs.mattermost.com/help/getting-started/accessibility.html) where post and search textboxes did not read characters when using the arrow keys to move back and forth through the text. [MM-17964](https://mattermost.atlassian.net/browse/MM-17964) and [MM-17974](https://mattermost.atlassian.net/browse/MM-17974) +- **v5.14.0, released 2019-08-16** + - Original 5.14.0 release + +Mattermost v5.14.0 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Compatibility + +#### Removed and Deprecated Features + + - We are removing support for Internet Explorer (IE11) in Mattermost v5.16.0, which releases on October 16, 2019. Learn more in our [forum post](https://forum.mattermost.com/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575). + +### Breaking Changes + + - Webhooks are now only displayed if the user is the creator of the webhook or a system administrator. + - With the update from Google+ to Google People, system admins need to ensure the ``GoogleSettings.Scope`` config.json setting is set to ``profile email`` and ``UserAPIEndpoint`` setting should be set to ``https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata`` per [updated documentation](https://docs.mattermost.com/deployment/sso-google.html). + +```{Important} +If you upgrade from a release earlier than 5.13, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Keyboard navigation and screen reader improvements + + - New keyboard navigation improvements enable you to move between app regions—like the post list, channel sidebar, and header—using F6 on the Desktop App and CTRL-F6 on a web browser. You can also use TAB, arrow keys, and ENTER to interact with buttons, links, and other elements in Mattermost. + - Screen readers are now much more compatible with Mattermost. Buttons, links, and app regions now have accurate readouts that enable visually impaired users to use Mattermost productively with screen readers. + - [Learn more](https://docs.mattermost.com/help/getting-started/accessibility.html) + +#### Bidirectional scrolling to land on oldest unread post + - No more scrolling required to get to the oldest unread post. Now when the channel opens when there are unreads it opens at the new messages line, regardless of how many unreads exist since the last time the user viewed the channel. + +#### Jira V2.1 + - Full list of features in v2.1: https://github.com/mattermost/mattermost-plugin-jira#jira-21-features. + +#### System Console tools to manage LDAP Groups within Teams and Channels (EE) + - New Team and Channel pages in the System Console allow administrators to easily manage teams and channels membership with LDAP Group Synchronization instead of using the CLI group commands released in v5.12. + +#### Pre-packaged Plugins + - [Jenkins plugin](https://github.com/mattermost/mattermost-plugin-jenkins) for interacting with jobs and builds via slash commands in Mattermost. + - [Antivirus plugin](https://github.com/mattermost/mattermost-plugin-antivirus) for scanning files uploaded to Mattermost. + - [GitLab plugin](https://github.com/mattermost/mattermost-plugin-gitlab) for getting notifications in Mattermost about mentions, review requests and comments. + +### Improvements + +#### User Interface (UI) + - Added support for allowing ``+`` and ``.`` in **System Console > Customization > Posts > Custom URL Schemes**. + - Added support for Range on files needed by Safari to view videos. + - Added ability to add info cards to the right-hand side section. + - Added support for rendering emojis in Message Attachment field titles. + - Changed "About" section references to use the site name when it is configured in **System Console > Custom Branding > Site Name**. + - Combined "Send messages on CTRL+ENTER" with code block setting. + - Added ability to upload files on paste when file constructor is not supported (ie. in Edge or IE11). + +#### Import/Export + - Added the ability to import Slack corporate export files with direct messages, group messages and private channels. + - Added support for exporting Global Relay to zip file. + +#### Webhooks +- ``EnableWebhookDebugging`` now logs the request id for additional context when debugging. + - Added support for plugins to dismiss posts through the ``MessageWillBePosted`` hook. Dismissed posts no longer show up as a client-side error. + - Added an optional "icon_emoji" field to incoming webhooks to use an emoji in place of the display picture when the webhook posts into Mattermost. + +#### Integrations + - Added support for interactive dialogs without elements, e.g. for confirmation dialogs. + - Added support for relative links in interactive message buttons, simplifying plugin development. + +#### Plugins + - Added support for plugins to override right-hand sidebar. + - Added support for plugins to trigger interactive dialogs programmatically, instead of only after a user action. + +#### Bot Accounts + - Added an identifier for compliance exports when a message is posted by a bot account. + - Created a dedicated System Console page at /admin_console/integrations/bot_accounts to organize bot configuration options. + +#### Command Line Interface (CLI) + - Added support for converting bot accounts to user accounts with email/password login through the CLI. + - Extended the config migrate command to handle SAML keys and certificates. + - Updated CLI channel list and search commands to show if a channel is private. + - Create CLI command "team modify" to modify team's privacy setting. + +#### Administration + - Office365 SSO was promoted out of beta. + - Removed maximum length from ``LinkMetadata`` value so that links can generate OpenGraph previews and be stored in the database. + - The config.json file is now generated with build time using defaults in code and not in ``default.json``. + - Added new settings to have more control over ``BindAddress`` and ``AdvertiseAddress`` in the cluster server to allow users to configure properly in situations where the servers are communicating through another server using NAT. + - implemented enhanced logging for CSRF warnings by adding the following information to each request: Remote Adddress, Path, User ID, Session ID. + +#### Enterprise Edition (EE) + - Added support for signing SAML requests, as required for Infosec approval. + - Added support for configuring the interface used for cluster peer discovery in High Availability clusters. + +### Bug Fixes + - Fixed an issue where pagination of group members was broken in LDAP Groups. + - Fixed an issue where the options to leave a team was disabled for all teams and not just the primary team when a primary team was set. + - Fixed an issue where bulk import got stuck when importing lines were missing the "type" entry. + - Fixed an issue where titles for webhooks, commands and OAuth apps were no longer bolded in the System Console. + - Fixed an issue where disabling email notifications also disabled email invites. + - Fixed an issue where Admins were shown a warning of a user's bot being deactivated even if they already were. + - Fixed an issue where a bot profile image disappeared when saving bot details. + - Fixed an issue where plus-sign was not visible on mobile browser view for reacting with a new emoji next to existing reactions. + - Fixed an issue in the System Console where the UserID in User Activity Logs changed from email to UserID. + - Fixed an issue where user got a notification to add a bot to a channel when mentioning it. + - Fixed an issue where permanenently deleting a bot user didn't remove it from the bots table. + - Fixed an issue where a scroll pop was caused by large image dimensions in markdown. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``ClusterSettings`` in ``config.json``: + - Added ``NetworkInterface`` to allow configuring devices to detect the IP in High Availability clusters. + - Added ``BindAddress`` and ``AdvertiseAddress`` to add more control over bind and advertising address in a cluster server. + - Under ``ComplianceSettings`` in ``config.json``: + - Added ``SignRequest`` to add support for signing SAML requests. + - Under ``PluginSettings`` in ``config.json``: + - Added ``AllowInsecureDownloadUrl`` to allow servers to download and install a plugin from a remote url via the System Console. + +### Open Source Components + + - Added ``core-js`` in https://github.com/mattermost/mattermost-mobile/. + - Added ``deepmerge`` in https://github.com/mattermost/mattermost-mobile/. + - Removed ``react-native-bottom-sheet`` from https://github.com/mattermost/mattermost-mobile/. + - Added ``react-hot-loader`` in https://github.com/mattermost/mattermost-webapp. + - Removed ``@babel/polyfill`` from https://github.com/mattermost/mattermost-webapp. + - Removed ``redux-persist-transform-filter`` from https://github.com/mattermost/mattermost-webapp. + - Removed ``url-search-params-polyfill`` from https://github.com/mattermost/mattermost-webapp. + - Removed ``whatwg-fetch`` from https://github.com/mattermost/mattermost-webapp. + +### API Changes + - Migrated user API endpoint from Google+ API to People API. + - Added ``api/v4/channels/group/search`` API endpoint to return the group channels whose members' usernames match the search term. + - Added ``/api/v4/channels/:channel_id/members_minus_group_members`` API endpoint to determine users who will be removed from a group-synchronized channel. + - Added ``api/v4/posts/unread`` API endpoint to support landing on the last unread post. + - Added ``api/v4/teams/:team_id/members_minux_group_members`` API endpoint to determine users who will be removed from a group-synchronized team. + - Added ``api/v4/users/group_channels`` API endpoint to get an object containing a key per group channel id in the query and its value as a list of users members of that group channel. + - Added ``api/v4/sessions/revoke/all`` API endpoint to add the ability to revoke sessions from all users. + +#### Plugin API + - Added ``GetBotIconImage``, ``SetBotIconImage`` and ``DeleteBotIconImage`` API endpoints to control bot icon images. + - Added ``api/v4/plugins/install_from_url`` API endpoint to allow server to download and install a plugin from a remote url. + +### Known Issues + - Users are unable to type in any other channel after leaving a draft post in preview mode in one channel and then switching to another channel. + - Google User API Endpoint shows outdated helper text. + - Making a post in an empty channel sometimes causes the channel to display a loading spinner. + - Deleting the last post in a channel causes the channel to only display a loading spinner. + - Markdown helper text is missing on Edit Channel Header modal. + - User count in a channel does not update until after refresh if a user automatically joins a channel. + - Long posts might overlap in compact view. + - Joining a new channel with few posts might not take the user to the bottom of the channel. + - Missing messages can be caused if network fails on API calls. + - Search help text popover may not display on narrow screen view. + - Expand/collapse in image icons are underlined. + - Messages may not load when opening a channel with multiple unread messages. + - Scrolling upwards while loading more posts sometimes causes you to jump upwards on Firefox. + - Post and comment boxes are expanding too early on Firefox. + - Modifying config files causes compliance exports to run twice. + - Using channel autocomplete while editing post causes current channel to be unread. + - Scroll pop may occur with embedded YouTube links. + - Clicking on a post will highlight it after returning to the tab/window. + - Plugin translation files are not updated on web-client when plugins are upgraded. + - Changes to Account Settings are being saved even when user does not clicks on Save button. + - SVG attachments bleed over into subsequent posts. + - Custom-Attributes plugin might crash. + - Pagination breaks when adding users to a team. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + + - [a-arias](https://github.com/a-arias), [aaronrothschild](https://github.com/aaronrothschild), [aayushbisen](https://github.com/aayushbisen), [adzimzf](https://github.com/adzimzf), [aeomin](https://translate.mattermost.com/user/aeomin/), [AGMETEOR](https://github.com/AGMETEOR), [alejandrosame](https://github.com/alejandrosame), [ali-farooq0](https://github.com/ali-farooq0), [alxsah](https://github.com/alxsah), [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [bbodenmiller](https://github.com/bbodenmiller), [bnoggle](https://github.com/bnoggle), [bradjcoughlin](https://github.com/bradjcoughlin), [chikei](https://github.com/chikei), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [devinbinnie](https://github.com/devinbinnie), [DSchalla](https://github.com/DSchalla), [elyscape](https://github.com/elyscape), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [eshyong](https://github.com/eshyong), [gabrieljackson](https://github.com/gabrieljackson), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [hvhallmann](https://github.com/hvhallmann), [Hyaxia](https://github.com/Hyaxia), [Inconnu08](https://github.com/Inconnu08), [irbrad](https://github.com/irbrad), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jesperhansen17](https://github.com/jesperhansen17), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnthompson365](https://github.com/johnthompson365), [Jonany](https://github.com/Jonany), [joshuabezaleel](https://github.com/joshuabezaleel), [justinegeffen](https://github.com/justinegeffen), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [keaton185](https://github.com/keaton185), [kosgrz](https://github.com/kosgrz), [krjn](https://github.com/krjn), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lpadgett](https://github.com/lpadgett), [lurcio](https://github.com/lurcio), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mounicapaladugu](https://github.com/mounicapaladugu), [mzaks](https://github.com/mzaks), [noxer](https://github.com/noxer), [ollykel](https://github.com/ollykel), [PeterDaveHello](https://github.com/PeterDaveHello), [phillipahereza](https://github.com/phillipahereza), [piperRyan](https://github.com/piperRyan), [Rajakavitha1](https://github.com/Rajakavitha1), [RajatVaryani](https://github.com/RajatVaryani), [rajiv-k](https://github.com/rajiv-k), [reflog](https://github.com/reflog), [rexredinger](https://github.com/rexredinger), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [Selimix](https://github.com/Selimix), [SezalAgrawal](https://github.com/SezalAgrawal), [srkgupta](https://github.com/srkgupta), [steevsachs](https://github.com/steevsachs), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tapaswenipathak](https://github.com/tapaswenipathak), [tekminewe](https://github.com/tekminewe), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [ulhosting](https://github.com/uhlhosting), [VolatianaYuliana](https://github.com/VolatianaYuliana), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [Willyfrog](https://github.com/Willyfrog) + +---- + +## Release v5.13 - [Quality Release](https://docs.mattermost.com/process/release-faq.html#release-overview) + +Mattermost v5.13.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.13.3, released 2019-08-22** + - Mattermost v5.13.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.13.2, released 2019-07-24** + - Fixed performance issues in channels with large message history due to a change made to posts query. [MM-16936](https://mattermost.atlassian.net/browse/MM-16936) + - Fixed an issue where some settings were not visible in the System Console. [MM-17114](https://mattermost.atlassian.net/browse/MM-17114) + - Fixed an issue where announcement banner overlapped content. [MM-17115](https://mattermost.atlassian.net/browse/MM-17115) + - Fixed an issue where the scroll position was not at the new message indicator on switching channels when there were 30-60 unread messages. [MM-17078](https://mattermost.atlassian.net/browse/MM-17078) +- **v5.13.1, released 2019-07-19** + - Fixed an issue with Jira plugin where creating or attaching to Jira issues failed due to GDPR changes released by Atlassian. Affected Jira Cloud only, not Jira Server or Jira Data Center. [MM-17060](https://mattermost.atlassian.net/browse/MM-17060) + - Fixed an issue in server logs where messages related to OpenGraph API were unnecessarily reported as errors. [MM-17043](https://mattermost.atlassian.net/browse/MM-17043) + - Fixed an issue in the System Console without an Enterprise Edition license where **Push Notification Contents** setting was not available. [MM-17008](https://mattermost.atlassian.net/browse/MM-17008) +- **v5.13.0, released 2019-07-16** + - Original 5.13.0 release + +### Compatibility + +#### Removed and Deprecated Features + + - We are removing support for Internet Explorer (IE11) in Mattermost v5.16.0, which releases on October 16, 2019. Learn more in our [forum post](https://forum.mattermost.com/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575). + - v4.10.0 as our current Extended Support Release (ESR) is coming to the end of its life cycle. We will be implementing version v5.9.0 as a new ESR starting July 16, 2019. Learn more in our [forum post](https://forum.mattermost.com/t/extended-support-release-update/7099). + +### Bug Fixes + - Fixed an issue where changing the timezone setting to "Set automatically" did not work on the mobile app. + - Fixed an issue where the channel introduction content sometimes disappeared on opening a channel. + - Fixed an issue with missing messages. + - Fixed an issue where disabling Join/Leave Messages and switching to a specific channel caused a white screen. + - Fixed an issue where the SMTP server password was no longer concealed in the System Console. + - Fixed an issue where Notifications and Plugins settings were missing in the System Console for restricted system administrators. + - Fixed an issue where "Enable AD/LDAP Group Sync" was visible in experimental System Console settings section in Team Edition servers. + - Fixed an issue where **System Console > SMTP > Connection Security** setting was missing in Team Edition servers. + - Fixed an issue where "Allow Mobile upload/download Files" options in the System Console where not hidden in Team Edition servers. + - Fixed an issue where channel links did not work inside brackets. + - Fixed an issue where uploading a team icon image fired a JS console error and a blank image preview. + - Fixed an issue on Safari where a user jumped to the top of the Direct Messages selection list every few seconds. + - Fixed an issue where "Error populating syncables" was seen on login when LDAP groups tried to add a user to a team that was at its maximum number of users. + - Fixed an issue where the slash command ``/rename`` was restricted to 22-character maximum channel name length. + - Fixed an issue where Manage Members menu was visible even if a user did not have Manage Member permissions when viewing the Main Menu. + - Fixed an issue where the "Set a Header" button in the channel introduction was not clickable. + - Fixed an issue where Group Message and private channel icons in the sidebar were misaligned. + - Fixed an issue where custom emojis sometimes overlapped in messages. + - Fixed an issue where bot tags were misaligned in search results and in the "in:" modifier in the search bar autocomplete. + - Fixed an issue where the post menu divider had a gap in mobile view. + - Fixed an issue where the bottom of right-hand side was cut off in tablet view. + - Fixed an issue where the channel dropdown menu user interface was broken in mobile view when Zoom plugin was enabled. + - Fixed an issue where the Save button was hidden in the System Console when a banner was displayed at the top of the page. + - Fixed an issue where users were not able to search for split parts of first/last names or for split characters such as ``_`` with elasticsearch autocomplete enabled. + - Fixed an issue where OAuth endpoints returned application/json content type for HTML redirects. + - Fixed an issue where json responses were not returned for errors on oauth API endpoints, and a 500 error was returned instead of 4xx errors. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``ElasticsearchSettings`` in ``config.json``: + - Added ``SkipTLSVerification`` to ignore certificate verification for Elasticsearch. + +#### Open Source Components + + - Added ``moment-timezone`` in https://github.com/mattermost/mattermost-redux/. + +#### Database Changes + + - ``plugins`` type entries in the ``Jobs`` table will be purged on upgrade. This job was incorrectly configured to run every minute, spamming the table with mostly useless records. All old records will be removed on upgrade, and the job will run daily instead. + +### Known Issues + - Cannot leave any team when a default [primary team](https://docs.mattermost.com/administration/config-settings.html#primary-team-experimental) is set. + - Titles for webhooks, commands and OAuth apps are no longer bolded in the System Console. + - Users can get logged out of server without a session expiry notification. + - Desktop app hangs on opening emoji picker. + - When a primary team is set, the options to leave a team is disabled for all teams, not just the primary team. + - Plugin crashes the server when calling ``w.WriteHeader(0)``. + - Bot account profile image disappears when saving bot details. + - Custom emoji containing specified letters do not appear in emoji autocomplete, unless they start with the letters or have been returned in the autocomplete before. + - Buttons inside ephemeral messages are not clickable / functional on the mobile app. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + + - [aaronrothschild](https://github.com/aaronrothschild), [aeomin](https://translate.mattermost.com/user/aeomin/), [adzimzf](https://github.com/adzimzf), [alxsah](https://github.com/alxsah), [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [Banyango](https://github.com/Banyango), [bbodenmiller](https://github.com/bbodenmiller), [bezumkin](https://github.com/bezumkin), [bolariin](https://github.com/bolariin), [bradjcoughlin](https://github.com/bradjcoughlin), [carmo-evan](https://github.com/carmo-evan), [chikei](https://github.com/chikei), [cjohannsen81](https://github.com/cjohannsen81), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cseeger-epages](https://github.com/cseeger-epages), [Dak425](https://github.com/Dak425), [danmaas](https://github.com/danmaas), [deanwhillier](https://github.com/deanwhillier), dependabot bot, [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [elyscape](https://github.com/elyscape), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [ewwollesen](https://github.com/ewwollesen), [gabrieljackson](https://github.com/gabrieljackson), [georgewitteman](https://github.com/georgewitteman), [GianOrtiz](https://github.com/GianOrtiz), [giorgosdi](https://github.com/giorgosdi), [glebtv](https://github.com/glebtv), [goku321](https://github.com/goku321), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [hanzei](https://github.com/hanzei), [harshilsharma63](https://github.com/harshilsharma63), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [Inconnu08](https://github.com/Inconnu08), [iomodo](https://github.com/iomodo), [it33](https://github.com/it33), [ivenk](https://github.com/ivenk), [jasonblais](https://github.com/jasonblais), [jesperhansen17](https://github.com/jesperhansen17), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jkl5616](https://github.com/jkl5616), [joewaitye](https://github.com/joewaitye), [johnthompson365](https://github.com/johnthompson365), [Jonany](https://github.com/Jonany), [jsmestad](https://github.com/jsmestad), [JtheBAB](https://github.com/JtheBAB), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kevinetienne](https://github.com/kevinetienne), [kim95175](https://github.com/kim95175), [kincl](https://github.com/kincl), [kosgrz](https://github.com/kosgrz), [krjn](https://github.com/krjn), [lassimus](https://github.com/lassimus), Lena, [letsila](https://github.com/letsila), [levb](https://github.com/levb),[lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [LocalHeroPro](https://github.com/LocalHeroPro), [lurcio](https://github.com/lurcio), [manland](https://github.com/manland), [marianunez](https://github.com/marianunez), [maruTA-bis5](https://github.com/maruTA-bis5), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mjthomp95](https://github.com/mjthomp95), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [moksahero](https://github.com/moksahero), [mounicapaladugu](https://github.com/mounicapaladugu), [mstoli](https://github.com/mstoli), [mzaks](https://github.com/mzaks), [nafisfaysal](https://github.com/nafisfaysal), [nils-schween](https://github.com/nils-schween), [patterns](https://github.com/patterns), [piperRyan](https://github.com/piperRyan), [pradeepmurugesan](https://github.com/pradeepmurugesan), [RajatVaryani](https://github.com/RajatVaryani), [reflog](https://github.com/reflog), [renatopeterman](https://github.com/renatopeterman), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [SezalAgrawal](https://github.com/SezalAgrawal), [Sheshagiri](https://github.com/Sheshagiri), [srkgupta](https://github.com/srkgupta), [steevsachs](https://github.com/steevsachs), [streamer45](https://github.com/streamer45), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tapaswenipathak](https://github.com/tapaswenipathak), [tarikeshaq](https://github.com/tarikeshaq), [tekminewe](https://github.com/tekminewe), [Theaxiom](https://github.com/Theaxiom), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [ThiefMaster](https://github.com/ThiefMaster), [tomasmik](https://github.com/tomasmik), [ulhosting](https://github.com/uhlhosting), [utaani](https://github.com/utaani), [waseem18](https://github.com/waseem18), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [willdot](https://github.com/willdot), [Willyfrog](https://github.com/Willyfrog), [Wipeout55](https://github.com/Wipeout55), [yuya-oc](https://github.com/yuya-oc), [zkry](https://github.com/zkry) + +---- + +## Release v5.12 - Feature Release + +Mattermost v5.12.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.12.6, released 2019-08-22** + - Mattermost v5.12.6 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.12.5, released 2019-07-19** + - Fixed an issue with Jira plugin where creating or attaching to Jira issues failed due to GDPR changes released by Atlassian. Affected Jira Cloud only, not Jira Server or Jira Data Center. [MM-17060](https://mattermost.atlassian.net/browse/MM-17060) +- **v5.12.4, released 2019-07-15** + - Fixed an issue with missing messages. [MM-16921](https://mattermost.atlassian.net/browse/MM-16921) +- **v5.12.3, released 2019-07-09** + - Fixed an issue where setting the MM_SQLSETTINGS_DATASOURCEREPLICAS environment variable broke the server startup. [MM-16719](https://mattermost.atlassian.net/browse/MM-16719) +- **v5.12.2, released 2019-07-03** + - Fixed an issue where Net Promoter Score (NPS) went into a loop when [Experimental Enable Automatic Replies feature](https://docs.mattermost.com/administration/config-settings.html#enable-automatic-replies-experimental) was turned on in Account Settings. +- **v5.12.1, released 2019-06-28** + - Fixed an issue where messages were sometimes missing after reconnecting the network. [MM-16423](https://mattermost.atlassian.net/browse/MM-16423) + - Fixed an issue where the client sometimes crashed while viewing a direct message channel. [MM-16480](https://mattermost.atlassian.net/browse/MM-16480) + - Fixed an issue where Net Promoter Score (NPS) printed an error message in server logs when Error and Diagnostics Reporting was disabled. [MM-16465](https://mattermost.atlassian.net/browse/MM-16465) + - Fixed an issue where Net Promoter Score (NPS) telemetry reporting surveys were disabled if the setting had not been modified. [MM-16554](https://mattermost.atlassian.net/browse/MM-16554) +- **v5.12.0, released 2019-06-16** + - Original 5.12.0 release + +### Breaking changes since last release + + - If your plugin uses the ``DeleteEphemeralMessage`` plugin API, update it to accept a ``postId string`` parameter. See [documentation](https://developers.mattermost.com/extend/plugins/server/reference/#API.DeleteEphemeralPost) to learn more. + - Image link and YouTube previews do not display unless **System Console > Enable Link Previews** is enabled. Please ensure that your Mattermost server is connected to the internet and has network access to the websites from which previews are expected to appear. [Learn more here](https://docs.mattermost.com/administration/config-settings.html#enable-link-previews). + - ``ExperimentalEnablePostMetadata`` setting was removed. Post metadata, including post dimensions, is now stored in the database to correct scroll position and eliminate scroll jumps as content loads in a channel. + +```{Important} +If you upgrade from a release earlier than 5.11, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Infinite Scroll + - Read messages more easily. Older posts are loaded automatically as you scroll up instead of having to click the "Load more messages" button at the top of the screen. This feature is not supported on Internet Explorer (IE11). + +#### Bot Accounts + - Users no longer have to rely on creating fake user accounts to act as bots for integrations. Instead, create a real bot account and use it to generate bot access tokens to interact with users and complete tasks. + - Users can can also use these bots to post to any channel in the system, whether it’s a private team, private channel or a direct message channel. + - For Enterprise deployments, bot accounts no longer count as an active user towards licensing subscriptions. + - To learn more about bot accounts, see [the documentation](https://developers.mattermost.com/integrate/reference/bot-accounts/). + +#### Jira Plugin 2.0 + - Enhanced existing plugin for a deep two-way integration between Jira and Mattermost. + - Send notifications for Jira issue creation, issue updates and comments to Mattermost channels. + - Users can also take quick actions in Mattermost, including creating Jira issues, attaching Mattermost messages to Jira issues, and transitioning issues via slash commands. + - For a full feature set for 2.0, see https://github.com/mattermost/mattermost-plugin-jira#jira-20-features. + +#### Pre-packaged Plugins + - New pre-packaged plugins bundled with this Mattermost release include: + - [GitHub plugin](https://github.com/mattermost/mattermost-plugin-github) for notifications, reminders and slash commands to stay up-to-date on issues and pull requests. Supports GitHub SaaS and Enterprise versions. + - [Autolink plugin](https://github.com/mattermost/mattermost-plugin-autolink) to automatically hyperlink text, such as adding links to your issue tracker when someone posts an issue key or number. + - [Custom Attributes plugin](https://github.com/mattermost/mattermost-plugin-custom-attributes) to add custom attributes in the user profile popover. + - [Welcome Bot plugin](https://github.com/mattermost/mattermost-plugin-welcomebot) to improve onboarding and HR processes by adding a Welcome Bot that helps add new team members to channels. + - [Amazon SNS CloudWatch plugin](https://github.com/mattermost/mattermost-plugin-aws-sns) to send alert notifications from [Amazon AWS CloudWatch](https://aws.amazon.com/cloudwatch/) to Mattermost channels via AWS SNS. + +#### System Console Reorganization + - Informational architecture restructure of the System Console to make a more logical flow to the settings and to provide a more cohesive experience for hiding features on the Mattermost Private Cloud product, where the system admin should not have access to change configurations that affect the environment directly. + +#### Net Promoter Score (NPS) + - We are gathering user feedback to help improve user experience and hear directly from our users. The feature can be disabled via **System Console > Plugins > Net Promoter Score**. + +#### AD/LDAP Group Sync Removals (Enterprise Edition E20) + - System Admins can manage the membership of private teams and channels with AD/LDAP groups, eliminating the need to individually add and remove members. Users in the groups are automatically removed from the team or channel when removed from an associated group. + +#### User/Channel Search & Autocomplete in Elasticsearch (Enterprise Edition E20) + - Added new settings in **System Console > Elasticsearch** to enable [Elasticsearch](https://docs.mattermost.com/deployment/elasticsearch.html) for autocompletion queries. When enabled, Elasticsearch uses its indexed data for user/channel search queries and autocomplete queries. + +### Improvements + +#### User Interface (UI) + - Added an option to add a user to a channel from the profile popover. + - Removed ``@`` for full name display in push notifications. + +#### Plugins + - Added support for Markdown in plugin System Console help text fields. + - Added support for plugins to override ephemeral posts. + +#### Localization + - Promoted Polish language to "official". + +#### Command Line Interface (CLI) + - Added a ``command modify`` CLI command to modify slash commands. + - Added a ``mattermost user convert --bot`` CLI command to convert user accounts to bot accounts. + - Implemented a new command ``config migrate`` for migrating configuration to and from the database. + - For AD/LDAP Group Sync, added the following CLI commands: + - ``group team enable`` to add the ability to switch a team to be group-constrained. + - ``group team disable``to add the ability to disable group constraint on the specified team. + - ``group team list`` to list the groups associated with a team. + - ``group team status`` to show the group constraint status of the specified team. + - ``group channel enable`` to add the ability to switch a channel to be group-constrained. + - ``group channel disable`` to disable group constraint on the specified channel. + - ``group channel list`` to list the groups associated with a channel. + - ``group channel status`` to show the group constraint status of the specified channel. + +#### Administration + - Added support for running two Mattermost instances on the same domain using subpaths. + - Added support for importing threads from Slack. + +### Bug Fixes + - Fixed an issue where releasing a mouse click while the cursor was outside of the Rename Channel modal would close the modal. + - Fixed an issue where a whitepage occured after uploading a plugin with an invalid ``settings_schema`` value. + - Fixed an issue where the announcement banner overlapped channel content. + - Fixed an issue where license expiration notice banner could not be dismissed prior to the license expiration date. + - Fixed an issue where the channel switcher autocomplete didn't function properly when autocompleting the name of a person who was the first person named in a group message channel. + - Fixed an issue where inline images in markdown preview didn't get expanded. + - Fixed an issue where replies to the parent post were not left-aligned. + - Fixed an issue where the timezone picker dropdown closed when trying to drag the scrollbar. + - Fixed an issue where the ``ExperimentalPrimaryTeam`` config.json setting no longer hid the "Leave Team" option. + - Fixed an issue where the setting position field for AD/LDAP sync in System Console did not block user from changing it in Account Settings. + - Fixed an issue where scrolling was not working on iOS browser sign-up and sign-in pages. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``"PluginSettings":`` in ``config.json``: + - Added ``"EnableHealthCheck": true``, to ensure all plugins are periodically monitored, and restarted or deactivated based on their health status. + - Under ``"NotificationLogSettings":`` in ``config.json``: + - Added ``"EnableConsole": true``, ``"ConsoleLevel": "DEBUG"``, ``"ConsoleJson": true``, ``"EnableFile": true``, ``"FileLevel": "INFO"``, ``"FileJson": true``, and ``"FileLocation": ""``, to implement a structured logger to keep track of push notifications. + - Under ``"ServiceSettings":`` in ``config.json``: + - Added ``"EnableBotAccountCreation": false`` to enable bot account creation. + - Added ``"DisableBotsWhenOwnerIsDeactivated": true`` to disable bots automatically when the owner is deactivated. + - Added ``"TrustedProxyIPHeader": []``, to explicitly define which IP headers are trusted. + +### Database Changes + - `SchemeGuest` column added to the `TeamMembers` table. + - `SchemeGuest` column added to the `ChannelMembers` table. + - `DefaultTeamGuestRole` column added to the `Schemes` table, and set to an empty string. + - `DefaultChannelGuestRole` column added to the `Schemes` table, and set to an empty string. + +### API Changes + +#### RESTful API v4 Changes + - Updated API to use gziphandler wrapper if server is configured to use gzip. This ensures that the Mattermost server can respond to REST API requests with compressed data (via gzip) to reduce the amount of bandwidth used. + - LDAP Group Sync: + - Added API endpoints ``getGroupsByChannel`` and ``GetGroupsByTeam`` to retrieve groups by team and by channel. + - Added ``group_constrained`` API to both ``/users`` and ``/users/search`` endpoints to be able to limit users listed to those allowed by group-constraints. + - Added the ``GetGroups`` API endpoint to retrieve lists of groups with searching, pagination, and member counts. + - Disabled Team InviteID modification via Create/Update actions and moved it to a dedicated API endpoint. + +#### Plugin API v4 Changes + - Added ``KVCompareAndSet(key string, old []byte, new []byte)`` to Plugin API to add support for transactional semantics with KV Store in plugin framework. + +### Known Issues + - Creating or attaching to Jira issues fails for Jira Cloud. This is resolved in v5.12.5. + - Messages related to OpenGraph API are unnecessarily reported as errors in the server logs. This is resolved in v5.13.1. + - **Push Notification Contents** setting is not available in the System Console in servers without an Enterprise Edition license. This is resolved in v5.13.1. + - Channels with large message history may have performance issues. This is resolved in v5.13.2. + - **Site Configuration > Notifications > Email Notification Contents** is missing from E10 servers. This is resolved in v5.13.2. + - Changing announcement banner overlaps content. This is resolved in v5.13.2. + - Scroll position is not at the new message indicator on switching channels with unreads between 30-60. This is resolved in v5.13.2. + - Titles for webhooks, commands and OAuth apps are no longer bolded in the System Console. + - Users can get logged out of server without a session expiry notification. + - Desktop app hangs on opening emoji picker. + - When a primary team is set, the options to leave a team is disabled for all teams, not just the primary team. + - Plugin crashes the server when calling ``w.WriteHeader(0)``. + - Bot account profile image disappears when saving bot details. + - Custom emoji containing specified letters do not appear in emoji autocomplete, unless they start with the letters or have been returned in the autocomplete before. + - Buttons inside ephemeral messages are not clickable / functional on the mobile app. + - On a server using a subpath, the URL opens a blank page if the System Admin changes the Site URL in the System Console UI. To fix, the System Admin should restart the server. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors +- [aeomin](https://translate.mattermost.com/user/aeomin/), [adzimzf](https://github.com/adzimzf), [amyblais](https://github.com/amyblais), [andresoro](https://github.com/andresoro), [asaadmahmood](https://github.com/asaadmahmood), [bolariin](https://github.com/bolariin), [bradjcoughlin](https://github.com/bradjcoughlin), [carmo-evan](https://github.com/carmo-evan), [chahat-arora](https://github.com/chahat-arora), [chikei](https://github.com/chikei), [cjohannsen81](https://github.com/cjohannsen81), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [composednitin](https://github.com/composednitin), [CooperAtive](https://github.com/CooperAtive), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [d28park](https://github.com/d28park), [danmaas](https://github.com/danmaas), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [dustinkirkland](https://github.com/dustinkirkland), [ejachang](https://github.com/ejachang), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [evan-a-a](https://github.com/evan-a-a), [farhadab](https://github.com/farhadab), [fjaeger](https://github.com/fjaeger), [gabrieljackson](https://github.com/gabrieljackson), [GianOrtiz](https://github.com/GianOrtiz), [giorgosdi](https://github.com/giorgosdi), [greensteve](https://github.com/greensteve), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [henrymori](https://github.com/henrymori), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [iomodo](https://github.com/iomodo), [IshankGulati](https://github.com/IshankGulati), [it33](https://github.com/it33), [ivanaairenee](https://github.com/ivanaairenee), [jasonblais](https://github.com/jasonblais), [JerryFireman](https://github.com/JerryFireman), [jesperhansen17](https://github.com/jesperhansen17), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [jkl5616](https://github.com/jkl5616), [johnthompson365](https://github.com/johnthompson365), [JtheBAB](https://github.com/JtheBAB), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kkirsche](https://github.com/kkirsche), [kosgrz](https://github.com/kosgrz), Lena, [letsila](https://github.com/letsila), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [liusy182](https://github.com/liusy182), [marianunez](https://github.com/marianunez), [matshch](https://github.com/matshch), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [MikeNicholls](https://github.com/MikeNicholls), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [pichouk](https://github.com/pichouk), [pradeepmurugesan](https://github.com/pradeepmurugesan), [prapti](https://github.com/prapti), [pravan](https://github.com/pravan), [redg3ar](https://github.com/redg3ar), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [rvillablanca](https://github.com/rvillablanca), [sapnasivakumar](https://github.com/sapnasivakumar), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [seansackowitz](https://github.com/seansackowitz), [sebastien-prudhomme](https://github.com/sebastien-prudhomme), [sergeyzhukov](https://github.com/sergeyzhukov), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tapaswenipathak](https://github.com/tapaswenipathak), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thePanz), [therealpuneeth20](https://github.com/therealpuneeth20), [torgeirl](https://github.com/torgeirl), [ulhosting](https://github.com/uhlhosting), [VolatianaYuliana](https://github.com/VolatianaYuliana), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [Wipeout55](https://github.com/Wipeout55), [z4cco](https://github.com/z4cco) + +---- + +## Release v5.11 - Quality Release + +Mattermost v5.11.0 contains low level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.11.1, released 2019-06-20** + - Mattermost v5.11.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.11.0, released 2019-05-16** + - Original 5.11.0 release + +### Breaking changes since last release + + - If your integration uses ``Update.Props == nil`` to clear ``Props``, this will no longer work in 5.11+. Instead, use ``Update.Props == {}`` to clear properties. This change was made because ``Update.Props == nil`` unintentionally cleared all ``Props``, such as the profile picture, instead of preserving them. + +```{Important} +If you upgrade from a release earlier than 5.10, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Bug Fixes + - Fixed an issue where plugin settings link didn't appear until refresh after uploading a plugin in the System Console. + - Fixed an issue where **System Console** > **Users** bottom section of "user actions" menu was cut off for the last three users in the screen. + - Fixed an issue where corners on image previews were squared instead of rounded. + - Fixed an issue where the hover effect was missing on images. + - Fixed an issue where a post action (via button or menu) reset the profile picture of the webhook post. + - Fixed an issue where a flagged post containing only file attachments didn't render in the sidebar until loaded in the centre. + - Fixed an issue where some strings in channel settings weren't localizable. + - Fixed an issue where clicking "Open" downloaded an image instead of opening it. + - Fixed an issue where an at-mention user autocomplete overlapped with the channel header when drafting a long message containing a file attachment. + - Fixed an issue where the reply bar showed gaps between posts in compact view. + - Fixed an issue where markdown preview of nested lists displayed differently from styling in posted message. + - Fixed an issue where Safari suggested auto-corrections in the channel switcher. + - Fixed an issue on Safari where the mention badge count didn't update immediately. + - Fixed an issue where the post action menu overlapped with posts on iOS/Safari on mobile view. + - Fixed an issue where interactive dialog's description text colour was difficult to see on dark themes. + - Fixed an issue where delete permissions for custom emoji team admin role were not always granted. + - Fixed an issue with a slight scroll pop on reaching loading indictor of search results. + - Fixed an issue where adding a user to a channel that is in the unreads section caused the channel to become read in the user's view. + - Fixed an issue where the channel menu dropdown icon had an unnecessary tooltip. + - Fixed an issue on LDAP Groups where adding a group to a team provided an unnecessary permission confirmation modal. + - Fixed an issue on mobile view where clicking on the attachment icon didn't bring up the dropdown menu. + +### Known Issues + - Buttons inside ephemeral posts are not clickable / functional on the mobile app. + - On a server using a subpath, the URL opens a blank page if the system admin changes the Site URL in the System Console UI. The system admin should restart the server to fix it. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + +Thank you to everyone who contributed to the Mattermost project in April 2019! + +[aeomin](https://translate.mattermost.com/user/aeomin/), [akrfjmt](https://github.com/akrfjmt), [ali-farooq0](https://github.com/ali-farooq0), [amyblais](https://github.com/amyblais), [andresoro](https://github.com/andresoro), [asaadmahmood](https://github.com/asaadmahmood), [BotKube](https://botkube.io/), [bradjcoughlin](https://github.com/bradjcoughlin), [bytemine GmbH](https://github.com/bytemine), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [CooperAtive](https://github.com/CooperAtive), [coreyhulen](https://github.com/coreyhulen), [courtneypattison](https://github.com/courtneypattison), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [d28park](https://github.com/d28park), [danmaas](https://github.com/danmaas), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fcorrea](https://github.com/fcorrea), [gabrieljackson](https://github.com/gabrieljackson), [gnufede](https://github.com/gnufede), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [happygaijin](https://github.com/happygaijin), [harshilsharma](https://github.com/harshilsharma), [hectorskypl](https://github.com/hectorskypl), [Herzum](https://github.com/herzum), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jfrerich](https://github.com/jfrerich), [johnbellone](https://github.com/johnbellone), [johnthompson365](https://github.com/johnthompson365), [JVasky](https://github.com/JVasky), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kingisaac95](https://github.com/kingisaac95), [kmandagie](https://github.com/kmandagie), [kosgrz](https://github.com/kosgrz), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [liusy182](https://github.com/liusy182), [ljmccaff](https://github.com/ljmccaff), [Mario-Hofstaetter](https://github.com/Mario-Hofstaetter), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [MParvin](https://github.com/MParvin), [mstoli](https://github.com/mstoli), [ninanung](https://github.com/ninanung), [oliverJurgen](https://github.com/oliverJurgen), [PeterDaveHello](https://github.com/PeterDaveHello), [prapti](https://github.com/prapti), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [RyPoints](https://github.com/RyPoints), [s4kh](https://github.com/s4kh), [sapnasivakumar](https://github.com/sapnasivakumar), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [Sheshagiri](https://github.com/Sheshagiri), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tengis617](https://github.com/tengis617), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thepanz), [thepill](https://github.com/thepill), [therealpuneeth20](https://github.com/therealpuneeth20), [ThiefMaster](https://github.com/ThiefMaster), [torgeirl](https://github.com/torgeirl), [tylarb](https://github.com/tylarb), [ulhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [z4cco](https://github.com/z4cco) + +---- + +## Release v5.10 - Feature Release + +Mattermost v5.10.0 contains medium to high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.10.2, released 2019-06-20** + - Mattermost v5.10.2 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.10.1, released 2019-05-16** + - Fixed an issue on Internet Explorer (IE11) where the system console opened a blank page. +- **v5.10.0, released 2019-04-16** + - Original 5.10.0 release + +### Breaking changes since last release + + - ``SupportedTimezonesPath`` setting in config.json and changes to timezones in the UI based on the timezones.json file was removed. This was made to support [storing configurations in the database](https://docs.mattermost.com/administration/config-in-database.html#configuration-in-a-database). + +```{Important} +If you upgrade from a release earlier than 5.9, please read the other [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Interactive Ephemeral Messages + - Added support for [message actions and buttons](https://developers.mattermost.com/integrate/plugins/interactive-messages/) in ephemeral messages. + +#### Configuration in Database + - Added experimental support for storing ``config.json`` in the database, improving the system console experience on read-only filesystems. Storing the configuration in the database is optional, as the existing ``config.json`` remains fully supported. + +### Improvements + +#### User Interface (UI) + - Added ability to use "c" and "sh" for code block syntax highlighting. + - Words that trigger mentions now supports Chinese. + - Added support for rendering emojis and hyperlinks in message attachment titles. + - Added support for showing the channel name in the message box. + - Added support for markdown in plugin system console help text fields. + - Added ability to convert Excel cells to markdown table when pasting in Mattermost. + - Added ability to render emojis in interactive message buttons. + +#### Plugins (Beta) + - Created a plugin component to override file previews. + - Added support for plugins to create link tooltips. + - Added experimental support for plugins to use bot accounts. + +#### Bulk Import/Export + - Added User Preference fields in bulk export. + - Added ability to include direct and group message channels and their posts in bulk export. + - Added ability to include deactivated users in bulk import. + +#### Command Line Tools (CLI) + - Created CLI command ``command show`` to allow seeing detailed information of a slash command. + - Created CLI command ``webhook show`` to allow seeing detailed information of a webhook. + - Created CLI command ``team rename`` to allow renaming teams. + - Created CLI command ``channel search`` to allow searching for channels. + +#### Administration + - Improved default session timeout behavour, including changing the default ``SessionLengthWebInDays`` from 30 to 180 days. + - Added full text search to the system console panel to easily find options in the configuration. + - (Advanced Permissions) Split managing emoji permissions into "create", "delete own" and "delete others". + - (Advanced Permissions) Added ``List_Public_Teams``, ``Join_Public_Teams``, ``List_Private_Teams`` and ``Join_Private_Teams`` permissions. + - Added support for LDAP groups search. + - Added a setting to the system console to change the minimum length of hashtags. + - Added support for setting Reply-To header in outbound Mattermost emails. + - Added support for invalidating all email invitations from the system console. + +### Bug Fixes + - Fixed an issue where enterprise features became immediately unavailable when the enterprise license expired with a 15 day grace period. + - Fixed an issue where an at-mention for username that starts with "all" did not highlight their entire username. + - Fixed an issue where the ``migrate_auth`` command did not work with valid license file. + - Fixed an issue where post metadata was requested if link previews were disabled. + - Fixed an issue where a channel did not get removed from the unreads section if the user navigated out of it via a permalink. + - Fixed an issue where a link from Access Control Groups to Group Filter on AD/LDAP did not work for subpath Site URL. + - Fixed an issue where expired channels appeared in "My Channels" section of channel switcher if using the **Automatically Close Direct Messages** setting. + - Fixed an issue where the text box reverted to default size after a user returned from the Integrations page. + - Fixed an issue where the profile popover wasn't allowed to close itself when opened through an at-mention. + - Fixed an issue where filtering by first name with Korean characters no longer worked for at-mentions. + - Fixed an issue where the **Remove MFA** option was visible for all users when **Enforce MFA** was enabled. + +### Compatibility + +#### Deprecated Features + + - Deprecated configurable ``timezones.json`` in favour of the existing hard-coded list built into the server. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + +- Under ``"ExperimentalSettings":`` in ``config.json``: + - Added ``"RestrictSystemAdmin": false``, to optionally constrain even system admins from changing critical settings. +- Under ``"ServiceSettings":`` in ``config.json``: + - Added ``"MinimumHashtagLength": 3``, to add the ability to change the minimum length of hashtags. + +### RESTful API Changes + - Added ``GetUsers`` API method to add the ability to list users. + - Added ``POST /bots`` to create a bot accounts. + - Added ``PUT /bots/{bot_user_id}`` to partially update a bot by providing only the fields you want to update. + - Added ``GET /bots/{bot_user_id}`` to get a bot specified by its bot id. + - Added ``GET /bots`` to get a page of a list of bots. + - Added ``POST /bots/{bot_user_id}/disable`` to disable a bot. + - Added ``POST /bots/{bot_user_id}/enable`` to enable a bot. + - Added ``POST /bots/{bot_user_id}/assign/{user_id}`` to assign a bot to the specified user. + +### Plugin API Changes + - Added the ``SearchPostsInTeam`` method to add the ability to search posts in a team. + - Added ``GetTeamMembersForUser`` and ``GetChannelMembersForUser`` to add the ability to get team and channel members for a specific user. + - Added ``GetBundleInfo() string`` method to add the ability to store assets elsewhere. + - Added ``CreateBot(bot *model.Bot) (*model.Bot, *model.AppError)`` to create the given bot and corresponding user. + - Added ``PatchBot(botUserId string, botPatch *model.BotPatch) (*model.Bot, *model.AppError)`` to apply the given patch to the bot and corresponding user. + - Added ``GetBot(botUserId string, includeDeleted bool) (*model.Bot, *model.AppError)`` to return the given bot. + - Added ``GetBots(options *model.BotGetOptions) ([]*model.Bot, *model.AppError)`` to return the requested page of bots. + - Added ``UpdateBotActive(botUserId string, active bool) (*model.Bot, *model.AppError)`` to mark a bot as active or inactive, along with its corresponding user. + - Added ``PermanentDeleteBot(botUserId string) *model.AppError`` to permanently delete a bot and its corresponding user. + +### Database Changes + - Granted the following permissions for the System Admin, in preparation for an upcoming bot accounts feature: + - PERMISSION_CREATE_BOT + - PERMISSION_READ_BOTS + - PERMISSION_READ_OTHERS_BOTS + - PERMISSION_MANAGE_BOTS + - PERMISSION_MANAGE_OTHERS_BOTS + - `Bots` table was added. + +### Known Issues + - Attachments menu on mobile view is partly cut off on the right-hand side. + - Clicking on the attachment icon doesn't bring up the dropdown menu on mobile browser. + - Content for ephemeral messages is not displayed on mobile apps. + - When login is done through SAML, text in **Account Settings** > **General** > **Email** is misaligned. + - On a server using a subpath, the URL opens a blank page if the system admin changes the Site URL in the System Console UI. The system admin should restart the server to fix it. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + +### Contributors + +Thank you to everyone who contributed to the Mattermost project in March 2019! + +- [7-plus-t](https://github.com/7-plus-t), [aeomin](https://translate.mattermost.com/user/aeomin/), [ali-farooq0](https://github.com/ali-farooq0), [amaddio](https://github.com/amaddio), [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [bcalik](https://github.com/bcalik), [benschuster788](https://github.com/benschuster788), [bradjcoughlin](https://github.com/bradjcoughlin), [checkaayush](https://github.com/checkaayush), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [comharris](https://github.com/comharris), [courtneypattison](https://github.com/courtneypattison), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [d28park](https://github.com/d28park), [danmaas](https://github.com/danmaas), [dchukmasov](https://github.com/dchukmasov), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fcorrea](https://github.com/fcorrea), [gnufede](https://github.com/gnufede), [grundleborg](https://github.com/grundleborg), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [gulhe](https://github.com/gulhe), [gupsho](https://github.com/gupsho), [hanzei](https://github.com/hanzei), [harshilsharma](https://github.com/harshilsharma), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [Hobby-Student](https://github.com/Hobby-Student), [it33](https://github.com/it33), [j8r](https://github.com/j8r), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jk2K](https://github.com/jk2K), [johnsenner](https://github.com/johnsenner), [JtheBAB](https://github.com/JtheBAB), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kelvintyb](https://github.com/kelvintyb), [kjkeane](https://github.com/kjkeane), [kosgrz](https://github.com/kosgrz), Lena, [letsila](https://github.com/letsila), [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [m3phistopheles](https://github.com/m3phistopheles), [MartB](https://github.com/MartB), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [MirlanMaksv](https://github.com/MirlanMaksv), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [nadaa](https://github.com/nadaa), [oliverJurgen](https://github.com/oliverJurgen), [pesintta](https://github.com/pesintta), [reflog](https://github.com/reflog), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [sadohert](https://github.com/sadohert), [sandlis](https://github.com/sandlis), [saturninoabril](https://github.com/saturninoabril), [stylianosrigas](https://github.com/stylianosrigas), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tejasbubane](https://github.com/tejasbubane), [thekiiingbob](https://github.com/thekiiingbob), [thePanz](https://github.com/thepanz), [ulhosting](https://github.com/uhlhosting), [wbernest](https://github.com/wbernest), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.9 - [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) + +Mattermost v5.9.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.9.8, released 2020-01-08** + - Mattermost v5.9.8 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where migrating accounts from email to SAML failed. [MM-21472](https://mattermost.atlassian.net/browse/MM-21472) +- **v5.9.7, released 2019-12-18** + - Mattermost v5.9.7 contains high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.9.6, released 2019-10-24** + - Mattermost v5.9.6 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.9.5, released 2019-10-12** + - Fixed an issue that will be introduced with a change in upcoming server v5.16 and desktop app v4.3 releases where desktop notifications will be broken as the desktop app will no longer be able to directly interact with the web app. [MM-18819](https://mattermost.atlassian.net/browse/MM-18819) +- **v5.9.4, released 2019-08-22** + - Mattermost v5.9.4 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.9.3, released 2019-07-19** + - Fixed an issue with unauthenticated LDAP bind. [MM-17055](https://mattermost.atlassian.net/browse/MM-17055) +- **v5.9.2, released 2019-06-20** + - Mattermost v5.9.2 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.9.1, released 2019-04-24** + - Mattermost v5.9.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.9.0, released 2019-03-16** + - Original 5.9.0 release + +### Breaking Changes since last release + + - If **DisableLegacyMfa** setting in ``config.json`` is set to ``true`` and multi-factor authentication is enabled, ensure your users have upgraded to mobile app version 1.17 or later. Otherwise, users who have MFA enabled may not be able to log in successfully. See [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. + - The public IP of the Mattermost application server is considered a reserved IP for additional security hardening in the context of untrusted external requests such as Open Graph metadata, webhooks or slash commands. See [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. + +```{Important} +If you upgrade from another release than 5.8, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Bug Fixes + + - Fixed an issue where emoji reactions did not appear on posts right away. + - Fixed an issue where the emoji `Recently Used` cleared entirely after logging out and back in. + - Fixed an issue where emoji not included in our list of text-based emoji were not rendered as jumboemoji. + - Fixed an issue where the default server/client locales got reverted to ``en`` on server startup. + - Fixed an issue where email notification setting in the webapp was out of sync with the mobile apps. + - Fixed an issue where a broken image displayed on login page if custom branding was enabled but no image had been uploaded. + - Fixed an issue where at-channel, at-all, at-here followed by a period were not highlighted as mentions. + - Fixed an issue where the Mattermost icon was pixelated in bookmark rendering on Google Chrome. + - Fixed an issue where **System Console > Users** page had broken user interface on narrow screens. + - Fixed an issue where at-channel notification showed incorrect number of timezones. + - Fixed an issue where leading whitespace with emoji affected emoji size so that they didn't render as jumboemoji. + - Fixed an issue where the System Console graphs did not load smoothly. + - Fixed an issue with inconsistent formatting in page header on **System Console > Notifications > Mobile Push**. + - Fixed an issue where invite tokens with a 48-hour expiry expired after 24 hours. + - Fixed an issue where a blank screen appeared when opening a group message channel from "More" modal using Enter key. + - Fixed an issue where Zoom plugin caused link metadata code to print warnings in the System Console. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - **Enable Image Proxy** setting is now ``false`` by default. See [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. + - Under ``"ServiceSettings"`` in ``config.json``: + - Added ``"DisableLegacyMFA": false,`` to keep the legacy checkMfa endpoint enabled to support mobile versions 1.16 and earlier. See [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. + +### Known Issues + + - On a server using a subpath, the URL opens a blank page if the system admin changes the Site URL in the System Console UI. The system admin should restart the server to fix it. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +Thank you to everyone who contributed to the Mattermost project in February 2019! + +[adzimzf](https://github.com/adzimzf), [aeomin](https://translate.mattermost.com/user/aeomin/), [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [aswathkk](https://github.com/aswathkk), [awbraunstein](https://github.com/awbraunstein), [bbodenmiller](https://github.com/bbodenmiller), [BK1603](https://github.com/BK1603), [bradjcoughlin](https://github.com/bradjcoughlin), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [courtneypattison](https://github.com/courtneypattison), [cpanato](https://github.com/cpanato), [cpoile](https://github.com/cpoile), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [danmaas](https://github.com/danmaas), [dannymohammad](https://github.com/dannymohammad), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [dom3k](https://github.com/dom3k), [dos1701](https://github.com/dos1701), [DSchalla](https://github.com/DSchalla), [ejachang](https://github.com/ejachang), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fcorrea](https://github.com/fcorrea), [gabrieljackson](https://github.com/gabrieljackson), [gruceqq](https://translate.mattermost.com/user/gruceqq/), [gupsho](https://github.com/gupsho), [hannaparks](https://github.com/hannaparks), [hanzei](https://github.com/hanzei), [hectorskypl](https://github.com/hectorskypl), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jdillard](https://github.com/jdillard), [jespino](https://github.com/jespino), [jfcastroluis](https://github.com/jfcastroluis), [jfrerich](https://github.com/jfrerich), [JtheBAB](https://github.com/JtheBAB), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kosgrz](https://github.com/kosgrz), [koukouloforos](https://github.com/koukouloforos), [kscheel](https://github.com/kscheel), Lena, [levb](https://github.com/levb), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [manland](https://github.com/manland), [maruTA-bis5](https://github.com/maruTA-bis5), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [migbot](https://github.com/migbot), [MirlanMaksv](https://github.com/MirlanMaksv), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [onnadi-work](https://github.com/onnadi-work), [patniharshit](https://github.com/patniharshit), [pichouk](https://github.com/pichouk), [R-Wang97](https://github.com/R-Wang97), [Robbe7730](https://github.com/Robbe7730), [rodcorsi](https://github.com/rodcorsi), [sadohert](https://github.com/sadohert), [sandlis](https://github.com/sandlis), [sanojsubran](https://github.com/sanojsubran), [saturninoabril](https://github.com/saturninoabril), [staabm](https://github.com/staabm), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tauu](https://github.com/tauu), [thedingwing](https://github.com/thedingwing), [thePanz](https://github.com/thepanz), [ulhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc), [zetaab](https://github.com/zetaab) + +---- + +## Release v5.8 - Feature Release + +Mattermost v5.8.0 contains low to high level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.8.2, released 2019-04-24** + - Mattermost v5.8.2 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.8.1, released 2019-03-16** + - Mattermost v5.8.1 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Turned image proxy off by default, unless a server already had it enabled (including new installs). Also, warnings about not getting embedded content for a post were downgraded or removed. See [important upgrade notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. +- **v5.8.0, released 2019-02-16** + - Original 5.8.0 release + +### Breaking Changes since last release + +- The local image proxy has been added, and images displayed within the client are now affected by the ``AllowUntrustedInternalConnections`` setting. See [documentation](https://docs.mattermost.com/administration/image-proxy.html#local-image-proxy) for more details if you have trouble loading images. + +```{Important} +If you upgrade from another release than 5.7, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Added support for LDAP Group Sync + - Lets admins set default team and channel membership based on LDAP groups. See more details [in the documentation](https://docs.mattermost.com/deployment/ldap-group-sync.html). + +#### Added multi-factor authentication support to Team Edition + - See more details on [this Forum post](https://forum.mattermost.com/t/multi-factor-authentication-mfa-in-team-edition/6287). + +#### Enhanced image performance + - Improved performance for images by adding support for image proxy servers, which are now integrated into the server and switched on by default. + - Note that this may cause problems loading images from within your local network due to security settings. See [here](https://docs.mattermost.com/administration/image-proxy.html#local-image-proxy) for more information. + +### Improvements + +#### User Interface (UI) + - Improved sorting of emoji in the emoji autocomplete and emoji picker search results. + - Added support for emoji picker for mobile web view. + +#### Notifications + - Added a channel notification setting to disable at-channel mentions. + +#### Administration + - Added the ability to search users by role in **System Console** > **Users**. + - Added a CLI command to modify an outgoing webhook. + - Added a CLI command to restore a team. + +#### Performance + - Added network connectivity improvements where the server no longer allows clients to auto-retry posts and to cause posts to appear twice. + +#### Slash Commands + - Added support for sending a message to a different channel than where the slash command was issued from. + - Added an option to send a message beginning with a "/" from the right-hand side. + +#### Plugins + - Added server support for updating a plugin instead of having to remove and install them as two separate actions. + +#### Attachments + - Optimized file attachment memory usage where possible. + +### Bug Fixes + + - Fixed an issue where "[user] is typing ..." was not removed when a message was composed and sent very quickly. + - Fixed an issue where an announcement banner displayed when the banner was enabled but the text field was blank. + - Fixed an issue where a language was not set if selected in Account Settings. + - Fixed an issue where removing rows from Send Email Invite modal didn't remove them immediately. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``"ServiceSettings"`` in ``config.json``: + - Added ``"ExperimentalLdapGroupSync": false``, to add support for experimental LDAP Group Sync feature. + - Under ``"LdapSettings"`` in ``config.json``: + - Added ``"GroupFilter": ""``, ``"GroupDisplayNameAttribute": ""`` and ``"GroupIdAttribute": ""``, to add the ability to configure group display name and unique identifier. + - Under ``"ImageProxySettings":`` in ``config.json``: + - Added ``"Enable": true,``, ``"ImageProxyType": "local",``, ``"RemoteImageProxyURL": "",`` and ``"RemoteImageProxyOptions": ""``, to allow integrating image proxy into the server and switching it on by default. + - Under ``"ExperimentalSettings":`` in ``config.json``: + - Added ``"LinkMetadataTimeoutMilliseconds": 5000`` and ``"DisablePostMetadata": false``, to enable post metadata by default. + +### API Changes + +#### RESTful API v4 Changes + - Added ``SearchTeams`` to plugin API to add the ability to search teams. + - Added ``GetTeamStats`` to plugin API to add the ability to get team statistics. + - Added ``/api/v4/posts/ids/reactions`` API endpoint to get the bulk reactions for posts. + - Added ``UpdateUserActive`` to plugin API to allow updating user's status as active or inactive. + - Add ``GetFile`` to plugin to add the ability to get files. + +### Known Issues + + - On a server using a subpath, the URL opens a blank page if the system admin changes the Site URL in the System Console UI. The system admin should restart the server to fix it. + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +Thank you to everyone who contributed to the Mattermost project in January 2019! + +[adzimzf](https://github.com/adzimzf), [aeomin](https://translate.mattermost.com/user/aeomin/), [amorriscode](https://github.com/amorriscode), [amyblais](https://github.com/amyblais), [ArchRoller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [bradjcoughlin](https://github.com/bradjcoughlin), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [danmaas](https://github.com/danmaas), [dannymohammad](https://github.com/dannymohammad), [deanwhillier](https://github.com/deanwhillier), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [dmamills](https://github.com/dmamills), [dom3k](https://github.com/dom3k), [DSchalla](https://github.com/DSchalla), [dv29](https://github.com/dv29), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [gabrieljackson](https://github.com/gabrieljackson), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [ja11sop](https://github.com/ja11sop), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [JtheBAB](https://github.com/JtheBAB), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [Kaya_Zeren](https://x.com/kaya_zeren), [kosgrz](https://github.com/kosgrz), Lena, [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [maruTA-bis5](https://github.com/maruTA-bis5), [meilon](https://github.com/meilon), [mgdelacroix](https://github.com/mgdelacroix), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mollyyoung](https://github.com/mollyyoung), [nashik](https://github.com/nashik), [nlowe](https://github.com/nlowe), [Ovski4](https://github.com/Ovski4), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [pradeepmurugesan](https://github.com/pradeepmurugesan), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [rononline](https://github.com/rononline), [ryoon](https://github.com/ryoon), [s4kh](https://github.com/s4kh), [sadohert](https://github.com/sadohert), [sapnasivakumar](https://github.com/sapnasivakumar), [saturninoabril](https://github.com/saturninoabril), [Sheshagiri](https://github.com/Sheshagiri), [sonasingh46](https://github.com/sonasingh46), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [thePanz](https://github.com/thepanz), [tomocy](https://github.com/tomocy), [ulhosting](https://github.com/uhlhosting), [unigiriunini](https://github.com/unigiriunini), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc), [zeroimpl](https://github.com/zeroimpl), [zetaab](https://github.com/zetaab) + +---- + +## Release v5.7 - Quality Release + +Mattermost v5.7.0 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.7.3, released 2019-03-16** + - Mattermost v5.7.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.7.2, released 2019-02-16** + - Mattermost v5.7.2 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.7.1, released 2019-02-01** + - Mattermost v5.7.1 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.7.0, released 2019-01-16** + - Original 5.7.0 release + +### Bug Fixes + + - Fixed an issue where push notification to clear unread messages badge from another client was not being forwarded. There are cases on the mobile app where the badge could still linger - see [MM-13722](https://mattermost.atlassian.net/browse/MM-13722) for more details. + - Fixed a SQL syntax error when a non-existent channelId was attempted to be viewed. + - Fixed an issue where OpenGraph and Post Metadata cache were purged on any config change with the image proxy enabled. + - Added a check for percent value on file upload progress to prevent the app from crashing. + - Fixed an issue where multi-line announcement banner text did not expand its background. + - Fixed an issue where channel modal text and icons were misaligned if only one channel type was available. + - Fixed an issue where every channel switch triggered a fetch for users in all Group Message channels for the user. + - Fixed an issue where the user was not redirected to sign up page to create first account on fresh install. + - Fixed an issue where scrollbar appeared in team sidebar when a user was a member of too many teams. + - Fixed an issue where wide images posted by a webhook could be cut off on the right-hand side. + - Fixed an issue where leaving a team showed a 403 error in the console. + - Fixed an issue where Code Theme did not save unless other colours were changed. + - Fixed an issue where Webapp only showed a star or mention count for active team. + - Fixed an issue where Web mobile view was missing the mute option in the channel menu. + - Fixed an issue where the "participant is typing" appeared a few seconds after a message was posted. + - Fixed an issue where a profile popover got cut off on the right-hand side if it included an admin badge and a long username. + +### Known Issues + + - Custom Terms of Service returns on refresh after clicking to agree. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://github.com/aeomin), [akhilanandbv003](https://github.com/akhilanandbv003), [amyblais](https://github.com/amyblais), [andrewbanchich](https://github.com/andrewbanchich), [ArchRoller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [bezumkin](https://github.com/bezumkin), [bradjcoughlin](https://github.com/bradjcoughlin), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [danmaas](https://github.com/danmaas), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hanzei](https://github.com/hanzei), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [ja11sop](https://github.com/ja11sop), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [johnthompson365](https://github.com/johnthompson365), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kosgrz](https://github.com/kosgrz), Lena, [letsila](https://github.com/letsila), [levb](https://github.com/levb), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [meilon](https://github.com/meilon), [mickmister](https://github.com/mickmister), [migbot](https://github.com/migbot), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mukulrawat1986](https://github.com/mukulrawat1986), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [rononline](https://github.com/rononline), [ryoon](https://github.com/ryoon), [s4kh](https://github.com/s4kh), [saturninoabril](https://github.com/saturninoabril), [Schrooms](https://github.com/Schrooms), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [thePanz](https://github.com/thePanz), [uhlhosting](https://github.com/uhlhosting), [vaithak](https://github.com/vaithak), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yakimant](https://github.com/yakimant), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.6 - Feature Release + +- **v5.6.5, released 2019-02-16** + - Mattermost v5.6.5 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.6.4, released 2019-02-01** + - Mattermost v5.6.4 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.6.3, released 2019-01-16** + - Mattermost v5.6.3 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.6.2, released 2018-12-22** + - Fixed JIRA plugin not sending messages back to Mattermost channels. +- **v5.6.1, released 2018-12-20** + - Fixed an issue where a user is not redirected to the account creation page on a fresh Mattermost server install. + - Fixed an issue where file uploads crashed the webapp for some users. + - Fixed slow channel switching load times, where every channel switch fetched users from all group message channels. + - Fixed JIRA plugin not working due to a rename of the JIRA plugin directory structure. +- **v5.6.0, released 2018-12-16** + - Original 5.6.0 release + +### Breaking Changes since the last release + + - Replaced WebRTC prototype with other video and audio calling solutions. [Learn more here](https://docs.mattermost.com/deployment/video-and-audio-calling.html). + - Removed support for IE11 Mobile View due to low usage and instability in order to invest that effort in maintaining a high quality experience on other more used browsers. End users on IE11 will thus have an increased minimum screen size. + - If EnablePublicChannelsMaterialization setting in config.json is set to false, an offline migration prior to upgrade may be required to synchronize the materialized table for public channels to increase channel search performance in the channel switcher (CTRL/CMD+K), channel autocomplete (~) and elsewhere in the UI. See [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for more details. + +```{Important} +If you upgrade from another release than 5.5, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Interactive Dialogs + - Added support for interactive dialogs to more easily collect structured information from users to perform an action or submit a request via an integration. [Learn more here](https://developers.mattermost.com/integrate/plugins/interactive-messages/) + +#### Languages + - Added support for Ukrainian language, bringing the number of supported languages to 16. + - Romanian language promoted out of beta. + +#### Command Line Interface (CLI) + - Added new CLI commands to improve admin productivity, including: + - ``command create`` to create a custom slash command for a specified team. + - ``command delete`` to delete a slash command. + - ``command move`` to move a slash command to a different team. + - ``command list`` to list all commands on specified teams or all teams by default. + - ``config get`` to retrieve the value of a config setting by its name in dot notation. + - ``config set`` to set the value of a config setting by its name in dot notation. + - ``config show`` to print the current Mattermost configuration in an easy to read format. + - ``team archive`` to archive teams based on name. + - ``team search`` to search for teams based on name. + - ``webhook create-incoming`` to create incoming webhook within specific channel. + - ``webhook create-outgoing`` to create outgoing webhook within specific channel. + - ``webhook delete`` to delete a webhook. + - ``webhook list`` to list all webhooks for a team or across the server. + - ``webhook modify-incoming`` to modify existing incoming webhook by changing its title, description, channel or icon url. + +### Improvements + +#### User Interface + - Added ability to remove profile pictures in Account Settings. + - Added a new loading bar that shows progress on file uploads. + - Added a new badge to the profile popover that indicates if a user is a System Admin. + - Added new channel sidebar reorganization options for the `ExperimentalGroupUnreadChannels` config.json setting, such as the ability to sort channels by recent messages. + - Added an option to be able to clear search results. + +#### Notifications + - Enabled push notifications by default on new Mattermost installs, via an encrypted TPNS (test push notification service). + - Added a channel notification setting to disable @-channel @-here @-all notifications in specific channels. + +#### Performance + - Increased performance for returning user autocomplete results. + +#### Plugins + - Added a "min_server_version" field to plugin.json manifest, which enables built-in control for preventing loading plugins that are not compatible with the Mattermost server version. + - Added ability for plugins to add channel header tooltips. + - Stopped hashing plugin keys on write to more effectively enumerate the keys stored by a plugin. + - Removed support for automatically unmarshalling a plugin's server configuration. + +#### Bulk Import/Export + - Added custom emoji and emoji reactions to bulk export tool. + - Added favorite channels to bulk export tool. + - Added user and channel notification preferences to bulk export tool. + - Added the ability to specify an email batching interval for bulk import. + +#### Slash Commands + - Added support for multiple responses from a slash command. + - Added an option to send a message when an invalid slash command is entered. + +#### Administration + - Added mobile support for Custom Terms of Service (Beta) + - Removed **System Console > Plugins (Beta) > Configuration** page and moved enabling plugins setting to the **Plugins (Beta) > Management** page. + - Introduced mlog/human package to consume and reformat structured logging with a human readable output. + +#### Enterprise Edition (E20) + - Data Retention promoted out of beta. + +### Bug Fixes + - Fixed an issue where pinned post list refreshed when a user posted a new message. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``"ServiceSettings"`` in ``config.json``: + - Added ``"TLSMinVer": "1.2"``, ``"TLSStrictTransport": false``, ``"TLSStrictTransportMaxAge": 63072000`` and ``"TLSOverwriteCiphers": []``, to configure TLS connection when not using a reverse proxy such as NGINX. + - Under ``"ExperimentalSettings"`` in ``config.json``: + - Added ``"EnablePostMetadata": false``, to disable post metadata from being loaded. + +### API Changes + +#### RESTful API v4 Changes + - Added ``GET /channels/{channel_id}/timezones`` to get a list of timezones for the users who are in the specified channel. + - Added ``page`` and ``per_page`` properties to ``POST /teams/{team_id}/posts/search`` call for Elasticsearch paging. + - Added ``DELETE /users/{user_id}/image`` to remove a user's profile picture. + - Added ``DELETE /brand/image`` to remove a custom branding image. + - Added ``POST /actions/dialogs/open`` and ``POST /actions/dialogs/submit`` to open and submit requests via interactive dialogs. + +#### Plugin API Changes + - **Changed ``GetTeamMembers(teamId string, offset, limit int)`` to ``GetTeamMembers(teamId string, page, perPage int)`` to be clearer and consistent with other APIs** + - **Changed ``GetPublicChannelsForTeam(teamId string, offset, limit int)`` to ``GetPublicChannelsForTeam(teamId string, page, perPage int)`` to be clearer and more consistent with other APIs** + - Added the following plugin API methods. For more information on each method, see the [server plugin reference](https://developers.mattermost.com/extend/plugins/server/reference/). + - ``GetChannelsForTeamForUser`` + - ``GetChannelMembers`` + - ``GetChannelMembersByIds`` + - ``GetChannelStats`` + - ``GetEmoji`` + - ``GetEmojiByName`` + - ``GetEmojiImage`` + - ``GetEmojiList`` + - ``GetPluginConfig`` + - ``SavePluginConfig`` + - ``GetPostsAfter`` + - ``GetPostsBefore`` + - ``GetPostsSince`` + - ``GetPostsForChannel`` + - ``GetPostThread`` + - ``GetProfileImage`` + - ``SetProfileImage`` + - ``GetTeamsForUser`` + - ``GetTeamsUnreadForUser`` + - ``GetTeamIcon`` + - ``SetTeamIcon`` + - ``RemoveTeamIcon`` + - ``GetUsersByUsernames`` + - ``GetUsersInChannel`` + - ``GetUsersInChannelByStatus`` + - ``GetUsersInTeam`` + - ``CreateDirectChannel`` + - ``SearchChannels`` + - ``SearchUsers`` + - ``GetFileLink`` + - ``UploadFile`` + - ``SetProfileImage`` + - ``KVSetWithExpiry`` + - ``KVDeleteAll`` + - ``KVList`` + +#### Database Changes + + - Added ``ExpireAt`` column to the ``PluginKeyValueStore`` table. + - Migrated user's accepted terms of service data into a new table called ``UserTermsOfService``. + - Removed ``idx_users_email_lower``, ``idx_users_username_lower``, ``idx_users_nickname_lower``, ``idx_users_firstname_lower`` and ``idx_users_lastname_lower`` indexes. + +### Known Issues + + - Login does not work when Custom Terms of Service is enabled and MFA is enforced. + - Custom Terms of Service returns on refresh after clicking to agree. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://github.com/aeomin), [amorriscode](https://github.com/amorriscode), [amyblais](https://github.com/amyblais), [ArchRoller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [bbodenmiller](https://github.com/bbodenmiller), [bd12](https://github.com/bd12), [chclaus](https://github.com/chclaus), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [chrux](https://github.com/chrux), [cobenash](https://github.com/cobenash), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [danmaas](https://github.com/danmaas), [der-test](https://github.com/der-test), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [gy741](https://github.com/gy741), [hanzei](https://github.com/hanzei), [harshilsharma](https://github.com/harshilsharma), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jlevesy](https://github.com/jlevesy), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [knrt10](https://github.com/knrt10), [letsila](https://github.com/letsila), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [meilon](https://github.com/meilon), [mickmister](https://github.com/mickmister), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mojicaj](https://github.com/mojicaj), [murugesan](https://github.com/pradeepmurugesan), [patniharshit](https://github.com/patniharshit), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [rononline](https://github.com/rononline), [ryoon](https://github.com/ryoon), [sandlis](https://github.com/sandlis), [saturninoabril](https://github.com/saturninoabril), [scottleedavis](https://github.com/scottleedavis), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [thePanz](https://github.com/thePanz), [ThiefMaster](https://github.com/ThiefMaster), [torlenor](https://github.com/torlenor), [tuxfamily](https://github.com/tuxfamily), [uhlhosting](https://github.com/uhlhosting), [vaithak](https://github.com/vaithak), [waseem18](https://github.com/waseem18), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc), [zeroimpl](https://github.com/zeroimpl), [zetaab](https://github.com/zetaab) + +---- + +## Release v5.5 - Quality Release + +- **v5.5.3, released 2019-02-01** + - Mattermost v5.5.3 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.5.2, released 2019-01-16** + - Mattermost v5.5.2 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.5.1, released 2018-12-06** + - Fixed a bug preventing Elasticsearch v6.0+ from working in Mattermost server versions 5.4 and 5.5. +- **v5.5.0, released 2018-11-16** + - Original 5.5.0 release + +### Bug Fixes + - Fixed an issue where clicking the two arrows to expand/collapse an image didn't work after posting an image. + - Fixed an issue where switching authentication methods from email/password to SAML (OKTA and OneLogin) showed session expiry message instead of a success message. + - Fixed an issue where message drafts occasionally posted to the channel even though user did not take any action to post it. + - Fixed an issue with Autoresponder feature where the reply message did not get inserted consistently. + - Fixed an issue where bolded channel names rendered over top of unbolded channel names in desktop. + - Fixed an issue where config.ServiceSettings.SiteURL could contain a trailing slash. + - Fixed a caching issue with archiving/unarchiving channels through API. + - Fixed UX issues when trying to edit pending posts from reply thread. + - Fixed an issue where "Enable Post Formatting" did not actually require page refresh. + - Fixed an issue where User AuthService Export value of "" could be incompatible for importer. + - Fixed an issue where search results that did not match case were not highlighted when returning hashtags in search results. + - Fixed issues with indentation on the right-hand side in desktop app compact view. + - Fixed an issue where the post header for bot messages was cutting off username before using available horizontal space. + - Fixed an issue where "undefined" was briefly shown on refresh with combined system messages. + - Fixed an issue where profile popover was cut-off at right-hand side root post. + - Fixed UX issues for some plugins that displayed a blank page when clicking on the "Settings" link from "Management" page in System Console. + - Fixed an issue where uploading a plugin resulted in a JS error and a blank page. + - Fixed an issue where some team icons did not fill bounding box on MacOS. + - Fixed an issue where there was no hover effect on emoji reactions. + - Fixed an issue where a permanent announcement banner pushed the bottom of a channel sidebar off screen. + - Fixed an issue where cancelling a change to channel notifications settings appeared to save the change. + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://github.com/aeomin), [Akash4927](https://github.com/Akash4927), [alexander-akhmetov](https://github.com/alexander-akhmetov), [amogozov](https://github.com/amogozov), [amorriscode](https://github.com/amorriscode), [amyblais](https://github.com/amyblais), [anchepiece](https://github.com/anchepiece), [ArchRoller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [Charliekenney23](https://github.com/Charliekenney23), [charvp](https://github.com/charvp), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [cjohannsen81](https://github.com/cjohannsen81), [cobenash](https://github.com/cobenash), [cometkim](https://github.com/cometkim), [cored](https://github.com/cored), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [czertbytes](https://github.com/czertbytes), [danmaas](https://github.com/danmaas), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [dos1701](https://github.com/dos1701), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [florianeichin](https://github.com/florianeichin), [fraziern](https://github.com/fraziern), [grundleborg](https://github.com/grundleborg), [gupsho](https://github.com/gupsho), [gy741](https://github.com/gy741), [hanzei](https://github.com/hanzei), [harshilsharma](https://github.com/harshilsharma), [harshilsharma](https://github.com/harshilsharma), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasimmons](https://github.com/jasimmons), [jasonblais](https://github.com/jasonblais), [JayaKrishnaNamburu](https://github.com/JayaKrishnaNamburu), [jespino](https://github.com/jespino), [JtheBAB](https://github.com/JtheBAB), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [KerryAlsace](https://github.com/KerryAlsace), [klingtnet](https://github.com/klingtnet), [knrt10](https://github.com/knrt10), [leblanc-simon](https://github.com/leblanc-simon), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lologarithm](https://github.com/lologarithm), [MattMattV](https://github.com/MattMattV), [meilon](https://github.com/meilon), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [mojicaj](https://github.com/mojicaj), [mukulrawat1986](https://github.com/mukulrawat1986), [n7st](https://github.com/n7st), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [powhu](https://github.com/powhu), [pradeepmurugesan](https://github.com/pradeepmurugesan), [pushkyn](https://github.com/pushkyn), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [rononline](https://github.com/rononline), [ryoon](https://github.com/ryoon), [s4kh](https://github.com/s4kh), [SaashaJoshi](https://github.com/SaashaJoshi), [saturninoabril](https://github.com/saturninoabril), [SergeyShpak](https://github.com/SergeyShpak), [sonasingh46](https://github.com/sonasingh46), [sudheerDev](https://github.com/sudheerDev), [thePanz](https://github.com/thePanz), [torlenor](https://github.com/torlenor), [tyvsmith](https://github.com/tyvsmith), [uhlhosting](https://github.com/uhlhosting), [uusijani](https://github.com/uusijani), [VPashkov](https://github.com/VPashkov), [waseem18](https://github.com/waseem18), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.4 - Feature Release + +Release date: 2018-10-16 + +- Mattermost v5.4.0 contains a low level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Breaking Changes since the last release + + - Mattermost mobile app version 1.13+ is required. File uploads will fail on earlier mobile app versions. + - In certain upgrade scenarios the new Allow Team Administrators to edit others posts setting under General then Users and Teams may be set to True while the Mattermost default in 5.1 and earlier and with new 5.4+ installations is False. + +```{Important} +If you upgrade from another release than 5.3, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Basic Export Tool + - Created a basic exporter tool to extract objects from Mattermost for allowing to merge two servers. + +### Improvements + +#### Web User Interface (UI) + - Added a draft indicator in the channel sidebar and channel switcher for channels with unsent messages. + - Added support for jumboemojis. + - Added support for searching in direct message and group message channels using the "in:" modifier. + - Last viewed channel on logout is restored on next session. + - Added support for consecutive messages in the right-hand side. + - Added tooltips to post info overlay buttons. + - Added a feature to post a code block on CTRL + ENTER. + - Expanded post text box area when composing long posts. + - Updated the pinned post list when it's open and the channel is switched so that the pinned post list updates to show the other channel's pinned posts. + - Download of common file types is not forced when viewing a public link. + +#### Command Line Interface (CLI) + - Added a new Command Line Interface for removing all users from a channel. + +#### Performance + - Improved channel switcher performance. + +#### Integrations + - Added interactive menus to message attachments. + - Added a autotranslation plugin. + - Added a button to copy the information from webhooks/slash commands such as the url and token. + - Added "Commented on..." text for files and message attachment type posts. + - Updated incoming and outgoing webhook description to 500 characters. + - Added hook ID to webhook requests in server logs. + - Plugins without a server or webapp component now fail to be activated. + +#### Notifications + - Desktop notifications now follow teammate name display setting. + - Added a mute/unmute option to channel dropdown menu. + - Added a mute icon to mobile view. + - Added support for notifying users when desktop/browser sessions expire. + +#### Autocomplete and Focus + - With "Send messages on CTRL+ENTER = ON", channel and user autocomplete now work. + - Cursor is now autofocused on edit box before the modal fully loads. + - Channel autocomplete closes after two consecutive tildes used for strikethrough formatting. + - If a user begins typing and the cursor is not in an input box, the cursor is automatically put into the center channel text input box. + +#### Administration + - Moved hiding join/leave messages to Team Edition. + - Added ``edit_others_posts`` as a permission setting for Team Edition. + - Added account setting option to hide channel switcher button in the sidebar. + +#### Compliance + - Added changes for E20 custom service terms. + - Team membership can be restricted based on email domains. + +### Bug Fixes + - Fixed an issue where logging in with LDAP account with MFA enabled resulted in "Error trying to authenticate MFA token" error when "Enable sign-in with username" was set to false. + - Fixed an issue where log-in page flashed briefly during process of verifying an updated email address. + - Fixed an issue where ""GET /api/v4/redirect_location" responses got stuck when “EnableLinkPreviews” was set to "false”. + - Fixed an issue where Account Settings teammate name display setting changed when System Console teammate name display setting was changed. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Enterprise Edition: + + - Under "SqlSettings": in ``config.json``: + - Added ``"EnablePublicChannelsMaterialization": true``, to increase channel search performance in the channel switcher (CTRL/CMD+K), channel autocomplete (~) and elsewhere in the UI. + +### API Changes + +#### Plugin API Changes + - Added slash commands with GET crush query parameters on configured endpoint URL to avoid parameters specified by both the user and Mattermost from being duplicated. + - Added a GetServerVersion() string method to the plugin API to return the current server version. + +#### Database Changes + - ``Description`` column was added to the ``OutgoingWebhooks`` table. + - ``Description`` column was added to the ``IncomingWebhooks`` table. + - ``AcceptedServiceTermsId`` column was added to the ``Users`` table. + - ``PublicChannels`` table was added. + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://github.com/aeomin), [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [ArchRoller](https://github.com/archroller), [avasconcelos114](https://github.com/avasconcelos114), [balcsida](https://github.com/balcsida), [bezumkin](https://github.com/bezumkin), [ccpaging](https://github.com/ccpaging), [chetanyakan](https://github.com/chetanyakan), [chikei](https://github.com/chikei), [cimfalab](https://github.com/cimfalab), [cjbirk](https://github.com/cjbirk), [cometkim](https://github.com/cometkim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [cvitter](https://github.com/cvitter), [danmaas](https://github.com/danmaas), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [dmitrysamuylovpharo](https://github.com/dmitrysamuylovpharo), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [FurmanovD](https://github.com/FurmanovD), [gramakri](https://github.com/gramakri), [greensteve](https://github.com/greensteve), [grundleborg](https://github.com/grundleborg), [gvengel](https://github.com/gvengel), [hanzei](https://github.com/hanzei), [harshilsharma](https://github.com/harshilsharma), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jazzzz](https://github.com/jazzzz), [jespino](https://github.com/jespino), [jkurian](https://github.com/jkurian), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kongr45gpen](https://github.com/kongr45gpen), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [meilon](https://github.com/meilon), [mikroskeem](https://github.com/mikroskeem), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [n1aba](https://github.com/n1aba), [n7st](https://github.com/n7st), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [pkuhner](https://github.com/pkuhner), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [ryoon](https://github.com/ryoon), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev), [tejasbubane](https://github.com/tejasbubane), [thawn](https://github.com/thawn), [thePanz](https://github.com/thepanz), [ThiefMaster](https://github.com/ThiefMaster), [uhlhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [xcompass](https://github.com/xcompass), [yuya-oc](https://github.com/yuya-oc), [zetaab](https://github.com/zetaab) + +---- + +## Release v5.3 - Feature Release + +Mattermost v5.3.0 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +- **v5.3.1, released 2018-09-19** + - Fixed an issue where HTML elements such as links did not display correctly for non-English languages. +- **v5.3.0, released 2018-09-16** + - Original 5.3.0 release + +### Breaking Changes since the last release + + - Those servers with Elasticsearch enabled will notice that hashtag search is case-sensitive. + +```{Important} +If you upgrade from another release than 5.2, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Search Date Filters +- Search for messages before, on, or after a specified date. + +#### IdAttribute Setting for SAML +- Added a new `IdAttribute` setting for SAML, which allows SAML users to change their email address without losing their account. + +### Improvements + +#### Web User Interface (UI) +- Added ability to set username and profile picture in **Outgoing Webhooks** setup page. +- Added "Deactivate Account" option under **Account Settings > Advanced**. +- Added member count for the **More Direct Messages** list. +- Expanded shortened (e.g. bitly) links for previewable content such as images and YouTube links. + +#### Performance +- Improved channel switcher performance by adding a short delay after the last character has been typed before querying the server for new autocomplete results. + +#### Integrations +- Added support for interactive message buttons to, for instance, delete or edit the post after clicking on a message button. + +#### Administration +- Created a telemetry event for when telemetry is turned off from the System Console. +- Added support for attachments in Direct Message channels to the [bulk import tool](https://docs.mattermost.com/onboard/bulk-loading-data.html). + +### Bug Fixes +- Fixed an issue where closing an archived channel did not redirect users to the last viewed channel. +- Fixed an issue where users were able to react to existing emojis in an archived channel. +- Fixed an issue where clicking "+" twice to add a public or private channel added a recently archived channel back to the left-hand side. +- Fixed an issue where channel autocomplete appeared to include all public channels, including deleted channels and channels one has never joined. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Enterprise Edition: + + - Under "SamlSettings": in ``config.json``: + - Added ``"EnableSyncWithLdapIncludeAuth": false,`` to override the SAML ID attribute with the AD/LDAP ID attribute if configured, or override the SAML Email attribute with the AD/LDAP Email attribute if SAML ID attribute is not present. See the [AD/LDAP](https://docs.mattermost.com/onboard/ad-ldap.html?&redirect_source=about-mm-com) documentation to learn more. + - Added ``"IdAttribute": "",`` to set the attribute in the SAML Assertion that will be used to bind users from SAML to users in Mattermost. + +### API Changes + +#### Plugin API Changes (Release Candidate) + - Added ``postId`` as a property for ``PostDropDownMenuComponent`` and as a parameter for the ``PostDropDownMenuAction`` function to improve the ability to add options to the post "..." action menu. + - Added ``FileInfo`` and ``file []byte`` to retrieve File Info for a specific fileId and to ensure the file is read for a specific path. + - Added ``GetLDAPUserAttributes``, which matches the functionality of the ``ldapextras`` built-in plugin that was removed in Mattermst v5.2. + +### Known Issues + + - When "Enable sign-in with username" is set to false, logging in with LDAP account with MFA enabled results in "Error trying to authenticate MFA token" error. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://github.com/aeomin), [amyblais](https://github.com/amyblais), [ArchRoller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [dcherniv](https://github.com/dcherniv), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [dmitrysamuylovpharo](https://github.com/dmitrysamuylovpharo), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [gvengel](https://github.com/gvengel), [Hanzei](https://github.com/Hanzei), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [Jessica-c53](https://github.com/Jessica-c53), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [meilon](https://github.com/meilon), [MerlinDMC](https://github.com/MerlinDMC), [michaelkochub](https://github.com/michaelkochub), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [n1aba](https://github.com/n1aba), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [pradeepmurugesan](https://github.com/pradeepmurugesan), [robert843](https://github.com/robert843), [rodcorsi](https://github.com/rodcorsi), [rononline](https://github.com/rononline), [rqtaylor](https://github.com/rqtaylor), [ryoon](https://github.com/ryoon), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [sjstyle](https://github.com/sjstyle), [sudheerDev](https://github.com/sudheerDev), [thePanz](https://github.com/thepanz), [ThiefMaster](https://github.com/ThiefMaster), [uhlhosting](https://github.com/uhlhosting), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.2 - Feature Release + + - **v5.2.2, released 2018-09-16** + - Mattermost v5.2.2 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). +- **v5.2.1, released 2018-08-23** + - Disabled the ability to search archived channels by default, given multiple issues were raised after v5.2.0 was released. The feature can be enabled in v5.2.1 via ``ExperimentalViewArchivedChannels`` setting. +- **v5.2.0, released 2018-08-16** + - Original 5.2.0 release + +### Security Update + +- Mattermost v5.2.0 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Breaking Changes since the last release + + - Those servers upgrading from v4.1 - v4.4 directly to v5.2 or later and have JIRA enabled will need to re-enable the JIRA plugin after an upgrade. + +```{Important} +If you upgrade from another release than 5.1, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Embed Mattermost in Other Apps (Beta) + - Added support for extensions, which allow you to embed Mattermost in other apps and websites via OAuth 2.0. + - A sample extension for Chrome [is here](https://github.com/mattermost/mattermost-chrome-extension). + +#### Plugins + - Added support to add/delete and enable/disable plugins via the CLI. + - See our [demo plugin](https://github.com/mattermost/mattermost-plugin-demo) that demonstrates the capabilities of a Mattermost plugin. For a starting point to write a Mattermost plugin, see our [sample plugin](https://github.com/mattermost/mattermost-plugin-sample). + - Breaking changes to the plugins framework introduced. To migrate your existing plugins to be compatible with Mattermost 5.2 and later, see our [migration guide](https://developers.mattermost.com/extend/plugins/migration/). + +#### Searching Archived Channels + - Added ability to search for archived channel content on desktop and mobile clients. + +#### Romanian Language + - Added support for Romanian language. + +### Improvements + +#### Web User Interface (UI) + - Added experimental custom default channels. + - Added link to profile pop-over from names in Join/Leave messages. + - Added support for webhook message attachments to trigger mentions. + - Stripped markdown formatting characters from desktop notifications and "Commented on..." text. + - Added ability to bulk import emoji. + - Added support for file attachments in bulk import. + +#### Plugins (All Beta) + - New [antivirus plugin](https://github.com/mattermost/mattermost-plugin-antivirus) to scan for viruses before uploading a file to Mattermost. Supports [ClamAV anti-virus software](https://www.clamav.net/) across browser, Desktop Apps and the Mobile Apps. + - New [GitHub plugin](https://github.com/mattermost/mattermost-plugin-github) to subscribe to notifications, and to keep track of unread GitHub messages and open pull requests requiring your attention. + - [Zoom plugin](https://docs.mattermost.com/configure/plugins-configuration-settings.html#zoom) now has one option to start a meeting rather than three separate ones to simplify the user experience. + +#### Server Plugins: Release Candidate + - A release candidate (RC) is released for server plugins. Stable release is expected in v5.3 or v5.4. + - Added various API methods for plugins to provide the same capabilities as the REST API. + - Added support to intercept file uploads before the file is uploaded to a Mattermost server. + - Added support for plugins to respond after a user joins/leaves a channel or a team, or creates a new channel. + - Added support for plugins to respond prior to or after a user logs in to a Mattermost server. + - Added support for plugins to update user status. Sample use case is setting a user’s status to Do Not Disturb based on Google Calendar events. + - Added CSRF tokens that are attached to users sessions. The tokens can be enforced as an alternative to XHR checks in the plugin request system. + - Added session token to context for ServeHTTP hook. + +#### Webapp Plugins: Beta + - Upcoming Mattermost UI redesign may cause breaking changes to webapp plugins. Hence, webapp plugins remain as beta in v5.2. + - Added support to override [...] post menu, and paperclip icon for file uploads. + - Added support for multiple plugins to add components at the same integration points instead of only allowing one plugin to do so. + - Removed ability to fully override profile popover. Instead, multiple plugins can now add to the profile popover via multiple integration points. + - For an up-to-date list of pluggable UI components, [see this list in our demo plugin](https://github.com/mattermost/mattermost-plugin-demo/tree/master/webapp#components). + +#### Administration + - In the compliance export status table, in System Console > Compliance > Compliance Export, added a number of exported records to Details column. + - Added support for cross-origin resource sharing. + +#### Command Line Interface (CLI) + - Enhanced log output from Permanent Delete CLI command to delete FileInfos for a user's posts. + - Addded channel renaming to CLI. + +#### Enterprise Edition + - Added the Global Relay Export CLI command. + - Added support to search plugin contents. + +### Bug Fixes + - Fixed an issue where the "Switch Channel" shortcut (⌘K) didn't work on dvorak layout on Mac. + - Fixed an issue where the Custom Integrations section in the System Console was blank after role changes. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under "ServiceSettings": in ``config.json``: + - Added ``"CorsExposedHeaders": ""``, to add a whitelist of headers that will be accessible to the requester. + - Added ``"CorsAllowCredentials": false``, to allow requests that pass validation to include the ``Access-Control-Allow-Credentials`` header. + - Added ``"CorsDebug": false``, to print messages to the logs to help when developing an integration that uses CORS. + - Under "TeamSettings" in ``config.json``: + - Added ``"ViewArchivedChannels": true``, to allow users to share permalinks and search for content of channels that have been archived. + - Added ``"ExperimentalDefaultChannels": ""``, to allow choosing the default channels every user is added to automatically after joining a new team. + +### API Changes + +#### RESTful API v4 Changes + - ``deleteReaction`` API was added to send the correct value for ``post.HasReactions``. + - Support for add/delete and enable/disable plugins via CLI was added. + - File download API was improved to stream files instead of loading them entirely into memory. + +#### Websocket Changes + - Support for add/delete and enable/disable plugins via CLI was added. + +#### Database Changes + - Two new columns were added in the ``OutgoingWebhooks`` table, "Username" and "IconURL". + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors +[aeomin](https://github.com/aeomin), [alanpog](https://github.com/alanpog), [Alexgoodman7](https://github.com/Alexgoodman7), [amyblais](https://github.com/amyblais), [archroller](https://github.com/archroller), [asaadmahmood](https://github.com/asaadmahmood), [burguyd](https://github.com/burguyd), [chikei](https://github.com/chikei), [cometkim](https://github.com/cometkim), [comharris](https://github.com/comharris), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [der-test](https://github.com/der-test), [DHaussermann](https://github.com/DHaussermann), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [falcon78921](https://github.com/falcon78921), [fdebrabander](https://github.com/fdebrabander), [grundleborg](https://github.com/grundleborg), [herooftimeandspace](https://github.com/herooftimeandspace), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [Jessica-c53](https://github.com/Jessica-c53), [JustinReynolds-MM](https://github.com/JustinReynolds-MM), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [kennethjeremyau](https://github.com/kennethjeremyau), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [meilon](https://github.com/meilon), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [pepf](https://github.com/pepf), [pichouk](https://github.com/pichouk), [pietroglyph](https://github.com/pietroglyph), [pjgrizel](https://github.com/pjgrizel), [pradeepmurugesan](https://github.com/pradeepmurugesan), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [ryoon](https://github.com/ryoon), [santos22](https://github.com/santos22), [saturninoabril](https://github.com/saturninoabril), [scherno2](https://github.com/scherno2), [seansackowitz](https://github.com/seansackowitz), [sudheerDev](https://github.com/sudheerDev), [tejasbubane](https://github.com/tejasbubane), [theblueskies](https://github.com/theblueskies), [ThiefMaster](https://github.com/ThiefMaster), [uhlhosting](https://github.com/uhlhosting), [uusijani](https://github.com/uusijani), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.1 - Feature Release + + - **v5.1.2, released 2018-09-16** + - Mattermost v5.1.2 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v5.1.1, released 2018-08-07** + - Mattermost v5.1.1 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v5.1.0, released 2018-07-16** + - Original 5.1.0 release + +### Security Update + +- Mattermost v5.1.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Breaking Changes since the last release + + - ``mattermost export`` CLI command is renamed to ``mattermost export schedule``. Make sure to update your scripts if you use this command. + +```{Important} +If you upgrade from another release than 5.0, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Gfycat integration + - Added easy access to sharing GIFs without leaving the Mattermost interface. System Admins can enable this feature in **System Console > Customization > GIF**. + +#### Auto-linking plugin (Beta) + - Messages can now be formatted into Markdown links automatically before they are saved to the Mattermost database. See [autolink plugin repository](https://github.com/mattermost/mattermost-plugin-autolink) to learn more. + +#### Support Mattermost on a subpath + - Added support for hosting Mattermost at any route (e.g., https://www.example.com/mattermost) with newly added subpath support. + +#### CSV Compliance Export ([Enterprise Edition E20](https://mattermost.com/pricing/)) + - Extended compliance export feature with CSV format. See [documentation](https://docs.mattermost.com/administration/compliance-export.html) to learn more. + +### Improvements + +#### Web User Interface + - Added highlighting for Elasticsearch results. + - Renamed "Delete Channel" to "Archive Channel". Channels can be unarchived [from the commandline](https://docs.mattermost.com/administration/command-line-tools.html#mattermost-channel-restore). + - Added Channel Purpose as a searchable field in the "More Channels" menu. + +#### Administration + - Added the ability to reset user emails in **System Console > Users**. + - Server restart is no longer required to run the job server for the first time. + +#### Command Line Interface (CLI) + - Made the `permissions reset` CLI command able to reset all custom-role related data. + - When `permanent delete user` CLI command is used, all files uploaded by the user are now deleted as well. + - ``export`` CLI command was updated to support scheduling exports via `export schedule`, and to export files in Actiance XML and CSV formats. + - Running the CLI outside of the bin directory is now less error prone. + +#### Enterprise Edition E20 + - Added experimental support for certificate-based authentication (CBA) to identify a user or a device before granting access to Mattermost. See [documentation](https://docs.mattermost.com/onboard/certificate-based-authentication.html) to learn more. + +### Bug Fixes + + - Fixed an issue where users could not reply to push notifications on iOS. + - Fixed an issue with an incorrect system message after converting a public channel to private. + - Fixed an issue with being unable to add emoji reactions after expanding the message details sidebar. + - Fixed an issue where [rate limiting settings](https://docs.mattermost.com/administration/config-settings.html#rate-limiting) could not be edited in the System Console, and weren't displayed in the User Interface if configured via `config.json`. + - Fixed an issue where deleted users shown as "Someone" in the Favorite Channels section could not be removed. + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under "ExperimentalSettings:" in ``config.json``: + - Added ``"ClientSideCertEnable": false,``, to enable client-side certification for your Mattermost server. + - Added ``"ClientSideCertCheck": "secondary"``, to control whether email and password are required following client-side certification. + - Under "ServiceSettings:" in ``config.json``: + - Added ``"ExperimentalLimitClientConfig": false``, to limit the number of config settings sent to users prior to login. Supported on mobile apps v1.10 and later. + - Added ``"EnableGifPicker": false,``, ``"GfycatApiKey": 2_KtH_W5,`` and ``"GfycatApiSecret": 3wLVZPiswc3DnaiaFoLkDvB4X0IV6CpMkj4tf2inJRsBY6-FnkT08zGmppWFgeof,`` to enable a built-in GIF integration with Gfycat. + - Added ``"EnableEmailInvitations": false``, to disable email invitations on the system. + - Under "SqlSettings:" in ``config.json``: + - Added ``"ConnMaxLifetimeMilliseconds": 3600000,``, to configure the maximum lifetime for a connection to the database. + +### API Changes + +#### RESTful API v4 Changes + + - A new ``matches`` field was added to ``POST teams/{team_id}/posts/search`` to return a list of matched terms within the post. This field will only be populated on servers running version v5.1 or greater with Elasticsearch enabled. + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[Alexgoodman7](https://github.com/Alexgoodman7), [amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [asaadmahmood](https://github.com/asaadmahmood), [Brodan](https://github.com/Brodan), [cjohannsen81](https://github.com/cjohannsen81), [cometkim](https://github.com/cometkim). [comharris](https://github.com/comharris), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [dmeza](https://github.com/dmeza), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [evelikov](https://github.com/evelikov), [fbartels](https://github.com/fbartels), [greensteve](https://github.com/greensteve), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jkurian](https://github.com/jkurian), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kennethjeremyau](https://github.com/kennethjeremyau), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lisakycho](https://github.com/lisakycho), [michaelgamble](https://github.com/michaelgamble), [mkraft](https://github.com/mkraft), [pichouk](https://github.com/pichouk), [Roy-Orbison](https://github.com/Roy-Orbison), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [stanchan](https://github.com/stanchan), [sudheerDev](https://github.com/sudheerDev),[svelle](https://github.com/svelle), [tejasbubane](https://github.com/tejasbubane), [ThiefMaster](https://github.com/ThiefMaster), [wiersgallak](https://github.com/wiersgallak), [wildloop](https://github.com/wildloop), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v5.0 - Feature Release + + - **v5.0.3, released 2018-08-07** + - Mattermost v5.0.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v5.0.2, released 2018-07-16** + - Mattermost v5.0.2 contains a high severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v5.0.1, released 2018-07-09** + - Fixed an issue where large Global Relay exports could cause export jobs to fail completely. + - **v5.0.0, released 2018-06-16** + - Original 5.0.0 release + +### Breaking Changes since the last release + +- All API v3 endpoints have been removed. [See documentation](https://api.mattermost.com/#tag/schema) to learn more about how to migrate your integrations to API v4. [Ticket #8708](https://mattermost.atlassian.net/browse/MM-8708). +- `platform` binary has been renamed to mattermost for a clearer install and upgrade experience. **You should point your `systemd` service file at the new `mattermost` binary.** All command line tools, including the bulk loading tool and developer tools, have also been renamed from platform to mattermost. [Ticket #9985](https://mattermost.atlassian.net/browse/MM-9985). +- A Mattermost user setting to configure desktop notification duration in **Account Settings** > **Notifications** > **Desktop Notifications** has been removed. +- Slash commands configured to receive a GET request now have the payload encoded in the query string instead of receiving it in the body of the request, consistent with standard HTTP requests. Although unlikely, this could break custom slash commands that use GET requests incorrectly. [Ticket #10201](https://mattermost.atlassian.net/browse/MM-10201). +- A new `config.json` setting to whitelist types of protocols for auto-linking has been added. [Ticket #9547](https://mattermost.atlassian.net/browse/MM-9547). +- A new `config.json` setting to disable the [permanent APIv4 delete team parameter](https://api.mattermost.com/#tag/teams%2Fpaths%2F~1teams~1%7Bteam_id%7D%2Fput) has been added. The setting is off by default for all new and existing installs, except those deployed on GitLab Omnibus. A System Administrator can enable the API v4 endpoint from the config.json file. [Ticket #9916](https://mattermost.atlassian.net/browse/MM-9916). +- An unused `ExtraUpdateAt` field has been removed from the channel model. [Ticket #9739](https://mattermost.atlassian.net/browse/MM-9739). + +```{Important} +If you upgrade from another release than 4.10, please read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html). +``` + +### Highlights + +#### Plugin Intercept + - Adds support for plugins to intercept posts prior to saving them into the database. + - Supports use cases such as auto-detecting and censoring restricted words, and auto-linking phrases. [Read our forum post to learn more](https://forum.mattermost.com/t/coming-soon-apiv4-mattermost-post-intercept/4982). + +#### Permissions Schemes + - System Scheme now sets the default permissions inherited system-wide by System Admins, Team Admins, Channel Admins and everyone else. + - Added new Team Schemes to override the default permissions in specific teams for Team Admins, Channel Admins and all other team members. + +#### Increased Character Limit on Posts + - Increased character limit to 16,383 on new deployments to allow posting long messages and to allow better Markdown formatting, including tables. + - For existing deployments, read [how to migrate your system](https://docs.mattermost.com/administration/important-upgrade-notes.html) to support the increased character limit. + +#### Combined Join/Leave Messages + - System messages related to joining, leaving, adding and removing people from channels and teams are combined into a single message to save space in channels. + +### Improvements + +#### Web User Interface + - Added a feature to collapse image upload using a collapse icon or using the ``/collapse`` command. + - Added a whitelist for valid types of links when autolinking. + - Updated the styling of default team icons. + +#### Performance + - Fixed ``update_status`` cluster event being sent thousands of times on restart of app servers. + +#### Integrations + - Slash commands configured to receive a GET request now have the payload encoded in the query string instead of receiving it in the body of the request. + - Added ability for webhooks to actually be locked to a channel. + +#### Notifications + - Updated email notification subject line and contents for Group Messages. + - Updated the styling of push notifications. + +#### System Console + - Added a System Console setting to disable the preview mode banner when email notifications are disabled. + +#### Administration + - Added Password Requirements and Customer Branding to Team Edition. + - Moved Themes per team to Team Edition. + +#### Enterprise Edition + - Added ``LoginIdAttribute`` to allow LDAP users to change their login ID without losing their account. + +### Bug Fixes + + - Fixed an issue where ``EnableUserCreation`` was set to `false` when not included in config.json. + - Fixed an issue where a public channel made private did not disappear automatically from clients not part of the channel. + - Fixed an issue where team icon did not get automatically saved when removed. + - Fixed an issue where Town Square channel disappeared from channel list for a non-admin users when "ExperimentalTownSquareIsReadOnly" `config.json` was set to `true` in config.json. + +### Compatibility + + - For a list of important changes with Mattermost v5.0, please [see our Forum announcement](https://forum.mattermost.com/t/upcoming-changes-with-mattermost-v5-0/5119). + +### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under ``"ServiceSettings":`` in ``config.json``: + - Added ``"EnableAPITeamDeletion": false,`` to disable the permanent APIv4 delete team parameter. + - Added ``"ExperimentalEnableHardenedMode": false`` to enable a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. + - Under ``"EmailSettings":`` in ``config.json``: + - Added ``"EnablePreviewModeBanner": true,`` to allow Preview Mode banner to be displayed so users are aware that email notifications are disabled. + - Under ``"ClusterSettings":`` in ``config.json``: + - Added ``"MaxIdleConns": 100,`` to add the maximum number of idle connections held open from one server to all others in the cluster. + - Added ``"MaxIdleConnsPerHost": 128,`` to add the maximum number of idle connections held open from one server to another server in the cluster. + - Added ``"IdleConnTimeoutMilliseconds": 90000`` to add the number of milliseconds to leave an idle connection open between servers in the cluster. + - Under ``"TeamSettings":`` in ``config.json``: + - Added ``"ExperimentalHideTownSquareinLHS": false,`` to hide Town Square in the left-hand sidebar if there are no unread messages in the channel. + - Under ``"DisplaySettings":`` in ``config.json``: + - Added ``"CustomUrlSchemes": [],``, to add a list of URL schemes that are used for autolinking in message text. + - Under ``"LdapSettings":`` in ``config.json``: + - Added ``"LoginIdAttribute": "",`` to add an attribute in the AD/LDAP server used to log in to Mattermost. + +#### API Changes + + - All APIv3 endpoints were removed. + - Improved file upload API to stream files instead of loading them entirely into memory. + - SAML login endpoints were moved out of API package. + - ``context.go`` was moved out of Api4 and into web. + - ``api4/handlers.go`` was created to create the API handlers using the Context and Handler from web. + - ``web/handlers.go`` was added to define the Handler struct, the base ServeHTTP function and a single web handler. + +#### WebSocket Changes + + - Ping/pong and reconnection handling were added to Go WebSocket client. + - Support was added for WebSocket custom dialer. + - ``channel_converted`` WebSocket event was added, which is published team-wide whenever a channel is converted from public to private. + +### Known Issues + + - [Image proxy](https://docs.mattermost.com/administration/image-proxy.html) cannot be saved in the System Console UI. Configure the settings in your `config.json` file instead. + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[aeomin](https://translate.mattermost.com/user/aeomin/), [amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [asaadmahmood](https://github.com/asaadmahmood), [balasankarc](https://github.com/balasankarc), [chclaus](https://github.com/chclaus), [chikei](https://github.com/chikei), [comharris](https://github.com/comharris), [compilenix](https://github.com/compilenix), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [der-test](https://github.com/der-test), [dkadioglu](https://github.com/dkadioglu), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fbartels](https://github.com/fbartels), [gnufede](https://github.com/gnufede), [grundleborg](https://github.com/grundleborg), [haraldkubota](https://github.com/haraldkubota), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jordanbuchman](https://github.com/jordanbuchman), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kayazeren](https://github.com/kayazeren), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [meilon](https://github.com/meilon), [mkraft](https://github.com/mkraft), [mlongo4290](https://github.com/mlongo4290), [odontomachus](https://github.com/odontomachus), [pichouk](https://github.com/pichouk), [pjgrizel](https://github.com/pjgrizel), [rodcorsi](https://github.com/rodcorsi), [Roy-Orbison](https://github.com/Roy-Orbison), [ryoon](https://github.com/ryoon), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev), [thePanz](https://github.com/thepanz), [uturkdogan](https://github.com/uturkdogan), [wget](https://github.com/wget), [wiersgallak](https://github.com/wiersgallak), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.10 - [Extended Support Release](https://docs.mattermost.com/administration/extended-support-release.html) + + - **v4.10.10, released 2019-06-20** + - Mattermost v4.10.10 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.9, released 2019-04-24** + - Mattermost v4.10.9 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.8, released 2019-03-16** + - Mattermost v4.10.8 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.7, released 2019-02-16** + - Mattermost v4.10.7 contains low to medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.6, released 2019-02-01** + - Mattermost v4.10.6 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.5, released 2019-01-16** + - Mattermost v4.10.5 contains medium level security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.4, released 2018-09-16** + - Mattermost v4.10.4 contains a high level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.3, released 2018-08-07** + - Mattermost v4.10.3 contains a medium level security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.2, released 2018-07-16** + - Mattermost v4.10.2 contains a high severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.10.1, released 2018-06-04** + - Mattermost v4.10.1 contains a moderate severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where the Mattermost screen went blank when viewing "Manage Members" list while another user was added to the channel. + - Fixed an issue where [automatic replies](https://docs.mattermost.com/administration/config-settings.html#enable-automatic-replies-experimental) weren't properly posting or suppressing emails. + - Fixed an issue where a member's roles for a team wasn't properly deleted when the team was deleted via the API, causing crashing issues. + - **v4.10.0, released 2018-05-16** + - Original 4.10.0 release + +### Highlights + +#### Convert Public Channels to Private + - Team and System Admins can now convert a channel to private from the user interface. System Admins can also convert channels back to public [via the commandline](https://docs.mattermost.com/administration/command-line-tools.html#platform-channel-modify). + +#### Performance Improvements + - Decreased loading time by up to 90% for users with lots of direct and group message channels. + +#### Environment Variables Support in GitLab Omnibus + - Simplified Mattermost administration by supporting environment variables in GitLab Omnibus. See [documentation](https://docs.gitlab.com/ee/update/) to learn more. + +### Improvements + +#### Web User Interface + - Removed support for transparent team icons to support any sidebar theme colors and added the ability to remove team icons. + - Added an experimental setting that users can use to set a custom message that will be automatically sent in response to Direct Messages. + - Added a loading animation for "Add Members" channel invite modal. + - Made SHIFT+UP switch keyboard focus to right-hand side if it's already open to the current thread. + - Removed an unnecessary WebRTC end user setting to avoid user errors and confusion. + - Added an on-hover effect for image link previews. + + #### Plugins + - Added better plugin error handling and reporting. + + #### Slash Commands + - Added ``/invite`` slash command to invite users to a channel. + - Improved slash command error message when payload has invalid JSON. + + #### Administration + - Added structured logging to more easily review server logs. + - Users' client no longer refreshes after changing a System Console or ``config.json`` setting. + + #### Command Line Interface (CLI) + - Added `/platform team list` command to list all teams on the server.. + +#### Enterprise Edition E20 + - Added cluster event types to [Performance Monitoring](https://docs.mattermost.com/scale/performance-monitoring.html). + +### Bug Fixes + + - Fixed an issue where focus with CTRL/CMD+SHIFT+L was always set to the right-hand side when reply thread was open. + - Fixed an issue where a user added to a channel wasn't immediately removed from other users' "Add Members" dialog. + - Fixed an issue where 'Copy Link' context menu option was partially hidden when right-clicking a team in team sidebar. + - Fixed an issue where a user could not log in to Mattermost when their login id ("authdata") failed to migrate properly during migration from LDAP to SAML. + - Fixed an issue where plugin configuration was not saved in the System Console. + - Removed duplicate indexes accidentally created on the ``Channels``, ``Emoji`` and ``OAuthAccessData`` tables. + +### Compatibility + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under `"TeamSettings"` in `config.json`: + - Added ``"ExperimentalEnableAutomaticReplies": false,`` to allow users to set a custom message that will be automatically sent in response to Direct Messages. + - Under `"LogSettings"` in `config.json`: + - Removed ``FileFormat`` and added ``"FileJson": true,`` and ``"ConsoleJson": true,`` to allow logged events to be written as a machine readable JSON format instead of the be printed as plain text. + +#### API Changes + +##### RESTful API v4 Changes + + - Support was added to RESTful API for sending ephemeral messages to users. + - An APIv4 endpoint of ``POST /channels/{channel_id}/convert`` was added to convert a channel from public to private and to restrict this setting to ``team_admin``. + - An APIv4 endpoint of ``DELETE /teams/{team_id}/image`` was added to remove team icon and restrict it to ``team_admin``. + +#### Database Changes + +**Users Table:** + + - Migrates SAML `AuthData` to lowercase via `"UPDATE Users SET AuthData=LOWER(AuthData) WHERE AuthService = 'saml'"` query. + +**Channels Table:** + + - Removed duplicate `Name_2` index. + +**Emoji Table:** + + - Removed duplicate `Name_2` index. + +**OAuthAccessData Table:** + + - Removed duplicate `ClientId_2` index. + +#### Upcoming Deprecated Features in Mattermost v5.0 + +The following deprecations are planned for the Mattermost v5.0 release, which is scheduled for summer/2018. This list is subject to change prior to the release. + +1. All API v3 endpoints will be removed. [See documentation](https://api.mattermost.com/#tag/schema) to learn more about how to migrate your integrations to API v4. [Ticket #8708](https://mattermost.atlassian.net/browse/MM-8708). +2. `platform` binary will be renamed to mattermost for a clearer install and upgrade experience. All command line tools, including the bulk loading tool and developer tools, will also be renamed from platform to mattermost. [Ticket #9985](https://mattermost.atlassian.net/browse/MM-9985). +3. A Mattermost user setting to configure desktop notification duration in **Account Settings** > **Notifications** > **Desktop Notifications** will be removed. +4. Slash commands configured to receive a GET request will have the payload being encoded in the query string instead of receiving it in the body of the request, consistent with standard HTTP requests. Although unlikely, this could break custom slash commands that use GET requests incorrectly. [Ticket #10201](https://mattermost.atlassian.net/browse/MM-10201). +5. A new `config.json` setting to whitelist types of protocols for auto-linking will be added. [Ticket #9547](https://mattermost.atlassian.net/browse/MM-9547). +6. A new `config.json` setting to disable the [permanent APIv4 delete team parameter](https://api.mattermost.com/#tag/teams%2Fpaths%2F~1teams~1%7Bteam_id%7D%2Fput) will be added. The setting will be off by default for all new and existing installs, except those deployed on GitLab Omnibus. A System Administrator can enable the API v4 endpoint from the config.json file. [Ticket #9916](https://mattermost.atlassian.net/browse/MM-9916). +7. An unused `ExtraUpdateAt` field will be removed from the channel model. [Ticket #9739](https://mattermost.atlassian.net/browse/MM-9739). + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Numbered lists can sometimes extend beyond the normal post area. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors +[amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [antoineHC](https://github.com/antoineHC), [asaadmahmood](https://github.com/asaadmahmood), [Autre31415](https://github.com/Autre31415), [cometkim](https://github.com/cometkim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [daanlevi](https://github.com/daanlevi), [DSchalla](https://github.com/DSchalla), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [guydemi](https://github.com/guydemi), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [iri-dw](https://github.com/iri-dw), [it33](https://github.com/it33), [james-mm](https://github.com/james-mm), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jordanbuchman](https://github.com/jordanbuchman), [jwilander](https://github.com/jwilander), [kethinov](https://github.com/kethinov), [koxen](https://github.com/koxen), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [liusy182](https://github.com/liusy182), [Merlin2001](https://github.com/merlin2001), [michaeltaylor-kerauno](https://github.com/michaeltaylor-kerauno), [mkraft](https://github.com/mkraft), [n1aba](https://github.com/n1aba), [pichouk](https://github.com/pichouk), [saturninoabril](https://github.com/saturninoabril), [stanchan](https://github.com/stanchan), [sudheerDev](https://github.com/sudheerDev), [tejasbubane](https://github.com/tejasbubane), [timconner](https://github.com/timconner), [tomo667a](https://github.com/tomo667a), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.9 - Feature Release + + - **v4.9.4, released 2018-06-04** + - Mattermost v4.9.4 contains a moderate severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.9.3, released 2018-05-15** + - Fixed an issue where plugin configuration got corrupted upon saving the configuration via the System Console. + - **v4.9.2, released 2018-05-04** + - Fixed an issue with permissions migration when ``AllowEditPost`` was set to "Always". + - **v4.9.1, released 2018-04-27** + - Fixed an issue where System Console permissions settings displayed a false error when running High Availability mode. + - Fixed a race condition on loading roles in the System Console. + - Reverted a change causing significant performance degradation when loading posts. + - Fixed a performance issue causing significant initial load time for the Desktop application. + - **v4.9.0, released 2018-04-16** + - Original 4.9.0 release + +### Highlights + +#### Channel Mute + - Added a `/mute` command, meaning that when a channel is muted, desktop, push and email notifications are not sent for the channel. + - Channel Mute is also accessible via Channel Notification Preferences. + - A muted channel gets sorted at the bottom of the left-hand sidebar section. + +#### Teammate Name Display Setting + - Added the setting for rendering of at-mentions by the teammate name display back to the Account Settings. + +#### Team Icons + - Added support for team icons in the team sidebar. + +#### Global Relay (Beta) ([Enterprise Edition E20](https://mattermost.com/pricing/) Add-On) + - Added export support for Global Relay as a compliance solution. [Learn more here](https://docs.mattermost.com/comply/compliance-export.html). + +### Improvements + +#### Web User Interface + - Users can now set their timezone in **Account Settings > Timezone**. + - Cursor now returns to the reply thread input box after deleting a reply on the right-hand sidebar. + +#### Performance + - Decreased channel load time by optimizing database queries used to fetch threads and parent posts in a channel. + - Decreased load time of large channels with 5,000+ messages by up to 90% by optimizing many client functions related to rendering posts and threads. + - Changing properties other than Site URL in ``/general/logging`` section will now require a server restart before taking effect. + +#### Plugins (Beta) + - Plugins now have more flexibility to format text, emojis and Markdown. + - Added support for plugins to add actions to the sidebar dropdowns. + +#### Administration + - Added support for AWS Identity and Access Management (IAM) roles for Amazon S3 file storage. + - Added a "Test Connection" button to test Amazon S3 connection. + +#### Enterprise Edition + - When `ExperimentalTownSquareIsReadOnly` is set to `true`, non-admins can no longer react to messages, pin messages or update channel information. + - Added cache invalidation totals to [Performance Monitoring](https://docs.mattermost.com/scale/performance-monitoring.html). + +### Bug Fixes + + - Fixed server log 404 error messages "We couldn't get the emoji" for numeric emojis. + - Fixed an issue where cursor jumped to end of line when trying to edit text in the middle of search bar. + - Fixed an issue where a download link opened images in a new tab instead of downloading them. + - Fixed an issue where Direct Message channel with yourself did not show up in channel switcher. + - Fixed an issue where deleting one username from "add member to a channel" field deleted all names. + - Fixed an issue where View/Manage members should have been sorted by username, not online status. + - Fixed an issue where a non-system-admin should not see `Is Trusted` option on OAuth 2.0 integrations. + - Fixed an issue with being unable to click on pinned post, channel members, and so on with keyboard focus on search box. + - Fixed an issue where Mattermost only imported first user during Slack import. + - Fixed an issue where cleared search term reappeared after closing RHS. + - Fixed an issue where a thumbnail appeared larger than expected in center channel when posting an image while the right hand side was open. + - Fixed an issue with adding users to channels when the usernames contained periods. + - Fixed an issue with a JavaScript error when using CMD/CTRL-K keyboard shortcut to change channels. + - Fixed an issue with not being able to get past second page of `/admin_console/users`. + - Fixed an issue where ALT+UP/DOWN caused error in console and then stopped working. + +### Compatibility + + - IE11 Compatibility View now shows an "Unsupported Browser" error page, [given it's not a supported version](https://docs.mattermost.com/install/requirements.html#pc-web-experience). + +#### Removed and Deprecated Features + + - To improve the production use of Mattermost with Docker, the docker image is now running a as non-root user and listening on port 8000. Please read the [upgrade instructions](https://github.com/mattermost/mattermost-docker#upgrading-mattermost-to-49) for important changes to existing installations. + +- Several configuration settings have been migrated to roles in the database and changing their `config.json` values no longer takes effect. These permissions can still be modified by their respective System Console settings as before. The affected `config.json` settings are: + - RestrictPublicChannelManagement + - RestrictPrivateChannelManagement + - RestrictPublicChannelCreation + - RestrictPrivateChannelCreation + - RestrictPublicChannelDeletion + - RestrictPrivateChannelDeletion + - RestrictPrivateChannelManageMembers + - EnableTeamCreation + - EnableOnlyAdminIntegrations + - RestrictPostDelete + - AllowEditPost + - RestrictTeamInvite + - RestrictCustomEmojiCreation + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### Upcoming Deprecated Features in Mattermost v5.0 + +The following deprecations are planned for the Mattermost v5.0 release, which is scheduled for summer/2018. This list is subject to change prior to the release. + +1. All API v3 endpoints will be removed. [See documentation](https://api.mattermost.com/#tag/APIv3-Deprecation) to learn more about how to migrate your integrations to API v4. [Ticket #8708](https://mattermost.atlassian.net/browse/MM-8708). +2. `platform` binary will be renamed to mattermost for a clearer install and upgrade experience. All command line tools, including the bulk loading tool and developer tools, will also be renamed from platform to mattermost. [Ticket #9985](https://mattermost.atlassian.net/browse/MM-9985). +3. A new `config.json` setting to whitelist types of protocols for auto-linking will be added. [Ticket #9547](https://mattermost.atlassian.net/browse/MM-9547). +4. A new `config.json` setting to disable the [permanent APIv4 delete team parameter](https://api.mattermost.com/#tag/teams%2Fpaths%2F~1teams~1%7Bteam_id%7D%2Fput) will be added. The setting will be off by default for all new and existing installs, except those deployed on GitLab Omnibus. A System Administrator can enable the API v4 endpoint from the config.json file. [Ticket #9916](https://mattermost.atlassian.net/browse/MM-9916). +5. An unused `ExtraUpdateAt` field will be removed from the channel model. [Ticket #9739](https://mattermost.atlassian.net/browse/MM-9739). + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under `MessageExportSettings` in `config.json`: + - Added `"CustomerType": "A9"`, to allow selecting the type of Global Relay customer account the user's organization has. + - Added `"EmailAddress": ""`, to allow selecting the email address the user's Global Relay server monitors for incoming compliance exports. + - Under ` "SamlSettings"` in `config.json`: + - Added `"ScopingIDPProviderId": ""`, to allow an authenticated user to skip the initial login page of their federated Azure AD server, and only require a password to log in. + - Added `"ScopingIDPName": ""`, to add the name associated with a user's Scoping Identity Provider ID. + - Under `DisplaySettings"` in `config.json`: + - Added `"ExperimentalTimezone": false`, to allow selecting the timezone used for timestamps in the user interface and email notifications. + +#### API Changes + + - It is required that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). + - All API v3 endpoints have been deprecated and are scheduled for removal in Mattermost v5.0. + +#### Database Changes + +**Users Table:** + + - Added `Timezone` column. + +**Teams Table:** + + - Added `LastTeamIconUpdate` column. + +**Channels Table:** + + - Removed `idx_channels_displayname` index. + +### Known Issues + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Numbered lists can sometimes extend beyond the normal post area. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [chclaus](https://github.com/chclaus), [chumbalum](https://github.com/chumbalum), [cjohannsen81](https://github.com/cjohannsen81), [CoolMoeDee](https://github.com/CoolMoeDee), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [dmeza](https://github.com/dmeza), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [gajananpp](https://github.com/gajananpp), [GitHubJasper](https://github.com/GitHubJasper), [gnufede](https://github.com/gnufede), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [james-mm](https://github.com/james-mm), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [koxen](https://github.com/koxen), [letsila](https://github.com/letsila), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [mkraft](https://github.com/mkraft), [moonmeister](https://github.com/moonmeister), [MusikPolice](https://github.com/MusikPolice), [panditsavitags](https://github.com/panditsavitags), [philippe-granet](https://github.com/philippe-granet), [pichouk](https://github.com/pichouk), [qichengzx](https://github.com/qichengzx), [Rudloff](https://github.com/Rudloff), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [stanchan](https://github.com/stanchan), [stephenkiers](https://github.com/stephenkiers), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [tejasbubane](https://github.com/tejasbubane), [thePanz](https://github.com/thePanz), [timconner](https://github.com/timconner), [tomo667a](https://github.com/tomo667a), [Vorlif](https://github.com/Vorlif), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.8 - Feature Release + + - **v4.8.2, released 2018-06-04** + - Mattermost v4.8.2 contains a moderate severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.8.1, released 2018-04-09** + - Mattermost v4.8.1 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed a performance issue by removing the `DisplayName` index on the Channels table. + - **v4.8.0, released 2018-03-16** + - Original 4.8.0 release + +### Security Update + +- Mattermost v4.8.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Enhanced compatibility with CloudFront + + - Added support for configuring CloudFront to host Mattermost's static assets. + - Allows for improved caching performance and shorter load times for those members of your team geographically distributed throughout the world. + +#### SAML Migration Command ([Enterprise Edition E20](https://mattermost.com/pricing/)) + + - Added a CLI command to easily migrate users to SAML. + +### Improvements + +#### Web User Interface + - Added a web app build hash to About Mattermost dialog to tell what version of the web app is being used. + - Switched search bar to a button in tablet view, to increase how much space is available in the channel header. + +#### Performance + - Reduced load times by optimizing database queries and WebSocket events destined for a single user. + - Created an iOS endpoint that enables users to upload files larger than 20MB. + - Improved caching of `getRootPosts` call. + +#### 508 Compliance + - Added alt attribute to profile pictures. + +#### Integrations + - Updated incoming webhooks to accept multipart/form-data content type such as that supplied by `curl -F`. + +#### Notifications + - A system message is now posted when a channel is moved between teams by the CLI command. + +#### Authentication + - Reduced OAuth SSO login errors by falling back to a constructed URL if Site URL is blank. + +#### System Console + - Removed plugin upload setting from System Console UI and prevented switching the setting from the API. + - Added paging to system console log viewer and set default value of `per_paging` for logs to 1000. + +### Bug Fixes + - Fixed an issue where sidebar unreads text setting was ignored in custom theme. + - Fixed an issue where emoji picker had an empty line at the bottom of the list. + - Fixed an issue with Markdown help wrapping on a second line in Edit Message dialog. + - Fixed an issue where after leaving last team the "Logout" link did nothing. + - Fixed an issue where focus was sometimes wrong on delete post modal. + - Fixed an issue where the bulk import tool didn't force Town Square membership. + - Fixed duplicate calls of the "view" request when switching channels. + - Fixed an issue where channel name was included in push notifications if someone posted only files with Push Notification Contents set to not include channel name. + - Fixed an issue where attempting to preview an attached document failed to finish "loading" if the file extension didn't match the actual file type. + - Fixed an issue where focus was not set to input box after replying to a message in Classic Mobile App. + - Fixed an issue where a username such as "user.name" gets a highlight only on "name" when @-icon is clicked. + - Fixed an issue where the "More Unreads Above" indicator didn't always work. + - Fixed an issue where IE11 posted placeholder from hidden textbox. + - Fixed an issue where last channel was not remembered after refresh when switching teams. + - Fixed an issue with no auto-focusing into input text when attaching a file in Classic Mobile App. + - Fixed an issue with not being able to type with composed characters (e.g. CJK) in View Team Members modal and channel switcher. + - Fixed an issue where insecure images were loaded by sending client before proxying. + - Fixed an issue with sandboxing support for CentOS and Bosh. + - Fixed an issue where JIRA plugin posts were not properly truncated. + - Fixed an issue where tall/wide emojis appeared stretched in emoji picker. + - Fixed an issue where web app could not be built if not in a git repository. + - Fixed an issue where jumping to a search result did not always load the context posts. + - Fixed an issue where edit box changed size on switching to markdown preview in some languages. + +### Compatibility + +#### Removed and Deprecated Features + + - All API v3 endpoints have been deprecated and are scheduled for removal in Mattermost v5.0. + - An unused `ExtraUpdateAt` field will be removed from the channel model in Mattermost v5.0. + - As Mattermost moves to a role-based permissions system in v4.9, a number of configuration settings will be migrated to roles in the database and changing their `config.json` values will no longer take effect. These permissions can still be modified by their respective System Console settings. The `config.json` settings to be migrated are: + - RestrictPublicChannelManagement + - RestrictPrivateChannelManagement + - RestrictPublicChannelCreation + - RestrictPrivateChannelCreation + - RestrictPublicChannelDeletion + - RestrictPrivateChannelDeletion + - RestrictPrivateChannelManageMembers + - EnableTeamCreation + - EnableOnlyAdminIntegrations + - RestrictPostDelete + - AllowEditPost + - RestrictTeamInvite + - RestrictCustomEmojiCreation + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under `ServiceSettings` in `config.json`: + - Added `AllowCookiesForSubdomains`, to ensure that the domain parameter is set for cookies, which allows the browser to send the cookies to subdomains as well. + - Added `WebsocketURL`, which allows the server to instruct clients where they should try to connect WebSockets to. + - Changed `EnableAPIV3` setting to `false` for new installs, as all API v3 endpoints have been deprecated and are scheduled for removal in Mattermost v5.0. + +### API Changes + + - It is required that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). + - All API v3 endpoints have been deprecated and are scheduled for removal in Mattermost v5.0. + +#### RESTful API v4 Changes + + - Updated `POST /files` to support requests with only the `channel_id` and `filename` defined as query parameters with the contents of a single file in the body of the request. + +### Known Issues + + - Google login fails on the Classic mobile apps. + - User can receive a video call from another browser tab while already on a call. + - Jump link in search results does not always jump to display the expected post. + - Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. + - Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. + - Searching with Elasticsearch enabled may not always highlight the searched terms. + - Team sidebar on desktop app does not update when channels have been read on mobile. + - Channel scroll position flickers while images and link previews load. + - Numbered lists can sometimes extend beyond the normal post area. + - Slack import through the CLI fails if email notifications are enabled. + - Push notifications don't always clear on iOS when running Mattermost in High Availability mode. + - CTRL/CMD+U shortcut to upload a file doesn’t work on Firefox. + +### Contributors + +[Alexgoodman7](https://github.com/Alexgoodman7), [amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [andruwa13](https://github.com/andruwa13), [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [billybrown1](https://github.com/billybrown1), [ccbrown](https://github.com/ccbrown), [chumbalum](https://github.com/chumbalum), [cometkim](https://github.com/cometkim), [CoolTomatos](https://github.com/CoolTomatos), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [GitHubJasper](https://github.com/GitHubJasper), [gnufede](https://github.com/gnufede), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [icelander](https://github.com/icelander), [it33](https://github.com/it33), [james-mm](https://github.com/james-mm), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kemenaran](https://github.com/kemenaran), [koxen](https://github.com/koxen), [leblanc-simon](https://github.com/leblanc-simon), [letsila](https://github.com/letsila), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lip-d](https://github.com/lip-d), [liusy182](https://github.com/liusy182), [lmikaellukerad](https://github.com/lmikaellukerad), [mkraft](https://github.com/mkraft), [moonmeister](https://github.com/moonmeister), [MusikPolice](https://github.com/MusikPolice), [pichouk](https://github.com/pichouk), [rqtaylor](https://github.com/rqtaylor), [saturninoabril](https://github.com/saturninoabril), [stanchan](https://github.com/stanchan), [stephenkiers](https://github.com/stephenkiers), [tejasbubane](https://github.com/tejasbubane), [thePanz](https://github.com/thePanz), [torgeirl](https://github.com/torgeirl), [Vaelor](https://github.com/Vaelor), [vordimous](https://github.com/vordimous), [XinyueWang94](https://github.com/XinyueWang94), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.7 - Feature Release + + - **v4.7.4, released 2018-04-09** + - Mattermost v4.7.4 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed a performance issue by removing the `DisplayName` index on the Channels table. + - **v4.7.3, released 2018-03-09** + - Mattermost v4.7.3 contains a moderate severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.7.2, released 2018-02-23** + - Fixed an issue where message attachments didn’t render emojis. + - Fixed an issue where channels with a name 26 characters long were inaccessible with a 404 error. + - Fixed “We couldn’t get the emoji” server log messages. + - Fixed an issue with being unable to switch to direct or group message channels via CTRL/CMD+K channel switcher or via “msg/groupmsg” slash commands. + - Fixed an issue where clicking on "Send Message" from a user's profile popover redirected to Town Square instead of the user's direct message channel. + - Fixed an issue where links to direct and group message channels opened in a new tab. + - **v4.7.1, released 2018-02-20** + - Fixed an issue with [compliance export](https://docs.mattermost.com/administration/compliance-export.html) outputs, resulting in `Failed to update ChannelMemberHistory table` error messages in the log when a user joins or leaves a channel. Issue updates [posted here](https://mattermost.atlassian.net/browse/MM-9633). + - **v4.7.0, released 2018-02-16** + - Original 4.7.0 release + +### Security Update + +- Mattermost v4.7.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Client-Side Performance + + - Added user-based rate limiting, in addition to rate limiting API access by IP address. + - Decreased page load time by loading custom emojis asynchronously rather than all on first page load. + - Optimized channel autocomplete (~) query by returning client-side results immediately. + - Decreased the size of most image assets by more than 25% by running `pngquant` to remove unnecessary metadata from PNGs. + +#### Image Proxy Support + + - Image proxy servers increase performance through a layer of caching, and provide custom options to resize images. + - Three new configuration keys, `ImageProxyType`, `ImageProxyURL`, `ImageProxyOptions`, ensure that posts served to the client will have their markdown modified such that all images are loaded through a proxy. + +#### Updated Image Thumbnails + + - Updated the appearance of image thumbnails, so that single thumbnails will now expand to a larger preview without clicking the image to open the preview window. + +#### Experimental Setting for Unreads Sidebar Section + + - Added an experimental setting to group unread channels in the channel sidebar. The setting [must first be enabled by the System Admin](https://docs.mattermost.com/administration/config-settings.html#group-unread-channels-experimental), by replacing `disabled` with either `default_off` or `default_on` in config.json. + +### Improvements + +#### Web User Interface + - Added a status icon in the channel member list and sorted it by user status. + - Added ability to preview images found in link previews. + - Added a `Copy Link` option for sidebar channels in the Desktop App. + - Added focus on the text box after hitting "Edit" on Account Settings options. + - Improved formatting of quotes in the channel header. + - Added a date separator for search results. + - Channel names are now sorted correctly in the left-hand-side by taking non-alphabetical characters into consideration (e.g. brackets, hash sign, etc.) + + #### Integrations + - Added username and profile picture to incoming webhook set up pages. + - Added support for Slack attachments in outgoing webhook responses. + +#### Emoji Picker + - Added the ability to navigate emoji picker with the keyboard. + - Added paging and search of custom emojis to webapp emoji picker. + +#### Channels + - Users are directed to the last channel they viewed in a team when switching to that team. + - Changed URLs of Direct Messages to use the form of `https://servername.com/messages/@username`, letting users open a direct message with each other via URL. + +#### Notifications + - Added a system message when a team is changed from public to private. + +#### Plugins (Beta) + - Zoom plugin now supports on-premise Zoom servers. + +#### Enterprise Edition +- Increased max length of `User.Position` field to 128 characters to meet LDAP max length. +- Increased OAuth state parameter limit. Some systems may send a state longer than 128 characters. + +### Bug Fixes + - Fixed an issue where OAuth account creation error page was unformatted. + - Fixed tab and alt-tab keyboard navigation for links on sign-in page. + - Fixed an issue where plugin slash commands didn't override username or icon. + - Fixed an issue where pagination for team members modal showed a next button when there are no more users to show. + - Fixed an issue where at-channel in `/header` should not trigger confirmation modal. + - Fixed an issue where auto-generated SAML Service provider login URL had two slashes instead of one. + - Fixed an issue where no unread mention appeared on non-mobile platform after receiving push notification. + - Fixed an issue where the text box was hidden by the keyboard when replying to a post in mobile view. + - Fixed username autocomplete not working with mixed cases. + - Fixed not being able to type Korean quickly in some dialogs. + - Fixed an issue where notification preference settings didn't respect case sensitivity for mention highlighting. + - Fixed where, after an ephemeral message, couldn't use `+:emoji:` to react to the previous message. + - Fixed Mattermost not loading on Firefox if the `media.peerconnection.enabled` setting in Firefox is set to false. + - Fixed login screen sometimes flashing before Mattermost server loads. + - Fixed an issue where bot messages from the Zoom plugin ignored the Zoom API URL field for on-prem Zoom servers. + - Disabled pull-to-refresh feature on Android (Chrome) to prevent unwanted page refresh. + - Fixed an issue where clicking `Save` in `Rename Channel` modal without changes did nothing. + - Fixed emoji picker search being case-sensitive. + - Fixed timestamp not being clickable in desktop mobile view. + - Fixed an issue where deleting a team via the API broke the web user interface. + +### Compatibility + +#### Removed and Deprecated Features + +- All API v3 endpoints have been deprecated, and scheduled for removal in Mattermost v5.0. +- The `mentionKeys` prop in post type plugins is now removed to fix case sensitive mention highlighting. Plugins can retrieve the `mentionKeys` prop from the store as needed. +- The permanent query parameter of the DELETE `/teams/{team_id}` APIv4 endpoint is not removed as previously announced, given customer and community feedback. +- As Mattermost moves to a role based permissions system in v4.8, a number of configuration settings will be migrated to roles in the database, and changing their `config.json` values will no longer take effect. These permissions can still be modified by their respective System Console settings. The `config.json` settings to be migrated are: + - RestrictPublicChannelManagement + - RestrictPrivateChannelManagement + - RestrictPublicChannelCreation + - RestrictPrivateChannelCreation + - RestrictPublicChannelDeletion + - RestrictPrivateChannelDeletion + - RestrictPrivateChannelManageMembers + - EnableTeamCreation + - EnableOnlyAdminIntegrations + - RestrictPostDelete + - AllowEditPost + - RestrictTeamInvite + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +#### Changes to Team Edition and Enterprise Edition: + + - Under `ServiceSettings` in `config.json`: + - Added `"ImageProxyType": ""`, `"ImageProxyOptions": ""`, and `"ImageProxyURL": ""` to ensure posts served to the client will have their markdown modified such that all images are loaded through a proxy. + - Added `"ExperimentalGroupUnreadChannels": disabled` to show an unread channel section in the webapp sidebar. The setting must first be enabled by the System Admin, by replacing `disabled` with either `default_off` or `default_on`. + - Added `"ExperimentalEnableDefaultChannelLeaveJoinMessages": true` that allows disabling of leave/join messages in the default channel, usually Town Square. + - Under `RateLimitingSettings` in `config.json`: + - Added `"VaryByUser": false`, a user-based rate limiting, to rate limit on token and on userID. + +### API Changes + + - It is required that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). + - All API v3 endpoints have been deprecated, and scheduled for removal in Mattermost v5.0. + +#### RESTful API v4 Changes + + - Added `GetChannelByName` and `GetTeamByName` to auto lowercase team and channel names in API requests. This ensures that the channel name is automatically lowercased for endpoints taking team or channel names as URL parameters. + - Added `POST /emoji/search`, `GET /emojis/name/{emoji_name}`, and `GET /emoji/autocomplete` to add consistency with user search/autocomplete endpoints. These API endpoints ensure that the benefits of `GET` for important performance related actions such as autocompleting are included. + - Added `/users/tokens/search` to allow System Admin to be able to find, manage and revoke personal access tokens as needed. This endpoint gets all tokens for all users if one has the `manage_system` permission. + +### WebSocket Event Changes + + - Added `delete_team` web socket event to notify client whenever a team is deleted (e.g. via API call). + +### Database Changes + +**Users Table:** + + - Increased size of `Position` field from 35 to 128 characters. + +**OAuthAuthData Table:** + + - Increased size of `State` field from 128 to 1024 characters. + +**ChannelMemberHistory Table:** + + - Removed `Email` column. + - Removed `Username` column. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Team sidebar on desktop app does not update when channels have been read on mobile. +- Channel scroll position flickers while images and link previews load. +- CTRL/CMD+U shortcut to upload a file doesn't work on Firefox. +- Numbered lists can sometimes extend beyond the normal post area. +- Slack import through the CLI fails if email notifications are enabled. +- Push notifications don't always clear on iOS when running Mattermost in High Availability mode. +- `[WARN] plugin sandboxing is not supported. plugins will run with the same access level as the server` log message is created when sandboxing isn't enabled for plugins. If you don't use plugins, you can ignore this message. + +### Contributors + +[amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [andruwa13](https://github.com/andruwa13), [asaadmahmood](https://github.com/asaadmahmood), [bbodenmiller](https://github.com/bbodenmiller), [Brunzer](https://github.com/Brunzer), [ccbrown](https://github.com/ccbrown), [chclaus](https://github.com/chclaus), [cherniavskii](https://github.com/cherniavskii), [CometKim](https://github.com/CometKim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [darkman](https://github.com/darkman), [der-test](https://github.com/der-test), [dlahn](https://github.com/dlahn), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fermulator](https://github.com/fermulator), [gig177](https://github.com/gig177), [grundleborg](https://github.com/grundleborg), [Hanzei](https://github.com/Hanzei), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [james-mm](https://github.com/james-mm), [jarredwitt](https://github.com/jarredwitt), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [kemenaran](https://github.com/kemenaran), [knechtionscoding](https://github.com/knechtionscoding), [laginha87](https://github.com/laginha87), [lasley](https://github.com/lasley), [letsila](https://github.com/letsila), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [liusy182](https://github.com/liusy182), [Matterchen](https://github.com/Matterchen), [mkraft](https://github.com/mkraft), [MusikPolice](https://github.com/MusikPolice), [phuihock](https://github.com/phuihock), [pichouk](https://github.com/pichouk), [Rohlik](https://github.com/Rohlik), [R-Wang97](https://github.com/R-Wang97), [santos22](https://github.com/santos22), [saturninoabril](https://github.com/saturninoabril), [stephenkiers](https://github.com/stephenkiers), [sudheerDev](https://github.com/sudheerDev), [tayre](https://github.com/tayre), [tejasbubane](https://github.com/tejasbubane), [tkbky](https://github.com/tkbky), [Tristramg](https://github.com/Tristramg), [ulm0](https://github.com/ulm0), [watadarkstar](https://github.com/watadarkstar), [xuxip](https://github.com/xuxip), [yeoji](https://github.com/yeoji), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.6 - Feature Release + + - **v4.6.3, release date 2018-04-09** + - Mattermost v4.6.3 contains a low severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.6.2, release date 2018-02-23** + - Mattermost v4.6.2 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.6.1, release date 2018-01-30** + - Fixed an issue where Let's Encrypt certificates were broken on Mattermost servers. The cache will be deleted upon upgrade so your certificate will be immediately renewed. Moreover, port 80 must be forwarded through a firewall, with [Forward80To443](https://docs.mattermost.com/administration/config-settings.html#forward-port-80-to-443) `config.json` setting set to `true`, to complete the Let's Encrypt certification. + - **v4.6.0, released 2018-01-16** + - Original 4.6.0 release + +### Highlights + +#### Client-Side Performance + +- Decreased channel switching time up to 45% by reducing post mounting time. +- Decreased up to 85% of the memory retained following a channel switch by fixing memory leaks of the `post_time.jsx` component. +- Decreased size of the most used icons and logos by 70-80% by running `pngquant` to remove unnecessary metadata from PNGs. + +### Improvements + +#### Web User Interface + +- Added a loading indicator while pinned posts and flagged posts lists are loading. +- Added a loading indicator to MFA sign in button. +- Added a tooltip for the '+' button when adding emoji reactions. +- Channel switcher (CTRL/CMD+K) now filters by usernames, full names and nicknames. +- Channel links are now rendered in the channel header. +- File names are now shown in attachment previews. + +#### Plugins (Beta) + +- Plugins now support slash commands. + +#### Notifications + +- Updated default notification settings for new accounts to provide a better onboarding experience. Each of these can be configured in Account Settings. In particular, the updated default settings include: + - Desktop notifications only sent for mentions and direct messages. + - Mobile push notifications only sent when the user is away or offline, not when online. + - Mentions of the user's first name doesn't trigger mentions. + +#### 508 Compliance + +- Default language is now declared in HTML for Mattermost webpages. +- Position of status indicators and reply icons updated when no CSS is rendered. +- Use programmatically identifiable headings for team and channel name. + +#### Administration + +- Incoming webhook display name is now included in the post.Props field for better auditing. +- System Admins can now reset their own password from the System Console users list. + +### Bug Fixes + +- Username updates are now immediately visible across all browser tabs. +- Server logs no longer contain info messages about initializing plugins when plugins are disabled. +- Fixed Mattermost not loading on Firefox v52. +- Fixed issues with user at-mention autocomplete when using Tab multiple times. +- Fixed an issue where typing an emoji reaction didn't add it to recently used emojis list. +- OAuth and SAML users can now be deactivated from the Mattermost System Console, assuming they are also deactivated in the SSO provider. +- Fixed email address validation for Microsoft Outlook formatted email addresses. +- Fixed an issue where posts sometimes didn't send on iOS Classic app. +- Team name can no longer be edited to be only one character long. +- Editing a message to remove all text no longer deletes the message if it contains a file attachment. +- Fixed an issue where searching for a channel using the second or third word in the name didn't work. +- Other users no longer see deleted GIF previews in reply threads. +- Fixed an issue where channels with Japanese or Cyrillic characters couldn't be created. +- Fixed timestamp minute display for Zoom plugins. +- Fixed an issue where page would load infinitely when trying to join a team with maximum capacity. +- Fixed an issue where channel notification preferences reverted to defaults after updating preferences in one of the channels. + +### Compatibility + +#### Removed and Deprecated Features + +- All API v3 endpoints are now deprecated, and scheduled for removal in Mattermost v5.0. +- The permanent query parameter of the DELETE `/teams/{team_id}` APIv4 endpoint for permanently deleting a team is scheduled for removal in Mattermost v4.7. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `"EnableTutorial": true` to control whether tutorial is shown to end users after account creation. This setting is experimental and may be replaced or removed in a future release. +- Under `TeamSettings` in `config.json`: + - Added `"ExperimentalPrimaryTeam": ""` to set the primary team of the server. This setting is experimental and may be replaced or removed in a future release. +- Under `EmailSettings` in `config.json`: + - Added `"LoginButtonColor": ""`, `"LoginButtonBorderColor": ""` and `"LoginButtonTextColor": ""` to set the style of the email login button for white labelling purposes. + +**Additional Changes to Enterprise Edition**: + +- Under `LdapSettings` in `config.json`: + - Added `"LoginButtonColor": ""`, `"LoginButtonBorderColor": ""` and `"LoginButtonTextColor": ""` to set the style of the LDAP login button for white labelling purposes. +- Under `SamlSettings` in `config.json`: + - Added `"LoginButtonColor": ""`, `"LoginButtonBorderColor": ""` and `"LoginButtonTextColor": ""` to set the style of the SAML login button for white labelling purposes. + +### API Changes + +- It is required that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All API v3 endpoints are now deprecated, and scheduled for removal in Mattermost v5.0. +- The permanent query parameter of the DELETE `/teams/{team_id}` APIv4 endpoint for permanently deleting a team is scheduled for removal in Mattermost v4.7. + +#### RESTful API v4 Changes + +- Added `/users/{user_id}/auth` to update a user's authentication method. This can be used to change them to/from LDAP authentication, for example. + +#### Plugin API Changes (Beta) + +- Added `RegisterCommand` to register a custom slash command. When the command is triggered, your plugin can fulfil it via the `ExecuteCommand` hook. +- Added `UnregisterCommand` to unregister a command previously registered via `RegisterCommand`. +- Added `GetChannelMember` to get a channel membership for a user. + +#### Plugin Hook Changes (Beta) + +- Added `ExecuteCommand` hook to execute a command that was previously registered via the `RegisterCommand` plugin API. + +### Database Changes + +**IncomingWebhooks Table:** +- Renamed `PostUsername` column to `Username`. +- Renamed `PostIconURL` column to `IconURL`. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Team sidebar on desktop app does not update when channels have been read on mobile. +- Channel scroll position flickers while images and link previews load. +- CTRL/CMD+U shortcut to upload a file doesn't work on Firefox. +- Numbered lists can sometimes extend beyond the normal post area. +- Slack import through the CLI fails if email notifications are enabled. +- Letters are skipped in a few dialogs when using Korean keyboard in IE11. +- Push notifications don't always clear on iOS when running Mattermost in High Availability mode. +- Deleting a team via the API breaks the user interface. +- Bot messages from the Zoom plugin ignore the Zoom API URL field for on-prem Zoom servers. + +### Contributors + +- [amyblais](https://github.com/amyblais), [AndersonWebStudio](https://github.com/AndersonWebStudio), [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [cvitter](https://github.com/cvitter), [dlahn](https://github.com/dlahn), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [g3d](https://github.com/g3d), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [james-mm](https://github.com/james-mm), [jarredwitt](https://github.com/jarredwitt), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [letsila](https://github.com/letsila), [lfbrock](https://github.com/lfbrock), [lieut-data](https://github.com/lieut-data), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [lisakycho](https://github.com/lisakycho), [liusy182](https://github.com/liusy182), [LordVeovis](https://github.com/LordVeovis), [Matterchen](https://github.com/Matterchen), [mkraft](https://github.com/mkraft), [MusikPolice](https://github.com/MusikPolice), [panditsavitags](https://github.com/panditsavitags), [pichouk](https://github.com/pichouk), [pixelbrackets](https://github.com/pixelbrackets), [pruthvip](https://github.com/pruthvip), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [skvale](https://github.com/skvale), [stephenkiers](https://github.com/stephenkiers), [sudheerDev](https://github.com/sudheerDev), [sumantro93](https://github.com/sumantro93), [tayre](https://github.com/tayre), [tborg](https://github.com/tborg), [tejasbubane](https://github.com/tejasbubane), [watadarkstar](https://github.com/watadarkstar), [yuya-oc](https://github.com/yuya-oc) + +---- + +## Release v4.5 - Feature Release + + - **v4.5.2, release date 2018-02-23** + - Mattermost v4.5.2 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.5.1, released 2018-01-16** + - Fixed an issue where Mattermost wouldn't load on certain versions of Firefox, including v52-54 and v57 in private mode. + - **v4.5.0, released 2017-12-16** + - Original 4.5.0 release + +### Highlights + +#### Zoom Plugin (Beta) + +- [Zoom](https://www.zoom.com) video calling and screensharing plugin. Learn more [here](https://docs.mattermost.com/configure/plugins-configuration-settings.html#zoom). +- Manage plugins from the **System Console > Plugins (Beta)** section. + +#### Actiance Support (Beta) ([Enterprise Edition E20](https://mattermost.com/pricing/) Add-On) + +- Compliance export support for [Smarsh](https://www.smarsh.com/) (formerly known as Actiance) as a compliance solution. Learn more [here](https://docs.mattermost.com/comply/compliance-export.html). +- Access compliance export from the **System Console > Advanced > Compliance Export (Beta)**. + +### Improvements + +#### Web User Interface +- `CTRL/CMD` + `/` now toggles the keyboard shortcuts dialog. +- Link previews now appear in the right-hand side in comment threads. +- Timestamp permalinks now open in the current view on desktop and browser. +- Pinned posts are now sorted newest to oldest. +- Updated markdown to better handle non-Latin characters in URLs. +- Added WebRTC call icon to desktop mobile view header. +- Added a '+' sign to quickly add emoji reactions to a post. +- Added support for different emoji skintones. +- Added inline playback for GIF attachments. + +#### Integrations + +- Added an option for an outgoing webhook to reply to the posted message as a comment. +- JIRA plugin is now bundled as a pre-packaged plugin manageable from the System Console > Plugins > Management. +- Added support for mentions with <@userid>, <!channel>, <!all> and <!here> in webhook posts. +- Personal access tokens can now be temporarily deactivated in the Account Settings. + +#### Channels + +- Direct Message channels with deactivated users are now hidden in the sidebar and can be reopened from the **More...** Direct Messages list. +- You can now open a direct message channel with yourself. + +#### Notifications + +- Removed unnecessary log messages posted when pending email notifications are deleted because a user comes online before the batch is sent. +- Desktop notification icon has been updated on Edge browsers. + +#### Keyboard Shortcuts + +- Added a `/groupmsg` command to start a new group message channel. +- Added CTRL+SHIFT+L to set focus to the message input box. + +#### System Console + +- Added a confirm modal to the Data Retention settings page. +- Added settings pages for uploading and managing plugins in the System Console > Plugins (Beta) section. +- Added the ability to revoke a user's sessions from the System Console. + +### Bug Fixes + +- Closing a direct or group message channel no longer purges channel preferences. +- Users no longer get a blank page after hitting "x" on a deleted message in permalink view. +- Fixed an issue where `AmazonS3Region` defaults to us-east-1 regardless of the value input. +- Channel links render as expected when linking to a channel that the current user does not belong to. +- Uppercase letter is no longer required for a password if the password requirement is set to at least 5 characters and a number. +- Profile image updates are now visible in other active clients and the right-hand side after the change. +- Plugins can no longer be uploaded if they have the same plugin ID. +- Creating a channel with a name including a reserved word no longer breaks the user interface. +- Fixed the AD/LDAP Test Connection button. +- Fixed an issue causing `invalid or expired session` server logs. +- Removed a duplicate error message on the login page after a password reset. +- Fixed an issue where the OAuth ClientID and Secret values were missing after setup. +- Emoji picker now works when the right-hand side is expanded. +- Error messages in the System Console user list no longer breaks the user interface. +- Fixed an issue where only System Admins could edit OAuth apps even if integration creation was not restricted to admins. +- Fixed an issue where "New messages v" bubble didn't always clear in a fresh direct message channel. +- Fixed channel preferences not restoring after closing and reopening a direct or group message channel. + +### Compatibility + +#### Removed and Deprecated Features +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `"EnablePreviewFeatures": true` to hide the **Advanced** > **Preview re-release features** section from Account Settings. + - Added `"CloseUnusedDirectMessages": false` to hide inactive direct message channels from the sidebar. + - Added `"ExperimentalEnableAuthenticationTransfer": true` to set whether users can change authentication methods. +- Under `EmailSettings` in `config.json`: + - Added `"UseChannelInEmailNotifications": false` to set whether email notifications contain the channel name in the subject line. +- Under `PluginSettings` in `config.json`: + - Added `"ClientDirectory": "./client/plugins"` to set the location of client plugins. + +**Additional Changes to Enterprise Edition**: + +- Added `MessageExportSettings` in `config.json`: + - Added `"EnableExport": false` to enable message export. + - Added `"DailyRunTime": "01:00"` to set the time for the daily export job. + - Added `"ExportFromTimestamp": 0` to set the timestamp for which posts to include in the message export. + - Added `"FileLocation": "export"` to set the message export location. + - Added `"BatchSize": 10000` to set how many new posts are batched together to a compliance export file. + +### API v4 Changes + +- It is recommended that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All API v3 endpoints are scheduled for removal on January 16, 2018. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Team sidebar doesn't always show unreads from other teams on first load. +- Team sidebar on desktop app does not update when channels have been read on mobile. +- System Admin cannot reset their own password via the System Console. +- Channel scroll position flickers while images and link previews load. +- CTRL/CMD+U shortcut to upload a file doesn't work on Firefox. +- Profile pictures and usernames don't immediately update across tabs or in the right-hand side comment threads. +- Numbered lists can sometimes extend beyond the normal post area. +- Typing an emoji reaction does not add it to recently used emojis. +- Server logs contain messages about initializing plugins even when plugins are disabled. + +### Contributors + +/mattermost-webapp + +- [asaadmahmood](https://github.com/asaadmahmood), [avasconcelos114](https://github.com/avasconcelos114), [ccbrown](https://github.com/ccbrown), [CometKim](https://github.com/CometKim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [deveshjadon98](https://github.com/deveshjadon98), [enahum](https://github.com/enahum), [fraziern](https://github.com/fraziern), [grundleborg](https://github.com/grundleborg), [h2oloopan](https://github.com/h2oloopan), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [KishoreFartiyal](https://github.com/KishoreFartiyal), [lfbrock](https://github.com/lfbrock), [mikelinden1](https://github.com/mikelinden1), [mkraft](https://github.com/mkraft), [MusikPolice](https://github.com/MusikPolice), [QuantumKing](https://github.com/QuantumKing), [rickbatka](https://github.com/rickbatka), [R-Wang97](https://github.com/R-Wang97), [santos22](https://github.com/santos22), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev), [tkbky](https://github.com/tkbky), [yth0625](https://github.com/yth0625) + +/mattermost-plugin-zoom + +- [crspeller](https://github.com/crspeller), [jwilander](https://github.com/jwilander) + +/mattermost-server + +- [amyblais](https://github.com/amyblais), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [cpfeiffer](https://github.com/cpfeiffer), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [letsila](https://github.com/letsila), [lindalumitchell](https://github.com/lindalumitchell), [mkraft](https://github.com/mkraft), [mogul](https://github.com/mogul), +[MusikPolice](https://github.com/MusikPolice), [yeoji](https://github.com/yeoji) + +/mattermost-mobile + +- [cpfeiffer](https://github.com/cpfeiffer), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jarredwitt](https://github.com/jarredwitt), [lfbrock](https://github.com/lfbrock), [mkraft](https://github.com/mkraft) + +/docs + +- [amyblais](https://github.com/amyblais), [bbodenmiller](https://github.com/bbodenmiller), [ccbrown](https://github.com/ccbrown), [comharris](https://github.com/comharris), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), +[jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lfbrock](https://github.com/lfbrock), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [mkdbns](https://github.com/mkdbns), [mkraft](https://github.com/mkraft), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-docker + +- [andruwa13](https://github.com/andruwa13), [muffl0n](https://github.com/muffl0n), [pichouk](https://github.com/pichouk), [xcompass](https://github.com/xcompass) + +/mattermost-load-test + +- [ccbrown](https://github.com/ccbrown), [crspeller](https://github.com/crspeller), [jasonblais](https://github.com/jasonblais) + +/mattermost-redux + +- [brettmc](https://github.com/brettmc), [ccbrown](https://github.com/ccbrown), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [mkraft](https://github.com/mkraft), [sudheerDev](https://github.com/sudheerDev) + +/mattermost-developer-documentation + +- [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [jwilander](https://github.com/jwilander), [MusikPolice](https://github.com/MusikPolice) + +/mattermost-plugin-jira + +- [ccbrown](https://github.com/ccbrown) + +/mattermost-webrtc + +- [enahum](https://github.com/enahum) + +/desktop + +- [dmeza](https://github.com/dmeza), [jasonblais](https://github.com/jasonblais), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-kubernetes + +- [cpanato](https://github.com/cpanato) + +/mattermost-selenium + +- [lindalumitchell](https://github.com/lindalumitchell) + +/mattermost-api-reference + +- [grundleborg](https://github.com/grundleborg), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-ios-classic + +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost-developer-kit + +- [jwilander](https://github.com/jwilander) + +/mattermost-build + +- [crspeller](https://github.com/crspeller), [mthornba](https://github.com/mthornba) + +/marked + +- [hmhealey](https://github.com/hmhealey) + +---- + +## Release v4.4.5 - Feature Release + + - **v4.4.5, release date 2017-12-11** + - Mattermost v4.4.5 contains a medium severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.4.4, release date 2017-12-06** + - Added a config.json setting, `ClientDirectory`, to set the directory to write web app plugins to. Added to better support plugins in GitLab Omnibus. + - **v4.4.3, released 2017-12-05** + - Fixed a medium level security issue affecting servers with [EnableOAuthServiceProvider](https://docs.mattermost.com/administration/config-settings.html#enable-oauth-2-0-service-provider) set to `true` and [EnableOnlyAdminIntegrations](https://docs.mattermost.com/administration/config-settings.html#restrict-managing-integrations-to-admins) set to `false`. If you're affected, [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.4.2, released 2017-11-23** + - Fixed an issue where AD/LDAP accounts get deactivated following an AD/LDAP sync if their email address between the AD/LDAP server and Mattermost don't match case. + - Fixed synchronization of SAML accounts with AD/LDAP. + - Fixed AD/LDAP "Test Connection" button in the System Console not working when AD/LDAP login is disabled. + - Fixed system messages not being translated into user's language set in **Account Settings > Display > Language**. + - Fixed system messages about channel header updates sometimes being incorrectly formatted. + - **v4.4.1, released 2017-11-16** + - Fixed an upgrade issue where an alternative config file location via ``--config`` flag is ignored. + - **v4.4.0, released 2017-11-16** + - Original 4.4.0 release + +### Highlights + +#### Plugins (Beta) +- Beta release of Mattermost plugins, which allow admins to more easily integrate with third-party systems, extend functionality and customize the user interface of your Mattermost server. See the [plugin](https://docs.mattermost.com/about/integrations.html#plugins) documentation to learn more. + +#### Do Not Disturb Status +- Added "Do Not Disturb" status to temporarily turn off all desktop and mobile push notifications. + +#### Support SAML sync via AD/LDAP ([Enterprise Edition E20](https://mattermost.com/pricing/)) +- Added support for periodically synchronizing SAML user attributes, including user deactivation and removal, from AD/LDAP. See [documentation](https://docs.mattermost.com/onboard/ad-ldap.html) to learn more. + +### Improvements + +#### Web User Interface +- Added an experimental feature to hide direct and group message channels after 7 days with no new messages. To enable it set `CloseUnusedDirectMessages` in `config.json` to `true`. +- Moved website previews out of beta, configurable in **Account Settings > Display**. Enable link previews in the [System Console](https://docs.mattermost.com/administration/config-settings.html#enable-link-previews). +- Made it easier to add a user to channel if mentioned user is not already a channel member. +- Added "Edit Account Settings" link to the bottom of your own profile popover to more easily edit your settings. +- URL address for internal links such as when hovering over the flag icon, is now hidden for better user experience. +- URL addresses for channels on the left-hand sidebar are now hidden on the desktop app. +- Added a loading spinner to Account Settings dialog after clicking the "Save" button. +- Added full date tooltip to post timestamps in right-hand sidebar and search results. +- Added "@" in front of the username field in user lists. + +#### Performance +- Reduced load times by optimizing database queries and adding composite indexes for the `Posts` table. +- Prevented sessions from being stuck in cache by clearing the session cache if permission is denied. +- Improved Elasticsearch bulk indexing query performance. + +#### Emoji Picker +- Added emoji picker to the Edit Message dialog. +- Removed categorization when searching for emojis in the emoji picker. + +#### Integrations +- Added the ability to edit OAuth 2.0 applications. +- Added improvements for interactive message buttons, such as displaying your username in ephemeral messages triggered by the message buttons. + +#### Slash Commands +- Added `/remove` and `/kick` slash commands to remove a user from the channel. + +#### WebRTC Video and Audio Calls (Beta) +- When you have multiple browser tabs open and receive a video call, the ringtone stops in all tabs when you accept the call. +- Multiple STUN and TURN servers are now supported. + +#### System Console +- Added a setting to disable channel wide (@-channel, @-all) mention confirmation in channels with more than five members. +- Admin now receives a prompt when leaving a System Console page with unsaved changes. + +#### Elasticsearch ([Enterprise Edition E20](https://mattermost.com/pricing/)) +- Added support for batched live indexing for Elasticsearch. +- Added a configurable timeout for Elasticsearch requests. +- Added a table to Elasticsearch System Console page to monitor indexing jobs. +- Elasticsearch connection is now asynchronous so that a broken Elasticsearch server cannot block the startup of the Mattermost server. + +### Bug Fixes +- Fixed mobile push notification settings not saving in the System Console. +- Fixes to channel link (~) autocomplete, such as not being able to autocomplete 'Town Square'. +- Fixed an issue where System Console was sometimes temporarily accessible after demoting a user to a member. +- Fixed failure to switch from email to SAML sign-in method if the user's email address has a plus sign. +- Fixed "More Channels" modal not showing the correct the page number when displaying search results. +- Fixed an incorrect error message when trying to add a user to a direct or group message channel via the APIs. +- Fixed an issue where downloading a file containing spaces didn't preserve the name. +- Fixed thumbnail image for .m4r file types. +- Fixed an issue where search in Manage Members dialog didn't update results when there were no matches. +- Fixed an issue where `in:` autocomplete for text search didn't display results after a hyphen in some servers. +- Fixed a missing "No results" screen for Elasticsearch text search. +- Fixed channel member count not updating until refresh when a user is added or removed. +- Fixed timestamp links on desktop app opening permalink view in a new app window. +- Fixed an error caused by creating a new direct message channel via the channel switcher (CTRL/CMD+K). +- Fixed SVG thumbnails not showing a preview. +- Fixed team sidebar showing unreads for deleted channels. +- Fixed a missing indicator when a message is pending but not yet sent. +- Fixed emoji autocomplete appearing when typing an emoticon like :-D. +- Fixed emoji names matching usernames triggering mentions. +- Fixed incorrect order of recent mentions when a hashtag is a word that triggers mentions. +- Fixed webhook message attachments longer than 8000 characters failing to post by truncating them, or splitting to multiple posts if the message has multiple attachments. +- Fixed `/msg` command arbitrarily switching teams. +- Fixed mentions not appearing linked in message drafts when in preview mode. +- Fixed an issue where an existing account could change their email address to one not in the [restricted domain list](https://docs.mattermost.com/administration/config-settings.html#restrict-account-creation-to-specified-email-domains). +- Fixed emoji reactions being added to system messages when using the `+:emoji:` command. +- Fixed an issue where message retention policy didn't work in Postgres databases if there were emoji reactions to delete. + +### Compatibility + +Composite database indexes were added to the `Posts` table. This may lead to longer upgrade times for servers with more than 1 million messages. + +Moreover, LDAP sync now depends on email. If you have AD/LDAP login enabled, make sure all users on your AD/LDAP server have an email address or that their account is deactivated in Mattermost. + +#### Removed and Deprecated Features +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `"CloseUnusedDirectMessages": false` to set whether users have the option to automatically close direct and group message channels older than 7 days. +- Under `TeamSettings` in `config.json`: + - Added `"EnableConfirmNotificationsToChannel": true` to set whether a confirmation is shown for channel wide (@-channel, @-all) mentions in channels with more than five members. +- Under `PluginSettings` in `config.json`: + - Added `"Enable": true` to set whether plugins are enabled on the server. + - Added `"EnableUploads": false` to set whether manual plugin uploads are enabled on the server. Disabling will keep existing plugins, including pre-packaged Mattermost plugins, installed on the server. + - Added `"Directory": "./plugins"` to specify the directory of where plugins are stored. + - Added `"Plugins": {}` to list installed plugins on the Mattermost server. + - Added `"PluginStates": {}` to set whether an installed plugin is active or inactive on the Mattermost server. + +**Additional Changes to Enterprise Edition**: + +- Under `SamlSettings` in `config.json`: + - Added `EnableSync: false` to set whether AD/LDAP synchronization is enabled. +- Under `LdapSettings` in `config.json`: + - Added `EnableSyncWithLdap: false` to set whether SAML user attributes, including deactivation, are periodically synchronized from AD/LDAP. +- Under `ElasticsearchSettings` in `config.json`: + - Added `"LiveIndexingBatchSize": 1` to set how many new posts are batched together before they are added to the Elasticsearch index. + - Added `"RequestTimeoutSeconds": 30` to set the timeout in seconds for Elasticseaerch calls. + - Added `"BulkIndexingTimeWindowSeconds": 3600` to set the maximum time window for a batch of posts being indexed by the Bulk Indexer. + +### Database Changes + +**Posts Table:** +- Added a composite index for `ChannelId, DeleteAt, CreateAt` +- Added a composite index for `ChannelId, UpdateAt` + +**UserAccessTokens Table:** +- Added `IsActive` column + +### API v4 Changes + +- It is recommended that any new integrations use API v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All API v3 endpoints are scheduled for removal on January 16, 2018. + +**Added routes (API v4)** +- `POST` at `/users/token/enable` + - Re-enables a personal access token that was previously disabled. +- `POST` at `/users/token/disable` + - Disables a personal access token and deletes any sessions that uses the token. The token can be re-enabled using `/users/tokens/enable.` +- `POST` at `/users/{user_id}/sessions/revoke/all` + - Revokes all user sessions from the provided user id and session id strings. +- `POST` at `/plugins` + - Uploads a plugin in a compressed .tar.gz. +- `GET` at `/plugins` + - Gets a list of active and inactive plugins. +- `DELETE` at `/plugins/{plugin_id}` + - Removes a previously uploaded plugin. +- `POST` at `/plugins/{plugin_id}/activate` + - Activates an installed plugin. +- `POST` at `/plugins/{plugin_id}/deactivate` + - Deactivates an active plugin. +- `GET` at `/plugins/webapp` + - Gets a list of plugin manifests for active plugins with webapp components. + +**Modified routes (API v4)** +- `POST` at `/logs` + - Unauthenticated users can now log ERROR or DEBUG messages when `ServiceSettings.EnableDeveloper` is set to `true`. + +### Websocket Event Changes + +**Added:** +- `user_role_updated` that occurs when a user role is updated. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- Deleted message doesn't clear unreads or unread mentions. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Channel links to channels that the current user does not belong to may not render correctly. +- Team sidebar doesn't always show unreads from other teams on first load. +- Uppercase letter is required for a password if the password requirement is set to at least 5 characters and a number. +- System Admin cannot reset their own password via the System Console. +- Channel scroll position flickers while images and link previews load. +- Closing a direct or group message channel, then re-opening later, doesn't restore channel preferences. +- CTRL/CMD+U shortcut to upload a file doesn't work on Firefox. +- Website previews are not displayed for comments on threads. +- User gets a blank page after hitting "x" on a deleted message in permalink view. +- Profile pictures don't immediately update across tabs or in the right-hand side comment threads. + +### Contributors + +/mattermost-webapp + +- [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [cherealnice](https://github.com/cherealnice), [CometKim](https://github.com/CometKim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [Hyeongmin-Kwon](https://github.com/Hyeongmin-Kwon), [jasonblais](https://github.com/jasonblais), [johncoleman83](https://github.com/johncoleman83), [jwilander](https://github.com/jwilander), [letsila](https://github.com/letsila), [longsleep](https://github.com/longsleep), [maruTA-bis5](https://github.com/maruTA-bis5), [MusikPolice](https://github.com/MusikPolice), [R-Wang97](https://github.com/R-Wang97), [ryantm](https://github.com/ryantm), [santos22](https://github.com/santos22), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev), [tkbky](https://github.com/tkbky), [yeoji](https://github.com/yeoji), [Zapix](https://github.com/Zapix) + +/docs + +- [amyblais](https://github.com/amyblais), [asaadmahmood](https://github.com/asaadmahmood), [bbodenmiller](https://github.com/bbodenmiller), [ccbrown](https://github.com/ccbrown), [comharris](https://github.com/comharris), [coreyhulen](https://github.com/coreyhulen), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [lindalumitchell](https://github.com/lindalumitchell), [lindy65](https://github.com/lindy65), [saturninoabril](https://github.com/saturninoabril), [shieldsjared](https://github.com/shieldsjared), [tolidano](https://github.com/tolidano) + +/mattermost-server + +- [ccbrown](https://github.com/ccbrown), [chclaus](https://github.com/chclaus), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [enahum](https://github.com/enahum), [fraziern](https://github.com/fraziern), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [ivernus](https://github.com/ivernus), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [longsleep](https://github.com/longsleep), [MusikPolice](https://github.com/MusikPolice), [rickbatka](https://github.com/rickbatka), [santos22](https://github.com/santos22), [saturninoabril](https://github.com/saturninoabril), [thePanz](https://github.com/thePanz) + +/mattermost-redux + +- [ccbrown](https://github.com/ccbrown), [CometKim](https://github.com/CometKim), [enahum](https://github.com/enahum), [fraziern](https://github.com/fraziern), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [MusikPolice](https://github.com/MusikPolice), [rickbatka](https://github.com/rickbatka), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev), [tkbky](https://github.com/tkbky), + +/mattermost-mobile + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [gelim](https://github.com/gelim), [hmhealey](https://github.com/hmhealey), [jarredwitt](https://github.com/jarredwitt) + +/desktop + +- [dmeza](https://github.com/dmeza), [jarredwitt](https://github.com/jarredwitt), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-docker + +- [pichouk](https://github.com/pichouk), [sebgl](https://github.com/sebgl) + +/mattermost-api-reference + +- [fraziern](https://github.com/fraziern), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [rickbatka](https://github.com/rickbatka) + +/mattermost-load-test + +- [crspeller](https://github.com/crspeller), [jasonblais](https://github.com/jasonblais) + +---- + +## Release v4.3.4 - Feature Release + + - **v4.3.4, release date 2017-12-11** + - Mattermost v4.3.4 contains a medium severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.3.3, released 2017-12-05** + - Fixed a medium level security issue affecting servers with [EnableOAuthServiceProvider](https://docs.mattermost.com/administration/config-settings.html#enable-oauth-2-0-service-provider) set to `true` and [EnableOnlyAdminIntegrations](https://docs.mattermost.com/administration/config-settings.html#restrict-managing-integrations-to-admins) set to `false`. If you're affected, [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.3.2, released 2017-11-10** + - Fixed an issue where after creating a new direct message channel via channel switcher (CTRL/CMD+K), all messages fail to post until a page refresh. + - **v4.3.1, released 2017-10-20** + - Fixed an upgrade issue where the database schema would appear to be out of date and throw a log warning. + - Fixed the Idle Timeout setting in `config.json` by changing the setting title from `SessionIdleTimeout` to `SessionIdleTimeoutInMinutes`. + - Fixed a regression where slash commands were not functional in Direct or Group Messages. + - Mattermost v4.3.1 contains a low severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.3.0, released 2017-10-16** + - Original 4.3.0 release + +### Security Update + +- Mattermost v4.3.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Data Retention Beta ([Enterprise Edition E20](https://mattermost.com/pricing/)) +- Automatically delete old messages and file uploads through custom data retention policies. + +#### Languages +- Promoted Italian and Turkish out of beta to release-quality translations. + +### Improvements + +#### Web User Interface +- Clicking on "More Unreads" bubble on channel sidebar now scrolls you to the next unread channel. +- Added status indicators to direct message channel header. + +#### Search +- Improved user search that supports two character full names and usernames. + +#### Integrations +- Ephemeral slash command responses now support attachements without text. +- Added CLI command to move custom slash commands between teams. + +#### Notifications +- Updating the channel header with channel-wide mentions no longer triggers notifications. + +#### Performance +- Improved initial load of the emoji picker, now supporting thousands of custom emojis including GIFs. + +#### Enterprise Edition +- Added tables in System Console for AD/LDAP sync, Elasticsearch and Data Retention to track the success of scheduled jobs. +- Added an idle timeout setting to automatically log out users who are inactive for a specified amount of time. +- Elasticsearch can now be used on a shared Elasticsearch cluster. +- Added metrics for monitoring Elasticsearch system health and usage. + +### Bug Fixes +- Fixed an issue where closing brackets were ignored in URL links. +- Fixed Leave Team icon size and inconsistent channel header icon hover effects on IE11 mobile view. +- Fixed an issue where right side menu disappeared after viewing search results on IE11 mobile view. +- Fixed other minor UI issues on IE11 desktop view. +- Fixed an issue where system and ephemeral messages could be flagged. +- Error text in Edit modal no longer overlaps with help text. +- Integration message attachments without `pretext` no longer overlap with username in Compact view. +- Fixed channel member list being sorted by username instead of teammate name display. +- "Password updated successfully" bar is now displayed after resetting password. +- Fixed a broken UI for an expired email verification link. +- Fixed integration message attachments not always rendering in comment threads. +- Fixed an issue where "Add Members" dialog would sometimes break. +- Slash command responses now handle charset and boundary sets correctly. +- Deactivated users are no longer counted in the Town Square member count. +- iOS push notifications are now consistently cleared from the homescreen if all mentions are read on another device. +- Webhooks no longer continue sending to the original channel if the target channel is changed. +- Emails containing symbols now render correctly when switching to email authentication from other methods. +- Attempting to open an invalid public file link no longer displays an unformatted error page. +- Interactive message action buttons no longer disappear after updating the message. +- Ticket links posted by the built-in JIRA plug-in are now correct if the JIRA URL has a custom context path. +- Error message is now displayed in the System Console if the localization available languages does not include the default client language. +- Fixed a race condition where bulk import sometimes fails to get team member when importing users. +- Closing the channel switcher on mobile no longer sets focus to the text box. +- Fixed an issue where the wrong channel name might appear in the right-hand side pinned post list. +- Fixed team sidebar now always showing unreads from other teams on first load. + +### Compatibility + +#### Removed and Deprecated Features +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `"SessionIdleTimeoutInMinutes": 0` to specify how long to wait before logging out inactive users. +- Under `ElasticsearchSettings` in `config.json`: + - Added `"IndexPrefix": ""` to allow Elasticsearch to be used on a shared Elasticseearch cluster. +- Under `DataRetentionSettings` in `config.json`: + - Added `"EnableMessageDeletion": false` to enable message deletion. + - Added `"EnableFileDeletion": false` to enable file deletion. + - Added `"MessageRetentionDays": 365` to set how long Mattermost keeps messages in channels and direct messages. + - Added `"FileRetentionDays": 365` to set how long Mattermost keeps file uploads in channels and direct messages. + - Added `"DeletionJobStartTime": "02:00"` to specify when to start the data retention job. + +### API v4 Changes + +- It is recommended that any new integrations use APIv4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +**Added routes (API v4)** +- `PUT` at `/oauth/apps/{app_id}` + - Update an OAuth 2.0 client application. +- `GET` at `/data_retention/policy` + - Gets the current data retention policy details from the server, including what data should be purged and the cutoff times for each data type that should be purged. + +**Modified routes (API v4)** +- `POST` at `/channels/members/{user_id}/view` + - Response includes `last_viewed_at_times` for Mattermost server 4.3 and newer. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- Deleted message doesn't clear unreads or unread mentions. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Channel links to channels that the current user does not belong to may not render correctly. +- Missing an indication if a message is pending but not yet sent. +- Recent mention results are not sorted correctly if hashtags is included in "words that trigger mentions". +- SVG thumbnails don't preview in the posted thumbnail. +- Emojis names matching usernames can trigger mentions. +- Integration message attachment fails to post if attachment length exceeds 7900 characters. +- Uppercase letter is required for a password if the password requirement is set to at least 5 characters and a number. +- Message retention policy may not work in Postgres databases if there are emoji reactions to delete. + +### Contributors + +/mattermost-server + +- [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [moonmeister](https://github.com/moonmeister), [MusikPolice](https://github.com/MusikPolice), [n1aba](https://github.com/n1aba), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-webapp + +- [asaadmahmood](https://github.com/asaadmahmood), [bbodenmiller](https://github.com/bbodenmiller), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jazzzz](https://github.com/jazzzz), [jwilander](https://github.com/jwilander), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [sudheerDev](https://github.com/sudheerDev) + +/desktop + +- [csduarte](https://github.com/csduarte), [dmeza](https://github.com/dmeza), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-mobile + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jarredwitt](https://github.com/jarredwitt), [lfbrock](https://github.com/lfbrock) + +/mattermost-api-reference + +- [atpons](https://github.com/atpons), [grundleborg](https://github.com/grundleborg), [jwilander](https://github.com/jwilander), [n1aba](https://github.com/n1aba), [pichouk](https://github.com/pichouk) + +/docs + +- [ccbrown](https://github.com/ccbrown), [crspeller](https://github.com/crspeller), [esethna](https://github.com/esethna), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65) + +/mattermost-developer-kit + +- [jwilander](https://github.com/jwilander) + +/marked + +- [hmhealey](https://github.com/hmhealey) + +/mattermost-docker + +- [localsnet](https://github.com/localsnet), [pdemagny](https://github.com/pdemagny), [pichouk](https://github.com/pichouk), [tivvit](https://github.com/tivvit) + +/mattermost-redux + +- [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jespino](https://github.com/jespino), [jwilander](https://github.com/jwilander), [n1aba](https://github.com/n1aba), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-selenium + +- [lindalumitchell](https://github.com/lindalumitchell) + +/mattermost-mattermod + +- [crspeller](https://github.com/crspeller), [hmhealey](https://github.com/hmhealey) + +/mattermost-build + +- [crspeller](https://github.com/crspeller) + +---- + +## Release v4.2.2 - Feature Release + + - **v4.2.2, release date 2017-12-11** + - Mattermost v4.2.2 contains a medium severity security fix. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.2.1, released 2017-10-20** + - Mattermost v4.2.1 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.2.0, released 2017-09-16** + - Original 4.2.0 release + +### Security Update + +- Mattermost v4.2.0 contains multiple security fixes ranging from low to moderate severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Interactive Message Buttons +- Added message buttons to support user interactions with posts made by incoming webhooks and custom slash commands. + +#### Mobile Support for AppConfig +- iOS and Android mobile apps now support Enterprise Mobility Management (EMM) solutions through integration with [App Config](https://www.appconfig.org/). See [documentation](https://docs.mattermost.com/deploy/mobile/deploy-mobile-apps-using-emm-provider.html) to learn more. + +### Improvements + +#### Web User Interface +- Redesigned the channel member list. +- Redesigned the message input box. +- Redesigned the keyboard shortcuts dialog (CTRL/CMD+/). +- Added a loading indicator when selecting a team on team selection page. +- Added an on hover effect for team icons in the team sidebar, and the channel name and favorite button in channel header. +- Added an active state for the channel member icon in channel header. +- Added a "+" icon next to the Direct Messages header on channel sidebar to open a new direct or group message. +- Added a tooltip for Main Menu next to user profile picture. +- Mouse cursor now changes to a "hand selector" when hovering over the paperclip icon to upload a file. + +#### Mobile View +- Made hover effects consistent across all header icons. +- Removed transparency of the [...] menu in the right-hand sidebar. +- Reduced opacity in channel info dialog. +- Updated background color of search bar. + +#### Integrations +- Added support for Slack-compatible delayed slash commands through the `response_url` parameter. +- Improved handling of content-types for integrations. + +#### Notifications +- Added support for plain text version of email notifications. +- Added "Joined the channel" system message for the person who created the channel. + +#### Administration +- Added a CLI command `platform channel move` to move a channel to another team. +- CLI command `platform team delete` now lets you delete teams with no channels. + +#### Enterprise Edition +- Removed the "Delete Channel" option for private channels, if you're the last channel member and policy setting restricts channel deletion to admins only. +- In multi-node cluster environment, scheduled tasks such as LDAP sync will only happen on a single node through leader election for increased performance. +- Added direct message channels to compliance exports. +- Added a CLI command `platform channel modify` to convert a public channel to private, and vice versa. +- Elasticsearch indexes over a certain age can be aggregated as part of the daily scheduled job. + +### Bug Fixes +- Fixed permalinks not always loading in the channel. +- Fixed an issue where a System Admin couldn't scroll to the bottom of the System Console sidebar in Firefox. +- Flag icon and the "x" icon to close website previews now properly aligned for replies in compact view. +- Fixed expand/collapse arrows not being visible for YouTube videos when image links are expanded by default. +- Fixed an issue where reacting to a post in the right-hand sidebar via emoji picker didn't add the emoji to "Recently Used" section. +- Pressing the ESC key no longer clears search box contents. +- Fixed an issue where turning off email batching in the System Console resulted in no email notification option selected in Account Settings. +- Fixed an issue where a user wasn't able to scroll down in message preview mode when using Markdown headings. +- Fixed an issue on Safari browsers where file thumbnails were sometimes blank. +- Fixed an issue where quotes weren't working inside URL links. +- Fixed an error when the language set in **Account Settings > Display** was removed from available languages in **System Console > Localization**. +- Fixed out-of-channel mentions for usernames with dashes and periods. +- Fixed an issue where a missing config setting sometimes caused server panic. +- Jumping to a group message channel from a flagged message list now adds the channel to the channel list. +- Character limits are no enforced when renaming a channel via `/rename`. +- Fixed channel header icons when WebRTC call is on-going. +- Fixed webhook message attachments not appearing in search results or flagged messages list. +- Timestamp on deleted, ephemeral, or pending posts is no longer a permalink, causing a blank page. +- Fixed focus issues on iPad Classic app. +- Fixed an issue where changing other user's profile image as a System Admin via the API didn't work. +- Fixed mention notifications firing for mentions inside triple backticks. +- Collapse and expand arrows no longer shown for image links when no image is available. +- A single collapsed link preview now stays collapsed after page refresh. +- With email batching enabled, if there is activity in Mattermost before email batch is sent, the email notification is not sent. +- Fixed an issue where copying and pasting SVG files into message draft never finish uploading. +- Autocomplete is no longer cut on the channel header modal. +- Fixed email notifications settings appearing saved despite cancelling the change. +- Notification confirmation message no longer appears when sending channel wide @-all and @-channel mentions in code blocks. + +### Compatibility + +#### Breaking Changes + +1 - Mattermost now handles multiple content types for integrations, including plaintext content type. If your integration suddenly prints the JSON payload data instead of rendering the generated message, make sure your integration is returning the `application/json` content-type to retain previous behavior. + +2 - By default, user-supplied URLs such as those used for Open Graph metadata, webhooks, or slash commands will no longer be allowed to connect to reserved IP addresses including loopback or link-local addresses used for internal networks. + +This change may cause private integrations to break in testing environments, which may point to a URL such as http://127.0.0.1:1021/my-command. + +If you point private integrations to such URLs, you may whitelist such domains, IP addresses, or CIDR notations via the [AllowedUntrustedInternalConnections config setting](https://docs.mattermost.com/administration/config-settings.html#allow-untrusted-internal-connections-to) in your local environment. Although not recommended, you may also whitelist the addresses in your production environments. See [documentation to learn more](https://docs.mattermost.com/administration/config-settings.html#allow-untrusted-internal-connections-to). + +Push notification, OAuth 2.0 and WebRTC server URLs are trusted and not affected by this setting. + +3 - Uploaded file attachments are now grouped by day and stored in `/data//teams/...` of your file storage system. + +4 - Mattermost `/platform` repo has been separated to `/mattermost-webapp` and `/mattermost-server`. This may affect you if you have a private fork of the `/platform` repo. [More details here](https://forum.mattermost.com/t/mattermost-separating-platform-into-two-repositories-on-september-6th/3708). + +#### Removed and Deprecated Features +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +The following settings were unintentionally added to ``config.json`` and are removed in Mattermost 4.2. + +- Under `SupportSettings` in `config.json`: + - `"AdministratorsGuideLink": "https://about.mattermost.com/administrators-guide/"` + - `"TroubleshootingForumLink": "https://about.mattermost.com/troubleshooting-forum/"` + - `"CommercialSupportLink": "https://about.mattermost.com/commercial-support/"` + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `AllowedUntrustedInternalConnections": ""` to specify domains, IP address or CIDR notations for internal connections. Used in testing environments when developing integrations locally on a development machine. Not recommended for use in production. +- Under `TeamSettings` in `config.json`: + - Added `EnableXToLeaveChannelsFromLHS: false` to set if a user can leave a channel by clicking "X" next to a channel in the channel sidebar. This setting is Beta and may be replaced or removed in a future release. +- Under `FileSettings` in `config.json`: + - Added `AmazonS3Trace: false` to enable additional debugging for Amazon S3. + +**Additional Changes to Enterprise Edition**: + +- Under `ElasticsearchSettings` in `config.json`: + - Added `AggregatePostsAfterDays": ""` to specify the age at which indexes will be aggregated as part of the daily scheduled job + - Added `PostsAggregatorJobStartTime": ""` to specify the start time of the daily scheduled aggregator job. +- Under `TeamSettings` in `config.json`: + - Added `ExperimentalTownSquareIsReadOnly: false` to set if Town Square is a read-only channel. Applies to all teams in the Mattermost server. This setting is Beta and may be replaced or removed in a future release. +- Added `ThemeSettings` in `config.json`. These settings are Beta and may be replaced or removed in a future release. + - Added `"EnableThemeSelection": true` to set whether end users can change their Mattermost theme. + - Added `"DefaultTheme": "default"` to set default theme for new users. + - Added `"AllowCustomThemes": true` to set whether end users can set a custom theme. + - Added `"AllowedThemes": []` to list which built-in Mattermost themes are available to users. + +### API v4 Changes +- It is recommended that any new integrations use APIv4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +**Added routes (API v4)** +- `POST` at `/posts/{post_id}/actions/{action_id}` + - To perform a post action, which allows users to interact with integrations through messages. + +### Known Issues +- Google login fails on the Classic mobile apps. +- Clicking on a channel during the tutorial makes the tutorial disappear. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- First load of the emoji picker is slow on low-speed connections or on deployments with hundreds of custom emoji. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- Deleted message doesn't clear unreads or unread mentions. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms. +- Searching with Elasticsearch enabled may not always highlight the searched terms. +- Channel links to channels that the current user does not belong to may not render correctly. +- Pinned posts list header sometimes shows an incorrect channel name. +- Missing an indication if a message is pending but not yet sent. +- Searching for users with one or two-letter names doesn't work. + +### Contributors + +/platform + +- [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [dmeza](https://github.com/dmeza), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [KenmyZhang](https://github.com/KenmyZhang), [lindalumitchell](https://github.com/lindalumitchell), [meilon](https://github.com/meilon), [MusikPolice](https://github.com/MusikPolice), [n1aba](https://github.com/n1aba), [pruthvip](https://github.com/pruthvip), [saturninoabril](https://github.com/saturninoabril), [stanhu](https://github.com/stanhu), [sudheerDev](https://github.com/sudheerDev), [Whiteaj36](https://github.com/Whiteaj36) + +/docs + +- [amyblais](https://github.com/amyblais), [balasankarc](https://github.com/balasankarc), [esethna](https://github.com/esethna), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65) + +/mattermost-redux + +- [aditya-konarde](https://github.com/aditya-konarde), [brettmc](https://github.com/brettmc), [ccbrown](https://github.com/ccbrown), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [kevin3274](https://github.com/kevin3274), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-mobile + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [lfbrock](https://github.com/lfbrock), [onepict](https://github.com/onepict) + +/desktop + +- [jasonblais](https://github.com/jasonblais), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-kubernetes + +- [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [escardin](https://github.com/escardin), [grundleborg](https://github.com/grundleborg) + +/mattermost-docker + +- [jasonblais](https://github.com/jasonblais), [pichouk](https://github.com/pichouk), [tejasbubane](https://github.com/tejasbubane) + +/mattermost-push-proxy + +- [coreyhulen](https://github.com/coreyhulen), [enahum](https://github.com/enahum) + +/mattermost-mdk + +- [jwilander](https://github.com/jwilander) + +/mattermost-api-reference + +- [ccbrown](https://github.com/ccbrown), [cpanato](https://github.com/cpanato), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [prixone](https://github.com/prixone) + +/mattermost-load-test + +- [crspeller](https://github.com/crspeller) + +---- + +## Release v4.1.2 - Feature Release + + - **v4.1.2, released 2017-10-20** + - Mattermost v4.1.2 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.1.1, released 2017-09-16** + - Mattermost v4.1.1 contains multiple security fixes ranging from low to medium severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.1.0, released 2017-08-16** + - Original 4.1.0 release + +### Security Update + +- Mattermost v4.1.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### JIRA App +- Built-in JIRA integration that can post to multiple channels using a single webhook. See the [Jira integration](https://docs.mattermost.com/integrate/jira.html) documentation for details. + +#### Personal Access Tokens +- Enables easier and more flexible integrations by authenticating against the REST API. See the [personal access token](https://developers.mattermost.com/integrate/reference/personal-access-token/) developers documentation for details. + +#### Updated iOS and Android Apps +- v1.1 of the Native [iOS](https://apps.apple.com/us/app/mattermost/id1257222717) and [Android](https://play.google.com/store/apps/details?id=com.mattermost.rn&hl=en_CA&gl=US) Apps are released with support for search, group messaging, viewing emoji reactions and improved performance on poor connections. + +#### Elasticsearch Beta ([Enterprise Edition E20](https://mattermost.com/pricing/)) +- Connect your Elasticsearch server to Mattermost, then build and manage your post index via the System Console interface. +- [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) is a distributed, RESTful search engine supporting highly efficient database searches in a [cluster environment](https://docs.mattermost.com/deployment/cluster.html). + +### Improvements + +#### Web User Interface +- Ephemeral messages now note that they are "(Only visible to you)" . +- Navigating to an invalid team invite link will now redirect to an error page. +- Cropping of image thumbnails now looks the same before and after posting. +- Clicking on @mentions will now open the contact card for the user. +- User lists now display full name and nickname. +- Added over 500 new emoji. +- Searching on slow connections now shows a loading spinner in the right-hand side. +- Added a close button next to link previews. +- Ephemeral messages will now always appear as parent posts. +- Added [...] menu to search results, pinned posts and flagged posts lists. +- Clicking the username in a profile popover inserts the username to the message box. + +#### Notifications +- Added an option to Push Notification Contents to send no channel name or message text +- Updated the default email frequency to 15 minutes if email batching is enabled by the System Admin. +- Users are now prompted from Account Settings to set Edge notification sounds in their browser settings. +- Updated the desktop notification text for incoming webhooks to more accurately reflect the payload. + +#### Files +- File uploads in a single message are ordered based on time of upload. When multiple files are selected, files are ordered in alphabetical order based on file name. + +#### Administration +- No longer require a refresh after a user is promoted to a Team Admin. +- Announcement banner now supports URLs. +- Bulk importer now supports user preferences, including favorite channels, flagged posts and notification preferences. +- Changed username to be the default name display setting in the System Console. +- Channel member list now follows the Teammate name display configuration setting. +- Added more debugging info to server logs for failed OAuth requests. +- Added a new System Console push notification content setting to only display sender name. +- Added support for unauthenticated, but encrypted SMTP connection. + +#### Integrations +- Null values are now ignored in webhook attachments. +- Outgoing webhooks can now fire if the post contains only an attachment. +- Added ``/code`` built-in slash command to create a code block. +- Added ``/purpose`` built-in slash command to set the channel purpose. +- Added ``/rename`` built-in slash command to rename the channel. +- Added ``/leave`` built-in slash command to leave a channel. + +#### Enterprise Edition E20 +- Added a System Console setting to disable file uploads and downloads on mobile. +- Added a new Email Notification Content setting to specify the amount of detail sent in email notification. +- Added support for server-side encryption of files in Amazon S3, using Amazon S3-managed keys. + +### Bug Fixes +- Fixed incorrectly rotated image thumbnails that were uploaded from mobile devices. +- Adding or removing reactions from a post with an image preview no longer causes the preview to expand or collapse. +- JavaScript error no longer thrown when file upload fails due to network interruption. +- Error messages in Account Setting fields no longer stack. +- Fixed Slack Import of non-ascii channel names. +- Changing the search term in the More Direct Messages member list now resets the search. +- Help text for the Channel Switcher (CTRL/CMD+K) is now shown on small desktop windows, and removed on mobile. +- Keyboard shortcut for Account Settings (CTR/CMD+SHIFT+A) now toggles. +- Fixed the Preview button in the text input box and message edit modal. +- Fixed a JavaScript error when switching teams while uploading a file. +- CLI tool to delete all users no longer requires a user argument. +- CLI tool now deletes webhooks and slash commands when deleting teams and channels. +- Custom slash commands no longer throw an error if used in a Direct Message channel. +- System Console now reads and honors the Amazon S3 Region setting. +- Fixed whitespace and trimming on code blocks and empty table cells. +- Disabled the "Create Account" button after the first click so the system does not attempt to create the account twice. +- More Channels modal no longer stops paging after the first two pages. +- Editing channel names now correctly limits character count to 22. +- Fixed broken links on the **System Console > Mobile Push** page. +- `/away` and `/offline` ephemeral messages can no longer contain extra text posted with the slash command. +- Fixed teams being sometimes incorrectly marked unread across tabs. +- Fixed JavaScript error thrown when viewing a channel containing an invalid emoji reaction. +- Periods after URLs are no longer added to the link. +- Recent emoji in emoji picker no longer shows deleted custom emoji. +- Fixed image thumbnails and previews on IE11. +- Fixed message attachments in incoming webhooks and slash commands not always truncating properly. +- Non-admins can now view their previously created integrations. + +### Compatibility + +#### Removed and deprecated features +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +The following settings were unintentionally added to ``config.json`` and will be removed in Mattermost 4.2, released on September 16th. + +- Under `SupportSettings` in `config.json`: + - `"AdministratorsGuideLink": "https://about.mattermost.com/administrators-guide/"` + - `"TroubleshootingForumLink": "https://about.mattermost.com/troubleshooting-forum/"` + - `"CommercialSupportLink": "https://about.mattermost.com/commercial-support/"` + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - `"EnableUserAccessTokens": false` to enable personal access tokens for integrations to authenticate against the REST API +- Under `EmailSettings` in `config.json`: + - Added `"EnableSMTPAuth": false` to support SMTP servers requiring no authentication + - Added `"EmailNotificationContentType": "full"` to specify the amount of detail sent in email notification contents + +**Additional Changes to Enterprise Edition**: + +- Under `FileSettings` in `config.json`: + - Added `"AmazonS3SSE": false` to enable server-side encryption for files in Amazon S3. + - Added `"EnableMobileUpload": true` to enable file uploads on mobile devices + - Added `"EnableMobileDownload": true` to enable file downloads on mobile devices +- Under `JobSettings` in `config.json`: + - Added `"RunJobs": true` to enable running jobs on the jobs server + - Added `"RunScheduler": true` to enable scheduling jobs on the job server +- Under `ElasticsearchSettings` in `config.json`: + - Added `"ConnectionUrl": "http://dockerhost:9200"` to set the URL of the Elasticsearch server + - Added `"Username": ""` to specify the username to access the Elasticsearch server + - Added `"Password": ""` to specify the password to access the Elasticsearch server + - Added `"EnableIndexing": false` to enable Elasticsearch indexing + - Added `"EnableSearching": false` to enable searching using Elasticsearch + - Added `"Sniff": true` to enable sniffing on the Elasticsearch server + - Added `"PostIndexReplicas": 1` to specify how many replicas to use for each post index + - Added `"PostIndexShards": 1` to specify how many shards to use for each post index + +### Database Changes + +**UserAccessToken Table:** +- Added table + +**JobStatuses Table:** +- Removed table + +**Jobs Table:** +- Added table + +**Users Table:** +- Modified ``Roles`` column maximum size from 64 to 256 characters + +### API v4 Changes +- Mattermost 4.0 has a stable release of API v4 endpoints. It is recommended that any new integrations use the v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +**Added routes (API v4)** +See [api.mattermost.com](https://api.mattermost.com/) for more details: +- `GET` at `api/v4/jobs` +- `POST` at `api/v4/jobs` +- `GET` at `api/v4/jobs/{job_id:[A-Za-z0-9]+}` +- `POST` at `api/v4/jobs/{job_id:[A-Za-z0-9]+}/cancel` +- `GET` at `api/v4/jobs/type/{job_type:[A-Za-z0-9_-]+}` +- `POST` at `api/v4/elasticsearch/purge_indexes` +- `POST` at `api/v4/users/{user_id:[A-Za-z0-9]+}/tokens` +- `GET` at `api/v4/users/{user_id:[A-Za-z0-9]+}/tokens` +- `GET` at `api/v4/users/{user_id:[A-Za-z0-9]+}/tokens/{token_id:[A-Za-z0-9]+}` +- `POST` at `api/v4/users/{user_id:[A-Za-z0-9]+}/tokens/revoke` + +### Known Issues + +- Google login fails on the Classic mobile apps. +- Clicking on a channel during the tutorial makes the tutorial disappear. +- User can receive a video call from another browser tab while already on a call. +- Jump link in search results does not always jump to display the expected post. +- First load of the emoji picker is slow on low-speed connections or on deployments with hundreds of custom emoji. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- A public channel doesn't always show up in another browser tab or client until after refresh. +- Deleted message doesn't clear unreads or unread mentions. +- Changing the search term in the More Direct Messages modal doesn't reset the page. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Searching stop words in quotes with Elasticsearch enabled returns more than just the searched terms +- Searching with Elasticsearch enabled may not always highlight the searched terms +- Channels links to channels that the current user does not belong to may not render correctly + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [94117nl](https://github.com/94117nl), [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [debanshuk](https://github.com/debanshuk), [dmeza](https://github.com/dmeza), [enahum](https://github.com/enahum), [fraziern](https://github.com/fraziern), [grundelborg](https://github.com/grundelborg), [harshavardhana](https://github.com/harshavardhana), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [lindalumitchell](https://github.com/lindalumitchell), [megos](https://github.com/megos), [moonmeister](https://github.com/moonmeister), [MusikPolice](https://github.com/MusikPolice), [Ppjet6](https://github.com/Ppjet6), [saturninoabril](https://github.com/saturninoabril), [tejaycar](https://github.com/tejaycar), [Whiteaj36](https://github.com/Whiteaj36) + +/docs + +- [amyblais](https://github.com/amyblais), [bkmgit](https://github.com/bkmgit), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [john-combs](https://github.com/john-combs), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lindy65](https://github.com/lindy65), [pichouk](https://github.com/pichouk), [prixone](https://github.com/prixone), [Samiksha416](https://github.com/Samiksha416) + +/mattermost-mobile + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [lfbrock](https://github.com/lfbrock) + +/mattermost-push-proxy + +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost-redux + +- [94117nl](https://github.com/94117nl), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [grundelborg](https://github.com/grundelborg), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-api-reference + +- [ccbrown](https://github.com/ccbrown), [grundelborg](https://github.com/grundelborg), [jwilander](https://github.com/jwilander), [thePanz](https://github.com/thePanz) + +/mattermost-kubernetes + +- [crspeller](https://github.com/crspeller) + +/mattermost-docker + +- [jminardi](https://github.com/jminardi), [jnbt](https://github.com/jnbt), [pichouk](https://github.com/pichouk) + +/mattermost-load-test + +- [crspeller](https://github.com/crspeller) + +/mattermost-bot-sample-golang + +- [fkr](https://github.com/fkr), [hmhealey](https://github.com/hmhealey) + +---- + +## Release v4.0.5 - Feature Release + + - **v4.0.5, released 2017-09-16** + - Mattermost v4.0.5 contains multiple security fixes ranging from low to medium severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v4.0.4, released 2017-08-18** + - Mattermost v4.0.4 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed issue when using single-sign-on with GitLab where using a non-English language option in **System Console > Localization** sometimes resulted in a login failure. + - **v4.0.3, released 2017-08-10** + - Fixed issue with `AmazonS3Region` config setting being ignored in Minio file storage setup. + - Fixed issue when using high availability mode in Enteprise Edition E20 where the bind address wasn't set correctly for the hashicorp memberlist. + - **v4.0.2, released 2017-07-31** + - Fixed issue when using single-sign-on with GitLab (and in Enterprise Edition with SAML, Office365 and G Suite), where using a non-English language option in Account Settings resulted in a login failure. + - Fixed issue with custom slash commands not working in direct message channels. + - Fixed issue with GitLab and SAML single sign-on in Mattermost mobile apps redirecting to a browser page. + - **v4.0.1, released 2017-07-18** + - Fixed issue where pinning or un-pinning messages didn't work if `AllowTimeLimit` config setting is set to `Never`. + - Fixed issue where uploading or removing the **Service Provider Public Certificate** file in **System Console > SAML** refreshed the page, losing all unchanged settings. + - Fixed deactivated users appearing in channel member, team member and direct message lists. + - Fixed PDF previews not loading. + - **v4.0.0, released 2017-07-16** + - Original 4.0.0 release + +### Security Update + +- Mattermost v4.0.0 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Native iOS and Android Apps +- Second generation mobile apps released for [iOS](https://apps.apple.com/us/app/mattermost/id1257222717) and [Android](https://play.google.com/store/apps/details?id=com.mattermost.rn). +- The apps are [EMM compatible starting with BlackBerry Dynamics](https://mattermost.com/blog/mattermost-2nd-gen-mobile-apps-released-emm-compatible-starting-with-blackberry-dynamics/). + +#### Updated Web User Interface +- Updated the appearance of channel header and channel sidebar in the web user interface. +- Updated the default theme, "Mattermost". To try it, go to **Account Settings > Display > Theme**. + +#### Emoji Picker +- The emoji picker offers quick access to emoji when composing messages or adding reactions. +- Promoted from Beta, and enabled to all users by default. + +#### Languages +- Added Italian translations to the user interface. + +#### API v4 (Stable Release) +- Mattermost webapp moved to API v4 endpoints, which allow for more powerful integrations and server interaction. +- API v3 endpoints are supported until January 16, 2018. To learn more about migrating to APIv4 endpoints, [see https://api.mattermost.com/](https://api.mattermost.com/). + +#### High Availability ([Enterprise Edition E20](https://mattermost.com/pricing/)) +- Mattermost servers are dynamically added and removed based on discovery and their cluster name using the hashicorp memberlist. +- Added support for experimental gossip protocol, where the server will attempt to communicate via the gossip protocol over the gossip port. + +### Improvements + +#### Web User Interface +- Adjusted post spacing to be consistent across Markdown formatting, replies and consecutive posts. +- On hover colour for pin and channel member icons now consistent with flag and recent mentions icons. +- Emojis are now vertically aligned in post view. +- Channel name, header and purpose now update in real time for all users. +- For reply threads in the center channel, the "Commented on" phrase now respects the teammate name display config setting. +- Code block language tag is no longer selectable making it easier to copy the code. +- Aligned the search box with right-hand side reply thread. +- New user profile pictures now update for other users upon refresh. +- Improved rendering of @mention highlighting in message view. + +#### Mobile Web +- Added "Create Team" and "Leave Team" options to the Main Menu. +- Updated the look of Account Settings pages on mobile. +- User profile popover no longer gets cropped in the center channel on iOS browser. +- Link preview image now resizes correctly on iOS browser. + +#### Notifications +- Unread messages and mentions now sync across browser tabs and devices. +- Improved desktop notifications for webhook attachments. + +#### Emoji Picker & Custom Emoji +- Newly created custom emoji immediately display to all users without requiring a refresh. +- Improved position of the emoji picker near the top of the channel or the right-hand side comment thread. + +#### Keyboard Shortcuts +- CTRL+SHIFT+K shortcut now toggles the Direct Message dialog open and closed. +- SHIFT+UP now opens a reply thread for the most recent message posted by a user, skipping system messages. + +#### Slash Commands +- Added the following built-in slash commands: + - `/header` command to set the channel header. + - `/help` command to open the Mattermost help page in a new browser tab. + - `/open` command to switch or join a channel. + - `/search` command to search text in messages. + - `/settings` command to open the Account Settings dialog. +- `/invite_people` slash command is now disabled when account creation is set to false. +- If a message starts with a / but fails to send (either due to timeout or invalid command), the message is put back to the input box. + +#### Bulk Import Tool +- Added support for Direct Message channels and posts to the [bulk import tool](https://docs.mattermost.com/deployment/bulk-loading.html). + +#### Authentication +- User creation via OAuth (GitLab/Google/Office365) properly restricted to accepted domains, [if specified](https://docs.mattermost.com/administration/config-settings.html#restrict-account-creation-to-specified-email-domains). +- **Invite New Member** dialog validates email addresses against accepted domains, if set. + +#### New URL Routes +- Added the ability to Direct Message by email or username with the following new routes for Direct Message channels: + - `.../teamname/messages/@username` + - `.../teamname/messages/email` + - `.../teamname/messages/user_id` (redirects to `...teamname/messages/@username`) + - `.../teamname/messages/id1_id2` (redirects to `...teamname/messages/@username`) +- Also added a new route for Group Message channels: + - `.../teamname/messages/generated_id` + +#### Link Previews +- After posting a message containing an image link, a preview is loaded only if one is available. + +#### Enterprise Edition +- When a SAML user uses a non-supported locale, the language now defaults to English, preventing login issues. + +### Bug Fixes +- Emoji picker now closes in Firefox when clicking outside of it. +- [...] menu no longer disappears in the comment thread when hovering over another post. +- New direct messages received while in no teams do not show as unread after rejoining a team. +- Fixed JavaScript errors when receiving messages when not belonging to a team. +- An empty push notification no longer sent for messages only containing file attachments. +- Custom emoji search results no longer filter by creator's first and last name. +- `/expand` and `/collapse` slash commands now properly collapse images in website link previews. +- Group Message channels that are favorited can now be closed. +- Deactivated users now properly listed in Direct and Group Message channels in the left-hand sidebar. +- Fixed search in team and channel Manage Members dialog. +- File upload cancelled if you click "x" on thumbnail while file is uploading in your message draft. +- Status no longer appears offline after joining a new team. +- An empty push notification is no longer sent for messages only containing file attachments. +- Center channel maintains scroll position when new messages are received in the channel. +- Deleting the focused post in permalink view now sends user to normal channel view. +- Max Users per Team setting in **System Console > Users and Teams** no longer includes inactive users. + +### Compatibility + +#### Breaking Changes + +- If you are using NGINX as a proxy for the Mattermost Server, replace the `location /api/v3/users/websocket {` line with `location ~ /api/v[0-9]+/(users/)?websocket$ {` in the `/etc/nginx/sites-available/mattermost` NGINX configuration file. +- If you are upgrading a High Availability Cluster: When upgrading from 3.10 or earlier to 4.0 or later, you must manually add new items to the *ClusterSettings* section of your existing ``config.json``. For more information about this, see the *Upgrading to Version 4.0 and Later* section of :doc:`../deployment/cluster`. + - Microsoft Edge v39 and earlier (EdgeHTML v14 and earlier) has an issue that may case errors during account creation, login and if MFA is enforced. We recommend upgrading to Edge v40 (or EdgeHTML v15). + +#### Removed and deprecated features +- System Console settings in **Files > Images** removed. This includes: + - Image preview height and width + - Profile picture height and width + - Image thumbnail height and width +- Font setting in Account Settings > Display removed. +- Account Settings option **Display** > **Teammate Name Display** moved to the System Console. +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Added `"EnableEmojiPicker": true` to control whether emoji picker is enabled on the server. Enabling the emoji picker with a large number of custom emoji may slow down performance. + - Added `"EnableChannelViewedMessages": true` to control whether `channel_viewed` WebSocket event is sent, which syncs unreads across clients and devices. Setting to false can lead to higher performance in large deployments. + - Added `"EnableAPIv3": true` to control whether version 3 endpoints of the REST API are allowed on the server. If the setting is disabled, integrations that rely on API v3 will fail and can then be identified for migration to API v4. +- Under `TeamSettings` in `config.json`: + - Added `"TeammateNameDisplay": "username"` to set how to display users' names in posts and the Direct Messages list. Deployments with LDAP or SAML enabled will have this set to `full_name` by default for better experience. +- Under `FileSettings` in `config.json`: + - Removed System Console settings in **Files > Images**, including: + - `"ThumbnailWidth": 120` + - `"ThumbnailHeight": 100` + - `"PreviewWidth": 1024` + - `"PreviewHeight": 0` + - `"ProfileWidth": 128` + - `"ProfileHeight": 128` +- Under `SqlSettings` in `config.json`: + - Modified `"QueryTimeout": 30` to also support query timeouts on PostgreSQL, in addition to MySQL. + +**Additional Changes to Enterprise Edition**: + +- Under `ClusterSettings` in `config.json`: + - Added `"ClusterName": ""` to set the cluster to join by name. Only nodes with the same cluster name will join together. This is to support Blue-Green deployments or staging pointing to the same database. + - Added `"OverrideHostname": ""` to override the hostname of this server with this property. It is not recommended to override the Hostname unless needed. + - Added `"UseIpAddress": true` to control whether the cluster attempts to communicate using the IP Address. + - Added `"UseExperimentalGossip": false` to control whether the server attempts to communicate via the gossip protocol over the gossip port. + - Added `"ReadOnlyConfig": true` to control whether changes made to settings in the System Console are ignored. When running in production it is recommended to set this value to true. + - Added `"GossipPort": 8074` to set the port used for the gossip protocol. Both UDP and TCP should be allowed on this port. + - Added `"StreamingPort": 8075` to set the port used for streaming data between servers. + - Removed ``"InterNodeListenAddress": ":8075"`` as this setting is no longer used. + - Removed ``"InterNodeUrls": []`` as this setting is no longer used. + +### API v4 Changes +- Mattermost 4.0 has a stable release of API v4 endpoints. It is recommended that any new integrations use the v4 endpoints. For more details, and for a complete list of available endpoints, see [https://api.mattermost.com/](https://api.mattermost.com/). +- All APIv3 endpoints are scheduled for removal on January 16, 2018. + +**Added routes (API v4)** +- `GET` at `/teams/invite/{invite_id}` + - To retrieve information about a team (including the name and id) corresponding to an invite_id. + +**Modified routes (API v4)** +- `DELETE` at `/teams/{team_id}` + - Added an optional query parameter, `permanent`, to permanently delete a team for compliance reasons. +- `GET` at `/users` + - Added the `sort` query parameter to add basic sorting when selecting users on a team. +- `GET` at `/emoji` + - Added paging to the `/emoji` call for increased performance. +- `POST` at `/teams/{team_id}/import` + - Updated to return a JSON body with the import results under a `results` JSON field to allow more data to be returned in the future without breaking changes. + +### Websocket Event Changes + +**Added:** +- `channel_updated` that occurs each time channel information is updated (such as name or header), so that the changes are propagated across clients. +- `channel_viewed` that occurs each time you view a channel, propagating the event to all clients and devices and syncing unreads. + +### Known Issues + +- Google login fails on the Classic mobile apps. +- Edge overlays desktop notification sound and system notification sound. +- Clicking on a channel during the tutorial makes the tutorial disappear. +- User can receive a video call from another browser tab while already on a call. +- Search autocomplete picker is broken on Classic Android app. +- Jump link in search results does not always jump to display the expected post. +- First load of the emoji picker is slow on low-speed connections or on deployments with hundreds of custom emoji. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- Outgoing webhooks do not fire when posts have no text content. +- A public channel doesn't always show up in another browser tab or client until after refresh. +- Null values in Slack attachments cause a 500 error for incoming webhooks. +- Keyboard shortcut CTRL/CMD+SHIFT+A does not close Account Settings. +- Deleted message doesn't clear unreads or unread mentions. +- Changing the search term in the More Direct Messages modal doesn't reset the page. +- Status may sometimes get stuck as away or offline in High Availability mode with IP Hash turned off. +- Cannot delete or edit parent posts in right-hand side reply threads. +- Empty cells in Markdown tables render incorrectly. +- `platform user deleteall` CLI command expects a user as an argument. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [94117nl](https://github.com/94117nl), [abustany](https://github.com/abustany), [alexrford](https://github.com/alexrford), [asaadmahmood](https://github.com/asaadmahmood), [ccbrown](https://github.com/ccbrown), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [dmeza](https://github.com/dmeza), [enahum](https://github.com/enahum), [ftKnox](https://github.com/ftKnox), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jwilander](https://github.com/jwilander), [kkamdooong](https://github.com/kkamdooong), [lindalumitchell](https://github.com/lindalumitchell), [megos](https://github.com/megos), [meilon](https://github.com/meilon), [moonmeister](https://github.com/moonmeister), [pieterlexis](https://github.com/pieterlexis), [saturninoabril](https://github.com/saturninoabril), [VeraLyu](https://github.com/VeraLyu), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/mattermost-mobile + +- [asaadmahmood](https://github.com/asaadmahmood), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [lfbrock](https://github.com/lfbrock), [omar-dev](https://github.com/omar-dev) + +/mattermost-redux + +- [94117nl](https://github.com/94117nl), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jarredwitt](https://github.com/jarredwitt), [jwilander](https://github.com/jwilander), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-api-reference + +- [cpanato](https://github.com/cpanato), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [Vaelor](https://github.com/Vaelor), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/docs + +- [94117nl](https://github.com/94117nl), [acgustafson](https://github.com/acgustafson), [amyblais](https://github.com/amyblais), [ccbrown](https://github.com/ccbrown), [crspeller](https://github.com/crspeller), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jwilander](https://github.com/jwilander), [kjkeane](https://github.com/kjkeane), [megos](https://github.com/megos), [pieterlexis](https://github.com/pieterlexis) + +/desktop + +- [yuya-oc](https://github.com/yuya-oc) + +/mattermost-kubernetes + +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost-push-proxy + +- [coreyhulen](https://github.com/coreyhulen), [ftKnox](https://github.com/ftKnox) + +/mattermost-docker + +- [pichouk](https://github.com/pichouk), [tejasbubane](https://github.com/tejasbubane) + +/mattermost-load-test + +- [crspeller](https://github.com/crspeller), [JeffSchering](https://github.com/JeffSchering) + +---- + +## Release v3.10.3 + + - **v3.10.3, released 2017-08-18** + - Mattermost v3.10.3 contains multiple security fixes ranging from low to high severity. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed issue when using single-sign-on with GitLab where using a non-English language option in **System Console > Localization** sometimes resulted in a login failure. + - **v3.10.2, released 2017-07-18** + - Mattermost v3.10.2 contains low severity security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v3.10.1, released 2017-07-16** + - Mattermost v3.10.1 contains a high severity security fix for an OAuth SSO vulnerability and two additional fixes for low severity security issues. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v3.10.0, released 2017-06-16** + - Original 3.10 release + +### Highlights + +#### Languages +- Added Turkish translations for the user interface. + +#### New and Improved Keyboard Shortcuts +- Redesigned the channel switcher (CTRL/CMD+K) for increased productivity. +- Browse direct and group message channels (CTRL/CMD+SHIFT+K) and reply to the most recent message (SHIFT+UP) with new shortcuts. + +### Improvements + +#### Web User Interface +- Enter key now confirms deletion on the screens to delete a custom emoji and delete a channel. +- Team and channel URLs now replace accented characters with their ASCII equivalents. +- Recent mentions and flagged posts icons in the header are now highlighted when they are active in the right-hand sidebar. +- Empty rows are now ignored in the Send Email Invite modal. +- Enter key now confirms leaving a team from the Leave Team modal. +- Profile popover now opens when clicking a username in mobile browser view. +- /join now allows switching to a private channel to which the user has access. +- Improved the formatting of Mattermost content when copying and pasting to other apps. +- Added the ability for users to view and modify their online status from their profile picture in the header. +- /loadtest command changed to /test. +- Ephemeral messages are removed from the right-hand sidebar after it is reopened. +- Added a markdown preview option to the message editing modal. +- Status indicators are now shown in the Direct Messages list. + +#### Notifications +- Added "@here" to the list of channel-wide mentions in Account Settings. +- Added a reminder when your Mattermost window is refreshed if a status override slash command is used to set yourself as /away or /offline. +- Users will see a confirmation dialog when attempting to use @all or @channel in a channel with over 5 users. +- Messages for others being added to a channel no longer trigger channels to be unread. + +#### Administration +- Added CLI tool for permanently deleting channels. +- Channel Admins can now delete user's messages within their channel if permitted in the System Console. +- Errors are now logged when failing to load config through the command line. +- Reduced unnecessary database reads and writes when bulk importing users. + +#### System Console +- System Console main dropdown menu now has links to the Admin Guide, Troubleshooting Forum, Commercial Support Page and the About Mattermost dialog. +- Added the ability to enable Legacy Signature (AWS Signature V2) with S3 compatible servers. + +#### Authentication +- Added a redirect to the appropriate team, channel or post if navigating to a Mattermost URL when logged out. +- Clicking a team invite link now joins the team in all active sessions. + +#### Performance +- Upgraded GORP to support connection timeouts on MySQL and missing database columns on MySQL and Postgres. + +#### Integrations +- Posts from webhooks that are greater than 4000 characters are now broken into multiple posts. + +#### Enterprise Edition +- Added an announcement banner visible to all end users to make maintenance announcements across the system. + +### Bug Fixes +- Dragging and dropping a file onto the left-hand sidebar no longer navigates away from Mattermost to open the file in the browser. +- Textbox will no longer overlap the center pane message area as it expands when typing. +- Fixed an issue where statuses could get stuck online after quitting the desktop app or closing the browser window in some cases. +- Profile pictures uploaded on mobile are now rotated in their correct orientation. +- The System Console help text for Minimum Password Length no longer dynamically updates as the input is changed. +- Fixed an issue where the autocomplete list may appear underneath a modal overlay. +- Updated error text when uploading a profile picture that is in an unsupported image format. +- Joined channels no longer appear in the "More..." channels list. +- Wide markdown images no longer cause horizontal scrolling in the center pane. +- Fixed theme styling for button active states. +- Fixed an issue where channels sometimes did not appear read if the channel was in focus when a new message was received. +- Fixed an issue where the autocomplete list would not close after using a slash command. +- Removed the system warning message that appears if mentioning a user that is not a member of a group message. +- Fixed an issue where wide embedded images produce horizontal scroll. +- Fixed a Javascript error that would occur when opening the System Console > SAML page. +- Removed the Channel Admin user interface in Team Edition since the policy restrictions are only available in Enterprise Edition. +- Adding a reaction to an ephemeral message no longer throws a Javascript error. +- Fixed an issue where clicking autocomplete suggestions would not populate the search box with the appropriate text. +- Fixed an issue where the System Console users list ignored the search term after selecting a team from the filter. +- Channel header messages no longer appear cut-off if using a slash. +- Corrected the formatting of the "Edited" indicator in the right-hand sidebar. +- Fixed the positioning of the pin icon and channel header on Edge. + +### Compatibility + +#### Removed and deprecated features +- System Console settings in **Files > Images** scheduled for removal in July 2017 release. This includes: + - Image preview height and width + - Profile picture height and width + - Image thumbnail height and width +- Font setting in Account Settings > Display scheduled for removal in July 2017 release. +- Account Settings options for **Display** > **Display Font** and **Display** > **Teammate Name Display** are scheduled for removal in July 2017 release. +- All APIv3 endpoints are scheduled for removal six months after APIv4 is stable. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + - Under `ServiceSettings` in `config.json`: + - Added `"GoroutineHealthThreshold": -1,` to set a threshold for number of goroutines. +- Under `SqlSettings` in `config.json`: + - Added `"QueryTimeout": 30` to set the number of seconds to wait for a response from the database after opening a connection and sending the query. +- Under `FileSettings` in `config.json`: + - Added `"AmazonS3SignV2": false` to enable Legacy Signature (AWS Signature V2) with S3 compatible servers. + +**Additional Changes to Enterprise Edition**: + - Under `AnnoucementSettings` in `config.json`: + - Added `"EnableBanner": false,` to enable an announcement banner visible for all users. + - Added `"BannerText": "",` to specify the text shown in the banner. + - Added `"BannerColor": "#f2a93b",` to set the banner background color. + - Added `"BannerTextColor": "#333333",` to set the banner text color. + - Added `"AllowBannerDismissal": true` to set whether the banner can be dismissed by users. + +### API Changes +- Mattermost 3.10 has a release candidate of APIv4 endpoints. To see the complete list of available endpoints, see [https://api.mattermost.com/v4/](https://api.mattermost.com/v4/). +- All APIv3 endpoints are scheduled for removal six months after APIv4 is stable. + +**Modified routes (APIv4)** +- `/system/ping` updated to return `500 Internal Server Error` with `{"status": "unhealthy"}` in the response body when `GoroutineHealthThreshold` is set in config.json and the number of goroutines on the server exceeds that threshold. If the number of goroutines is below the threshold or `GoroutineHealthThreshold` is not set in config.json, `200 OK` is returned with no response body. + +### Known Issues + +- Google login fails on the mobile apps. +- Edge overlays desktop notification sound and system notification sound. +- Status appears offline briefly after joining a new team. +- User popover can get cropped in the center channel on iOS. +- Clicking on a channel during the tutorial makes the tutorial disappear. +- Custom emoji search results filter by the creator's first/last name in addition to the emoji name. +- Reactions are displayed on messages deleted by other users. +- User can receive a video call from another browser tab while already on a call. +- Search autocomplete picker is broken on Android. +- Jump link in search results does not always jump to display the expected post. +- First load of the emoji picker is slow on low-speed connections. +- Emoji picker for reactions doesn't always position correctly. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- New direct messages received while in no teams do not show as unread after joining a team. +- User is not logged out immediately when logging self out from Active Sessions list. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- CTRL+SHIFT+K doesn't toggle modal open and closed. +- Deactivated users do not appear in the Direct Message and Group Message sidebar channel list. +- Outgoing webhooks do not fire when posts have no text content. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [dmeza](https://github.com/dmeza), [doh5](https://github.com/doh5), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [harshavardhana](https://github.com/harshavardhana), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [kulak-at](https://github.com/kulak-at), [saturninoabril](https://github.com/saturninoabril), [tjuerge](https://github.com/tjuerge) + +/docs + +- [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [esethna](https://github.com/esethna), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jwilander](https://github.com/jwilander), [kjkeane](https://github.com/kjkeane), [lindy65](https://github.com/lindy65), [mikedaniel18](https://github.com/MikeDaniel18) + +/mattermost-api-reference + +- [94117nl](https://github.com/94117nl), [cpanato](https://github.com/cpanato), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [senk](https://github.com/senk) + +/mattermost-redux + +- [94117nl](https://github.com/94117nl), [cpanato](https://github.com/cpanato), [enahum](https://github.com/enahum), [jarredwitt](https://github.com/jarredwitt), [jwilander](https://github.com/jwilander) + +/mattermost-mobile + +- [asaadmahmood](https://github.com/asaadmahmood), [cpanato](https://github.com/cpanato), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [lfbrock](https://github.com/lfbrock), [rthill](https://github.com/rthill) + +/desktop + +- [yuya-oc](https://github.com/yuya-oc) + +/mattermost-docker + +- [carlosasj](https://github.com/carlosasj), [FingerLiu](https://github.com/FingerLiu), [mkdbns](https://github.com/mkdbns), [pichouk](https://github.com/pichouk), [xcompass](https://github.com/xcompass) + +/android + +- [coreyhulen](https://github.com/coreyhulen), [der-test](https://github.com/der-test), [lfbrock](https://github.com/lfbrock) + +/mattermost-selenium + +- [doh5](https://github.com/doh5), [lindalumitchell](https://github.com/lindalumitchell) + +/gorp + +- [jwilander](https://github.com/jwilander) + +/ios + +- [coreyhulen](https://github.com/coreyhulen), [PrestonL](https://github.com/PrestonL) + +/mattermost-kubernetes + +- [coreyhulen](https://github.com/coreyhulen) + +---- + +## Release v3.9.2 + + - **v3.9.2, released 2017-07-18** + - Mattermost v3.9.2 contains low severity security fixes. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v3.9.1, released 2017-07-16** + - Mattermost v3.9.1 contains a high severity security fix for an OAuth SSO vulnerability and two additional fixes for low severity security issues. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v3.9.0, released 2017-05-16** + - Original 3.9 release + +### Security Update + +- Mattermost v3.9.0 contains a low severity [security update](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.9.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. + +### Highlights + +#### Languages + +- Added Polish translations for the user interface. + +#### Redux + +- Mattermost Webapp moved over to Redux for increased performance and more stable infrustructure. + +#### APIv4 Release Candidate + +- Mattermost HTTP REST APIs moved to v4 endpoints allowing for more powerful integrations and server interaction. +- To learn more about the available APIv4 endpoints, [see our documentation](https://api.mattermost.com/v4/). +- APIv3 endpoints are supported until six months after the stable release of APIv4 endpoints in Q3 of 2017. + +### Improvements + +#### Web User Interface +- Lower and upper vertical margins for posts are now equal. +- Comments only containing a file attachment have a reduced vertical spacing in the center channel. +- First line of message text is now aligned with username. +- Added padding between timestamp and pinned posts badge in comment threads in compact view. +- Added "View Members" option to Town Square. +- Moved "Start Video Call" option to the bottom of the profile popover. +- Added a confirmation dialog when leaving a private channel. +- User preferences such as display settings now sync between browser tabs, between different browsers, and across devices. + +#### Performance +- Added the ability to isolate searches to specific read-replicas for full text search queries for higher performance. +- Added default read and write timeouts for MySQL datasource to prevent hub processing deadlock. +- Added password field to the [bulk import tool](https://docs.mattermost.com/deployment/bulk-loading.html). +- Added the ability to disable full text search queries and statuses via `config.json` for higher performance. + +#### Emoji Picker (Beta) +- Enable the emoji picker in **Account Settings > Advanced > Preview pre-release features**. +- Custom emoji now maintains aspect ratio in the emoji picker. +- Improved user experience for closing the Emoji picker after reacting to a message. + +#### Keyboard Shortcuts +- Added a link to keyboard shortcuts documentation via the team Main Menu. +- Pressing ENTER once in the channel switcher (CTRL/CMD+K) now switches the channel. +- Using a mouse to select a channel in the channel switcher (CTRL/CMD+K) now switches to the correct channel. + +#### Markdown Text Formatting +- Added a margin for Markdown inline images. +- Improved Markdown heading sizes in the desktop view. + +#### On-Boarding +- Added "Already have an account? Click here to sign in" link to the sign up page. +- Improved experience of joining a team using an invite link. + +#### Files +- SVG files now render in file preview. + +#### CLI Tool +- Added new CLI commands: + - `platform config validate` for validating the `config.json` file. + - `platform user search` for searching users based on username, email, or user ID. + +#### OAuth 2.0 Service Provider +- OAuth 2.0 service provider now always returns the refresh token. +- New refresh token now issued when granting a new access token. + +#### System Console + - Added a confirmation dialog when deactivating a user. + - Server logs are now always printed in English regardless of Default Server Language, for easier troubelshooting. + - The `AllowCorsFrom` config setting (in **System Console > Connections > Enable cross-origin requests from**) now supports multiple domain names. + - Added a setting to disable file and image uploads on messages. + +#### Enterprise Edition + - Added new [performance monitoring metrics](https://docs.mattermost.com/scale/performance-monitoring.html) for + - The total number of connections to all the search replica databases + - The total number of WebSocket broadcasts sent + +### Bug Fixes +- Long custom emoji names no longer float out of the emoji picker. +- Deleted custom emojis no longer stay in "recently used" section of the emoji picker. +- The maximum length of the "Position" field increased to 64 characters in the database. The previous limit caused problems with LDAP synchronization. +- Pinning a post in center channel no longer changes pinned posts list in the right-hand sidebar. +- Pinning a post in center channel now adds the pinned post badge to search results. +- Fixed error message text for **Edit URL** field in channel creation dialog. +- Disabled config file watcher while running from makefile. +- Fixed Go client's `GetTeamByName()` function. +- Recent mentions search now properly includes `@[username]` in the search. +- Updated error message when entering a password longer than maximum number of characters. +- Don't send the same message multiple times when hitting "Retry" on a failed post. +- Fixed the help text for the channel purpose in private channels. +- When ability to change the header is restricted, "Set a Header" option is no longer shown in the channel intro. +- Mention notifications now trigger if the word is formatted in bold, italic or strikethrough, and won't if it's inside a code block. +- In mobile view, Manage Members menu option no longer reads "View Members" for channel admins. +- Usernames with dots now get mention notifications when followed by a comma or other symbol. +- Deactivated users are no longer listed in the "Manage Members" modal. +- Collapsible Account Setting menus now open properly in iOS Safari and Chrome browsers. +- Removing an expired license now removes the blue bar header message. +- "Next" button in More Channels list now takes you to the top of the next page, instead of the bottom. +- Blue bar "Preview Mode" header message now disappears after enabling email notifications. +- Full name is now editable in Account Settings if the first and last name attributes are not specified in **System Console > Authentication > LDAP**. +- Added a back button to pinned posts list on the right-hand sidebar. +- "Pinned" icon no longer overlaps text on consecutive posts or replies that have Markdown headings. +- Uploading a profile picture on iOS no longer throws an error. +- Fixed group message names in channel switcher (CTRL/CMD+K) for group messages that are not in your sidebar. +- Channel notification preferences no longer appear saved when clicking Cancel. +- Channel creation permissions aren't set to channel admins when it doesn't exist. + +### Compatibility + +#### Breaking changes: + +- If you're using NGINX as a proxy for the Mattermost Server, replace the `location /api/v3/users/websocket {` line with `location ~ /api/v[0-9]+/(users/)?websocket$ {` in the `/etc/nginx/sites-available/mattermost` NGINX configuration file. +- Existing email invite links, password reset links, and email verification links in emails generated by your Mattermost server will be invalidated after upgrading to v3.9.0. +- Firefox ESR 45 has an [end-of-life scheduled for June 13](https://en.wikipedia.org/wiki/Firefox_version_history) and is therefore no longer supported. We recommend upgrading to [Firefox ESR 52](https://www.mozilla.org/en-US/firefox/52.0esr/releasenotes/). + +#### Removed and deprecated features +- System Console settings in **Files > Images** scheduled for removal in July 2017 release. This includes: + - Image preview height and width + - Profile picture height and width + - Image thumbnail height and width +- All APIv3 endpoints are scheduled for removal six months after APIv4 is stable. + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json`, or the System Console when available. + +**Changes to Team Edition and Enterprise Edition**: + + - Under `ServiceSettings` in `config.json`: + - Added `"EnablePostSearch": true` to control whether users can search messages. Disabling can lead to higher performance in large deployments. + - Added `"EnableUserStatuses": true` to control whether user statuses are shown in the web user interface. Disabling can lead to higher performance in large deployments. + - Under `FileSettings` in `config.json`: + - Added `"EnableFileAttachments": true` to control whether users can upload files and images on messages. + + - Under `EmailSettings` in `config.json`: + - Removed `"PasswordResetSalt": ""` given tokens are now used for signing of password reset emails. + + - Under `SqlSettings` in `config.json`: + - Added `"DataSourceSearchReplicas": []` to specify the connection strings for search replica databases for handling search queries. + +**Additional Changes to Enterprise Edition**: + + - Under `ServiceSettings` in `config.json`: + - Added `"LicenseFileLocation": ""` to specify the path and filename of the Enterprise license file on disk. On startup, if Mattermost cannot find a valid license in the database from a previous upload, it will look for the file specified here. + +### Database Changes + +**OAuthAccessData Table:** +- Added `Scope` column + +**PasswordRecovery Table:** +- Removed `PasswordRecovery` table and moved entries to a common token store + +### API Changes + +- Mattermost 3.9 has a release candidate of APIv4 endpoints. To see the complete list of available endpoints, see [https://api.mattermost.com/v4/](https://api.mattermost.com/v4/). +- All APIv3 endpoints to be removed six months after APIv4 endpoints are stable. + +### Websocket Event Changes + +- Added `preferences_changed` and `preferences_deleted` to sync preferences between browser tabs, between different browsers, and across devices when a preference is changed or deleted. + +### Known Issues + +- Google login fails on the mobile apps. +- Slack import doesn't add merged members/e-mail accounts to imported channels. +- User can receive a video call from another browser tab while already on a call. +- Sequential messages from the same user appear as separate posts on mobile view. +- Search autocomplete picker is broken on Android. +- Jump link in search results does not always jump to display the expected post. +- First load of the emoji picker is slow at low connections. +- Emoji picker for reactions doesn't always position correctly. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. +- Emoji picker is sometimes cut off on comment threads on the right-hand sidebar. +- User status can get stuck online after quitting the desktop app or closing the browser window. +- New direct messages received while in no teams do not show as unread after joining a team. +- Profile picture uploaded from mobile appears rotated. +- User is not logged out immediately when logging self out from Active Sessions list. +- Certain code block labels don't appear while scrolling on iOS mobile web. +- System Console user list filter does not show accurate results if applied after entering a search query. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [doh5](https://github.com/doh5), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [gstraube](https://github.com/gstraube) , [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [justinwyer](https://github.com/justinwyer), [jwilander](https://github.com/jwilander), [lindalumitchell](https://github.com/lindalumitchell), [prixone](https://github.com/prixone), [Rudloff](https://github.com/Rudloff), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [simon0191](https://github.com/simon0191), [VeraLyu](https://github.com/VeraLyu) + +/docs + +- [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fjarlq](https://github.com/fjarlq), [it33](https://github.com/it33), [ivernus](https://github.com/ivernus), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [justinwyer](https://github.com/justinwyer), [lindy65](https://github.com/lindy65), [senk](https://github.com/senk) + +/mattermost-api-reference + +- [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [dagit](https://github.com/dagit), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-redux + +- [enahum](https://github.com/enahum), [jarredwitt](https://github.com/jarredwitt), [jwilander](https://github.com/jwilander) + +/desktop + +- [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-mobile + +- [asaadmahmood](https://github.com/asaadmahmood), [cpanato](https://github.com/cpanato), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock) + +/mattermost-docker + +- [esethna](https://github.com/esethna), [pichouk](https://github.com/pichouk), [xcompass](https://github.com/xcompass) + +/mattermost-push-proxy + +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost-selenium + +- [doh5](https://github.com/doh5), [lindalumitchell](https://github.com/lindalumitchell), [coreyhulen](https://github.com/) + +/mattermost-kubernetes + +- [coreyhulen](https://github.com/coreyhulen) + +/gcm + +- [coreyhulen](https://github.com/coreyhulen), [csduarte](https://github.com/csduarte) + +---- + +## Release v3.8.3 + +### Notes on Patch Release + + - **v3.8.3, released 2017-07-16** + - Mattermost v3.8.3 contains a high severity security fix for an OAuth SSO vulnerability and two additional fixes for low severity security issues. [Upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - **v3.8.2, released 2017-04-21** + - Changed the client to use `window.location.origin` instead of siteURL, fixing WebSocket connection issues with Mattermost 3.8 upgrade. + - Fixed a few APIv4 endpoints in support of the next [React Native mobile app](https://github.com/mattermost/mattermost-mobile) release. + - **v3.8.1, released 2017-04-19** + - Mattermost v3.8.1 contains a security update and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue with Site URL sometimes breaking the OAuth2 login flow, including login using GitLab. + - Reverted a change preventing LDAP usernames from beginning with a number. + - Fixed a permission issue with group message channel creation. + - **v3.8.0, released 2017-04-16** + - Original 3.8 release + +### Security Update + +- Mattermost v3.8.0 contains multiple [security updates](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.8.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. + +### Highlights + +#### Native iOS and Android Apps (Beta) +- Second generation mobile apps, built using React Native, are available for beta testing. + +#### Pinned Posts +- Important messages can be pinned to the channel for easy reference. Pinned posts are visible to all channel members. + +#### Emoji Picker and Improved Emoji Reactions (Beta) +- The picker offers quick access to emoji when composing messages or adding reactions. Enable the emoji picker in **Account Settings > Advanced > Preview pre-release features**. +- The picker is "Beta" while speed of the first load with lots of custom emoji is improved. + +#### System Users List +- The System Console now consolidates all users into a system-wide list that can be filtered by team. The users list can be used to manage team membership and team roles for any user on the system. + +#### Configure Using Environment Variables +- Override `config.json` settings using environment variables. + +### Improvements + +#### Web User Interface +- Date separators now appear between posts in the right-hand sidebar. +- Non-square profile pictures are now cropped in the middle rather than being stretched. +- Post timestamps now have an expanded date tooltip. +- The "Add Members" modal now autofocuses on the search box when opened from the "Manage Members" modal. +- Reduced the margins and line height in compact view. +- There is now a confirmation dialog before deleting a custom emoji. +- Updated the error page for invalid permalinks. +- Updated the error page for "Private browsing not supported" in Safari. + +#### Performance +- Added index and cache to reactions store + +#### Search +- File attachments thumbnails are now shown in search results. +- Flagged posts from other teams are no longer displayed. + +#### Channels +- Favorite channels are now sorted alphabetically regardless of channel type. +- Town Square now has a default channel purpose. +- Users added to a group message are now removed from the Direct Messages search list. +- "Private Groups" have been renamed to "Private Channels". + +#### Mobile +- Executing a search now closes the keyboard and removes the keyboard focus from the text box. + +#### Integrations +- The integrations confirmation page can now be dismissed with the ENTER key. + +#### Link Previews +- Updated the UI for link previews by removing an extra blue vertical bar. +- Added support for link preview requests through a separate proxy. + +#### Notifications +- Users can no longer configure email notification settings if the notifications are disabled for the system. + +#### Onboarding +- Existing users on the server can now easily be added to a team via the Main Menu. + +#### Enterprise Edition +- Policy controls for restricting permissions to add and remove members from private channels. +- Added the ability to read the license file from the disk. +- The configuration file is now reloaded after applying an Enterprise Edition license on startup. + +### Bug Fixes +- Fixed line wrapping of the timestamp in Account Settings > Security > View Access History. +- Fixed an inconsistent error message when creating a channel with a display name of one or two characters. +- Removed the duplicate "Back" button on the Team Creation page. +- The AltGR key no longer triggers keyboard shortcuts. +- Saving a team name without making changes no longer throws an error message. +- Group messages are now sorted alphabetically with direct messages. +- The "Create Channel" button will now only appear in the "More Channels" modal when the user has the permission to create channels. +- The Town Square channel menu no longer has redundant dividers with certain combinations of System Console > Policy settings. +- Fixed an issue where some conversations would not trigger the channel to appear unread in the left-hand sidebar. +- Fixed an issue where usernames sometimes did not appear when hovering over reactions. +- Fixed an issue where link previews would sometimes cause a horizontal scroll bar to appear. +- iOS code blocks no longer wrap to the next line. +- Removed an extra border in Markdown tables on iOS. +- Usernames in the channel member list are now properly aligned. +- Fixed a console error that was thrown when switching teams. +- Fixed occasionial flickering of channel autocomplete. +- Link preview images no longer appear outside of the preview container. + +### Compatibility + +#### Breaking changes: +- The **System Console > Configuration > [Site URL](https://docs.mattermost.com/administration/config-settings.html#site-url)** field is now mandatory. Set the Site URL in the System Console, or in the `gitlab.rb` file if you are using GitLab Mattermost. +- Server logs are now written to the `mattermost.log` file located in the directory specified in **System Console > Logging > [File Log Directory](https://docs.mattermost.com/administration/config-settings.html#file-log-directory)**. Set the directory name in the System Console, or in the `gitlab.rb` file if you are using GitLab Mattermost. + +#### Removed and deprecated features +- Backwards compatibility with the old CLI tool is removed in v3.8. See [documentation to learn more about the new CLI tool](https://docs.mattermost.com/administration/command-line-tools.html). +- Deprecated APIv3 routes removed in v3.8: + - `GET` at `/channels/more` (replaced by /`channels/more/{offset}/{limit}`) + - `POST` at `/channels/update_last_viewed_at` (replaced by `/channels/view`) + - `POST` at `/channels/set_last_viewed_at` (replaced by `/channels/view`) + - `POST` at `/users/status/set_active_channel` (replaced by `/channels/view`) +- All APIv3 endpoints to be removed six months after APIv4 goes stable (replaced by APIv4 endpoints). + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + + - Under `EmailSettings` in `config.json`: + - Added `"SkipServerCertificateVerification": false` to skip verification of smtp server certificates. + +**Additional Changes to Enterprise Edition**: + + - Under `TeamSettings` in `config.json`: + - Added `"RestrictPrivateChannelManageMembers": all` to set who can add and remove members from private groups. + +### Database Changes + +**Posts Table:** +- Added `IsPinned` column + +### API Changes + +**New routes (APIv3):** +- `GET` at `/channels/{channel_id}/pinned` + - Returns the pinned posts in a channel +- `POST` at `/channels/{channel_id}/posts/{post_id}/pin` + - Pins a post to a channel +- `POST` at `/channels/{channel_id}/posts/{post_id}/unpin` + - Unpins a post from a channel + +**Removed routes (APIv3):** +- `GET` at `/channels/more` (replaced by /`channels/more/{offset}/{limit}`) +- `POST` at `/channels/update_last_viewed_at` (replaced by `/channels/view`) +- `POST` at `/channels/set_last_viewed_at` (replaced by `/channels/view`) +- `POST` at `/users/status/set_active_channel` (replaced by `/channels/view`) + +### Websocket Event Changes + +**Added:** +- `added_to_team` that occurs when the current user is added to a team by another user. + +**Modified** +- Added a `seq` field to websocket events that increments with each event sent to the client. + +### Known Issues + +- "Pinned" icon sometimes overlaps image posts. +- Full name is not editable in Account Settings if the first and last name attributes are removed from **System Console > Authentication > LDAP**. +- Usernames with dots do not get mention notifications when followed by a comma. +- Slack import doesn't add merged members/e-mail accounts to imported channels. +- User can receive a video call from another browser tab while already on a call. +- Sequential messages from the same user appear as separate posts on mobile view. +- Search autocomplete picker is broken on Android. +- Jump link in search results does not always jump to display the expected post. +- Blue bar "Preview Mode" header message sometimes does not disappear after enabling email notifications. +- Removing an expired license may not remove the blue bar header message until a refresh. +- First load of the emoji picker is slow at low connections. +- Emoji picker for reactions doesn't always position correctly. +- Deleted custom emoji stay in "recently used" section of the emoji picker. +- Scrollbar is sometimes not visible in the left-hand sidebar after switching teams. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server: + +- [aautio](https://github.com/aautio), [asaadmahmood](https://github.com/asaadmahmood), [bonespiked](https://github.com/bonespiked), [bradhowes](https://github.com/bradhowes), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [doh5](https://github.com/doh5), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jostyee](https://github.com/jostyee), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lindalumitchell](https://github.com/lindalumitchell), [prixone](https://github.com/prixone), [R-Wang97](https://github.com/R-Wang97), [saturninoabril](https://github.com/saturninoabril), [VeraLyu](https://github.com/VeraLyu) + +/docs: + +- [coreyhulen](https://github.com/coreyhulen), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jwilander](https://github.com/jwilander), [lindy65](https://github.com/lindy65), [Rohlik](https://github.com/Rohlik) + +/mattermost-redux: + +- [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jarredwitt](https://github.com/jarredwitt), [jwilander](https://github.com/jwilander) + +/mattermost-api-reference: + +- [cpanato](https://github.com/cpanato), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [saturninoabril](https://github.com/saturninoabril), [senk](https://github.com/senk) + +/mattermost-mobile: + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [lfbrock](https://github.com/lfbrock), [saturninoabril](https://github.com/saturninoabril) + +/mattermost-selenium: + +- [coreyhulen](https://github.com/coreyhulen), [lindalumitchell](https://github.com/lindalumitchell) + +/desktop: + +- [jasonblais](https://github.com/jasonblais), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-docker: + +- [xcompass](https://github.com/xcompass) + +/mattermost-kubernetes: + +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost-load-test: + +- [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte) + +---- + +## Release v3.7.5 + +### Notes on Patch Release + + - **v3.7.5, released 2017-04-27** + - Fixed a number of low to moderate severity security issues, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Note: The **System Console > Configuration > [Site URL](https://docs.mattermost.com/administration/config-settings.html#site-url)** field is now mandatory. Set the Site URL in the System Console, or in the `gitlab.rb` file if you are using GitLab Mattermost. + - **v3.7.4, released 2017-04-13** + - Fixed a number of low to high severity security issues, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - **v3.7.3, released 2017-03-23** + - Fixed a high severity security issue, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Fixed an issue with telemetry data collection + - **v3.7.2, released 2017-03-17** + - Fixed an issue with LDAP, SAML, and OAuth logins where 1 and 2 character usernames displayed incorrectly + - **v3.7.1, released 2017-03-16** + - Fixed an issue where some [System Console > Policy settings](https://docs.mattermost.com/administration/config-settings.html#policy) were incorrectly applied to Team Edition, breaking the System Console UI + - **v3.7.0, released 2017-03-16** + - Original 3.7 release + +### Security Update + +- Mattermost v3.7.0 contains a [security update](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.7.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. + +### Highlights + +#### Group Messaging + +- Added support for multi-party direct messages, you can now quickly create conversations with a small group of people directly from the Direct Message list + +#### Channel Push Notification Preferences + +- Added channel notification preferences for mobile push to customize your notification settings + +#### New Website Link Previews + +- Improved display of link previews for website content when available, replacing the previous preview feature that handled only a subset of links + +#### Bulk User Import Tool + +- Convert your existing data into our new import format, and use this tool to import teams, channels, users and posts from other systems + +#### Channel Admins ([Enterprise E10 & E20](https://mattermost.com/pricing/)) + +- Added a new "Channel Admin" role to grant permissions for renaming and deleting a channel + +#### SAML OneLogin ([Enterprise E20](https://mattermost.com/pricing/)) + +- Added support for OneLogin authentication and account creation via SAML 2.0. + +### Improvements + +#### Performance + +- Loading new users can now be run on a live system without a major impact on performance through the new bulk user import tool +- Optimized SQL queries by adding index for PostId, removing ParentId from delete post queries, and fixing blank post queries +- Increased performance for "user typing..." messages by moving the check from server to client +- Increased performance for direct message channels by removing `MakeDirectChannelVisible` call and adding client handling +- Moved channel permission checks back to using cache +- Added caching for emoji, file info, profile images and website link previews +- Adding index and caching to reactions +- Increased performance when receiving messages by + - removing the `viewChannel` requests when receiving a new post and only marking the channel as read when switching into it, out of it or when closing the app + - removing the `view_channel` websocket event from the server + - removing the `getChannel` and `getTeamUnreads` requests when receiving a new post + - adding client handling for marking channels and teams unread + - adding `getMyChannelMembers` request to web app when window becomes active after ten seconds +- Increased time between database recycles +- Improved mobile push proxy connections by disabling keep-alives +- Fixed Minio not properly closing read objects +- Fixed file info caching and emoji reaction issues on Aurora read replicas +- Added reloading, removing and uploading of Enterprise license key to cache purge + +#### Web User Interface + +- Update status indicators shown in post view +- Show `(Edited)` indicator if a message has been edited +- `(message deleted)` placeholder is no longer shown to the user that deleted the message +- Added a link to Manage Members modal from channel members list +- Added support for image previews if the URL contains a custom query +- Added support for all timecode formats for YouTube previews +- System message is now posted after changing channel purpose +- Reinstated the delete option on system messages +- Clicking on timestamps on messages now open a permalink view +- Removed new lines for system messages posted after updating channel header +- Focus is set back to message box after uploading a file +- Added machine-readable date and time to timestamps +- Adjusted tablet view so the browser URL bar doesn't overlap the message box +- Channel header can now be up to 1024 characters long +- Changed custom theme vector to a list of name value pairs to more easily add new theme colours + +#### Mobile + +- New push proxy server supports multiple apps (in preparation for the second generation mobile apps) +- New push proxy server is backwards compatible with the old iOS and Android apps +- Unread channels on the channel view are indicated with a red dot, and unread mentions with a red dot and mention count +- Added floating timestamp to mobile right hand side +- Send icon is disabled for messages and comments until a valid message is typed +- Removed redundant search hint popover and updated search buttons +- Removed "@"-symbol preceeding usernames and full names in push notifications + +#### Text Formatting + +- Added support for explicit image sizes in markdown +- Terms such as `_AAA_BBB_` now italicize correctly +- First backslash is now truncated when posting file paths that start with `\\` +- Markdown isn't rendered for system messages posted after renaming a channel +- Messages beginning with `[some_text]: some_text` now longer post as blank space +- Pipe characters (`|`) in a Markdown table now work + +#### Integrations + +- Added edit screens for incoming and outgoing webhooks +- When no username is set for a slash command response, the username of the person is now used instead of "webhook" +- Added a confirmation dialog to prevent accidentally deleting an integration + +#### Localization + +- System messages are now localized based on language set in the Account Settings + +#### Onboarding + +- Clicking on email verification link now automatically fills in your email address on the sign in page +- On login with GitLab SSO, Mattermost username and email are now synced with GitLab username and email + +#### Slack Import + +- Added support for Slack's Markdown-like post formatting +- Added support for topic & purpose system messages +- Channels imported from Slack with the same name as a deleted channel now import successfully +- Added support for users who don't have a non-empty email address in Slack + +#### System Console + +- Added active users statistics to Site Statistics page +- Focus is set to server log control in **System Console > Reporting > Logs** when loading the panel + +#### Enterprise Edition + +- Added WebSocket events, webhook events and cluster request time logging for Performance Monitoring +- Added new policy settings to **System Console > General > Policy** to + - restrict who can delete messages + - restrict whether messages can be edited and for how long + +### Bug Fixes + +- Fixed an error where a channel would no longer load after using a GitLab built-in Mattermost slash command `/project issue show <number>` +- Outdated results in modal searches are now properly discarded +- Fixed order of channels on the sidebar +- Fixed search highlighting for wildcard searches and hashtags +- Clicking "Send message" link in profile popover in a comment thread, now properly opens the direct message channel +- Fixed channels missing from "More Channels" modal after leaving them +- Fixed webhook messages not appearing in channels the creator wasn't in +- Angled brackets around mailto links now longer autolink +- Fixed an issue where "New messages below" bubble didn't disappear properly on mobile view +- Fixed CLI panic on `platform channel create` command if team does not exist +- Team invite link now directs user to a private team after account creation with LDAP +- `Create a New Team` menu option is now in the Main Menu for System Admins when team creation is disabled +- Fixed the response for malformed command execute request +- New message indicator no longer appears for ephemeral posts +- Fixed emoji aliases not showing up in autocomplete +- Mention badge now properly updates on the team sidebar when switching teams +- (at)-mention preceeded by a "#"-symbol now displays correctly +- Don't allow APIs to create user accounts that start with a number preventing them from signing in +- Using a mouse to choose an emoji from the autocomplete now works +- Fixed syntax highlighting on mobile +- Fixed inconsistent styling of file uploads between mobile and desktop +- Push notifications are no longer missing username when preferences set to "For all activity" +- Fixed a bug where the Go driver was using a wrong URL for `/users/claim/email_to_oauth` route + +### Compatibility + +#### Removed and deprecated features + + - Removed `ServiceSettings: "SegmentDeveloperKey"` setting in `config.json` + - Backwards compatibility with the old CLI tool will be removed in Mattermost v3.8 April/2017 release. See [documentation to learn more about the new CLI tool](https://docs.mattermost.com/administration/command-line-tools.html). + - Deprecated APIv3 routes to be removed in Mattermost v3.8 April/2017 release: + - `GET` at `/channels/more` (replaced by /`channels/more/{offset}/{limit}`) + - `POST` at `/channels/update_last_viewed_at` (replaced by `/channels/view`) + - `POST` at `/channels/set_last_viewed_at` (replaced by `/channels/view`) + - `POST` at `/users/status/set_active_channel` (replaced by `/channels/view`) + - All APIv3 endpoints to be removed six months after APIv4 goes stable (replaced by APIv4 endpoints).) + +For a list of past and upcoming deprecated features, see the [removed and deprecated features](https://docs.mattermost.com/about/deprecated-features.html) documentation for details. + +#### config.json + +Changes from v3.6 to v3.7: + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + + - Under `ServiceSettings` in `config.json`: + - Added `"TimeBetweenUserTypingUpdatesMilliseconds": 5000` to control how frequently the "user is typing..." messages are updated + - Added `"EnableUserTypingMessages": true` to control whether "user is typing..." messages are displayed below the message box + - Added `"EnableLinkPreviews": false` to control whether a preview of website content is displayed below the message + +**Additional Changes to Enterprise Edition**: + + - Under `ServiceSettings` in `config.json`: + - Added `"RestrictPostDelete": all` to set who can delete messages + - Added `"AllowEditPost": always` to set whether messages can be edited + - Added `"PostEditTimeLimit": 300` to set how long messages can be edited, if `"AllowEditPost": time_limit` is specified + - Added `"ClusterLogTimeoutMilliseconds": 2000` to control frequency of cluster request time logging for [performance monitoring](https://docs.mattermost.com/deployment/metrics.html) + +### Database Changes from v3.6 to v3.7 + +**Posts Table:** +- Added `EditAt` column + +### API Changes from v3.6 to v3.7 + +**New routes (APIv3):** +- `POST` at `/channels/create_group` + - Creates a new group message channel +- `POST` at `/hooks/incoming/update` + - Updates an incoming webhook +- `POST` at `/hooks/outgoing/update` + - Updates an outgoing webhook +- `GET` at `/teams/{team_id}/...` + - Returns a post list, based on the provided channel and post ID. +- `POST` at `/channels/{channel_id}/update_member_roles` + - Updates the user's roles in a channel + +### Websocket Event Changes from v3.6 to v3.7 + +**Added:** +- `channel_create` that occurs each time a channel is created +- `group_added` that occures when a new group message channel is created + +**Removed:** +- `view_channel` that occurred when a new message was received + +### Known Issues + +- Slack import doesn't add merged members/e-mail accounts to imported channels +- User can receive a video call from another browser tab while already on a call +- Sequential messages from the same user appear as separate posts on mobile view +- Edge overlays desktop notification sound with system notification sound +- Search autocomplete picker is broken on Android +- Jump link in search results does not always jump to display the expected post +- Running CLI without access to logs causes panic +- Switching channels with CTRL/CMD+K doesn't work properly when using the mouse +- Reacting to a deleted message in the right-hand sidebar throws an error +- Sometimes no email verification is sent to the new email address after changing your email in Account Settings. A workaround is to sign in with the new email address and hitting "Resend Email" on the "Email not verified" page +- Clicking "Load more messages" sometimes brings you to the bottom of the page +- Switching to a channel with unreads sometimes doesn't jump to the correct scrolling position + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [aautio](https://github.com/aautio), [akihikodaki](https://github.com/akihikodaki), [andreistanciu24](https://github.com/andreistanciu24), [asaadmahmood](https://github.com/asaadmahmood), [ayadav](https://github.com/ayadav), [AymaneKhouaji](https://github.com/AymaneKhouaji), [bjoernr-de](https://github.com/bjoernr-de), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [CrEaK](https://github.com/CrEaK), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [debanshuk](https://github.com/debanshuk), [enahum](https://github.com/enahum), [erikgui](https://github.com/erikgui), [favadi](https://github.com/favadi), [gig177](https://github.com/gig177), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jazzzz](https://github.com/jazzzz), [JeffSchering](https://github.com/JeffSchering), [joannekoong](https://github.com/joannekoong), [jostyee](https://github.com/jostyee), [jurgenhaas](https://github.com/jurgenhaas), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [khawerrind](https://github.com/khawerrind), [laur89](https://github.com/laur89), [lfbrock](https://github.com/lfbrock), [mikaoelitiana](https://github.com/mikaoelitiana), [morenoh149](https://github.com/morenoh149), [mpoornima](https://github.com/mpoornima), [pan-feng](https://github.com/pan-feng), [pepf](https://github.com/pepf), [Rudloff](https://github.com/Rudloff), [ruzette](https://github.com/ruzette), [saturninoabril](https://github.com/saturninoabril), [senk](https://github.com/senk), [Zaicon](https://github.com/Zaicon), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/api-reference + +- [debanshuk](https://github.com/debanshuk), [enahum](https://github.com/enahum), [jwilander](https://github.com/jwilander), [ruzette](https://github.com/ruzette), [Zaicon](https://github.com/Zaicon) + +/docs + +- [asaadmahmood](https://github.com/asaadmahmood), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [ilabdsf](https://github.com/ilabdsf), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jostyee](https://github.com/jostyee), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [matmorel](https://github.com/matmorel), [senk](https://github.com/senk), [vladimirprieto](https://github.com/vladimirprieto), [wget](https://github.com/wget) + +/mobile + +- [asaadmahmood](https://github.com/asaadmahmood), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock) + +/docker + +- [darkrasid](https://github.com/darkrasid), [nikosch86](https://github.com/nikosch86), [xcompass](https://github.com/xcompass) + +/desktop + +- [asaadmahmood](https://github.com/asaadmahmood), [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [yuya-oc](https://github.com/yuya-oc) + +/selenium + +- [coreyhulen](https://github.com/coreyhulen), [esethna](https://github.com/esethna), [lindalumitchell](https://github.com/lindalumitchell) + +/push-proxy + +- [coreyhulen](https://github.com/coreyhulen), [jostyee](https://github.com/jostyee), [it33](https://github.com/it33) + +/load-test + +- [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller) + +---- + +## Release v3.6.7 + +### Notes on Patch Release + + - **v3.6.7, released 2017-04-27** + - Fixed a number of low to moderate severity security issues, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Note: The **System Console > Configuration > [Site URL](https://docs.mattermost.com/administration/config-settings.html#site-url)** field is now mandatory. Set the Site URL in the System Console, or in the `gitlab.rb` file if you are using GitLab Mattermost. + - **v3.6.6, released 2017-04-13** + - Fixed a number of low to high severity security issues, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Fixed an issue where Direct Messages list didn't always properly update in the left-hand sidebar + - Upgraded MySQL driver for better performance + - **v3.6.5, released 2017-03-23** + - Fixed a high severity security issue, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - **v3.6.4, released 2017-03-16** + - Fixed an issue where some [System Console > Policy settings](https://docs.mattermost.com/administration/config-settings.html#policy) were incorrectly applied to Team Edition, breaking the System Console UI + - **v3.6.3, released 2017-03-16** + - Fixed a security issue, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - **v3.6.2, released 2017-01-31** + - Fixed a high severity security issue, and [upgrading](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://mattermost.com/security-updates/) 14 days after release as per the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Improved performance of web sockets and typing messages + - Note: Some deployments using multiple URLs to reach Mattermost via proxy forwarding are reporting issues with the security fix in 3.6.2. [The issue is being tracked in our ticketing system](https://mattermost.atlassian.net/browse/PLT-5635). + - **v3.6.1, released 2017-01-19** + - Fixed a performance regression when sending many notifications at once (for example, when `@all` or `@channel` is used in a channel with many users) + - Fixed an issue where the config flag for the CLI was not backwards compatible + - Fixed an upgrade issue where for some databases, the Team Description index was not created properly + - Fixed an issue with messages not showing up after computer wakes from sleep + - **v3.6.0, released 2017-01-16** + - Original 3.6 release. + +### Security Update + +- Mattermost v3.6.0 contains a [security update](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.6.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Thanks to Julien Ahrens for contributing the security report through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Team Sidebar +- Added a new sidebar on left-hand side to improve cross-team notifications and team switching +- New sidebar improves user experience on the [Mattermost Desktop Apps](https://mattermost.com/apps) when engaging with multiple teams + +#### MFA Enforcement ([Enterprise E10 & E20](https://mattermost.com/pricing/)) +- Added support for MFA Enforcement. When set to true, all users with email or LDAP authentication are required to set up MFA for their accounts + +#### Performance Monitoring ([Enterprise E20](https://mattermost.com/pricing/)) +- Added support for performance monitoring in large-scale deployments to help optimize systems for maximum performance using integrations with [Prometheus](https://github.com/prometheus/prometheus) and [Grafana](https://grafana.com/) +- Includes metrics for caching, database connections, processing, logins and messaging. See [documentation to learn more](https://docs.mattermost.com/scale/performance-monitoring.html) + +#### Improved Command Line Interface +- New version of CLI with a more intuitive interface, interactive help documentation, and some added functionality. See [documentation to learn more](https://docs.mattermost.com/administration/command-line-tools.html) + +### Improvements + +#### Performance +- Added server-based channel autocomplete, search and paging +- Reduced lag on channel switcher (CTRL/CMD+K) and at-mention autocomplete +- Improved on-boarding performance by removing new user event handling on the client +- Improved channel switching performance by combining API events and only pulling user statuses the client doesn't yet have +- Added session cache directly to web connections +- Added caching for files, user profiles and for the last 60 posts in a channel +- Added ETag for user profile pictures and modified ETag for posts to improve caching validation +- Added caching to post and channel calls +- Fixed channel cache not being sent to a cluster +- Added a configuration setting to disable intensive System Console statistics queries for maximum performance ([Enterprise E10 & E20 only](https://mattermost.com/pricing/)) + +#### Notifications +- Desktop notifications no longer appear for the channel you are actively viewing +- Push and email notifications now follow the setting for Teammate Name Display +- Notifications for @mentions of your username can no longer be turned off + +#### Account Settings +- Added a "Position" field, where users can add a job title to be shown in their profile popover + +#### Team Settings +- Team description can be set by a Team Admin and is visible to all users on the join teams screen and in the tool tip over the team name +- Slack Import can now import integration messages + +#### Slash Commands +- Existing slash commands can now be edited by the creator or by Team and System Admins +- Slash commands now work on the right-hand sidebar +- Added support for slash commands to set the username and icon directly from the reply payload + +#### Channels +- System message is now posted for all users when a channel or group is renamed +- Any channel member can now remove other users from the channel + +#### Messaging +- Added support for non-alphanumeric unicode characters in hashtags +- Custom Emojis larger than 64kB can now be uploaded and they will be appropriately resized + +#### User Interface +- Added a direct message link to the profile popover +- Added an indicator to convey a new message is received when scrolled up in the center pane +- Removed status indicators on posts by webhooks +- Channel switcher (CTRL/CMD+K) search results for direct messages now match message autocomplete +- Autocomplete is now case insensitive for @-mentions, emojis, slash commands and channel linking + +#### Enterprise Edition +- Split out channel management permissions into separate settings for creation, deletion, and renaming a channel +- Ability to set the maximum number of users in a channel that will disable @all and @channel notifications +- Added ability to set a user's Position field with LDAP sync or SAML +- New option to purge all in-memory caches for sessions, accounts and channels + +### Bug Fixes +- Integrations that post to Direct Message channels now mark the channel as Unread +- @mention autocomplete will now filter on Chinese, Japanese, Korean names +- Text focus is now set on the text input area after channel creation +- Editing old posts no longer causes them to repost for other members of the channel +- Email invitation subject line no longer displays HTML characters in place of apostrophes in the team name +- Current user is no longer displayed in the direct messages modal +- Searching on direct messages modal now happens on typing rather than after hitting ENTER +- More Channels modal now resets search when opening and closing the dialog +- Channel switcher (CTRL/CMD+K) now works for direct message channels of users outside the team +- Using the command line to invite users no longer sends an invalid join team link +- Sleeping and waking your computer while logged into Mattermost no longer causes a console error +- Searching for users in double in quotes in the direct message modal no longer throws an error +- XML file preview no longer throws a JavaScript error +- User autocomplete in message box no longer matches against email +- Channel linking (with ~ shortcut) now works for channels you don't belong to +- Fixed statistics for websockets and database connections in **System Console** > **Site Statistics** to work in [High Availability mode](https://docs.mattermost.com/deployment/cluster.html) +- Slash commands now work in newly created private channels without requiring a refresh +- Zapier app channel dropdown selector works again +- Fixed sign in errors for non-admin accounts when custom emojis are restricted to Team and System Admins +- Fixed encoding of file names when downloading attachments +- Unflagging or flagging a post in the right-hand sidebar no longer forces a scroll to the top of the flagged posts list +- User list in **System Console > Teams** is no longer blank on first load +- Fixed a bug where sometimes the right-hand sidebar would not display properly when switching to view another channel + +### Compatibility +Changes from v3.5 to v3.6: + +**Special Upgrade Note:** +(Enterprise Edition) If you previously had values set for `RestrictPublicChannelManagement` and `RestrictPrivateChannelManagement`, the new settings for `RestrictPublicChannelCreation`, `RestrictPrivateChannelCreation`, `RestrictPublicChannelDeletion`, and `RestrictPrivateChannelDeletion` will take those settings as their default values. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + +Deprecated Settings: + + - Under `ServiceSettings` in `config.json`: + - `"SegmentDeveloperKey"` to be removed in v3.7 + +**Additional Changes to Enterprise Edition**: + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + +- Under `ServiceSettings` in `config.json`: + - Added `”EnforceMultifactorAuthentication": false` to control whether MFA in enforced +- Under `TeamSettings` in `config.json`: + - Changed `"RestrictPublicChannelManagement": "all"` to only control who can edit the channel header, purpose, and name of public channels (previously it also controlled creation and deletion) + - Changed `"RestrictPrivateChannelManagement": "all"` to only control who can edit the channel header, purpose, and name of private groups (previously it also controlled creation and deletion) + - Added `"RestrictPublicChannelCreation": "all"` to control who can create public channels + - Added `"RestrictPrivateChannelCreation": "all"` to control who can create private groups + - Added `"RestrictPublicChannelDeletion”: "all"` to control who can delete public channels + - Added `"RestrictPrivateChannelDeletion": "all"` to control who can delete private channels + - Added `"MaxNotificationsPerChannel": 1000` to set the maximum number of channel members for which `@all` and `@channel` notifications will be sent +- Under `LdapSettings` in `config.json`: + - Added `"PositionAttribute": ""` to select an LDAP attribute to synchronize for the user position (job title) field +- Under `SamlSettings` in `config.json`: + - Added `"PositionAttribute": ""` to select an LDAP attribute to synchronize for the user position (job title) field +- Added `MetricsSettings` in `config.json` for performance monitoring settings: + - Added `"Enable": false` to control whether performance monitoring is enabled + - Added `"BlockProfileRate": 0` to control the [fraction of goroutine blocking events that are reported in the blocking profile](https://pkg.go.dev/runtime#SetBlockProfileRate) + - Added `"ListenAddress": :8067` to control the address the server will listen on to expose performance metrics +- Added `AnalyticsSettings` in `config.json` for analytics settings: + - Added `"MaxUsersForStatistics": 2500` to set the maximum number of users on the server before statistics for total posts, total hashtag posts, total file posts, posts per day, and active users with posts per day are no longer counted (use this setting to improve performance on large instances) + +### Database Changes from v3.5 to v3.6 + +**Posts Table:** +- Added `HasReactions` column + +**Teams Table:** +- Added `Description` column + +**Users Table:** +- Added `Position` column + +**Status Table:** +- Removed `ActiveChannel` column + +### API Changes from v3.5 to v3.6 + +**New routes:** +- Added `POST` at `/commands/update` + - Updates a slash command +- Added `GET` at `/users/name/{username}` + - Returns a user matching the given username +- Added `GET` at `/users/email/{email}` + - Returns a user matching the given email +- Added `GET` at `/users/autocomplete` + - Returns a list of users on the system that have a username, full name, or nickname that match against the provided term +- Added `GET` at `/teams/name/{team_name}` + - Returns team object for a given team name +- Added `GET` at `/teams/{team_id}/channels/name/{channel_name}` + - Returns a channel for a given channel name +- Added `POST` at `/teams/{team_id}/channels/{channel_id}/members/ids` + - Returns channel member objects for the channel and user IDs specified +- Added `GET` at `/teams/members` + - Returns an array with the teams the current user belongs to +- Added `GET` at `/teams/unread` + - Returns an array containing the amount of unread messages and mentions for the teams the current user belongs to +- Added `POST` at `/teams/{team_id}/channels/view` + - Performs all actions related to viewing a channel, including marking channels as read, clearing push notifications, and updating the active channel +- Added `POST` at `/teams/{team_id}/channels/{channel_id}/posts/{post_id}/reactions/save` + - Saves an emoji reaction for a post, returns the saved reaction if successful +- Added `POST` at `/teams/{team_id}/channels/{channel_id}/posts/{post_id}/reactions/delete` + - Removes an emoji reaction for a post in the given channel, returns nil if successful +- Added `GET` at `/teams/{team_id}/channels/{channel_id}/posts/{post_id}/reactions'` + - Returns a list of all emoji reactions for a post +- Added `GET` at `/admin/invalidate_all_caches` + - Purge all the in-memory caches for things like sessions, accounts, channels; deployments using High Availability will attempt to purge all the servers in the cluster (this may adversely impact performance) +- Added `GET` at `/channels/more/{offset}/{limit}` + - Returns a page of public channels the user is not in based on the provided offset and limit +- Added `POST` at `/channels/more/search` + - Returns a list of public channels the user is not in that match the search criteria +- Added `GET` at `/channels/autocomplete` + - Returns a list of public channels that match the provided string + +**Deprecated routes:** +- `GET` at `/channels/more` (replaced by /`channels/more/{offset}/{limit}`) to be removed in v3.7 +- `POST` at `/channels/update_last_viewed_at` (replaced by `/channels/view`) to be removed in v3.8 +- `POST` at `/channels/set_last_viewed_at` (replaced by `/channels/view`) to be removed in v3.8 +- `POST` at `/users/status/set_active_channel` (replaced by `/channels/view`) to be removed in v3.8 + +**Removed routes:** +- `POST` at `/teams/create_from_signup` +- `POST` at `/teams/signup` + +**Changed routes:** + - Updated `teams/{team_id}/commands/execute` endpoint request body field from `channelId` to `channel_id` + +### Websocket Event Changes from v3.5 to v3.6 + +**Added:** +- `update_team` that occurs each time the team info is updated +- `reaction_added` that occurs when an emoji reaction is added to a post +- `reaction_removed` that occurs when an emoji reaction is removed from a post + +### Known Issues + +- Slack Import doesn't add merged members/e-mail accounts to imported channels +- User can receive a video call from another browser tab while already on a call +- Video calls do not work with Chrome v56 and later +- Sequential messages from the same user appear as separate posts on mobile view +- Edge overlays desktop notification sound with system notification sound +- Deleting a message from a permalink view doesn't show delete until refresh +- Search autocomplete picker is broken on Android + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [asaadmahmood](https://github.com/asaadmahmood), [bjoernr-de](https://github.com/bjoernr-de), [bolecki](https://github.com/bolecki), [brendanbowidas](https://github.com/brendanbowidas), [CometKim](https://github.com/CometKim), [coreyhulen](https://github.com/coreyhulen), [cpanato](https://github.com/cpanato), [crspeller](https://github.com/crspeller), [debanshuk](https://github.com/debanshuk), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [fraziern](https://github.com/fraziern), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [khawerrind](https://github.com/khawerrind), [lfbrock](https://github.com/lfbrock), [maruTA-bis](https://github.com/maruTA-bis), [pepf](https://github.com/pepf), [raphael0202](https://github.com/raphael0202), [Rudloff](https://github.com/Rudloff), [Yangchen1](https://github.com/Yangchen1), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/docs + +- [aureliojargas](https://github.com/aureliojargas), [axilleas](https://github.com/axilleas), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [nils-werner](https://github.com/nils-werner), [okin](https://github.com/okin), [quentinus95](https://github.com/quentinus95), [qyra](https://github.com/qyra), [shieldsjared](https://github.com/shieldsjared), [tejasbubane](https://github.com/tejasbubane), [Tethik](https://github.com/Tethik), [yangchen1](https://github.com/yangchen1), [yumenohosi](https://github.com/yumenohosi), [yuya-oc](https://github.com/yuya-oc), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/mattermost-docker-preview + +- [cpanato](https://github.com/cpanato), [hyeseongkim](https://github.com/hyeseongkim), [jasonblais](https://github.com/jasonblais), [mattermost-build](https://github.com/mattermost-build) + +/desktop + +- [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [yuya-oc](https://github.com/yuya-oc) + +/mattermost-mobile + +- [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [thomchop](https://github.com/thomchop) + +/mattermost-load-test + +- [crspeller](https://github.com/crspeller), [it33](https://github.com/it33) + +/mattermost-driver-javascript + +- [Mattermost-build](https://github.com/Mattermost-build) + +/android + +- [CometKim](https://github.com/CometKim), [coreyhulen](https://github.com/coreyhulen), [DavidLu1997](https://github.com/DavidLu1997), [dmeza](https://github.com/dmeza), [esethna](https://github.com/esethna) + +/mattermost-webrtc + +- [enahum](https://github.com/enahum) + +/mattermost-api-reference + +- [CometKim](https://github.com/CometKim), [cpanato](https://github.com/cpanato), [enahum](https://github.com/enahum), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander), [MartinDelille](https://github.com/MartinDelille), [trarbr](https://github.com/trarbr), [ZJvandeWeg](https://github.com/ZJvandeWeg) + +/mattermost-docker + +- [Andrey9kin](https://github.com/Andrey9kin), [esethna](https://github.com/esethna), [jasonblais](https://github.com/jasonblais) + +/ios + +- [esethna](https://github.com/esethna) + +/mattermost-push-proxy + +- [coreyhulen](https://github.com/coreyhulen) + +Thanks also to those who reported bugs that benefited the release, in alphabetical order: + + - [bjoernr-de](https://github.com/bjoernr-de) ([#5079](https://github.com/mattermost//mattermost-server/issues/5079)), [S6066](https://github.com/S6066) ([#5011](https://github.com/mattermost//mattermost-server/issues/5011)) + +---- + +## Release v3.5.1 + +### Notes on Patch Release + + - **v3.5.1, released 2016-11-23** + - Security update to preventing cross-site scripting and remote code execution, thanks to Harrison Healey for [reporting responsibly](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + - Fixed an issue where usernames would sometimes not appear beside posts and the reply arrow would throw an error. + - The channel purpose is no longer cut off in the user interface of the **More...** channel menu. + - Fixed a scroll issue where the center channel didn't always scroll to the bottom when switching channels. + - Fixed a server error that occurred when searching for users using an asterisk. + - Fixed an issue where direct message channel headers would sometimes disappear. + - "New Messages" indicator is fixed so it no longer remains visible after switching channels. + - Fixed an issue where users could not join a public channel by navigating to the channel URL. + - Email and push notifications are made asynchronous to fix a delay sending messages when HPNS was enabled. + - Autocomplete timeout is decreased to make autocomplete more responsive to quick typing. + - **v3.5.0, released 2016-11-16** + - Original 3.5 release. + +### Security Update + +- Mattermost v3.5.1 contains multiple [security updates](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.5.1](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. Thanks to Alyssa Milburn and Harrison Healey for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Languages +- Added Russian translations for the user interface. +- Promoted Chinese (both simplified and traditional), German, French and Japanese to release-quality translations, removing beta tags. + +#### Performance improvements for mobile and web experience + + - Ability to download assets in parallel via HTTP2 support. + - Reduced CPU bottlenecks and optimized SQL queries. + - Reduced load times through paging controls, server-side search and on-the-fly data loading that requests data as the client needs it. + - Added paging APIs for profiles, channels and user lists. + - Added client-scaling for auto-complete and status indicators. + - Added server-side in-memory caching to reduce DB reads/writes. + +#### Connection Security +- TLS is now supported directly on the Mattermost server. Learn more in our [documentation](https://docs.mattermost.com/deploy/server/setup-tls.html). +- Support for automatically fetching certificates through Let's Encrypt. + +#### Minio File Storage +- Minio fully manages S3 API requests with automatic bucket location management across S3 regions. + +#### Favorite Channels +- Added the ability to select Favorite Channels that appear at the top of the channels sidebar. + +#### Video and Audio Calling (early-preview) +- Added early preview of video and audio calling option using self-hosted proxy. +- Intended as working prototype for community development, not recommended for production. +- Early preview does not include logging or detailed documentation. + +#### Improved Slack Import +- Added the ability to import files from Slack (CLI command also supported). +- Added the ability to import bot/integration messages, Join/Leave messages, and /me messages. +- Duplicate users are now merged. +- Channel topics, purpose, and users now import correctly. +- Channel links now import correctly. + +### Improvements + +#### iOS Apps +- Channel settings, account settings, and channel header now render as full screen modals for better visibility +- [...] menu options now displayed larger for better usability +- Keyboard doesn't automatically close when sending a message, letting you quickly send several messages in succession +- When the "Download" link is clicked on files, a "Back" button lets users get back to the app + +#### Android Apps +- Channel settings, account settings, and channel header now render as full screen modals for better visibility +- [...] menu options now displayed larger for better usability +- Disabled screen rotation +- Fixed where clicking on download button for a file attachment did nothing +- Keyboard doesn't automatically close when sending a message, letting you quickly send several messages in succession + +#### User Interface +- Text (.txt) files now show a preview in the image previewer +- Status indicators are now visible in compact view +- Clicking on a profile picture in center channel or right hand sidebar brings up profile popover +- The "@" and flag icons next to search bar now toggles results +- [...] menu no longer displayed for system messages +- Browser tab name now changes when switching to System Console or Integrations pages +- A loading icon now shows on the team selection page +- On mobile devices, the keyboard now stays open after sending a message to make sending multiple messages easier + +#### Notifications +- Notification sound settings are now honored on the [Mattermost Desktop Apps](https://mattermost.com/apps/) +- Push notifications can now be received on more than one device + +#### Channel Shortlinking +- Channels can be shortlinked using the ~ character. +- Auto-complete works with both the channel handle and name + +#### Integrations +- If a webhook is sent to a direct message channel that has not been created yet, the channel is now automatically created + +#### Keyboard Shortcuts +- CTRL/CMD+SHIFT+M now toggles recent mentions results + +#### Team Settings +- Team names are now restricted to be a minimum of two characters long, instead of four, to support abbreviated team names + +#### System Console +- Maximum number of channels per team is now configurable + +#### Enterprise Edition: +- Made the MFA secret key visible, so it's possible to set up Google Authenticator without scanning the QR code + +### Bug Fixes +- Files can now be sent in Direct Messages across teams +- Correct login method now shown in System Console user lists +- Channel switcher (CTRL/CMD+K) no longer throws an error when switching to a user outside of your current team +- Channel switcher (CTRL/CMD+K) now works for creating new Direct Message channels +- Channels on the left hand side now sort numerically, alphabetically, and based on locale +- Fixed incorrect error message when trying a team URL with one character +- `/join` no longer throws an error for non-admin accounts +- Added System Message when user joins Off-Topic channel +- Added the "View Members" option to the channel menu on mobile +- Send button is now visible on tablet sized screens + +### Compatibility +Changes from v3.4 to v3.5: + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `ServiceSettings` in `config.json`: + - Removed `"RestrictTeamNames": true` that controlled whether newly created team names were restricted. + - Added `"ConnectionSecurity": ""` to select the type of encryption between Mattermost and your server. + - Added `"TLSCertFile": ""` to specify the certificate file to use. + - Added `"TLSKeyFile": ""` to specify the private key to use. + - Added `"UseLetsEncrypt": false` to enable automatic retreval of certificates from the Let's Encrypt. + - Added `"LetsEncryptCertificateCacheFile": "./config/letsencrypt.cache"` to specify the file to store certificates retrieved and other data about the Let's Encrypt service. + - Added `"Forward80To443": false` to enable forwarding of all insecure traffic from port 80 to secure port 443. + - Added `"ReadTimeout": 300` to specify the maximum time allowed from when the connection is accepted to when the request body is fully read. + - Added `"WriteTimeout": 300` to specify the maximum time allowed from the end of reading the request headers until the response is written. +- Under `FileSettings` in `config.json`: + - Addded `AmazonS3SSL": true` to allow insecure connections to Amazon S3. +- Under `RateLimitSettings` in `config.json`: + - Changed: `"Enable": false` to disable rate limiting by default + - Added `"MaxBurst": 100` to set the maximum number of requests allowed beyond the per second query limit +- Under `TeamSettings` in `config.json`: + - Added `"MaxChannelsPerTeam": 2000` to set the maximum number of channels per team +- Under `WebrtcSettings` in `config.json` + - Added `"Enable": false` to enable one-on-one video calls. + - Added `"GatewayWebsocketUrl": ""` to specify the websocket used to signal and establish communication between the peers. + - Added `"GatewayAdminUrl": ""` to specify the URl to obtain valid tokens for each peer to establish the connection. + - Added `"GatewayAdminSecret": ""` to specify your admin secret password to access the Gateway Admin URL. + - Added `"StunURI": ""` to specify your STUN URI. + - Added `"TurnURI": ""` to specify your TURN URI. + - Added `"TurnUsername": ""` to specify your TURN username + - Added `"TurnSharedKey": ""` to specify your TURN server shared key to created dynamic passwords to establish the connection. + +### Database Changes from v3.4 to v3.5 + +**FileInfo Table** + +- Added `FileInfo` table + +**Posts Table** + +- Added `FileIds` column +- Added indexes for `DeleteAt` + +**Channels Table**, **Commands Table**, **Emoji Table**, **Teams Table**, **IncomingWebhooks Table**, **OutgoingWebhooks Table** + +- Added indexes for `CreateAt` +- Added indexes for `UpdateAt` +- Added indexes for `DeleteAt` + +**TeamMembers Table** + +- Added indexes for `DeleteAt` + +**Sessions Table** + +- Added indexes for `ExpiresAt` +- Added indexes for `CreateAt` +- Added indexes for `Last ActivityAt` + +**Users Table** + +- Added indexes for `CreateAt` +- Added indexes for `UpdateAt` +- Added indexes for `DeleteAt` +- Added full text indexes for `idx_users_all_txt`: Username, FirstName, LastName, Nickname, Email +- Added full text indexes for `idx_users_names_txt`:Username, FirstName, LastName, Nickname + +### API Changes from v3.4 to v3.5 + +**New routes:** + +- Added `POST` at `/users/search` + - Search for user profiles based on username, full name and optionally team id. +- Added `GET` at `/users/{offset}/{limit}` + - Retrieves a page of system-wide users +- Added `POST` at `/teams/{team_id}/update_member_roles` + - Update a user's roles for the specified team. +- Added `GET` at `/teams/{team_id}/channels/{channel_id}/members/{user_id}` + - Retrieves the channel member for the specified user. Useful for fetching the channel member after updates are made to it. If the channel member does not exist, then return an error. +- Added `GET` at `/teams/{team_id}/stats` + - Returns stats for teams which includes total user count and total active user count. +- Added `GET` at `/teams/{team_id}/members/{offset}/{limit}` + - To page through team members +- Added `POST` at `/teams/{team_id}/members/ids` + - Retrieves a list of team members based on user ids +- Added `GET` at `/teams/{team_id}/members/{user_id}` + - Retrieves a single team member +- Added `GET` at `/teams/{team_id}/posts/{post_id}/get_file_infos` + - Retrieves file attachment info for a post +- Added `GET` at `/channels/{channel_id}/users/{offset}/{limit}` + - Retrieves profiles for users in the channel +- Added `GET` at `/channels/{channel_id}/users/not_in_channel/{offset}/{limit}` + - Retrieves profiles for users not in the channel +- Added `POST` at `/webrtc/token` + - Retrieves a valid token and servers to establish a webrtc connection between the peers + +**Moved routes:** + +- Updated `GET` at `/channels/{channel_id}/extra_info` to `/channels/{channel_id}/stats` + - No longer returns a list of channel members and only returns the member count +- Updated `POST` at `/users/profiles/{team_id}` to `/teams/{team_id}/users/{offset}/{limit}` + - Functionally performs the same, just moves it to match our other APIs that need a team ID. +- Updated `GET` at `/members/{team_id}` to `/teams/{team_id}/members/{offset}/{limit}` + - Allows paging through team members + +**Removed routes:** + +- Removed `GET` at `/users/direct_profiles` +- Removed `GET` at `/users/profiles_for_dm_list/{team_id}/{offset}/{limit}` + +**Modified Routes** + +- Added `POST` at `/users/{user_id}/update_roles` + - Only allows updating of system wide roles. If you want to update team wide roles, please use the new route `/teams/{team_id}/update_member_roles` + +**Changes to File Routes:** + +Routes used to get files and their metadata from the server have been changed substantially in 3.5 so that each file will be given a unique identifier to make them easier to use through the API. In addition, the `Filenames` field of each post has been deprecated in favor of the new `FileIds` field. + +- The response type of `GET` at `/teams/{team_id}/files/upload` has been changed to return more information about the uploaded file. See [the documentation for this route on api.mattermost.com](https://api.mattermost.com/#tag/files%2Fpaths%2F~1teams~1%7Bteam_id%7D~1files~1upload%2Fpost) for more information +- Split `GET` at `/teams/{team_id}/files/get/{channel_id}/{user_id}/{filename}` into: + - `GET` at `/files/{file_id}/get` + - Get a file + - `GET` at `/files/{file_id}/get_thumbnail` + - Get a small thumbnail for image files + - `GET` at `/files/{file_id}/get_preview` + - Get a medium-sized preview image for image files +- Updated `GET` at `/teams/{team_id}/files/get_info/{channel_id}/{user_id}/{filename}` to `/files/{file_id}/get_info` +- Updated `GET` at `/teams/{team_id}/files/get_public_link` to `/files/{file_id}/get_public_link` +- Added `GET` at `/public/files/{file_id}/get` + - Get a file without logging in + - The previous route `GET` at `/public/files/get/{team_id}/{channel_id}/{user_id}/filename` has been deprecated, but will remain available for files that were uploaded prior to 3.5 + +### Known Issues + +- Channel autolinking with `~` only works if you are a member of the channel +- Slack Import doesn't add merged members/e-mail accounts to imported channels +- User can receive a video call from another browser tab while already on a call +- Video calls do not work with Chrome v56 and later +- Sequential messages from the same user appear as separate posts on mobile view +- Slash commands do not work in newly created private channels until a hard refresh +- Edge overlays desktop notification sound with system notification sound +- Pressing escape to close autocomplete clears the textbox on IE11 +- Channel switcher doesn't work for users outside of your current team +- Deleting a messages from a permalink view doesn't show delete until refresh +- Channel dropdown selector no longer works in the Zapier App but the Channel ID can still be entered manually +- Search autocomplete picker is broken on Android +- Channel push notification preferences do not work for the inactive teams if you have multiple teams on a single server. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [alsma](https://github.com/alsma), [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [digitaltoad](https://github.com/digitaltoad), [dmeza](https://github.com/dmeza), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [grundleborg](https://github.com/grundleborg), [harshavardhana](https://github.com/harshavardhana), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lfbrock](https://github.com/lfbrock), [npcode](https://github.com/npcode), [R-Wang97](https://github.com/R-Wang97), [Rudloff](https://github.com/Rudloff), [S4KH](https://github.com/S4KH), [shieldsjared](https://github.com/shieldsjared), [thomchop](https://github.com/thomchop), [usmanarif](https://github.com/usmanarif), [wget](https://github.com/wget), [yangchen1](https://github.com/yangchen1) + +/ios + +- [coreyhulen](https://github.com/coreyhulen), [lfbrock](https://github.com/lfbrock), [thomchop](https://github.com/thomchop) + +/desktop + +- [asaadmahmood](https://github.com/asaadmahmood), [itsmartin](https://github.com/itsmartin), [jasonblais](https://github.com/jasonblais), [jcomack](https://github.com/jcomack), [jnugh](https://github.com/jnugh), [magicmonty](https://github.com/magicmonty), [Razzeee](https://github.com/Razzeee), [yuya-oc](https://github.com/yuya-oc) + +/docs + +- [asaadmahmood](https://github.com/asaadmahmood), [chikei](https://github.com/chikei), [crspeller](https://github.com/crspeller), [erikthered](https://github.com/erikthered), [esethna](https://github.com/esethna), [gabx](https://github.com/gabx), [gmorel](https://github.com/gmorel), [grundleborg](https://github.com/grundleborg), [hannaparks](https://github.com/hannaparks), [harshavardhana](https://github.com/harshavardhana), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [JeffSchering](https://github.com/JeffSchering), [kunthar](https://github.com/kunthar), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [npcode](https://github.com/npcode), [reach3r](https://github.com/reach3r), [Rudloff](https://github.com/Rudloff), [rwillmer](https://github.com/rwillmer), [shieldsjared](https://github.com/shieldsjared), [StraylightSky](https://github.com/StraylightSky), [thiyagaraj](https://github.com/thiyagaraj), [yangchen1](https://github.com/yangchen1), [yumenohosi](https://github.com/yumenohosi), [yuya-oc](https://github.com/yuya-oc), [Zhouzi](https://github.com/Zhouzi) + +/mattermost-docker + +- [5ak3t](https://github.com/5ak3t), [npcode](https://github.com/npcode), [rothgar](https://github.com/rothgar) + +/android + +- [coreyhulen](https://github.com/coreyhulen), [DavidLu1997](https://github.com/DavidLu1997), [dmeza](https://github.com/dmeza), [it33](https://github.com/it33), [mattchue](https://github.com/mattchue) + +/mattermost-bot-sample-golang + +- [hmhealey](https://github.com/hmhealey), [pneisen](https://github.com/pneisen) + +/mattermost-load-test + +- [athingisathing](https://github.com/athingisathing), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [csduarte](https://github.com/csduarte), [enahum](https://github.com/enahum), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais) + +/mattermost-driver-javascript + +- [crspeller](https://github.com/crspeller) + +/mattermost-api-reference + +- [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [hmhealey](https://github.com/hmhealey), [jwilander](https://github.com/jwilander) + +/mattermost-mobile + +- [dmeza](https://github.com/dmeza), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [mfpiccolo](https://github.com/mfpiccolo), [thomchop](https://github.com/thomchop) + +---- + +## Release v3.4.0 + +Release date: 2016-09-16 + +### Highlights + +#### Zapier Integration +- Integrate over [700 public cloud applications](https://zapier.com/apps) using [Zapier](https://zapier.com), with full support for Markdown formatting. To start, [click here to accept an invitation to Zapier](https://zapier.com/partner/iframe/login?next=%2Fdeveloper%2Fpublic-invite%2F152128%2F3a3df937fd2e873dd65f4c365d17251c%2F&%3Btype=login&type=login), then [follow the setup guide](https://docs.mattermost.com/integrations/zapier.html). + +#### OAuth 2.0 Service Provider +- Users with an account on a Mattermost server can securely sign in to third-party applications with an OAuth 2.0 protocol. See [documentation](https://docs.mattermost.com/configure/integrations-configuration-settings.html#integrate-enableoauthserviceprovider) to learn more. + +#### Improved Notifications and Status Indicators +- Users can now control how often email notifications are sent +- Users can now control whether push notifications are sent when they are online, offline or away +- Users can now set the display duration of a desktop notification +- Email notifications now include channel names +- Android push notifications are now cleared after the message is read somewhere else +- /away, /online, /offline can now be used to manually set your status +- Status indicators are now shown on the profile pictures in the centre channel and right hand side + +### Improvements + +#### Files and Images +- PDFs now show a preview in the image previewer on browsers, desktop apps, and mobile apps + +#### Integrations +- After an integration is created, a confirmation screen now displays the relevant token, webhook URL or OAuth client secret + +#### System Console +- Added connection security option `PLAIN` for SMTP +- Salt settings in the config.json now ship blank and are autogenerated after install +- Added [Error and Diagnostics Reporting option](https://docs.mattermost.com/administration/config-settings.html#enable-diagnostics-and-error-reporting) to help Mattermost, Inc. improve reliability and performance for your deployment configuration. + +#### Slack Import +- Slack import now imports @mentions mapped to user names + +#### User Interface +- Improved design of signup pages when multiple account creation methods are enabled +- User profile popover now shows both username and full name (if available) +- @mention autocomplete now groups users according to who is in the channel +- Channel URL no longer updates when the Channel Name changes +- Markdown headings are now rendered in Compact View +- A System Message now posts when new users join Town Square + +#### Enterprise Edition: +- Added a CLI tool for creating channels +- Added a display option to hide join/leave messages from view (user added and user removed messages still appear) +- System Admins can now test their LDAP connection using a “Test Connection” button +- FirstName and LastName fields are now optional for LDAP and SAML + +### Bug Fixes +- Old public links are now invalidated when the salt is regenerated. +- Messages can now be flagged from the search results list +- Count of unread mentions are no longer mixed when switching between multiple teams. +- Recent Mentions search on mobile no longer contains `@all` +- For those using the mobile view on desktop, CTRL+ENTER now sends messages on mobile web view +- User removed from team now shows up in DM list under "Outside this team" +- Mentions update properly when team is switched + +### Compatibility +Changes from v3.3 to v3.4: + +**Special Note** + +(Only affects servers with public links enabled) After upgrading to v3.4, existing public links will no longer be valid. This is because in past versions, when the Public Link Salt was regenerated existing public links were not invalidated. Now, when the salt is regenerated, existing links are made invalid. + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + + - Under `EmailSettings` in `config.json`: + - Added `"EnableEmailBatching": false` to enable batching of email notifications configurable in Account Settings. To enable email batching, the `SiteURL` field must be filled out and `Enable` under `ClusterSettings` must be set to `false` to disable high availability mode. + - Added `"EmailBatchingBufferSize": 256` to specify the maximum number of notifications batched into a single email. + - Added `"EmailBatchingInterval": 30` to specify the maximum frequency, in seconds, which the batching job checks for new notifications. + + - Under `LogSettings` in `config.json`: + - Added `"EnableDiagnostics": true` to increase reliability and performance of Mattermost for your deployment configuration by sending encrypted [error reporting and diagnostic information](https://docs.mattermost.com/administration/config-settings.html#enable-diagnostics-and-error-reporting) to Mattermost, Inc. + +**Additional Changes to Enterprise Edition:** + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + +- Under `LdapSettings` in `config.json`: + - `"FirstNameAttribute": ""` is no longer a required field + - `"LastNameAttribute": ""` is no longer a required field +- Under `SamlSettings` in `config.json`: + - `"FirstNameAttribute": ""` is no longer a required field + - `"LastNameAttribute": ""` is no longer a required field + +### Database Changes from v3.3 to v3.4 + +**Status Table** + + - Added `Manual` column. + - Added `ActiveChannel` column. + +### API Changes from v3.3 to v3.4 + +**New routes:** + - Added `GET` at `/oauth/authorized` + - Returns the OAuth2 Apps authorized by the user. On success it returns a list of sanitized OAuth2 Authorized Apps by the user. + - Added `POST` at `/oauth/"+clientId+"/deauthorize` + - Deauthorizes a user on an OAuth 2.0 app, where `clientId` corresponds to the application. Returns status OK on success or an AppError on fail. + - Added `POST` at `/oauth/"+clientId+"/regen_secret` + - Generates a new OAuth App Client Secret, where `clientId` corresponds to the application. Returns an OAuth2 App on success. Must be authenticated as a user and the same user who registered the app or a System Admin. + - Added `POST` at `/admin/ldap_test` + - Will run a connection test on the current LDAP settings. It will return the standard OK response if settings work. Otherwise it will return an appropriate error. + - Added `POST` at `/users/status/set_active_channel` + - Sets the Status.ActiveChannel field which is used to tell if the user is actively viewing a channel or not. + - Added `GET` at `/admin/recently_active_users/{teamId}` + - Returns a list of recent active users. + +### Known Issues + +- Upgrading from 3.2 to 3.4 will be incomplete due to a migration code not being run properly. You can either: + - Upgrade from 3.2 to 3.3 and then from 3.3 to 3.4, or + - Upgrade from 3.2 to 3.4, then run the following SQL query to make Mattermost rerun upgrade steps that were not properly completed: `UPDATE Systems SET Value = '3.1.0' WHERE Name = 'Version';` +- Deleted messages don't disappear from the channel for the user who deleted the message, if the message was previously edited and right hand sidebar is open. +- A single collapsed link or image preview re-opens after refresh. +- Files sent in private chat to members in a different team are not accessible. +- YouTube video links show as “Video not found” on Desktop App if "Allow mixed content" is turned on. +- “More” option under Direct Message list no longer shows count of team members not in your direct message list. +- On Firefox, CTRL/CMD+U keyboard shortcut to upload a file doesn’t work. +- Webhook attachments don’t show up in search results. +- Messages sometimes don't appear deleted until the page is refreshed. +- When joining a channel from a public link, the page sometimes loads for a long time and requires a refresh. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server +- [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [cybershambles](https://github.com/cybershambles), [daizenberg](https://github.com/daizenberg), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [gramakri](https://github.com/gramakri), [grundleborg](https://github.com/grundleborg), [hmhealey](https://github.com/hmhealey), [HugoGiraudel](https://github.com/HugoGiraudel), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [joonsun-baek](https://github.com/joonsun-baek), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [npcode](https://github.com/npcode), [paranbaram](https://github.com/paranbaram), [phrix32](https://github.com/phrix32), [R-Wang97](https://github.com/R-Wang97), [shieldsjared](https://github.com/shieldsjared) + +/ios +- [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock) + +/desktop +- [asaadmahmood](https://github.com/asaadmahmood), [jasonblais](https://github.com/jasonblais), [jgis](https://github.com/jgis), [jnugh](https://github.com/jnugh), [Razzeee](https://github.com/Razzeee), [St-Ex](https://github.com/St-Ex), [yuya-oc](https://github.com/yuya-oc) + +/docs +- [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [DavidLu1997](https://github.com/DavidLu1997), [esethna](https://github.com/esethna), [friism](https://github.com/friism), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [kaakaa](https://github.com/kaakaa), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [pmccarthy01](https://github.com/pmccarthy01), [rudloff](https://github.com/Rudloff), [shieldsjared](https://github.com/shieldsjared), [yangchen1](https://github.com/yangchen1) + +/mattermost-docker +- [npcode](https://github.com/npcode), [xcompass](https://github.com/xcompass) + +/android +- [coreyhulen](https://github.com/coreyhulen), [enahum](https://github.com/enahum), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock) + +/push-proxy +- [jwilander](https://github.com/jwilander) + +/mattermost-heroku +- [it33](https://github.com/it33), [jwilander](https://github.com/jwilander) + +---- + +## Release v3.3.0 + +Expected release date: 2016-08-16 + +### Security Update + +- Mattermost v3.3.0 contains [security updates](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.3.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. +- Thanks to Bastian Ike for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Languages +- Added Dutch, Korean, Simplified Chinese and Traditional Chinese translations for the user interface. +- Promoted Portuguese and Spanish to release-quality translations. + +#### Flagged Messages +- Added the ability to flag a message for follow up, so users can track messages they want to go back to later. + +#### Improved Statuses +- Improved response time of status indicator changing between online/offline/away. +- Added status indicators to the Direct Message and Channel member lists. +- Added `@here` to mention users who are online. + +#### Google SSO ([Enterprise E20](https://mattermost.com/pricing/)) +- Users can sign in to Mattermost with their Google credentials and new Mattermost user accounts are automatically created on first login. + +#### Office 365 SSO (Beta) ([Enterprise E20](https://mattermost.com/pricing/)) +- Users can sign in to Mattermost with their Office 365 credentials and new Mattermost user accounts are automatically created on first login. + +#### High Availability Mode (Beta) ([Enterprise E20](https://mattermost.com/pricing/)) +- Support for highly available application servers configurable in the System Console and configuration files. See [documentation](https://docs.mattermost.com/deployment/cluster.html) for more details. + +### Improvements + +#### iOS app +- Fixed issue where “Refresh/Log out” was appearing frequently. +- Fixed issue where center channel appears blank after initial page load. +- Keyboard is now closed when a user executes a search. + +#### Mobile (iOS and Android apps) +- Enter key now creates a new line instead of sending the message. +- Added links to the mobile apps in the welcome email, tutorial, and main menu. +- Added a landing page that informs users of the mobile app when they access the site on a mobile web browser. +- Permalinks are now available on mobile. +- Made it easier to click on the ... menu when in the right-hand sidebar view. +- Enable auto-complete for "from:" and "in:". + +#### User Interface +- Channel header is now added to the View Info modal. +- Configured channel introduction to respect the full width and centred channel views. +- Removed signup link from sign in page if all signup methods are disabled. +- Improved channel header popover behaviour. + +#### Authentication +- The username "matterbot" is now restricted from account creation. +- Link to create an account is hidden on the login page if no account creation methods are turned on in the System Console. +- All team members can View Members for the team or specific channels. + +#### Notifications +- Mention notifications can be turned on for any new messages in comment threads that you participate in. + +#### Keyboard Shortcuts +- Added icons next to channel names and improved sorting in the channel switcher (CTRL/CMD+K). +- Keyboard shortcuts that open modals can now toggle them open and closed (CTRL/CMD+SHIFT+A, CTRL/CMD+K). + +#### Integrations +- Added an option to trigger outgoing webhook if the first word starts with the specified trigger word. + +#### System Console +- Username is now added to the System Console users list. +- Legal and Support links are now hidden in the user interface if no link is specified in the System Console. +- If the Terms of Service link is left blank in the System Console then it defaults to the "Mattermost Conditions of Use" page. + +#### [Enterprise E10, E20](https://mattermost.com/pricing/) + +- Added the ability to set different themes for each team. +- Added a checkbox to apply theme settings to all teams of which you are a member. +- Users disabled or removed from the AD/LDAP server are now made “Inactive” in Mattermost (previously their sessions were revoked and could no longer log in, but their account status was not set to “Inactive”). +- Added the ability to force migrating authentication methods. +- Added Site Description field to the System Console > Customization > Custom Branding section. +- AD/LDAP `Bindusername` and `Bindpassword` fields in the System Console are now optional to support anonymous binding. + +### Bug Fixes + +- The behavior of setting for Link Previews in Account Settings is no longer reversed. +- Hitting the URL of a private team you used to belong to now redirects properly. +- Search terms contained in hashtags are now highlighted in the search results. +- Fixed an issue with quick typesetting on IE-11 and Edge. +- Fixed an issue with uploading SAML certificates if the files were removed from `config.json`. +- Multiple files can now be selected on the file upload dialog of the desktop app. +- Fixed a scrolling issue with the channel switcher. +- Fixed system messages showing a small empty white box. +- Fixed a markdown formatting issue with multiple lists in a row. +- Team Admins can no longer demote System Admins. +- The channel header now respects the setting for Channel Display Mode. +- The System Console no longer freezes if accessing via URL when not logged in. +- Site Name is now restricted to 30 characters to avoid text overflow. +- Error is no longer thrown when switching between teams in the System Console. +- Invalid password error is thrown if System Admin resets a password to something that doesn't meet the specified password requirements. +- Fixed the percentage loading indicator on the image preview modal. +- File upload overlay now appears on Edge. +- Maximum Users per Team and Minimum Password Length now default to reasonable values if a bad input is saved. +- Right-hand side now updates when a new profile picture is saved. +- Channels in the Channel Switcher are sorted by their handle if their display name is identical. +- Setting the length for mobile sessions is now fixed in the System Console. +- The “Test Connection” button in the System Console > Notifications > Email section now properly uses the saved SMTP password. +- System Admins no longer receive a JavaScript error if a new message is received while in the System Console. +- Dropdown in the Manage Members modal is no longer empty for System Admins. +- @all is now correctly highlighted if the trigger setting is selected in Account Settings. +- Fixed unformatted error message on account creation page if no creation methods are enabled. +- Corrected the formatting of some help text in the System Console. +- Color picker in Custom Theme settings now disappears once setting has been saved on mobile. +- System Console menu no longer cuts off long team names. + +### Compatibility +Changes from v3.2 to v3.3: + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition:** + +- Under a new section `NativeAppSettings`: + - Added `"AppDownloadLink": "https://mattermost.com/download/#mattermostApps"` to point towards a download page for native apps. + - Added `"AndroidAppDownloadLink": "https://about.mattermost.com/mattermost-android-app/"` to point towards the Android app. + - Added `"IosAppDownloadLink": "https://about.mattermost.com/mattermost-ios-app/"` to point towards the iOS app. +- Under `ServiceSettings`: + - Added `"SiteURL": ""` to allow the server to overwrite the site_url. +- Under `TeamSettings`: + - Added `"UserStatusAwayTimeout": 300` to specify the number of seconds before users are considered "away". + +**Additional Changes to Enterprise Edition:** + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + +- Under `TeamSettings`: + - Added `"CustomDescriptionText": ""` to set the site description shown in login screens and user interface. +- Under `GoogleSettings` in `config.json`: + - Changed: `"Scope": "profile email"` to set the standard setting for OAuth to determine the scope of information shared with OAuth client. + - Changed: `"AuthEndpoint": "https://accounts.google.com/o/oauth2/v2/auth"` to set the authorization endpoint for Google SSO. + - Changed: `"TokenEndpoint": "https://www.googleapis.com/oauth2/v4/token"` to set the token endpoint for Google SSO. + - Changed: `"UserApiEndpoint": "https://www.googleapis.com/plus/v1/people/me"` to set the user API endpoint for Google SSO. +- Under a new section `Office365Settings`: + - Added `"Enable": false` to allow login using Office 365 SSO when set to `true`. + - Added `"Secret": ""` to set the Client Secret received when registering the application with Google. + - Added `"Id": ""` to set the Client ID received when registering the application with Google. + - Added `"Scope": "User.Read"` to set the standard setting for OAuth to determine the scope of information shared with OAuth client. + - Added `"AuthEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"` to set the authorization endpoint for Office 365 SSO. + - Added `"TokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token"` to set the token endpoint for Office 365 SSO. + - Added `"UserApiEndpoint": "https://graph.microsoft.com/v1.0/me"` to set the user API endpoint for Office 365 SSO. +- Under `LdapSettings` in `config.json`: + - `"BindUsername": ""` and `"BindPassword": ""` are no longer required fields, so anonymous binding is possible. +- Under a new section `ClusterSettings`: + - Added `"Enable": false` to enable High Availability mode. + - Added `"InterNodeListenAddress": ":8075"` to specify the address the server will listen on for communicating with other servers. + - Added `"InterNodeUrls": []` to specify the internal/private URLs of all the Mattermost servers separated by commas. + +### Database Changes from v3.2 to v3.3 + +**OAuthAccessData Table** + + - Added `ClientId` column. + - Added `UserId` column. + - Removed `AuthCode` column. + - Set Unique key on `ClientId` and `UserId` columns. + - Removed index from `idx_oauthaccessdata_auth_code` column. + - Added indexes to `idx_oauthaccessdata_client_id`, `idx_oauthaccessdata_user_id` and `idx_oauthaccessdata_refresh_token` columns. + +**OAuthApps Table** + + - Added `IconURL` column. + +**OutgoingWebhooks Table** + + - Added `TriggerWhen` column. + +**Status Table** + + - Added `Status` table. + +**Users Table** + + - Removed `LastActivityAt` column. + - Removed `LastPingAt` column. + - Removed `ThemeProps` column. + +### API Changes from v3.2 to v3.3 + +**Updated admin routes:** + - Changed `users/status` from `POST` to `GET` + +**New admin routes:** + - Added `GET` at `/posts/flagged/{offset:[0-9]+}/{limit:[0-9]+}` + - Returns a list of posts that have been flagged by the user; `offset` is the offset to start the page at; `limit` is the max number of posts to return. + - Added `GET` at `/admin/cluster_status` + - Returns a json with a status of each of the reachable nodes in the cluster + - Added `GET` at `/oauth/list` + - Returns a list of OAuth 2.0 apps registered by the user + - Added `GET` at `/oauth/app/{clientId:""}` + - Returns a Sanitized OAuth 2.0 application where `clientId` corresponds to the application + - Added `POST` at `/oauth/delete` + - Returns status = OK if the OAuth 2.0 application owned by the current user was successfully deleted. + - Added `GET` at `/oauth/access_token` + - Returns the access token for OAuth 2.0 application + - Added `POST` at `/preferences/delete` + - Returns status = OK if the list of preferences owned by the current user were successfully deleted. + - Added `POST` at `/admin/remove_certificate` + - Returns a map[string]interface{} if removing the x509 base64 Certificates and Private Key files used with SAML exists on the file system. + +### Known Issues + +- Desktop apps sometimes require a refresh to solve 404 errors. +- Deleted messages don't disappear from the channel for the user who deleted the message, if the message was previously edited and right hand sidebar is open. +- After receiving an error for creating a channel with one character, updated channel name is not saved. +- A single collapsed preview re-opens after refresh. +- Removed user from team still appears in DM list from the team. +- Files sent in private messages to members in a different team are not accessible. +- YouTube videos show as “Video not found” on Desktop App. +- “More” option under Direct Message list no longer shows count of team members not in your direct message list. +- /join sometimes throws an error. +- On Firefox, CTRL/CMD+U keyboard shortcut doesn’t work. +- Sometimes only the last character typed in the channel switcher appears. +- Webhook attachments don’t show up in search results. +- Count of unread mentions are sometimes mixed when switching between multiple teams. +- Office 365 login sometimes causes a bad token error. +- Messages sometimes don't appear deleted until the page is refreshed. +- When joining a channel from a public link, the page sometimes loads for a long time and requires a refresh. +- After leaving a team, joining or creating a team sometimes causes an error. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server + +- [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [eadmund](https://github.com/eadmund), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [hmhealey](https://github.com/hmhealey), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [lfbrock](https://github.com/lfbrock), [maruTA-bis5](https://github.com/maruTA-bis5), [Rudloff](https://github.com/Rudloff), [samogot](https://github.com/samogot), [yuters](https://github.com/yuters) + +/desktop + +- [jasonblais](https://github.com/jasonblais), [jnugh](https://github.com/jnugh), [Razzeee](https://github.com/Razzeee), [timroes](https://github.com/timroes), [yuya-oc](https://github.com/yuya-oc) + +/android + +- [coreyhulen](https://github.com/coreyhulen), [jasonblais](https://github.com/jasonblais) + +/ios + +- [coreyhulen](https://github.com/coreyhulen), [macdabby](https://github.com/macdabby), [jasonblais](https://github.com/jasonblais) + +/docs + +- [asaadmahmood](https://github.com/asaadmahmood), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65) + +/mattermost-docker + +- [npcode](https://github.com/npcode) + +/mattermost-driver-javascript + +- [jwilander](https://github.com/jwilander) + +/mattermost-bot-sample-golang + +- [coreyhulen](https://github.com/coreyhulen), [jasonblais](https://github.com/jasonblais) + +---- + +If we missed your name, please let us know at feedback@mattermost.com. Recognition is a manual process and mistakes can happen. We want to include anyone who's made a pull request that got merged during the release. + +## Release v3.2.0 + +Release date: 2016-07-16 + +### Security Update + +- Mattermost v3.2.0 contains [multiple security updates](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.2.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. +- Thanks to Bastian Ike, Mohammad Razavi, Steve MacQuiddy, Christer Mjellem Strand and Jonas Arneberg for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Languages + +- Added German translation for the user interface if enabled by the System Admin from **System Console > Localization > Available Languages**. + +#### Custom Emoji + +- Create Custom Emoji from the **Main Menu** > **Custom Emoji** when enabled from **System Console** > **Customization** > **Custom Emoji**. +- Restrict the permissions required to create Custom Emoji (Enterprise). + +#### Performance +- Gzip compression for static content files decreases time for first page load, enabled from **System Console** > **Configuration**. +- Reduced the total Mattermost package size from 25.7MB to 18.9MB. + +#### Policy ([Enterprise E10, E20](https://mattermost.com/pricing/)) + +- Restrict the permission levels required to send team invitiations in **System Console** > **Policy**. +- Restrict the permission levels required to manage public and private channels, including creating, deleting, renaming, and setting the channel header or purpose. + +#### SAML Single Sign-On ([Enterprise E20](https://mattermost.com/pricing/)): + +- Users can sign in to Mattermost with their SAML credentials and new Mattermost user accounts are automatically created on first login. Mattermost pulls user information from SAML, including first and last name, email and username. +- Mattermost officially supports Okta and Microsoft ADFS as the identity providers (IDPs), but you may also try configuring SAML for a custom IDP. + +### Improvements + +**On-Boarding and Off-Boarding** + +- After account creation, users are automatically directed to the team where they were invited instead of the Team Selection page. +- "Get Team Invite Link" is now accessible on mobile. +- Users can now be removed from teams via the **Main Menu** > **Manage Members** modal. + +**System Console** + +- Updated labeling of System Console settings in the UI for consistency and accuracy. +- ([Enterprise E20](https://mattermost.com/pricing/)) High availability support via **Reload Configuration from Disk** and **Recycle Database Connections** buttons had help text added so they're easier to understand. +- Allow System Admins to create teams even if team creation is disabled via the System Console. + +**Notifications** + +- Address displayed in the email notification footer is now configurable in the System Console. +- Direct Message desktop notifications now display with a "Direct Message" title. + +**Web UI** + +- Reply button and [...] menu now appear in a hovering UI element to increase the available margin width in the center channel. +- Right-hand sidebar can now be expanded when viewing threads or search results. +- Text emoticons now show up as the first entries in the autocomplete list +- @mention autocomplete now filters on nickname, full name, and username. +- Added an online indicator to the header of Direct Message channels. +- Added database type to the About Mattermost dialog. +- Removed unnecessary resizing when opening and closing the right hand sidebar. +- Removed jumping of the center channel when new messages are posted. +- Updated the channel info dialog to be more user friendly. + +**[Enterprise E10, E20](https://mattermost.com/pricing/)** + +- [New command line tools](https://docs.mattermost.com/administration/command-line-tools.html) added, such as adding and removing users from channels, and restoring previously deleted channels. +- Added a button to manually trigger AD/LDAP synchronization. +- Updating AD/LDAP Synchronization Interval to no longer require a server restart to take effect. +- Improved logging for AD/LDAP synchronization. +- Added validation to the AD/LDAP settings in the System Console so an error is triggered if required fields are missing. + +### Bug Fixes + +- Privacy settings in the system console now refresh correctly when hiding email addresses or full names. +- Fixed the cross contamination of new channels created on different teams in the same browser. +- Updated the GitLab SSO error message for clarity if another Mattermost account is already associated with the GitLab account. +- Team creation via GitLab SSO no longer throws an error if email domains are restricted. +- Channel header no longer disappears after renaming a channel +- Testing the email connection in the System Console no longer throws an error. +- Multiline list items are now displayed correctly on new lines. +- Error message is updated when switching from email to GitLab SSO authentication that is already used by another account. +- Timestamps no longer require a page refresh when switching between 12h and 24h display formats. +- Hashtags containing `¿` are now returned with proper highlighting in search results. +- No longer require a page refresh before enabling compliance reporting in the System Console. +- `@all` no longer sends mentions if unselected in Account Settings. +- Users are no longer redirected to the switch teams page after changing authentication method from GitLab SSO to email. +- Invalid MFA token error message now clears correcly from the UI. +- Errors now correctly clear from the UI when changing passwords. +- System Console users list no longer throws an error when trying to demote a member from a System Admin. +- iOS radio buttons no longer stay selected when switching between options. +- Email addresses now display for System Admins even if hidden in the System Console. +- Code themes now save when updated via Account settings. +- File name is now displayed instead of the full path to the file in code snippet previews. +- Config settings are refreshed immediately when **Reload Configuration from Disk** is clicked. +- Preview feature checkboxes now reset after changes are canceled. +- Updated the markdown parser to fix poor handling of certain links. +- Error box highlighting on the claim AD/LDAP account page is fixed to only highlight the invalid input box. +- Errors in the system console are now properly aligned. +- Button to resend verification email no longer throws an error when clicked. +- Direct Messages modal loads faster since it is no longer cleared from memory each time it closes. +- Graphs in the **System Console > Site Statistics** now have the same start date for comparison. +- Fixed an issue where new languages are not added by default. Any server which is upgraded to Mattermost v3.1 will need to manually set **System Console > Localization > Available Languages** blank to have new languages added by default. +- Previously, a few shortcuts that used CTRL were overwriting existing messaging shortcuts in Mac. This has been changed so they only work with CMD. See [documentation](https://docs.mattermost.com/help/messaging/keyboard-shortcuts.html) for more details. +- Email body now contains the `siteURL` when inviting a user by email via CLI (command line interface) +- YouTube videos now stop playing when collapsed. +- Fixed error when adding an incoming webhook to a public channel the user is currently not in. +- Error merssage displayed on password reset page is now formatted correctly. + +### Compatibility +Changes from v3.1 to v3.2: + +#### config.json + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `EmailSettings` in `config.json`: + - Added `"FeedbackOrganization": ""` to specify organization name and address, which will be displayed on email notifications from Mattermost. + +- Under `ServiceSettings` in `config.json`: + - Added `"EnableCustomEmoji": false`. When set to `true`, enables Custom Emoji option in the Main Menu where users can create customized emoji. + +- Under `LocalizationSettings` in `config.json`: + - Changed: `"AvailableLocales": ""` to allow new languages be added by default. + +- Under `LogSettings` in `config.json`: + - Added `"EnableWebhookDebugging": true`. When set to `true`, contents of incoming webhooks are printed to log files for debugging. + +**Additional Changes to Enterprise Edition:** + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + +- Under `TeamSettings` in `config.json`: + - Added `"RestrictTeamInvite": "all"` to set the permissions required to send team invites. + - Added `"RestrictPublicChannelManagement": "all"` to set the permissions required to manage public channels. + - Added `"RestrictPrivateChannelManagement": "all"` to set the permissions required to manage private channels. + +- Under `ServiceSettings` in `config.json`: + - Added `"RestrictCustomEmojiCreation": "all"` to set the permissions required to create custom emoji. + +- Under `SamlSettings` in `config.json`: + - Added `"Enable": false` to allow login using SAML. See [documentation](https://docs.mattermost.com/deployment/sso-saml.html) to learn more about configuring SAML for Mattermost. + - Added `"Verify": false` to control whether Mattermost verifies the signature sent from the SAML Response matches the Service Provider Login URL. + - Added `"Encrypt": false`to control whether Mattermost will decrypt SAML Assertions encrypted with your Service Provider Public Certificate. + - Added `"IdpUrl": ""` to set the SAML SSO URL where Mattermost sends a SAML request to start login sequence. + - Added `"IdpDescriptorUrl": ""` to set the Identity Provider Issuer URL for the Identity Provider you use for SAML requests. + - Added `"AssertionConsumerServiceURL": ""` to set the Service Provider Login URL. + - Added `"IdpCertificateFile": ""` to set the public authentication certificate issued by your Identity Provider. + - Added `"PublicCertificateFile": ""` to set certificate used to generate the signature on a SAML request to the Identity Provider for a service provider initiated SAML login, when Mattermost is the Service Provider. + - Added `"PrivateKeyFile": ""` to set the private key used to decrypt SAML Assertions from the Identity Provider. + - Added `"FirstNameAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the first name of users in Mattermost. + - Added `"LastNameAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the last name of users in Mattermost. + - Added `"EmailAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the email of users in Mattermost. + - Added `"UsernameAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the username of users in Mattermost. + - Added `"NicknameAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the nickname of users in Mattermost. + - Added `"LocaleAttribute": ""` to set the attribute in the SAML Assertion that will be used to populate the language of users in Mattermost. + - Added `"LoginButtonText": ""` set the text that appears in the login button on the login page. + +- Under `LdapSettings` in `config.json`: + - `"FirstNameAttribute": ""`, `"LastNameAttribute": ""`, `"BindUsername": ""`, and `"BindPassword": ""` are now required fields. + - Added `"MaxPageSize": 0` to set the maximum number of users that will be requested from the AD/LDAP server at one time. + +#### Database Changes from v3.1 to v3.2 + +**TeamMembers Table** +- Added `DeleteAt` column. + +**Emoji Table** +- Added `Emoji` table. + +### Known Issues + +- In System Console > Notifications > Email the "Test Connection" button does not properly use the saved SMTP password. The temporary workaround is to re-type your SMTP Server Password into the field prior to using the "Test Connection", and then to "Save" afterwards. +- The behavior of setting for Link Previews in Account Settings is reversed. +- “More” option under Direct Message list no longer shows count of team members not in your direct message list. +- Webhook attachments don't show up in search results. +- On Firefox, System Console sidebar completely disappears when an AD/LDAP setting is saved. +- On Firefox, CTRL/CMD+U keyboard shortcut doesn't work. +- `/join` sometimes throws an error. +- Sometimes only the last character typed in the channel switcher appears. +- Formatting of multiple lists in a row breaks markdown. +- Hitting the URL of a private team you used to belong to shows a blank Team Selection page. +- Accessing the System Console URL when logged out causes the browser to hang. +- YouTube videos show as "Video not found" on Desktop App +- Search terms contained in hashtags are not highlighted in the search results. +- Files sent in private messages to members in a different team are not accessible. +- Center channel appears blank after initial page load on iOS. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server +- [42wim](https://github.com/42wim), [apheleia](https://github.com/apheleia), [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen),[crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [hmhealey](https://github.com/hmhealey), [iansim](https://github.com/iansim), [it33](https://github.com/it33), [jwilander](https://github.com/jwilander), [kevynb](https://github.com/kevynb), [lfbrock](https://github.com/lfbrock), [samogot](https://github.com/samogot), [tbalthazar](https://github.com/tbalthazar), [tehraven](https://github.com/tehraven), [thiyagaraj](https://github.com/thiyagaraj), [yumenohosi](https://github.com/yumenohosi) + +/ios +- [coreyhulen](https://github.com/coreyhulen) + +/desktop +- [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [magicmonty](https://github.com/magicmonty), [Razzeee](https://github.com/Razzeee), [yuya-oc](https://github.com/yuya-oc) + +/docs +- [apheleia](https://github.com/apheleia), [asaadmahmood](https://github.com/asaadmahmood), [crspeller](https://github.com/crspeller), [esethna](https://github.com/esethna), [Fonata](https://github.com/Fonata), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [npcode](https://github.com/npcode), [yangchen1](https://github.com/yangchen1) + +/mattermost-driver-javascript +- [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [samogot](https://github.com/samogot) + +/mattermost-docker +- [npcode](https://github.com/npcode) + +/mattermost/push-proxy +- [coreyhulen](https://github.com/coreyhulen) + +If we missed your name, please let us know at feedback@mattermost.com. Recognition is a manual process and mistakes can happen. We want to include anyone who's made a pull request that got merged during the release. + +---- + +## Release v3.1.0 + +Release date: 2016-06-16 + +### Security Update + +- Mattermost v3.1.0 contains [multiple security updates](https://mattermost.com/security-updates/). [Upgrading to Mattermost v3.1.0](https://docs.mattermost.com/administration/upgrade.html) is highly recommended. +- Thanks to Uchida Taishi for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### Keyboard shortcuts and channel switcher + +- Added keyboard shortcuts for navigation, messages and files +- Added channel switcher available from CTRL+K in Windows and CMD+K on Mac. +- See [shortcut documentation](https://docs.mattermost.com/help/messaging/keyboard-shortcuts.html) or use the `/shortcuts` slash command for details. + +#### Upgraded System Console + +- Re-organized System Console to make settings easier to find for new users. +- Added setting to set default server and client languages. + +#### Upgraded Push Notification options + +- Added ability for mobile push notifications to trigger on only mentions, all activity and no activity, configurable from **Account Settings** > **Notifications** > **Mobile push notifications** +- Added ability to trigger mobile push notifications while user is logged into Mattermost on desktop. + +#### Compact View + +- Added "Compact" view option to display more text on a smaller screen, configurable from **Account Settings** > **Display** > **Message Display**. + +### Improvements + +iOS App +- Account Settings > Notifications option lets users to enable mobile push notifications for chosen activities. +- Push notifications sent even if a user is online on desktop. +- Removed auto-capitalization on login screen, so email is no longer capitalized. + +Android App +- Account Settings > Notifications option lets users to enable mobile push notifications for chosen activities. +- Push notifications sent even if a user is online on desktop. +- Removed auto-capitalization on login screen, so email is no longer capitalized. + +User Interface + +- Account Settings > Display option lets users set channels to compact view. +- Autocomplete closes with ESC button. +- Sequential messages with a username also show profile pictures. +- Channel introduction message conforms to the channel width chosen in Account Settings > Display. +- The message '[user] is typing' now uses the username instead of the display name. +- Date markers now show absolute time. + +Performance + +- Performance improvements to posting and replying. +- Online status in Direct Message list updated on first load. + +Notifications + +- `@all` mention added back with equivalent functionality to `@channel`. +- An email notification is now sent when username is changed. + +Channels +- Removed the option to leave a channel for the last person in a private group, so private groups can no longer end up in an ownerless state. + +Messaging + +- Move link preview toggle out of preview feature list and add /collapse and /expand. + +Localization + +- New settings to configure localization options for teams, including default language. +- [Mattermost Translation Server](https://translate.mattermost.com/) upgraded to better support product localization processes. + +Integrations + +- Integrations now support advanced formatting through [message attachments](https://developers.mattermost.com/integrate/reference/message-attachments/). +- Added support for sending `@channel` notifications by using ``. +- Added support for raw new lines in the text payload. +- Added validation for command trigger words. + +Onboarding + +- Slash command `/invite_people [email address]` sends an email invite to your Mattermost team. + +Enterprise + +- (E10 and higher): Added AD/LDAP synchronization to automatically deactivate Mattermost accounts after AD/LDAP accounts are deactivated. Previous behavior only checked AD/LDAP credentials on sign-in. Synchronization time defaults to one hour and is configurable from **System Console** > **Synchronization Interval**. +- (E20 and higher): Added support for [high availability database configurations](https://docs.mattermost.com/deployment/ha.html) using read replicas and a manual failover process to deploy database reconfigurations without stopping the Mattermost server. + +### Bug Fixes + +- Incoming webhooks have been made available in all public channels, and in private channels the user belongs to. +- A space between two named emojis is no longer required for correct rendering. +- Emojis now render inside parenthesis or brackets. +- Links that are enclosed with a right parenthesis now work properly. +- Search term highlighting now updates when search terms change but return the same posts. +- Search results now properly highlight for searches containing @username, non-latin characters, terms inside Markdown code blocks, and hashtags containing a dash. +- A single numbered item no longer resets numbering to 1. +- Previews for removed YouTube videos no longer throw a 404 error. +- Team and System Admins can now update channel settings after leaving and rejoining the channel. +- After initial load on iOS, centre channel no longer appears blank. +- When creating a team with a new account, channel introduction message is now displayed. +- Sidebar notification for direct messages now clear once viewed, regardless of which team you are in. +- Custom brand image size is now properly limited on IE11. + +### Compatibility +Changes from v3.0 to v3.1: + +**config.json** + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + + - Under `LocalizationSettings` in `config.json`: + - Added `"DefaultServerLocale": “en”` to set default language for the system messages and logs + - Added `"DefaultClientLocale": “en”` to set default language for newly created users and for pages where the user hasn't logged in + - Added `"AvailableLocales": “en,es,fr,ja,pt-BR”` to set which languages are available for users in Account Settings. The language specified in `DefaultClientLocale` should be included in this list. + +**Additional Changes to Enterprise Edition:** + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + + - Under `LdapSettings` in `config.json`: + - Added `"SyncIntervalMinutes": "60"` to allow system admins adjust how frequently Mattermost performs AD/LDAP synchronization to update users + +### Known Issues + +- “More” option under Direct Message list no longer shows count of team members not in your direct message list. +- Emoji smileys ending with a letter at the end of a message do not auto-complete as expected. +- Incorrect formatting when a new line is added directly after a list. +- On Postgres databases, searching for websites and emails does not work properly and hashtags which end with an inverted questionmark aren't properly highlighted. +- On Firefox, search results for hashtags are not properly highlighted. +- Clicking on a desktop notification from another team doesn’t open the team. +- Webhook attachments don't show up in search results. +- On Firefox, System Console sidebar completely disappears when an AD/LDAP setting is saved +- On Firefox, CTRL/CMD+U keyboard shortcut doesn't work +- Copying and pasting an image from a browser doesn't work +- YouTube videos continue playing when collapsed +- Code theme under Account Settings > Display > Theme doesn't save unless entered in vectorized form +- `/join` sometimes throws an error +- When upgrading to 3.X, syntax highlighting using Solarized code theme is lost +- In Compact view, clicking on a file in the first post in the right hand sidebar attempts to download the file +- Unable to leave a private channel in mobile view +- `@all` notifications received even after being unselected from notification options +- Channel header disappears after renaming a channel (fixed with channel switch) +- Updates to **System Console** > **Privacy** settings for existing users requires a session update +- Invalid config setting causes server to panic on start + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server +- [apheleia](https://github.com/apheleia), [ArthurHlt](https://github.com/ArthurHlt), [asaadmahmood](https://github.com/asaadmahmood), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [goofy-bz](https://github.com/goofy-bz), [gramakri](https://github.com/gramakri), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [jwilander](https://github.com/jwilander), [kevynb](https://github.com/kevynb), [khoa-le](https://github.com/khoa-le), [lfbrock](https://github.com/lfbrock), [rompic](https://github.com/rompic), [ryoon](https://github.com/ryoon), [samogot](https://github.com/samogot), [ScriptAutomate](https://github.com/ScriptAutomate), [tbalthazar](https://github.com/tbalthazar), [tehraven](https://github.com/tehraven/) + +/ios +- [coreyhulen](https://github.com/coreyhulen), [lfbrock](https://github.com/lfbrock) + +/android +- [coreyhulen](https://github.com/coreyhulen), [DavidLu1997](https://github.com/DavidLu1997), [it33](https://github.com/it33), [lfbrock](https://github.com/lfbrock), [nineinchnick](https://github.com/nineinchnick) + +/desktop +- [CarmDam](https://github.com/CarmDam), [it33](https://github.com/it33), [jnugh](https://github.com/jnugh), [MetalCar](https://github.com/MetalCar), [Razzeee](https://github.com/Razzeee), [yuya-oc](https://github.com/yuya-oc) + +/docs +- [apheleia](https://github.com/apheleia), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [hannaparks](https://github.com/hannaparks), [hmhealey](https://github.com/hmhealey), [it33](https://github.com/it33), [jasonblais](https://github.com/jasonblais), [lfbrock](https://github.com/lfbrock), [maxlmo](https://github.com/maxlmo), [mkhsueh](https://github.com/mkhsueh), [npcode](https://github.com/npcode), [TwizzyDizzy](https://github.com/TwizzyDizzy) + +/mattermost-driver-javascript +- [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [enahum](https://github.com/enahum), [jwilander](https://github.com/jwilander) + +/mattermost-docker +- [npcode](https://github.com/npcode), [pierreozoux](https://github.com/pierreozoux) + +/mattermost/push-proxy +- [coreyhulen](https://github.com/coreyhulen) + +/mattermost/mattermost-docker-preview +- [crspeller](https://github.com/crspeller) + +If we missed your name, please let us know at feedback@mattermost.com. Recognition is a manual process and mistakes can happen. We want to include anyone who's made a pull request that got merged during the release. + +---- + +## Release v3.0.3 + +Release date: 2016-05-27 + +Notes on patch releases: +- v3.0.3, released 2016-05-27 + - Fixed an error with AD/LDAP signup if user already existed. + - Fixed an error where setting language to one of the supported langugages caused a blank page. + - Fixed an error where upgrading team admins on the primary team with AD/LDAP and GitLab accounts caused an error. +- v3.0.2, released 2016-05-17 + - Security update to reduce information disclosure, thanks to Andreas Lindh for [reporting responsibly](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/) + - Fixed an error where, when using Postgres, attempting to log in with an AD/LDAP that has the same email address or username as an email-based account shows a confusing error message. + - Fixed an error accounts using email authentation attempt to create new teams. + - Fixed an error where if you upgrade having never previously saved config.json from System Console, saving from System Console will not work. +- v3.0.1, released 2016-05-16 + - v3.0.1 fixed an error in GitLab SSO, thanks to [ArthurHlt](https://github.com/ArthurHlt) for the pull request fixing the issue. +- v3.0.0, released 2016-05-16 + - Original 3.0 release. + +### Security Update + +- Mattermost v3.0.3 contains multiple security updates. [Upgrading to Mattermost v3.0.3](https://docs.mattermost.com/administration/upgrade.html#upgrading-to-team-edition-3-0-x-from-2-x) is highly recommended. +- Thanks to Yoni Ramon from the Tesla security team, Andreas Lindh and Uchida Ta for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Major Version Release + +Mattermost 3.0 is a new major version of Mattermost with fundamental changes affecting Mattermost 2.x deployments. [An understanding of the upgrade process from 2.x to 3.0](https://docs.mattermost.com/upgrade/upgrading-mattermost-server.html?&redirect_source=mm-org), including manual steps, is required to upgrade successfully. + +### Highlights + +#### Unified Accounts + +- Users manage a single account across multiple teams +- Users from different teams can share messages and files +- Improved multi-team login and sign-up experience + +#### Enterprise Edition Security, Authentication and Branding Upgrades + +- Added multi-factor authentication +- Added multiple Active Directory/LDAP upgrades (TLS, filters, custom labels, nickname support) +- Added tools for custom branding + +#### User Interface Upgrades +- New Emoji set +- Added full width option for text display +- Improved UI for managing webhooks and slash commands + +#### iOS and Android mobile app improvements +- Added support for multiple teams +- New option to include message snippets in push notifications +- Added auto-correct + +### Languages + +- Added Japanese translation for user interface. + +### Improvements + +iOS app +- Added support for multiple teams on the same server. +- Added autocorrect. +- Note: Users of Mattermost 3.0 server need to install new iOS 3.0 app. iOS 2.x apps are not compatible with Mattermost 3.0 server. Also, iOS 3.0 app is not compatible with Mattermost 2.x server. + +Android app +- Added support for multiple teams on the same server. +- Added autocorrect. +- Note: Users of Mattermost 3.0 server need to install new Android 3.0 app. Android 2.x apps are not compatible with Mattermost 3.0 server. Also, Android 3.0 app is not compatible with Mattermost 2.x server. + +User Interface +- Switched to new emoji set. +- Account Settings > Display option lets users set the channel view to full width. +- Smoother overlay transition when opening sidebar on mobile. +- Back and forward browser buttons can now move back and forward in channel history. + +Integrations +- Moved webhooks and slash command settings to a new “Integrations” page. +- Added "Display Name" and “Description” to incoming and outgoing webhooks. +- Changed webhooks to always show the username and profile picture, even if posts are consecutive. +- Added a /msg command to open a direct message channel with another user. + +Authentication +- Changed the user model so accounts are per server instead of per team. +- Updated the login flow so users can select which team to open after signing in. +- Combined Email, Username, and AD/LDAP options into one login box so users can enter their credentials and the system will identify which kind of authentication to use. +- GitLab SSO now creates an account from the "Sign In" button if an account previously did not exist. + +Files and Attachments +- Added a preview for code files in the image viewer. + +Notifications +- Added the option to enable full snippets in push notifications. + +Search +- Changed searches to connect terms with "AND" instead of "OR". + +Enterprise: +- Added the ability to map nickname to an AD/LDAP field. +- Added the ability to filter AD/LDAP users, so only users selected by the filter can log in to Mattermost. +- Added the option to connect to AD/LDAP with TLS or STARTTLS +- Added the option to replace the “AD/LDAP username” login field placeholder text with custom text. +- Users can now switch between AD/LDAP and email login from Account Settings > Security > Sign-in Method. +- Added the option to sign up with AD/LDAP on the "Get Team Invite" link and email invite sign up pages. +- Added multi-factor authentication. +- Added compliance reporting and the option to generate daily compliance reports. +- Added custom branding, so System Admins can set a custom logo and text on the sign in page. +- Added a command line option to upload a license file. + +### Bug Fixes + +- Posts from webhooks now fire notifications to the user who created the webhook. +- Edit post option no longer appears, but doesn't work, on other users' posts in the right-hand sidebar. +- Text input box does not stay scrolled to the bottom when drafting a long message in Firefox. +- Webhooks in search results now show the username/profile pic of the bot, instead of the user who set up the webhook. +- Outgoing webhooks triggers now work when followed by any type of white space, instead of only spaces +- "User is typing" message now follows Teammate Name Display setting +- Log in with GitLab on mobile now works in the case where there is a space after the email address +- Links in System Console > Legal and Support settings now open properly even if http or https is not included +- Timestamps are displayed in 12-hour format when set to 24-hour format. + +### Compatibility +Changes from v2.2 to v3.0: + +**iOS and Android** + +Mattermost iOS and Android app v3.0 requires Mattermost server v3.0 and higher. + +**APIs** + +Web Service API is upgraded to Version 3 and previous Version 1 API is no longer supported. Golang driver, Javascript driver, incoming and outgoing webhooks and Slash commands continue to function as in previous release + +**config.json** + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +**Changes to Team Edition and Enterprise Edition**: + +- Under `TeamSettings` in `config.json`: + - Added `"EnableOpenServer": false` to set whether users can sign up to the server without an invite. + - Removed `"EnableTeamListing": false` since the team directory was replaced with new functionality. + +- Under `EmailSettings` in `config.json`: + - Added `"PushNotificationContents": "generic"` to set whether push notifications send a generic message (`generic`) or send a snippet of the conversation (`full`) + +- Under `SupportSettings` in `config.json`, default support links were changed and need to be manually updated for existing installs: + - Changed: `TermsOfServiceLink: https://about.mattermost.com/default-terms/` + - Changed: `PrivacyPolicyLink: "https://about.mattermost.com/default-privacy-policy/` + - Changed: `AboutLink: "https://about.mattermost.com/default-about/` + - Changed: `HelpLink: "https://about.mattermost.com/default-help/` + - Changed: `ReportAProblemLink: "https://about.mattermost.com/default-report-a-problem/` + - Changed: `SupportEmail: "feedback@mattermost.com` + +**Additional Changes to Enterprise Edition:** + +The following config settings will only work on servers with an Enterprise License that has the feature enabled. + +- Under `ServiceSettings` in `config.json`: + - Added `"EnableMultifactorAuthentication": false` to enable Multifactor Authentication + +- Under `TeamSettings` in `config.json`: + - Added `"EnableCustomBrand": false` to set whether custom branding of the login page is turned on. + - Added `"CustomBrandText": ""` to set what text will show up on the login page, if `"EnableCustomBrand":` is set to `true`. + +- Under `LdapSettings` in `config.json`: + - Added `"ConnectionSecurity":""` to set the type of connection security Mattermost uses to connect to AD/LDAP. Options are `""` (no security), `TLS` or `STARTTLS`. + - Added `"UserFilter": ""` (optional) to set an AD/LDAP Filter to use when searching for user objects. + - Added `"NicknameAttribute": ""` to set the attribute in the AD/LDAP server that will be used to populate the nickname field in Mattermost. + - Added `"SkipCertificateVerification": false` to set whether the certificate verification step for TLS or STARTTLS connections is skipped. (For testing purposes only. Should be set to `false` in production.) + - Added `"LoginFieldName": ""` to set the help text in the login box (for example, AD/LDAP username or Company username). + +- Added `ComplianceSettings` to `config.json`: + - Added `"Enable": false` to set whether compliance reports are enabled. + - Added `"Directory": "./data/"` to set where the reports are stored. + - Added `"EnableDaily": false` to set whether Daily Reports are turned on. + +#### Database Changes from v2.2 to v3.0 + +Version 3.0 uses a different database than version 2.0. A one-way change to the database will be required when upgrading from v2.2 to v3.0. + +### Known Issues + +- “More” option under Direct Message list no longer shows count of team members not in your direct message list. +- Emoji smileys ending with a letter at the end of a message do not auto-complete as expected. +- Incorrect formatting when a new line is added directly after a list. +- Searching for a username or hashtag containing a dot now returns the correct results. +- On Postgres databases, searching for websites, emails, and searching with quotations does not work properly. +- Search term highlighting doesn't update when search terms change but return the same posts. +- Search results don't highlight properly for searches containing @username, non-latin characters, terms inside Markdown code blocks, or hashtags containing a dash. +- Custom brand image size isn’t properly limited on IE11. + +### Contributors + +Many thanks to all our contributors. In alphabetical order: + +/mattermost-server +- [alanmoo](https://github.com/alanmoo), [ArthurHlt](https://github.com/ArthurHlt), [asaadmahmood](https://github.com/asaadmahmood), [augustohp](https://github.com/augustohp), [brunoqc](https://github.com/brunoqc), [chengweiv5](https://github.com/chengweiv5), [Compaurum](https://github.com/Compaurum), [coreyhulen](https://github.com/coreyhulen), [crspeller](https://github.com/crspeller), [CyrilTerets](https://github.com/CyrilTerets), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [FeliciousX](https://github.com/FeliciousX), [hauschke](https://github.com/hauschke), [hmhealey](https://github.com/hmhealey), [insin](https://github.com/insin), [it33](https://github.com/it33), [jwilander](https://github.com/jwilander), [khoa-le](https://github.com/khoa-le), [lfbrock](https://github.com/lfbrock), [loafoe](https://github.com/loafoe), [maruTA-bis5](https://github.com/maruTA-bis5), [moogle19](https://github.com/moogle19), [olivierperes](https://github.com/olivierperes), [pjgrizel](https://github.com/pjgrizel), [qcu](https://github.com/qcu), [rodrigocorsi2](https://github.com/rodrigocorsi2), [ryoon](https://github.com/ryoon), [samogot](https://github.com/samogot), [stupied4ever](https://github.com/stupied4ever), [takashibagura](https://github.com/takashibagura), [usmanarif](https://github.com/usmanarif), [yumenohosi](https://github.com/yumenohosi) + +/mattermost-docker +- [npcode](https://github.com/npcode), [xcompass](https://github.com/xcompass), [it33](https://github.com/it33) + +/ios +- [coreyhulen](https://github.com/coreyhulen), [it33](https://github.com/it33) + +/android +- [arusahni](https://github.com/arusahni), [JohnMaguire](https://github.com/JohnMaguire), [lindy65](https://github.com/lindy65), [nicolas-raoul](https://github.com/nicolas-raoul), [ptersilie](https://github.com/ptersilie) + +/desktop +- [asaadmahmood](https://github.com/asaadmahmood), [it33](https://github.com/it33), [jeremycook](https://github.com/jeremycook), [lloeki](https://github.com/lloeki), [mgielda](https://github.com/mgielda), [yuya-oc](https://github.com/yuya-oc) + +/docs +- [ajerezr](https://github.com/ajerezr), [apheleia](https://github.com/apheleia), [asaadmahmood](https://github.com/asaadmahmood), [crspeller](https://github.com/crspeller), [DavidLu1997](https://github.com/DavidLu1997), [enahum](https://github.com/enahum), [esethna](https://github.com/esethna), [it33](https://github.com/it33), [lfbrock](https://github.com/lfbrock), [lindy65](https://github.com/lindy65), [pjgrizel](https://github.com/pjgrizel), [schemacs](https://github.com/schemacs) + +---- + +## Release v2.2.0 + +Release date: 2016-04-16 + +### Security Update + +- Mattermost v2.2.0 contains multiple security updates. [Upgrading to Mattermost v2.2.0](https://docs.mattermost.com/administration/upgrade.html#upgrading-team-edition) is highly recommended. +- Thanks to Jim Hebert from Fitbit Security, Andreas Lindh, and Uchida Taishi for contributing security reports through the [Mattermost Responsible Disclosure Policy](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### Highlights + +#### New themes + +- User now have access to additional themes from Account Settings > Display Settings > Themes > See other themes +- A [contest for the user community to contribute new themes is now available.](https://forum.mattermost.com/t/share-your-favorite-mattermost-theme-colors/1330) + +#### French language translation + +- French language translation is now available. + +#### TPNS and EAS options + +- [Enterprise App Store](https://docs.mattermost.com/administration-guide/configure/environment-configuration-settings.html#push-notification-server-location) (EAS) and [Test Push Notification Service](https://docs.mattermost.com/administration-guide/configure/environment-configuration-settings.html#test-push-notifications-service-tpns) (TPNS) option are now included in **System Console** > **Email Settings** > **Push Notification Settings** as built-in options. + +### Languages + +- Added French language translation (Beta) available from **Account Settings** > **Display**. + +### Improvements + +User Interface + +- New themes can be imported into Mattermost user interface from [production documentation](https://docs.mattermost.com/help/settings/theme-colors.html#custom-theme-examples). + +### Bug Fixes + +- Characters in some posts will no longer display as HTML entities, such as `'` + +### Known Issues + +- Regression: Get Public Link downloads a file and does not product a public link. +- Edit post option appears, but doesn't work, on other users' posts in the right-hand sidebar. +- Text input box does not stay scrolled to the bottom when drafting a long message in Firefox. +- File name tooltip stays open after clicking to download. +- Unable to paste images into the text box on Firefox, Safari, and IE11. +- Archived channels are not removed from the "More" menu for the person that archived the channel until after refresh. +- First load of an empty channel does not display the introduction message. +- Search results don't highlight searches for @username, non-latin characters, or terms inside Markdown code blocks. +- Searching for a username or hashtag containing a dot returns a search where the dot is replaced with the "or" operator. +- Hashtags containing a dash incorrectly highlight in the search results. +- Emoji smileys ending with a letter at the end of a message do not auto-complete as expected. +- Incorrect formatting when a new line is added directly after a list. +- Timestamps are displayed in 12-hour format when set to 24-hour format. +- Syntax highlighting code block is missing the label for Latex documents. +- Posts from webhooks do not fire notifications to the user who created the webhook. +- Theme color vector is not updated after making custom changes to a default theme. +- Search term highlighting doesn't update on IE11 when search terms change but return the same posts. +- Team creation via SSO fails when email domain is restricted. + +### Contributors + +Many thanks to all our external contributors. In no particular order: + +- [pjgrizel](https://github.com/pjgrizel), [tbolon](https://github.com/tbolon) , [jblobel](https://github.com/jblobel), [rodrigocorsi2](https://github.com/rodrigocorsi2) , [enahum](https://github.com/enahum), [schemacs](https://github.com/schemacs), [raelga](https://github.com/raelga) + +---- + +## Release v2.1.0 + +Release date: 2016-03-16 + +### Highlights + +- New Android application now available. +- New desktop applications for Windows, Mac and Linux now in beta. +- Brazilian Portuguese translation added. + +### Security Update + +Mattermost v2.1.0 contains a security update for a cross-site scripting vulnerability in Mattermost v1.2, v1.3, v1.4 and v2.0. [Upgrading to Mattermost v2.1.0](https://docs.mattermost.com/administration/upgrade.html#upgrading-team-edition) is highly recommended. Thanks to Luke Arntson for the [RPD report](https://mattermost.com/security-vulnerability-report/?redirect_source=mm-org/). + +### New Features + +Android Application + +- New [Mattermost Android App](https://github.com/mattermost/android) supporting push notifications available for devices running Android 4.4.2+. Requires Mattermost server 2.1 and higher. See [list of tested devices](https://github.com/mattermost/android/blob/master/DEVICES.md). + +Desktop Application + +- New [Desktop Application](https://github.com/mattermost/desktop) for Windows, Mac, and Linux now available as a beta release. + +Languages + +- Added Portuguese language translation (Beta) available from **Account Settings** > **Display**. + +### Improvements + +System Console + +- Removed unused “Disable File Storage” option from the System Console as it is no longer relevant. +- Added a warning message if a system admin demotes themselves. +- System Console statistics now use a client store instead of fetching data and storing it in state. + +Messaging + +- Custom slash commands now support temporary messages that appear only to the user that issued the command. +- Username autocomplete list no longer suggests inactive users. + +Mobile + +- Significant responsiveness and speed improvements using [fastclick](https://github.com/ftlabs/fastclick). +- Team name and username are now shown in the LHS header. +- Added a button to go back to the team URL page from the login page. + +Files and Images + +- Increased the maximum size of image uploads to 24 megapixels. + +User Interface + +- Custom theme color selectors are now organized into categories. +- Add Members and Manage Members dialogs can now be filtered using a search bar. +- Deactivated members no longer appear in the channel members list. +- Keyboard focus is set to the text input box in the right-hand sidebar if a user clicks the reply icon. +- Permalinks are now displayed in a Copy Permalink dialog instead of a popover. +- Permalink option is now available from the [...] menu on messages and comments in the right-hand sidebar. +- Reply icon now only appears on-hover for messages that don’t have replies. +- Scroll bar now appears in the center channel. + +#### Bug Fixes + +- System console user management tab now shows username and email on different lines. +- Yellow text box error no longer appears when the system is connected. +- Wildcard search on MySQL databases is now fixed. +- Usernames in the center channel no longer appear as “...” on login. +- Deleted messages now delete in the right-hand sidebar and center channel without requiring a page refresh. +- Contact us email address in the footer of notification emails now uses the SupportEmail config setting instead of FeedbackEmail. +- Email addresses are now required to have at least one letter before and after the @ sign. +- Firefox desktop notifications are now fixed for some users experiencing missed notifications. +- “User is typing” message containing long usernames no longer causes text wrapping. +- Usernames appearing as “...” in the right-hand sidebar when performing a search is fixed. +- Links that end in image extensions but do not actually link to raw images no longer generate a blank image preview. +- Channel handle field in the Rename Channel dialog is now visible on themes with dark backgrounds. +- Autolinked images no longer persist after the post containing the link is deleted. +- Code theme selector on IE11 now only shows one dropdown arrow and clicking directly on the arrow opens the dropdown. +- Save/Cancel buttons for language selection in Account Settings are now formatted the same as other settings. +- Inconsistent field spacing in the Channel Info dialog is fixed. +- Recent mentions icon no longer jumps to the left of the search bar when the right-hand sidebar is opened. +- Custom slash command hints now show up in the autocomplete list. +- GIF links inside code blocks no longer auto-post the GIFs. +- Changing usernames no longer adds the old username to “words that trigger mentions”. +- Notification email footer is now translated based on the sender’s language setting. +- Slash command `/me` now posts as the user instead of a webhook message. +- Logout slash command now forces logout. +- Public links to file attachments on deleted posts no longer work. +- Error message is now shown in IE11 when uploading more than 5 files or a file over 50 MB. + +### Compatibility +Changes from v2.0 to v2.1: + +**Android** +- Mattermost Android Application is for use with Mattermost server v2.1 and higher. + +**config.json** +- The following setting was added and can be modified under `ServiceSettings` in `config.json` or the System Console. + - `"AllowCorsFrom": ""` to allow the system to serve HTTP requests to other domains specified. + +#### Known Issues + +- Edit post option appears, but doesn't work, on other users' posts in the right-hand sidebar. +- Text input box does not stay scrolled to the bottom when drafting a long message in Firefox. +- Some characters in posts may display as HTML entities, such as `'`. This can be fixed by switching to a different language and then back again. +- File name tooltip stays open after clicking to download. +- Unable to paste images into the text box on Firefox, Safari, and IE11. +- Archived channels are not removed from the "More" menu for the person that archived the channel until after refresh. +- First load of an empty channel does not display the introduction message. +- Search results don't highlight searches for @username, non-latin characters, or terms inside Markdown code blocks. +- Searching for a username or hashtag containing a dot returns a search where the dot is replaced with the "or" operator. +- Hashtags containing a dash incorrectly highlight in the search results. +- Emoji smileys ending with a letter at the end of a message do not auto-complete as expected. +- Incorrect formatting when a new line is added directly after a list. +- Timestamps are displayed in 12-hour format when set to 24-hour format. +- Syntax highlighting code block is missing the label for Latex documents. +- Posts from webhooks do not fire notifications to the user who created the webhook. +- Theme color vector is not updated after making custom changes to a default theme. +- Search term highlighting doesn't update on IE11 when search terms change but return the same posts. +- Team creation via SSO fails when email domain is restricted. + +#### Contributors + +Many thanks to all our external contributors. In no particular order: + +- [yuya-oc](https://github.com/yuya-oc), [rodrigocorsi2](https://github.com/rodrigocorsi2), [enahum](https://github.com/enahum), [khoa-le](https://github.com/khoa-le), [alanmoo](https://github.com/alanmoo), [daizenberg](https://github.com/daizenberg), [GuillaumeAmat](https://github.com/GuillaumeAmat), [kernicPanel](https://github.com/kernicPanel), [timlyo](https://github.com/timlyo), [ttyniwa](https://github.com/ttyniwa) + +---- + +## Release v2.0.0 + +Expected Release date: 2016-02-16 + +### Highlights + +#### Incremented Version Number: Mattermost "2.0" + +- Version number incremented from "1.x" to "2.x" indicating major product changes, including: + +##### Localization + +- Addition of localization support to entire user interface plus error and log messages +- Added Spanish language translation (Beta quality) available from **Account Settings** > **Display** + +##### Enhanced Support for Mobile Devices + +- BREAKING CHANGE to APIs: New Android and updated iOS apps require Mattermost server 2.0 and higher +- iOS added app support for GitLab single sign-on +- iOS added app support for AD/LDAP single sign-on (Enterprise Edition only) + +##### Upgrade and Deployment Improvements +- Mattermost v2.0 now upgrades from up to two previous major builds (e.g. v1.4.x and v1.3.x) +- Added option to allow use of insecure TLS outbound connections to allow use of self-signed certificates + +### New Features + +Localization + +- Addition of localization support to entire user interface plus error and log messages +- Added Spanish language translation (Beta quality) available from **Account Settings** > **Display** + +Slash Commands + +- Added [Slack-compatible slash commands](https://developers.mattermost.com/integrate/slash-commands/slack/) to integrate with external systems + +iOS + +- [iOS app](https://github.com/mattermost/ios) added support for GitLab single sign-on +- [iOS app](https://github.com/mattermost/ios) added support for AD/LDAP single sign-on (Enterprise Edition only) + +Android + +- New open source Android application compatible with Mattermost 2.0 and higher + +System Console + +- Added **Site Reports** to view system statistics on posts, channels and users. + +### Improvements + +Upgrading + +- Mattermost v2.0 now upgrades from up to two previous major builds (e.g. v1.4.x and v1.3.x). + +Files and Images + +- Public links to images and files created by users no longer expire +- OGG attachments now play in preview window on Chrome and Firefox + +Onboarding + +- “Get Team Invite Link” option is disabled from the main menu if user creation is disabled for the team +- Tutorial colors improved to provide higher contrast with new default theme + +Authentication + +- Added ability to sign in with username as an alternative to email address +- Switching from email to SSO for sign in now updates email address to use the SSO email + +System Console + +- Added option to allow use of insecure TLS outbound connections to allow use of self-signed certificates +- Removed unused "Disable File Storage" option from **System Console** > **File Storage** +- Added warning if a user demotes their account from System Administrator + +Search + +- Hashtag search is no longer case sensitive +- System messages no longer appear in search results +- Date separator added to search results +- Moved the recent mentions icon to the right of the search bar + +Messaging +- Changed the comment bubble to a reply arrow to make post replies and the right-hand sidebar more discoverable +- Time stamp next to sequential posts made by users now shows HH:MM instead of on-hover timestamp +- Code blocks now support horizontal scrolling if content exceeds the max width + +User Interface + +- Away status added to note users who have been idle for more than 5 minutes. +- Long usernames are now truncated in the center channel and right-hand sidebar +- Added more favicon sizes for home screen icons on mobile devices + +#### Bug Fixes + +- Incorrect “Mattermost unreachable” error on iOS no longer appears +- Dialog to confirm deletion of a post now supports hitting “ENTER” to confirm deletion. +- Keyboard focus on the New Channel modal on IE11 is now contained within the text box. +- LHS indicator for “Unread Posts Above/Below” now displays on IE11 +- Unresponsive UI when viewing a permalink is fixed if a user clicks outside the text on the "Click here to jump to recent messages" bar. +- Dismissed blue bar error messages no longer re-appear on page refresh. +- Console error is no longer thrown on first page load in Firefox and Edge. +- Console error and missing notification is fixed for the first direct message received from any user. +- Comment bubble in Firefox no longer appears with a box around it on-hover. +- Home screen icons on Android and iOS devices now appear with the Mattermost logo. +- Switching channels now clears the “user is typing” message below the text input box. +- iOS devices are no longer detected as “unknown” devices in the session history. + +### Compatibility +Changes from v1.4 to v2.0: + +**iOS** + +Mattermost iOS app v2.0 requires Mattermost server v2.0 and higher. + +**config.json** + +Multiple setting options were added to `config.json`. Below is a list of the additions and their default values on install. The settings can be modified in `config.json` or the System Console. + +- Under `ServiceSettings` in `config.json`: + - `"EnableCommands": false` to set whether users can create slash commands from **Account Settings** > **Integrations** > **Commands** + - `"EnableOnlyAdminIntegrations": true` to restrict integrations to being created by admins only. + - `"EnableInsecureOutgoingConnections": false` sets whether outgoing HTTPS requests can accept unverified, self-signed certificates. + - Optional: `"WebsocketSecurePort" : 443` sets the port on which the secured WebSocket will listen using the `wss` protocol. If this setting is not present in `config.json`, it defaults to `443`. + - Optional: `"WebsocketPort": 80` sets the port on which the unsecured WebSocket will listen using the `ws` protocol. If this setting is not present in `config.json`, it defaults to `80`. + +- Under `EmailSettings` in `config.json`: + - `"EnableSignInWithEmail": true` allows users to sign in using their email. + - `"EnableSignInWithUsername": false` sets whether users can sign in with their username. Typically only used when email verification is disabled. + +**Localization** + +There are two new directories for i18n localization JSON files: +- mattermost-server/i18n for server-side localization files +- mattermost-webapp/i18n for client-side localization files + +#### Database Changes from v1.4 to v2.0 + +The following is for informational purposes only, no action needed. Mattermost automatically upgrades database tables from the previous version's schema using only additions. + +##### Users Table +1. Added `Locale` column + +##### Licenses Table +1. Added `Licenses` Table + +##### Commands Table +1. Added `Commands` Table + +#### Known Issues + +- Navigating to a page with new messages containing inline images added via markdown causes the channel to scroll up and down while loading the inline images. +- Microsoft Edge does not yet support drag and drop for file attachments. +- No error message on IE11 when uploading more than 5 files or a file over 50 MB. +- File name tooltip stays open after clicking to download. +- Scroll bar does not appear in the center channel. +- Unable to paste images into the text box on Firefox, Safari, and IE11. +- Importing from Slack fails to load channels in certain cases. +- System Console > Teams > Statistics > Newly Created Users shows all users as created "just now". +- Username and email display on single line in System Console user management tab. +- Searching for a phrase in quotations returns more than just the phrase on installations with a Postgres database. +- Archived channels are not removed from the "More" menu for the person that archived the channel until after refresh. +- First load of an empty channel does not display the introduction message. +- Search results don't highlight searches for @username, non-latin characters, or terms inside Markdown code blocks. +- Searching for a username or hashtag containing a dot returns a search where the dot is replaced with the "or" operator. +- Search term highlighting doesn't update on IE11 when search terms change but return the same posts. +- Hashtags less than three characters long are not searchable. +- Hashtags containing a dash incorrectly highlight in the search results. +- Users remain in the channel counter after being deactivated. +- Permalinks for the second message or later consecutively sent in a group by the same author displaces the copy link popover or causes an error. +- Emoji smileys ending with a letter at the end of a message do not auto-complete as expected. +- Logout slash command does not force a logout. +- Incorrect formatting when a new line is added directly after a list. +- Timestamps are displayed in 12-hour format when set to 24-hour format. +- GIF links inside code blocks auto-post the GIFs. +- Syntax highlighting code block is missing the label for Latex documents. +- Deleted messages don't delete in the right-hand sidebar until a page refresh. + +#### Contributors + +Special thanks to [enahum](https://github.com/enahum) for creating the Spanish localization! + +Many thanks to all our external contributors. In no particular order: + +- [enahum](https://github.com/enahum), [trashcan](https://github.com/trashcan), [khoa-le](https://github.com/khoa-le), [alanmoo](https://github.com/alanmoo), [fallenby](https://github.com/fallenby), [loafoe](https://github.com/loafoe), [gramakri](https://github.com/gramakri), [pawelad](https://github.com/pawelad), [cifvts](https://github.com/cifvts), [rosskusler](https://github.com/rosskusler), [apskim](https://github.com/apskim) + +---- + +## Release v1.4.0 + +Expected Release date: 2016-01-16 + +### Release Highlights + +#### Data Center Support + +- Deployment guides on Red Hat Enterprise Linux 6 and 7 now available +- Legal disclosure and support links (terms of service, privacy policy, help, about, and support email) now configurable +- Over a dozen new configuration options in System Console + +#### Mobile Experience + +- iOS reference app now available from iTunes +- Date headers now show when scrolling on mobile, so you can quickly see when messages were sent +- Added "rapid scroll" support for jumping quickily to bottom of channels on mobile + +### New Features + +Mobile Experience +- Date headers now show when scrolling on mobile, so you can quickly see when messages were sent +- Added "rapid scroll" support for jumping quickily to bottom of channels on mobile + +Authentication + +- Accounts can now switch between email and GitLab SSO sign-in options +- New ability to customize session token length + +System Console + +- Added **Legal and Support Settings** so System Administrators can change the default Terms of Service, Privacy Policy, and Help links +- Under **Service Settings** added options to customize expiry of web, mobile and SSO session tokens, expiry of caches in memory, and an EnableDeveloper option to turn on Developer Mode which alerts users to any console errors that occur + +### Improvements + +Performance and Testing + +- Added logging for email and push notifications events in DEBUG mode + +Integrations + +- Added support to allow optional parameters in the `Content-Type` of incoming webhook requests + +Files and Images + +- Animated GIFs autoplay in the image previewer + +Notifications and Email + +- Changed email notifications to display the server's local timezone instead of UTC + +User Interface + +- Updated the "About Mattermost" dialog formatting +- Going to domain/teamname now goes to the last channel of your previous session, instead of Town Square +- Various improvements to mobile UI, including a floating date indicator and the ability to quickly scroll to the bottom of the channel + +#### Bug Fixes + +- Fixed issue where usernames containing a "." did not get mention notifications +- Fixed issue where System Console did not save the "Send push notifications" setting +- Fixed issue with Font Display cancel button not working in Account Settings menu +- Fixed incorrect default for "Team Name Display" settings +- Fixed issue where various media files appeared broken in the media player on some browsers +- Fixed cross-contamination issue when multiple accounts log into the same team on the same browser +- Fixed issue where color pickers did not update when a theme was pasted in +- Increased the maximum number of channels + +### Compatibility + +#### Config.json Changes from v1.3 to v1.4 + +Multiple settings were added to `config.json`. Below is a list of the changes and their new default values in a fresh install. + +The following options can be modified in the System Console: + +- Under `ServiceSettings` in `config.json`: + - Added: `"EnableDeveloper": false` to set whether developer mode is enabled, which alerts users to any console errors that occur + - Added: `"SessionLengthWebInDays" : 30` to set the number of days before web sessions expire and users will need to log in again + - Added: `"SessionLengthMobileInDays" : 30` to set the number of days before native mobile sessions expire + - Added: `"SessionLengthSSOInDays" : 30` to set the number of days before SSO sessions expire + - Added: `"SessionCacheInMinutes" : 10` to set the number of minutes to cache a session in memory +- Added `SupportSettings` section to `config.json`: + - Added: `"TermsOfServiceLink": "/static/help/terms.html"` to allow System Administrators to set the terms of service link + - Added: `"PrivacyPolicyLink": "/static/help/privacy.html"` to allow System Administrators to set the privacy policy link + - Added: `"AboutLink": "/static/help/about.html"` to allow System Administrators to set the about page link + - Added: `"HelpLink": "/static/help/help.html"` to allow System Administrators to set the help page link + - Added: `"ReportAProblemLink": "/static/help/report_problem.html"` to allow System Administrators to set the home page for the support website + - Added: `"SupportEmail":"feedback@mattermost.com"` to allow System Administrators to set an email address for feedback and support requests + +The following options are not present in the System Console, and can be modified manually in the `config.json` file: + +- Under `FileSettings` in `config.json`: + - Added: `"AmazonS3Endpoint": ""` to set an endpoint URL for an Amazon S3 instance + - Added: `"AmazonS3BucketEndpoint": ""` to set an endpoint URL for Amazon S3 buckets + - Added: `"AmazonS3LocationConstraint": false` to set whether the S3 region is location constrained + - Added: `"AmazonS3LowercaseBucket": false` to set whether bucket names are fully lowercase or not + +#### Known Issues + +- When navigating to a page with new messages as well as message containing inline images added via markdown, the channel may move up and down while loading the inline images +- Microsoft Edge does not yet support drag and drop +- No scroll bar in center channel +- Pasting images into text box fails to upload on Firefox, Safari, and IE11 +- Public links for attachments attempt to download the file on IE, Edge, and Safari +- Importing from Slack breaks @mentions and fails to load in certain cases with comments on files +- System Console > TEAMS > Statistics > Newly Created Users shows all of the users are created "just now" +- Favicon does not always become red when @mentions and direct messages are received on an inactive browser tab +- Searching for a phrase in quotations returns more than just the phrase on Mattermost installations with a Postgres database +- Deleted/Archived channels are not removed from the "More" menu of the person that deleted/archived the channel until after refresh +- Search results don't highlight searches for @username, non-latin characters, or terms inside Markdown code blocks +- Searching for a username or hashtag containing a dot returns a search where the dot is replaced with the "or" operator +- Hashtags less than three characters long are not searchable +- After deactivating a team member, the person remains in the channel counter +- Certain symbols (<,>,-,+,=,%,^,#,*,|) directly before or after a hashtag cause the message to not show up in a hashtag search +- Security tab > Active Sessions reports iOS devices as "unknown" +- Getting a permalink for the second message or later consecutively sent in a group by the same author displaces the copy link popover or causes an error + +#### Contributors + +Many thanks to our external contributors. In no particular order: + +- [npcode](https://github.com/npcode), [hjf288](https://github.com/hjf288), [apskim](https://github.com/apskim), [ejm2172](https://github.com/ejm2172), [hvnsweeting](https://github.com/hvnsweeting), [benburkert](https://github.com/benburkert), [erikthered](https://github.com/erikthered) + +---- + +## Release v1.3.0 + +Release date: 2015-12-16 + +### Release Highlights + +#### iOS App + +- New [Mattermost iOS App](https://github.com/mattermost/ios) now available for iPhone, iPad, and iPod Touch +- New [Mattermost Push Notification Service](https://github.com/mattermost/push-proxy) to relay notifications to custom iOS applications + +#### Search Upgrades + +- Jump to search results in archives using new message permalinks +- It's easier to find what you're looking for with improved auto-complete in search + +#### Advanced Formatting + +- Express more in symbols, with new emoji auto-complete +- Express more in numbers, with rendering of mathematical expressions using Latex (start code blocks with ```latex) +- Personalize your look with new custom font settings under **Account Settings** > **Display** > **Display Font** + +### New Features + +Authentication +- Added unofficial SSO support for GitHub.com and GitHub Enterprise using GitLab UI + +Archives +- Added permalink feature that lets users link to a post in the message archives +- Added ability to "Jump" to archives from a search result + +Account Settings +- Added "Preview pre-release features" setting, to allow user to preview early features ahead of their official release +- Added "Display font" setting, so users can select which font to use + +Messaging & Comments +- Added in-line previews for links from select websites and for URLs pointing to an image (enabled via Account Settings -> Advanced -> Preview pre-release features) +- Added emoji autocomplete + +Extras +- Added `/loadtest url` tool for manually [testing text processing](https://github.com/mattermost/mattermost/tree/master/server/tests) + +### Improvements + +Performance +- Updated getProfiles service to return less data +- Refactored several modals to use React-Boostrap +- Refactored the center channel + +Messaging & Comments +- Added Markdown support for task lists +- Added "Help" link for messaging +- Added ability to preview a Markdown message before sending (enabled via Account Settings -> Advanced -> Preview pre-release features) + +Onboarding +- Minor upgrades to tutorial + +User Interface +- Visually combined sequential messages from the same user +- Added ability to rename "Town Square" +- Teammate name display option now applies to messages and comments +- Menus and search improved on mobile UI +- Switched to Emoji One style emojis + +#### Bug Fixes + +- Removed the @all mention to keep users from accidentally spamming team sites +- Fixed bug where the member list only showed "20" members for channels with more than 20 members +- Fixed bug where the channel sidebar didn't order correctly on Postgres databases +- Fixed bug where search results did not highlight when searching with quotation marks, wildcard, or in: and from: modifiers +- Fixed bug with the cancel button not properly resetting the text in some account settings fields +- Fixed bug where editing a post to be empty caused a 404 error +- Fixed bug where logging out did not work properly on IE11 +- Fixed issue where refreshing the page with the right hand sidebar open caused "..." to show up in place of usernames +- Fixed issue where invite to channel modal did not update properly when switching between channels + +### Compatibility + +#### Config.json Changes from v1.2 to v1.3 + +Multiple settings were added to `config.json`. These options can be modified in the System Console, or manually updated in the existing config.json file. This is a list of changes and their new default values in a fresh install: +- Under `EmailSettings` in `config.json`: + - Removed: `"ApplePushServer": ""` which is replaced with `SendPushNotifications` and `PushNotificationServer` + - Removed: `"ApplePushCertPublic": ""` which is replaced with `SendPushNotifications` and `PushNotificationServer` + - Removed: `"ApplePushCertPrivate": ""` which is replaced with `SendPushNotifications` and `PushNotificationServer` + - Added: `"SendPushNotifications": false` to control whether mobile push notifications are sent to the server specified in `PushNotificationServer` + - Added: `"PushNotificationServer": ""` to specify the address of the proxy server that re-sends push notifications to their respective services like APNS (Apple Push Notification Services) + +#### Known Issues + +- System Console does not save Email Settings when "Save" is clicked +- When navigating to a page with new messages as well as message containing inline images added via markdown, the channel may move up and down while loading the inline images +- Microsoft Edge does not yet support drag and drop +- Media files of type .avi .mkv .wmv .mov .flv .mp4a do not play properly +- No scroll bar in center channel +- Pasting images into text box fails to upload on Firefox, Safari, and IE11 +- Slack import @mentions break +- Usernames containing a "." do not get mention notifications + +#### Contributors + +Many thanks to our external contributors. In no particular order: + +- [florianorben](https://github.com/florianorben), [npcode](https://github.com/npcode), [42wim](https://github.com/42wim), [cifvts](https://github.com/cifvts), [rompic](https://github.com/rompic), [jdhoek](https://github.com/jdhoek), [Tsynapse](https://github.com/Tsynapse), [alexgaribay](https://github.com/alexgaribay), [vladikoff](https://github.com/vladikoff), [jonathanwiesel](https://github.com/jonathanwiesel), [tamtamchik](https://github.com/tamtamchik) + +---- + +## Release v1.2.1 + +- **Released:** 2015-11-16 + +### Security Notice + +Mattermost v1.2.1 is a Quality Release addressing a security issue in v1.2.0 affecting a newly introduced outgoing webhooks feature. Specifically, in v1.2.0 there was a check missing from outgoing webhooks, so a team member creating outgoing webhooks could in theory find a way to listen to messages in private channels containing popular words like "a", "the", "at", etc. For added security, Mattermost v1.2.1 now installs with incoming and outgoing webhooks disabled by default. + +To limit the impact of this security issue, Mattermost v1.2.0 has been removed from the source repo. It is recommended that anyone who's installed v1.2.0 upgrade to v1.2.1 via [the procedure described in the Mattermost Upgrade Guide](https://docs.mattermost.com/administration/upgrade.html#upgrade-team-edition-for-2-2-x-and-earlier). + +### Release Highlights + +#### Outgoing webhooks + +- Mattermost users can now interact with external applications using [outgoing webhooks](https://developers.mattermost.com/integrate/webhooks/outgoing/) +- An [application template](https://github.com/mattermost/mattermost-integration-giphy) demonstrating user queries sent to the Giphy search engine via Mattermost webhooks now available +- A community application, [Matterbridge](https://github.com/42wim/matterbridge?files=1), shows how to use webhooks to connect Mattermost with IRC + +#### Search Scope Modifiers + +- Adding search term `in:[channel_url_name]` now limits searches within a specific channel +- Adding search term `from:[username]` now limits searches to messages from a specific user + +#### Syntax Highlighting + +- Syntax highlight for code blocks now available for `Diff, Apache, Makefile, HTTP, JSON, Markdown, JavaScript, CSS, nginx, ObjectiveC, Python, XML, Perl, Bash, PHP, CoffeeScript, C, SQL, Go, Ruby, Java, and ini` + +#### Usability Improvements + +- Added tutorial to teach new users how to use Mattermost +- Various performance improvements to support teams with hundreds of users +- Direct Messages "More" menu now lets you search for users by username and real name + +### Improvements + +Onboarding + +- New tutorial explaining how to use Mattermost for new users + +Messaging and Notifications + +- Users can now search for teammates to add to **Direct Message** list via **More** menu +- Users can now personalize Direct Messages list by removing users listed +- Link previews - Adding URL with .gif file adds image below message +- Added new browser tab alerts to indicate unread messages and mentions + +Search + +- Adding search term `in:[channel_url_name]` now limits searches within a specific channel +- Adding search term `from:[username]` now limits searches to messages from a specific user +- Tip explaining search options when clicking into search box + +Integrations + +- [Outgoing webhooks](https://developers.mattermost.com/integrate/webhooks/outgoing/) now available +- Made available [application template showing outgoing webhooks working with Mattermost and external application](https://github.com/mattermost/mattermost-integration-giphy) + +User Interface + +- Member list in Channel display now scrollable, and includes Message button to message channel members directly +- Added ability to edit previous message by hitting UP arrow +- Syntax highlighting added for code blocks + - Languages include `Diff, Apache, Makefile, HTTP, JSON, Markdown, Java, CSS, nginx, ObjectiveC, Python, XML, Perl, Bash, PHP, CoffeeScript, C, SQL, Go, Ruby, Java, and ini`. + - Use by adding the name of the language on the first link of the code block, for example: ```python + - Syntax color theme can be defined under **Account Settings** > **Appearance Settings** > **Custom Theme** +- Updated Drag & Drop UI +- Added 24 hour time display option + +Team Settings + +- Added Team Settings option to include account creation URL on team login page +- Added Team Settings option to include link to given team on root page +- Ability to rotate invite code for invite URL + +Extras + +- Added `/shrug KEYWORD` command to output: `¯\_(ツ)_/¯ KEYWORD` +- Added `/me KEYWORD` command to output: _`KEYWORD`_ +- Added setting option to send a message on control-enter instead of enter + +System Console + +- New statistics page +- Configurable option to create an account directly from team page + +#### Bug Fixes + +- Various fixes to theme colors +- Fixed issue with the centre channel scroll position jumping when right hand side was opened and closed +- Added support for simultaneous login to different teams in different browser tabs +- Incoming webhooks no longer disrupted when channel is deleted +- You can now paste a Mattermost incoming webhook URL into the same field designed for a Slack URL and integrations will work + +### Compatibility + +- IE 11 new minimum version for IE, since IE 10 share fell below 5% on desktop +- Safari 9 new minimum version for Safari, since Safari 7 and 8 fell below 1% each on desktop + +#### Config.json Changes from v1.1 to v1.2 + +Multiple settings were added to `config.json`. These options can be modified in the System Console, or manually updated in the existing config.json file. This is a list of changes and their new default values in a fresh install: +- Under `TeamSettings` in `config.json`: + - Added: `"RestrictTeamNames": true` to control whether team names can contain reserved words like www, admin, support, test, etc. + - Added: `"EnableTeamListing": false` to control whether teams can be listed on the root page of the site +- Under `ServiceSettings` in `config.json` + - Added: `"EnableOutgoingWebhooks": false` to control whether outgoing webhooks are enabled + - Changed: `"EnableIncomingWebhooks": true` to `"EnableIncomingWebhooks": false` to turn incoming webhooks off by default, to increase security of default install. Documentation updated to enable webhooks before use. + +#### Database Changes from v1.1 to v1.2 + +The following is for informational purposes only, no action needed. Mattermost automatically upgrades database tables from the previous version's schema using only additions. Sessions table is dropped and rebuilt, no team data is affected by this. + +##### Channels Table +1. Renamed `Description` to `Header` +2. Added `Purpose` column with type `varchar(1024)` + +##### Preferences Table +1. Added `Preferences` Table + +##### Teams Table +1. Added `InviteId` column with type `varchar(32)` +2. Added `AllowOpenInvite` column with type `tinyint(1)` +3. Added `AllowTeamListing` column with type `tinyint(1)` +4. Added `idx_teams_invite_id` index + +#### Known Issues + +- When navigating to a page with new messages as well as message containing inline images added via markdown, the channel may move up and down while loading the inline images +- Microsoft Edge does not yet support drag and drop +- After upgrading to v1.2 existing users will see the newly added tutorial tips upon login (this is a special case for v1.2 and will not happen in future upgrades) +- Channel list becomes reordered when there are lowercase channel names in a Postgres database +- Member list only shows "20" members for channels with more than 20 members +- Searches containing punctuation are not highlighted in the results (including in: or from: search modifiers and searches with quotations) +- Media files of type .avi .mkv .wmv .mov .flv .mp4a do not play properly +- Editing a post so that it's text is blank (which should delete it) throws a 404 +- No scroll bar in centre channel +- Theme color import from Slack fails to import the “Active Channel” selection color +- Pasting images into text box fails to upload on Firefox and Safari +- Users cannot claim accounts imported from Slack via password reset +- Slack import @mentions break + +#### Contributors + +Many thanks to our external contributors. In no particular order: + +- [florianorben](https://github.com/florianorben), [trashcan](https://github.com/trashcan), [girishso](https://github.com/girishso), [apaatsio](https://github.com/apaatsio), [jlebleu](https://github.com/jlebleu), [stasvovk](https://github.com/stasvovk), [mcmillhj](https://github.com/mcmillhj), [sharms](https://github.com/sharms), [jvasallo](https://github.com/jvasallo), [layzerar](https://github.com/layzerar), [optimistiks](https://github.com/optimistiks), [Tsynapse](https://github.com/Tsynapse), [vinnymac](https://github.com/vinnymac), [yuvipanda](https://github.com/yuvipanda), [toyorg](https://github.com/toyorg) + +---- + +## Release v1.2.0 (Redacted Release) + +- **Final release:** 2015-11-16 (**Note:** This release was removed from public availability and replaced by v1.2.1 owing to a security issue with the new outgoing webhooks feature. See v1.2.1 Release Notes for details). + +## Release v1.1.1 (Quality Release) + +Released 2015-10-20 + +### About Quality Releases + +This is a Quality Release (v1.1.1) and recommended only for users needing a fix to the specific issue listed below. All other users should use the most recent major stable build release (v1.1.0). + +[View more information on Mattermost release numbering](https://docs.mattermost.com/process/release-process.html#release-numbering). + +### Release Purpose + +#### Provide option for upgrading database from Mattermost v0.7 to v1.1 + +Upgrading Mattermost v0.7 to Mattermost v1.1 originally required installing Mattermost v1.0 to upgrade from the Mattermost v0.7 database, followed by an install of Mattermost v1.1. + +This was problematic for installing Mattermost with GitLab omnibus since GitLab 8.0 contained Mattermost v0.7 and GitLab 8.1 was to include Mattermost v1.1 + +Therefore Mattermost v1.1.1 was created that can upgrade the database in Mattermost v0.7 to Mattermost v1.1 directly. + +Users who configured Mattermost v0.7 within GitLab via the `config.json` file should consult [documentation on upgrading configurations from Mattermost v0.7 to Mattermost v1.1](https://docs.mattermost.com/administration/upgrade.html#upgrade-team-edition-for-2-2-x-and-earlier). + +#### Removes 32-char limit on salts + +Mattermost v1.1 introduced a 32-char limit on salts that broke the salt generating in GitLab and this restriction was removed for 1.1.1. + +## Release v1.1.0 + +Released: 2015-10-16 + +### Release Highlights + +#### Incoming Webhooks + +Mattermost now supports incoming webhooks for channels and private groups. This developer feature is available from the Account Settings -> Integrations menu. Documentation on how developers can use the webhook functionality to build custom integrations, along with samples, is available at https://docs.mattermost.com/guides/integration.html. + +### Improvements + +Integrations + +- Improved support for incoming webhooks, including the ability to override a username and post as a bot instead + +Documentation + +- Added documentation on config.json and System Console settings +- Docker Toolbox replaces deprecated Boot2Docker instructions in container install documentation + +Theme Colors + +- Improved appearance of dark themes + +System Console + +- Client side errors now written to server logs +- Added "EnableSecurityFixAlert" option to receive alerts on relevant security fix alerts +- Various improvements to System Console UI and help text + +Messaging and Notifications + +- Replaced "Quiet Mode" in the Channel Notification Settings with an option to only show unread indicator when mentioned + +### Bug Fixes + +- Fixed regression causing "Get Public Link" on images not to work +- Fixed bug where certain characters caused search errors +- Fixed bug where System Administrator did not have Team Administrator permissions +- Fixed bug causing scrolling to jump when the right hand sidebar opened and closed + +### Known Issues + +- Slack import is unstable due to change in Slack export format +- Uploading a .flac file breaks the file previewer on iOS + +### Compatibility + +#### Config.json Changes from v1.0 to v1.1 + +##### Service Settings + +Multiple settings were added to `config.json` and System Console UI. Prior to upgrading the Mattermost binaries from the previous versions, these options would need to be manually updated in existing config.json file. This is a list of changes and their new default values in a fresh install: +- Under `ServiceSettings` in `config.json`: + - Added: `"EnablePostIconOverride": false` to control whether webhooks can override profile pictures + - Added: `"EnablePostUsernameOverride": false` to control whether webhooks can override profile pictures + - Added: `"EnableSecurityFixAlert": true` to control whether the system is alerted to security updates + +#### Database Changes from v1.0 to v1.1 + +The following is for informational purposes only, no action needed. Mattermost automatically upgrades database tables from the previous version's schema using only additions. Sessions table is dropped and rebuilt, no team data is affected by this. + +##### ChannelMembers Table +1. Removed `NotifyLevel` column +2. Added `NotifyProps` column with type `varchar(2000)` and default value `{}` + +### Contributors + +Many thanks to our external contributors. In no particular order: + +- [chengweiv5](https://github.com/chengweiv5), [pstonier](https://github.com/pstonier), [teviot](https://github.com/teviot), [tmuwandi](https://github.com/tmuwandi), [driou](https://github.com/driou), [justyns](https://github.com/justyns), [drbaker](https://github.com/drbaker), [thomas9987](https://github.com/thomas9987), [chuck5](https://github.com/chuck5), [sjmog](https://github.com/sjmog), [chengkun](https://github.com/chengkun), [sexybern](https://github.com/sexybern), [tomitm](https://github.com/tomitm), [stephenfin](https://github.com/stephenfin) + +---- + +## Release v1.0.0 + +Released 2015-10-02 + +### Release Highlights + +#### Markdown + +Markdown support is now available across messages, comments and channel descriptions for: + +- **Headings** - in five different sizes to help organize your thoughts +- **Lists** - both numbered and bullets +- **Font formatting** - including **bold**, _italics_, ~~strikethrough~~, `code`, links, and block quotes) +- **In-line images** - useful for creating buttons and status messages +- **Tables** - for keeping things organized +- **Emoticons** - translation of emoji codes to images like :sheep: :boom: :rage1: :+1: + +See [documentation](https://docs.mattermost.com/help/messaging/formatting-text.html) for full details. + +#### Themes + +Themes as been significantly upgraded in this release with: + +- 4 pre-set themes, two light and two dark, to customize your experience +- 18 detailed color setting options to precisely match the colors of your other tools or preferences +- Ability to import themes from Slack + +#### System console and command line tools + +Added new web-based System Console for managing instance level configuration. This lets IT admins conveniently: + +- _access core settings_, like server, database, email, rate limiting, file store, SSO, and log settings, +- _monitor operations_, by quickly accessing log files and user roles, and +- _manage teams_, with essential functions such as team role assignment and password reset + +In addition new command line tools are available for managing Mattermost system roles, creating users, resetting passwords, getting version info and other basic tasks. + +Run `./platform -h` for documentation using the new command line tool. + +### New Features + +Messaging, Comments and Notifications + +- Full markdown support in messages, comments, and channel description +- Support for emoji codes rendering to image files + +Files and Images + +- Added ability to play video and audio files + +System Console + +- UI to change config.json settings +- Ability to view log files from console +- Ability to reset user passwords +- Ability for IT admin to manage members across multiple teams from single interface + +User Interface + +- Ability to set custom theme colors +- Replaced single color themes with pre-set themes +- Added ability to import themes from Slack + +Integrations + +- (Preview) Initial support for incoming webhooks + +### Improvements + +Documentation + +- Added production installation instructions +- Updated software and hardware requirements documentation +- Re-organized install instructions out of README and into separate files +- Added Code Contribution Guidelines +- Added new hardware sizing recommendations +- Consolidated licensing information into LICENSE.txt and NOTICE.txt +- Added markdown documentation + +Performance + +- Enabled Javascript optimizations +- Numerous improvements in center channel and mobile web + +Code Quality + +- Reformatted Javascript per Mattermost Style Guide + +User Interface + +- Added version, build number, build date and build hash under Account Settings -> Security + +Licensing + +- Compiled version of Mattermost v1.0.0 now available under MIT license + +### Bug Fixes + +- Fixed issue so that SSO option automatically set `EmailVerified=true` (it was false previously) + +### Compatibility + +A large number of settings were changed in `config.json` and a System Console UI was added. This is a very large change due to Mattermost releasing as v1.0 and it's unlikely a change of this size would happen again. + +Prior to upgrading the Mattermost binaries from the previous versions, the below options would need to be manually updated in your existing config.json file to migrate successfully. This is a list of changes and their new default values in a fresh install: +#### Config.json Changes from v0.7 to v1.0 + +##### Service Settings + +- Under `ServiceSettings` in `config.json`: + - Moved: `"SiteName": "Mattermost"` which was added to `TeamSettings` + - Removed: `"Mode" : "dev"` which deprecates a high level dev mode, now replaced by granular controls + - Renamed: `"AllowTesting" : false` to `"EnableTesting": false` which allows the use of `/loadtest` slash commands during development + - Removed: `"UseSSL": false` boolean replaced by `"ConnectionSecurity": ""` under `Security` with new options: _None_ (`""`), _TLS_ (`"TLS"`) and _StartTLS_ ('"StartTLS"`) + - Renamed: `"Port": "8065"` to `"ListenAddress": ":8065"` to define address on which to listen. Must be prepended with a colon. + - Removed: `"Version": "developer"` removed and version information now stored in `model/version.go` + - Removed: `"Shards": {}` which was not used + - Moved: `"InviteSalt": "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"` to `EmailSettings` + - Moved: `"PublicLinkSalt": "TO3pTyXIZzwHiwyZgGql7lM7DG3zeId4"` to `FileSettings` + - Renamed and Moved `"ResetSalt": "IPxFzSfnDFsNsRafZxz8NaYqFKhf9y2t"` to `"PasswordResetSalt": "vZ4DcKyVVRlKHHJpexcuXzojkE5PZ5eL"` and moved to `EmailSettings` + - Removed: `"AnalyticsUrl": ""` which was not used + - Removed: `"UseLocalStorage": true` which is replaced by `"DriverName": "local"` in `FileSettings` + - Renamed and Moved: `"StorageDirectory": "./data/"` to `Directory` and moved to `FileSettings` + - Renamed: `"AllowedLoginAttempts": 10` to `"MaximumLoginAttempts": 10` + - Renamed, Reversed and Moved: `"DisableEmailSignUp": false` renamed `"EnableSignUpWithEmail": true`, reversed meaning of `true`, and moved to `EmailSettings` + - Added: `"EnableOAuthServiceProvider": false` to enable OAuth2 service provider functionality + - Added: `"EnableIncomingWebhooks": false` to enable incoming webhooks feature + +##### Team Settings + +- Under `TeamSettings` in `config.json`: + - Renamed: `"AllowPublicLink": true` renamed to `"EnablePublicLink": true` and moved to `FileSettings` + - Removed: `AllowValetDefault` which was a guest account feature that is deprecated + - Removed: `"TermsLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"PrivacyLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"AboutLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"HelpLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"ReportProblemLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"TourLink": "/static/help/configure_links.html"` removed since option didn't need configuration + - Removed: `"DefaultThemeColor": "#2389D7"` removed since theme colors changed from 1 to 18, default theme color option may be added back later after theme color design stablizes + - Renamed: `"DisableTeamCreation": false` to `"EnableUserCreation": true` and reversed + - Added: ` "EnableUserCreation": true` added to disable ability to create new user accounts in the system + +##### SSO Settings + +- Under `SSOSettings` in `config.json`: + - Renamed Category: `SSOSettings` to `GitLabSettings` + - Renamed: `"Allow": false` to `"Enable": false` to enable GitLab SSO + +##### AWS Settings + +- Under `AWSSettings` in `config.json`: + - This section was removed and settings moved to `FileSettings` + - Renamed and Moved: `"S3AccessKeyId": ""` renamed `"AmazonS3AccessKeyId": "",` and moved to `FileSettings` + - Renamed and Moved: `"S3SecretAccessKey": ""` renamed `"AmazonS3SecretAccessKey": "",` and moved to `FileSettings` + - Renamed and Moved: `"S3Bucket": ""` renamed `"AmazonS3Bucket": "",` and moved to `FileSettings` + - Renamed and Moved: `"S3Region": ""` renamed `"AmazonS3Region": "",` and moved to `FileSettings` + +##### Image Settings + +- Under `ImageSettings` in `config.json`: + - Renamed: `"ImageSettings"` section to `"FileSettings"` + - Added: `"DriverName" : "local"` to specify the file storage method, `amazons3` can also be used to setup S3 + +##### EmailSettings + +- Under `EmailSettings` in `config.json`: + - Removed: `"ByPassEmail": "true"` which is replaced with `SendEmailNotifications` and `RequireEmailVerification` + - Added: `"SendEmailNotifications" : "false"` to control whether email notifications are sent + - Added: `"RequireEmailVerification" : "false"` to control if users need to verify their emails + - Replaced: `"UseTLS": "false"` with `"ConnectionSecurity": ""` with options: _None_ (`""`), _TLS_ (`"TLS"`) and _StartTLS_ (`"StartTLS"`) + - Replaced: `"UseStartTLS": "false"` with `"ConnectionSecurity": ""` with options: _None_ (`""`), _TLS_ (`"TLS"`) and _StartTLS_ (`"StartTLS"`) + +##### Privacy Settings + +- Under `PrivacySettings` in `config.json`: + - Removed: `"ShowPhoneNumber": "true"` which was not used + - Removed: `"ShowSkypeId" : "true"` which was not used + +#### Database Changes from v0.7 to v1.0 + +The following is for informational purposes only, no action needed. Mattermost automatically upgrades database tables from the previous version's schema using only additions. Sessions table is dropped and rebuilt, no team data is affected by this. + +##### Users Table +1. Added `ThemeProps` column with type `varchar(2000)` and default value `{}` + +##### Teams Table +1. Removed `AllowValet` column + +##### Sessions Table +1. Renamed `Id` column `Token` +2. Renamed `AltId` column `Id` +3. Added `IsOAuth` column with type `tinyint(1)` and default value `0` + +##### OAuthAccessData Table +1. Added new table `OAuthAccessData` +2. Added `AuthCode` column with type `varchar(128)` +3. Added `Token` column with type `varchar(26)` as the primary key +4. Added `RefreshToken` column with type `varchar(26)` +5. Added `RedirectUri` column with type `varchar(256)` +6. Added index on `AuthCode` column + +##### OAuthApps Table +1. Added new table `OAuthApps` +2. Added `Id` column with type `varchar(26)` as primary key +2. Added `CreatorId` column with type `varchar(26)` +2. Added `CreateAt` column with type `bigint(20)` +2. Added `UpdateAt` column with type `bigint(20)` +2. Added `ClientSecret` column with type `varchar(128)` +2. Added `Name` column with type `varchar(64)` +2. Added `Description` column with type `varchar(512)` +2. Added `CallbackUrls` column with type `varchar(1024)` +2. Added `Homepage` column with type `varchar(256)` +3. Added index on `CreatorId` column + +##### OAuthAuthData Table +1. Added new table `OAuthAuthData` +2. Added `ClientId` column with type `varchar(26)` +2. Added `UserId` column with type `varchar(26)` +2. Added `Code` column with type `varchar(128)` as primary key +2. Added `ExpiresIn` column with type `int(11)` +2. Added `CreateAt` column with type `bigint(20)` +2. Added `State` column with type `varchar(128)` +2. Added `Scope` column with type `varchar(128)` + +##### IncomingWebhooks Table +1. Added new table `IncomingWebhooks` +2. Added `Id` column with type `varchar(26)` as primary key +2. Added `CreateAt` column with type `bigint(20)` +2. Added `UpdateAt` column with type `bigint(20)` +2. Added `DeleteAt` column with type `bigint(20)` +2. Added `UserId` column with type `varchar(26)` +2. Added `ChannelId` column with type `varchar(26)` +2. Added `TeamId` column with type `varchar(26)` +3. Added index on `UserId` column +3. Added index on `TeamId` column + +##### Systems Table +1. Added new table `Systems` +2. Added `Name` column with type `varchar(64)` as primary key +3. Added `Value column with type `varchar(1024)` + +#### Contributors + +Many thanks to our external contributors. In no particular order: + +- [jdeng](https://github.com/jdeng), [Trozz](https://github.com/Trozz), [LAndres](https://github.com/LAndreas), [JessBot](https://github.com/JessBot), [apaatsio](https://github.com/apaatsio), [chengweiv5](https://github.com/chengweiv5) + +## Release v0.7.0 (Beta1) + +Released 2015-09-05 + +### Release Highlights + +#### Improved GitLab Mattermost support + +Following the release of Mattermost v0.6.0 Alpha, GitLab 7.14 offered an automated install of Mattermost with GitLab Single Sign-On (co-branded as "GitLab Mattermost") in its omnibus installer. + +New features, improvements, and bug fixes recommended by the GitLab community were incorporated into Mattermost v0.7.0 Beta1--in particular, extending support of GitLab SSO to team creation, and restricting team creation to users with verified emails from a configurable list of domains. + +#### Slack Import (Preview) + +Preview of Slack import functionality supports the processing of an "Export" file from Slack containing account information and public channel archives from a Slack team. + +- In the feature preview, emails and usernames from Slack are used to create new Mattermost accounts, which users can activate by going to the Password Reset screen in Mattermost to set new credentials. +- Once logged in, users will have access to previous Slack messages shared in public channels, now imported to Mattermost. + +Limitations: + +- Slack does not export files or images your team has stored in Slack's database. Mattermost will provide links to the location of your assets in Slack's web UI. +- Slack does not export any content from private groups or direct messages that your team has stored in Slack's database. +- The Preview release of Slack Import does not offer pre-checks or roll-back and will not import Slack accounts with username or email address collisions with existing Mattermost accounts. Also, Slack channel names with underscores will not import. Also, mentions do not yet resolve as Mattermost usernames (still show Slack ID). These issues are being addressed in [Mattermost v0.8.0 Migration Support](https://mattermost.atlassian.net/issues/MM-364?filter=10002). + +### New Features + +GitLab Mattermost + +- Ability to create teams using GitLab SSO (previously GitLab SSO only supported account creation and sign-in) +- Ability to restrict team creation to GitLab SSO and/or users with email verified from a specific list of domains. + +File and Image Sharing + +- New drag-and-drop file sharing to messages and comments +- Ability to paste images from clipboard to messages and comments + +Messaging, Comments and Notifications + +- Send messages faster with from optimistic posting and retry on failure + +Documentation + +- New style guidelines for Go, React and Javascript + +### Improvements + +Messaging, Comments and Notifications + +- Performance improvements to channel rendering +- Added "Unread posts" in left hand sidebar when notification indicator is off-screen + +Documentation + +- Install documentation improved based on early adopter feedback + +### Bug Fixes + +- Fixed multiple issues with GitLab SSO, installation and on-boarding +- Fixed multiple IE 10 issues +- Fixed broken link in verify email function +- Fixed public links not working on mobile + +### Contributors + +Many thanks to our external contributors. In no particular order: + +- [asubset](https://github.com/asubset), [felixbuenemann](https://github.com/felixbuenemann), [CtrlZvi](https://github.com/CtrlZvi), [BastienDurel](https://github.com/BastienDurel), [manusajith](https://github.com/manusajith), [doosp](https://github.com/doosp), [zackify](https://github.com/zackify), [willstacey](https://github.com/willstacey) + +Special thanks to the GitLab Mattermost early adopter community who influenced this release, and who play a pivotal role in bringing Mattermost to over 100,000 organizations using GitLab today. In no particular order: + +- [cifvts](https://forum.mattermost.com/users/cifvts/activity), Chryb, cookacounty, bweston92, mablae, picharmer, cmtonkinson, cmthomps, m.gamperl, StanMarsh, jeanmarc-leroux, dnoe, dblessing, mechanicjay, larsemil, vga, stanhu, kohenkatz, RavenB1, [booksprint](https://forum.mattermost.com/users/booksprint/activity), [scottcorscadden](https://forum.mattermost.com/users/scottcorscadden/activity), [sskmani](https://forum.mattermost.com/users/sskmani/activity), [gosure](https://forum.mattermost.com/users/gosure/activity), [jigarshah](https://forum.mattermost.com/users/jigarshah/activity) + +Extra special thanks to GitLab community leaders for successful release of GitLab Mattermost Alpha: + +- marin, sytse + +---- + +## Release v0.6.0 (Alpha) + +Released 2015-08-07 + +### Release Highlights + +- Simplified on-prem install +- Support for GitLab Mattermost (GitLab SSO, Postgres support, IE 10+ support) + +### Compatibility + +*Note: While use of Mattermost Preview (v0.5.0) and Mattermost Alpha (v0.6.0) in production is not recommended, we document compatibility considerations for a small number of organizations running Mattermost in production, supported directly by Mattermost product team.* + +- Switched Team URLs from team.domain.com to domain.com/team + +### New Features + +GitLab Mattermost + +- OAuth2 support for GitLab Single Sign-On +- PostgreSQL support for GitLab Mattermost users +- Support for Internet Explorer 10+ for GitLab Mattermost users + +File and Image Sharing + +- New thumbnails and formatting for files and images + +Messaging, Comments and Notifications + +- Users now see posts they sent highlighted in a different color +- Mentions can now also trigger on user-defined words + +Security and Administration + +- Enable users to view and log out of active sessions +- Team Admin can now delete posts from any user + +On-boarding + +- “Off-Topic” now available as default channel, in addition to “Town Square” + +### Improvements + +Installation + +- New "ByPassEmail" setting enables Mattermost to operate without having to set up email +- New option to use local storage instead of S3 +- Removed use of Redis to simplify on-premise installation + +On-boarding + +- Team setup wizard updated with usability improvements + +Documentation + +- Install documentation improved based on early adopter feedback + +### Contributors + +Many thanks to our external contributors. In no particular order: + +- [ralder](https://github.com/ralder), [jedisct1](https://github.com/jedisct1), [faebser](https://github.com/faebser), [firstrow](https://github.com/firstrow), [haikoschol](https://github.com/haikoschol), [adamenger](https://github.com/adamenger) + +## Release v0.5.0 (Preview) + +Released 2015-06-24 + +### Release Highlights + +- First release of Mattermost as a team communication service for sharing messagse and files across PCs and phones, with archiving and instant search. + +### New Features + +Messaging and File Sharing + +- Send messages, comments, files and images across public, private and 1-1 channels +- Personalize notifications for unreads and mentions by channel +- Use #hashtags to tag and find messages, discussions and files + +Archiving and Search + +- Search public and private channels for historical messages and comments +- View recent mentions of your name, username, nickname, and custom search terms + +Anywhere Access + +- Use Mattermost from web-enabled PCs and phones +- Define team-specific branding and color themes across your devices diff --git a/docs/main/product-overview/version-archive.mdx b/docs/main/product-overview/version-archive.mdx new file mode 100644 index 000000000000..f0bc6c6adc4b --- /dev/null +++ b/docs/main/product-overview/version-archive.mdx @@ -0,0 +1,1216 @@ +--- +title: "Version Archive" +--- +import Inc0_common_esr_support_rst from './common-esr-support-rst.mdx'; + + + +If you want to check that the version of Mattermost you are installing is the official, unmodified version, compare the SHA-256 checksum or the file's GPG signature with the one published in this version archive. To verify the GPG signature of a Mattermost release, use the public key stored at the following URL: [https://deb.packages.mattermost.com/pubkey.gpg](https://deb.packages.mattermost.com/pubkey.gpg). + + + +Our package signing key has been moved away from Keybase. If you still reference Keybase in your deployment steps for retrieving the key, update them to the new key location: [https://deb.packages.mattermost.com/pubkey.gpg](https://deb.packages.mattermost.com/pubkey.gpg). + + + +
+ +Mattermost Enterprise + +Mattermost Enterprise Edition v11.6.1 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-6-feature-release) - [Download](https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `8e95b90aaab80fa2c7e203a35aa1a9a0795b5daa3ef1e92360a54a0c614bdba9` +- GPG Signature: [https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.6.1/mattermost-11.6.1-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.6.1/sbom-enterprise-v11.6.1.json](https://releases.mattermost.com/11.6.1/sbom-enterprise-v11.6.1.json) + +Mattermost Enterprise Edition v11.5.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-5-feature-release) - [Download](https://releases.mattermost.com/11.5.4/mattermost-11.5.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.5.4/mattermost-11.5.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `849dafc4e23ef8a9b25a34866c8217cad68c87aa26986ebc71aba2c9f60cef81` +- GPG Signature: [https://releases.mattermost.com/11.5.4/mattermost-11.5.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.5.4/mattermost-11.5.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.5.4/sbom-enterprise-v11.5.4.json](https://releases.mattermost.com/11.5.4/sbom-enterprise-v11.5.4.json) + +Mattermost Enterprise Edition v11.4.5 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-4-feature-release) - [Download](https://releases.mattermost.com/11.4.5/mattermost-11.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.4.5/mattermost-11.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `6dd4ccad5aae23542ad3ff71b6e4602dcfb853b0a1b3e8ecaff010f000bec37a` +- GPG Signature: [https://releases.mattermost.com/11.4.5/mattermost-11.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.4.5/mattermost-11.4.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.4.5/sbom-enterprise-v11.4.5.json](https://releases.mattermost.com/11.4.5/sbom-enterprise-v11.4.5.json) + +Mattermost Enterprise Edition v11.3.3 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-3-feature-release) - [Download](https://releases.mattermost.com/11.3.3/mattermost-11.3.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.3.3/mattermost-11.3.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `4203118c2abbe069eac3ce3a06657ef7e91928f9f127766edc592b4633a79375` +- GPG Signature: [https://releases.mattermost.com/11.3.3/mattermost-11.3.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.3.3/mattermost-11.3.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.3.3/sbom-enterprise-v11.3.3.json](https://releases.mattermost.com/11.3.3/sbom-enterprise-v11.3.3.json) + +Mattermost Enterprise Edition v11.2.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-2-feature-release) - [Download](https://releases.mattermost.com/11.2.4/mattermost-11.2.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.2.4/mattermost-11.2.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `189231eb79918a276866d1c33d922979f3214368a7e9239b413afa7ca309dc04` +- GPG Signature: [https://releases.mattermost.com/11.2.4/mattermost-11.2.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.2.4/mattermost-11.2.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.2.4/sbom-enterprise-v11.2.4.json](https://releases.mattermost.com/11.2.4/sbom-enterprise-v11.2.4.json) + +Mattermost Enterprise Edition v11.1.3 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-1-feature-release) - [Download](https://releases.mattermost.com/11.1.3/mattermost-11.1.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.1.3/mattermost-11.1.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `21404826d65a96fedd8b7bffd23871cabc3c1bfeca8e498dbac1d30030a8b7d6` +- GPG Signature: [https://releases.mattermost.com/11.1.3/mattermost-11.1.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.1.3/mattermost-11.1.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.1.3/sbom-enterprise-v11.1.3.json](https://releases.mattermost.com/11.1.3/sbom-enterprise-v11.1.3.json) + +Mattermost Enterprise Edition v11.0.7 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-0-major-release) - [Download](https://releases.mattermost.com/11.0.7/mattermost-11.0.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.0.7/mattermost-11.0.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `89024ccd1a3eebaa2e6779ffb125b169642689606788c3ef41deda40c1f99369` +- GPG Signature: [https://releases.mattermost.com/11.0.7/mattermost-11.0.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.0.7/mattermost-11.0.7-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/11.0.7/sbom-enterprise-v11.0.7.json](https://releases.mattermost.com/11.0.7/sbom-enterprise-v11.0.7.json) + +Mattermost Enterprise Edition v10.12.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-12-feature-release) - [Download](https://releases.mattermost.com/10.12.4/mattermost-10.12.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.12.4/mattermost-10.12.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `4b360d1bd3802767472177e2f6097a7e0c7ec271471f6530ccfbf81f650970a4` +- GPG Signature: [https://releases.mattermost.com/10.12.4/mattermost-10.12.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.12.4/mattermost-10.12.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.12.4/sbom-enterprise-v10.12.4.json](https://releases.mattermost.com/10.12.4/sbom-enterprise-v10.12.4.json) + +Mattermost Enterprise Edition v10.11.15 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-11-extended-support-release) - [Download](https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz` +- SHA-256 Checksum: `95bb6cae04a572dd9ab40b0b402910d90c811fc17dd931cc0b678d86d3cb1bb0` +- GPG Signature: [https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.11.15/mattermost-10.11.15-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.11.15/sbom-enterprise-v10.11.15.json](https://releases.mattermost.com/10.11.15/sbom-enterprise-v10.11.15.json) + +Mattermost Enterprise Edition v10.10.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-10-feature-release) - [Download](https://releases.mattermost.com/10.10.3/mattermost-10.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.10.3/mattermost-10.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `c970e77aad18f273a25f333192559cb808f73c28b8a89f2bf49be755ec2eff91` +- GPG Signature: [https://releases.mattermost.com/10.10.3/mattermost-10.10.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.10.3/mattermost-10.10.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.10.3/sbom-enterprise-v10.10.3.json](https://releases.mattermost.com/10.10.3/sbom-enterprise-v10.10.3.json) + +Mattermost Enterprise Edition v10.9.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-9-feature-release) - [Download](https://releases.mattermost.com/10.9.5/mattermost-10.9.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.9.5/mattermost-10.9.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `736cb5b1b91f3e0af929a73a4454b241f090b9caba2e95360755c4f8ce18cd7b` +- GPG Signature: [https://releases.mattermost.com/10.9.5/mattermost-10.9.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.9.5/mattermost-10.9.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.9.5/sbom-enterprise-v10.9.5.json](https://releases.mattermost.com/10.9.5/sbom-enterprise-v10.9.5.json) + +Mattermost Enterprise Edition v10.8.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-8-feature-release) - [Download](https://releases.mattermost.com/10.8.4/mattermost-10.8.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.8.4/mattermost-10.8.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `a23ea26f9bc8d8602c7f7e8111c971777369b047b0a765376bb958aac3214076` +- GPG Signature: [https://releases.mattermost.com/10.8.4/mattermost-10.8.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.8.4/mattermost-10.8.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.8.4/sbom-enterprise-v10.8.4.json](https://releases.mattermost.com/10.8.4/sbom-enterprise-v10.8.4.json) + +Mattermost Enterprise Edition v10.7.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-7-feature-release) - [Download](https://releases.mattermost.com/10.7.4/mattermost-10.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.7.4/mattermost-10.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `b2afe1d1b5dde60aa34524196cf6c41dc0a61f1e164646c2dc82816dea868ea9` +- GPG Signature: [https://releases.mattermost.com/10.7.4/mattermost-10.7.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.7.4/mattermost-10.7.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.7.4/sbom-enterprise-v10.7.4.json](https://releases.mattermost.com/10.7.4/sbom-enterprise-v10.7.4.json) + +Mattermost Enterprise Edition v10.6.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-6-feature-release) - [Download](https://releases.mattermost.com/10.6.6/mattermost-10.6.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.6.6/mattermost-10.6.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `c763ba7d25b42051d8ff6b3de18cf9ec312d4e5d985f754a37c29f86988cb93b` +- GPG Signature: [https://releases.mattermost.com/10.6.6/mattermost-10.6.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.6.6/mattermost-10.6.6-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.6.6/sbom-enterprise-v10.6.6.json](https://releases.mattermost.com/10.6.6/sbom-enterprise-v10.6.6.json) + +Mattermost Enterprise Edition v10.5.14 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-5-extended-support-release) - [Download](https://releases.mattermost.com/10.5.14/mattermost-10.5.14-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.5.14/mattermost-10.5.14-linux-amd64.tar.gz` +- SHA-256 Checksum: `60f16420e02755bdb244f5bc429eac6a550c0e9450c2a41ea9c10c35de8b9a6d` +- GPG Signature: [https://releases.mattermost.com/10.5.14/mattermost-10.5.14-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.5.14/mattermost-10.5.14-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.5.14/sbom-enterprise-v10.5.14.json](https://releases.mattermost.com/10.5.14/sbom-enterprise-v10.5.14.json) + +Mattermost Enterprise Edition v10.4.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-4-feature-release) - [Download](https://releases.mattermost.com/10.4.5/mattermost-10.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.4.5/mattermost-10.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `f85f4cf564f940f82a37c17a94f8689dda9c0e79c58a204c7d175c9ecb620773` +- GPG Signature: [https://releases.mattermost.com/10.4.5/mattermost-10.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.4.5/mattermost-10.4.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.4.5/sbom-enterprise-v10.4.5.json](https://releases.mattermost.com/10.4.5/sbom-enterprise-v10.4.5.json) + +Mattermost Enterprise Edition v10.3.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-3-feature-release) - [Download](https://releases.mattermost.com/10.3.4/mattermost-10.3.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.3.4/mattermost-10.3.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `9fcb1474697dcb4d93b6c6bf191929b0d2b977198de1df4692dacf560752c2a8` +- GPG Signature: [https://releases.mattermost.com/10.3.4/mattermost-10.3.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.3.4/mattermost-10.3.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.3.4/sbom-enterprise-v10.3.4.json](https://releases.mattermost.com/10.3.4/sbom-enterprise-v10.3.4.json) + +Mattermost Enterprise Edition v10.2.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-2-feature-release) - [Download](https://releases.mattermost.com/10.2.3/mattermost-10.2.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.2.3/mattermost-10.2.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `f7c92924dded7a661face5b9b3857969908b6b63f6f42e3078ab2393d23c6ac8` +- GPG Signature: [https://releases.mattermost.com/10.2.3/mattermost-10.2.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.2.3/mattermost-10.2.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.2.3/sbom-enterprise-v10.2.3.json](https://releases.mattermost.com/10.2.3/sbom-enterprise-v10.2.3.json) + +Mattermost Enterprise Edition v10.1.7 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-1-feature-release) - [Download](https://releases.mattermost.com/10.1.7/mattermost-10.1.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.1.7/mattermost-10.1.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `6a7bfe7370f319d4f3a1a5aa27463af5e9b7851eca5ce7d285a3125a8b91c28d` +- GPG Signature: [https://releases.mattermost.com/10.1.7/mattermost-10.1.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.1.7/mattermost-10.1.7-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.1.7/sbom-enterprise-v10.1.7.json](https://releases.mattermost.com/10.1.7/sbom-enterprise-v10.1.7.json) + +Mattermost Enterprise Edition v10.0.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-0-major-release) - [Download](https://releases.mattermost.com/10.0.4/mattermost-10.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.0.4/mattermost-10.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `25c3753707404294070177495062aaef7d5e0100cc01343c27732225e4bbb8f6` +- GPG Signature: [https://releases.mattermost.com/10.0.4/mattermost-10.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.0.4/mattermost-10.0.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://releases.mattermost.com/10.0.4/sbom-enterprise-v10.0.4.json](https://releases.mattermost.com/10.0.4/sbom-enterprise-v10.0.4.json) + +Mattermost Enterprise Edition v9.11.18 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-11-extended-support-release) - [Download](https://releases.mattermost.com/9.11.18/mattermost-9.11.18-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.11.18/mattermost-9.11.18-linux-amd64.tar.gz` +- SHA-256 Checksum: `51539cdf3a92b38b7b9c6929b4fe23c58326edd383660abae758c2e1de7722d6` +- GPG Signature: [https://releases.mattermost.com/9.11.18/mattermost-9.11.18-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.11.18/mattermost-9.11.18-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.10.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-10-feature-release) - [Download](https://releases.mattermost.com/9.10.3/mattermost-9.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.10.3/mattermost-9.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `638433634efbffe3c1d373b3f344406d37fcc3ab86292d4381890e3eeb86fb9d` +- GPG Signature: [https://releases.mattermost.com/9.10.3/mattermost-9.10.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.10.3/mattermost-9.10.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.9.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-9-feature-release) - [Download](https://releases.mattermost.com/9.9.3/mattermost-9.9.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.9.3/mattermost-9.9.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `34afe64f9af5eec6c1e3b4de23603e2a7b5b7adef41524d22582d806652ae065` +- GPG Signature: [https://releases.mattermost.com/9.9.3/mattermost-9.9.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.9.3/mattermost-9.9.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.8.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-8-feature-release) - [Download](https://releases.mattermost.com/9.8.3/mattermost-9.8.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.8.3/mattermost-9.8.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `2afc1e26ed56dcbb51e7b44f5e9a32a385cf9df20e554deebec44703da0f099d` +- GPG Signature: [https://releases.mattermost.com/9.8.3/mattermost-9.8.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.8.3/mattermost-9.8.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.7.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-7-feature-release) - [Download](https://releases.mattermost.com/9.7.6/mattermost-9.7.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.7.6/mattermost-9.7.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `94b1c43b1e69baf0c2431e5a4c0b439bf02f4b5a07125ce365ec8dcd9b816714` +- GPG Signature: [https://releases.mattermost.com/9.7.6/mattermost-9.7.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.7.6/mattermost-9.7.6-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.6.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-6-feature-release) - [Download](https://releases.mattermost.com/9.6.3/mattermost-9.6.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.6.3/mattermost-9.6.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `a636fbfb994dc4d4a5debd775149e17ae08d5af159c39d458facb7d8188ba4e4` +- GPG Signature: [https://releases.mattermost.com/9.6.3/mattermost-9.6.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.6.3/mattermost-9.6.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.5.14 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-5-extended-support-release) - [Download](https://releases.mattermost.com/9.5.14/mattermost-9.5.14-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.5.14/mattermost-9.5.14-linux-amd64.tar.gz` +- SHA-256 Checksum: `f165cbf967214e5ce2f83c3414bc606ceb28cdf71c2454bdd823d6f97997dadb` +- GPG Signature: [https://releases.mattermost.com/9.5.14/mattermost-9.5.14-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.5.14/mattermost-9.5.14-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.4.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-4-feature-release) - [Download](https://releases.mattermost.com/9.4.5/mattermost-9.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.4.5/mattermost-9.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `17a49bfe180bc51a6ed33597fe713afed7f5a586e9f7adcb88e5c58c7860ba4c` +- GPG Signature: [https://releases.mattermost.com/9.4.5/mattermost-9.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.4.5/mattermost-9.4.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.3.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-3-feature-release) - [Download](https://releases.mattermost.com/9.3.3/mattermost-9.3.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.3.3/mattermost-9.3.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `26296f0d8ae4acaa389adc8fb5a5917620f8a0d0017fae29ab1adc3856feb164` +- GPG Signature: [https://releases.mattermost.com/9.3.3/mattermost-9.3.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.3.3/mattermost-9.3.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.2.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-2-feature-release) - [Download](https://releases.mattermost.com/9.2.6/mattermost-9.2.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.2.6/mattermost-9.2.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `65d9cdbc10e2bd28b723fcffb6a723140013b6d7ad3e0cd9f4a3d68d32442575` +- GPG Signature: [https://releases.mattermost.com/9.2.6/mattermost-9.2.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.2.6/mattermost-9.2.6-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.1.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-1-feature-release) - [Download](https://releases.mattermost.com/9.1.5/mattermost-9.1.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.1.5/mattermost-9.1.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `1cf5c7d68a837d746fdb30f2fe88abbb34ca0badd9f4b297d18988c691f47b35` +- GPG Signature: [https://releases.mattermost.com/9.1.5/mattermost-9.1.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.1.5/mattermost-9.1.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v9.0.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-0-major-release) - [Download](https://releases.mattermost.com/9.0.5/mattermost-9.0.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.0.5/mattermost-9.0.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `5ed5118cb6bdb089fd47a087eea75746044acc3716162d7c1c40beaa6468941c` +- GPG Signature: [https://releases.mattermost.com/9.0.5/mattermost-9.0.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.0.5/mattermost-9.0.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v8.1.13 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v8-1-extended-support-release) - [Download](https://releases.mattermost.com/8.1.13/mattermost-8.1.13-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/8.1.13/mattermost-8.1.13-linux-amd64.tar.gz` +- SHA-256 Checksum: `d0a7edf4eb0aff7219cc589e41b280178665601a6d3daa0272528fabba9ec331` +- GPG Signature: [https://releases.mattermost.com/8.1.13/mattermost-8.1.13-linux-amd64.tar.gz.sig](https://releases.mattermost.com/8.1.13/mattermost-8.1.13-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v8.0.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v8-0-major-release) - [Download](https://releases.mattermost.com/8.0.4/mattermost-8.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/8.0.4/mattermost-8.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `185e57bba4bcefd316cf1f83cfc73556c0646d6ea935e11be53ee1881817bf74` +- GPG Signature: [https://releases.mattermost.com/8.0.4/mattermost-8.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/8.0.4/mattermost-8.0.4-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.10.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-10-feature-release) - [Download](https://releases.mattermost.com/7.10.5/mattermost-7.10.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.10.5/mattermost-7.10.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `5937103d7c7d298343740f9c5f8e87595d829eaf288d4aec834ce7e087a047de` +- GPG Signature: [https://releases.mattermost.com/7.10.5/mattermost-7.10.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.10.5/mattermost-7.10.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.9.6 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-9-feature-release) - [Download](https://releases.mattermost.com/7.9.6/mattermost-7.9.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.9.6/mattermost-7.9.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `33b256f77b215c3fbc09e042dde9a45182c079eba56df684b405161f0d68454b` +- GPG Signature: [https://releases.mattermost.com/7.9.6/mattermost-7.9.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.9.6/mattermost-7.9.6-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.8.15 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-8-extended-support-release) - [Download](https://releases.mattermost.com/7.8.15/mattermost-7.8.15-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.8.15/mattermost-7.8.15-linux-amd64.tar.gz` +- SHA-256 Checksum: `778328d4c2716f10a8b2965d071d6f1c68a0ee98e046dd41669ba460d518170a` +- GPG Signature: [https://releases.mattermost.com/7.8.15/mattermost-7.8.15-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.8.15/mattermost-7.8.15-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.7.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-7-feature-release) - [Download](https://releases.mattermost.com/7.7.4/mattermost-7.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.7.4/mattermost-7.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `942fa455b9f533ad191ea9404b34b4a5d9de7f90f966608fd06c66af2325b601` +- GPG Signature: [https://releases.mattermost.com/7.7.4/mattermost-7.7.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.7.4/mattermost-7.7.4-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-5-feature-release) - [Download](https://releases.mattermost.com/7.5.2/mattermost-7.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.5.2/mattermost-7.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `66fce67ba3a0fcb2ec4f85f2143010b1c3603be8c2c30cc30f2b583a8e2a3345` +- GPG Signature: [https://releases.mattermost.com/7.5.2/mattermost-7.5.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.5.2/mattermost-7.5.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.4.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-4-feature-release) - [Download](https://releases.mattermost.com/7.4.1/mattermost-7.4.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.4.1/mattermost-7.4.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `86d60e7b38c849012aacdbeeaa25f808db9871ffe5d181f4c070bc4d0d3028b2` +- GPG Signature: [https://releases.mattermost.com/7.4.1/mattermost-7.4.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.4.1/mattermost-7.4.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.3.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-3-feature-release) - [Download](https://releases.mattermost.com/7.3.1/mattermost-7.3.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.3.1/mattermost-7.3.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `3981e3dc8237802888817eca8b3c2d39bfd3e8b6b6e9f9c29050c2aa8460953f` +- GPG Signature: [https://releases.mattermost.com/7.3.1/mattermost-7.3.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.3.1/mattermost-7.3.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.2.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-2-feature-release) - [Download](https://releases.mattermost.com/7.2.1/mattermost-7.2.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.2.1/mattermost-7.2.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `f074d167fc29d872b80d0754882db62e2b922139517227d43f7a8ba417a524ec` +- GPG Signature: [https://releases.mattermost.com/7.2.1/mattermost-7.2.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.2.1/mattermost-7.2.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.1.9 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-1-extended-support-release) - [Download](https://releases.mattermost.com/7.1.9/mattermost-7.1.9-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.1.9/mattermost-7.1.9-linux-amd64.tar.gz` +- SHA-256 Checksum: `e9c1af69a8ff1e3340210801cc1cadee653e086edacc2e3247acc37d83762c51` +- GPG Signature: [https://releases.mattermost.com/7.1.9/mattermost-7.1.9-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.1.9/mattermost-7.1.9-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v7.0.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-0-major-release) - [Download](https://releases.mattermost.com/7.0.2/mattermost-7.0.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.0.2/mattermost-7.0.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `e7597ab12598c908e0b4b2c4c35e87cdbad5a1db54a676d35787d1c41481eb5b` +- GPG Signature: [https://releases.mattermost.com/7.0.2/mattermost-7.0.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.0.2/mattermost-7.0.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.7.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-7-feature-release) - [Download](https://releases.mattermost.com/6.7.2/mattermost-6.7.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.7.2/mattermost-6.7.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `db3faada1a1673fcae4a4f7a26a630874498d11ee181e10fb93797f68939d3c1` +- GPG Signature: [https://releases.mattermost.com/6.7.2/mattermost-6.7.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.7.2/mattermost-6.7.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.6.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-6-feature-release) - [Download](https://releases.mattermost.com/6.6.2/mattermost-6.6.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.6.2/mattermost-6.6.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `895b89b87803b083eb4cd25ab4441f71c77930054c868df0d4f5ef19bae41bf8` +- GPG Signature: [https://releases.mattermost.com/6.6.2/mattermost-6.6.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.6.2/mattermost-6.6.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-5-feature-release) - [Download](https://releases.mattermost.com/6.5.2/mattermost-6.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.5.2/mattermost-6.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `4b10b7d6d8e17c167bb103da86b12957aaf40ab8c008b99a1c4653771516274d` +- GPG Signature: [https://releases.mattermost.com/6.5.2/mattermost-6.5.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.5.2/mattermost-6.5.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.4.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-4-feature-release) - [Download](https://releases.mattermost.com/6.4.3/mattermost-6.4.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.4.3/mattermost-6.4.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `099dbd1f62cd69a97ee664eee3b71646a8916f109b0493088403836fc8e5e5b5` +- GPG Signature: [https://releases.mattermost.com/6.4.3/mattermost-6.4.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.4.3/mattermost-6.4.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.3.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-3-extended-support-release) - [Download](https://releases.mattermost.com/6.3.10/mattermost-6.3.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.3.10/mattermost-6.3.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `40f5417f438a8c9c26106b037a2352ebffdb0f6236ac2a4e8ad91c602e65e1f2` +- GPG Signature: [https://releases.mattermost.com/6.3.10/mattermost-6.3.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.3.10/mattermost-6.3.10-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.2.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-2-feature-release) - [Download](https://releases.mattermost.com/6.2.5/mattermost-6.2.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.2.5/mattermost-6.2.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `2196a1402f19a4c27d284271c76191fa27ed5011e46c5e8bc31dd1d1c5b50b0e` +- GPG Signature: [https://releases.mattermost.com/6.2.5/mattermost-6.2.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.2.5/mattermost-6.2.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.1.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-1-feature-release) - [Download](https://releases.mattermost.com/6.1.3/mattermost-6.1.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.1.3/mattermost-6.1.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `b0d7b2792b5ff6ee510eac9a4f57cbf30a82c495d495f2d873bf9d00fe39a3ae` +- GPG Signature: [https://releases.mattermost.com/6.1.3/mattermost-6.1.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.1.3/mattermost-6.1.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v6.0.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-0-feature-release) - [Download](https://releases.mattermost.com/6.0.4/mattermost-6.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.0.4/mattermost-6.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `23ca2886e0ec0a785920cd78d47284b8eff543ee8ba07df5cdd4042acd549246` +- GPG Signature: [https://releases.mattermost.com/6.0.4/mattermost-6.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.0.4/mattermost-6.0.4-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.39.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-39-quality-release) - [Download](https://releases.mattermost.com/5.39.3/mattermost-5.39.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.39.3/mattermost-5.39.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `c2feb80ffc9378f224a8f24e2dc4d6ec5ab0daa19c6a473503e64fcc473f5172` +- GPG Signature: [https://releases.mattermost.com/5.39.3/mattermost-5.39.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.39.3/mattermost-5.39.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.38.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-38-feature-release) - [Download](https://releases.mattermost.com/5.38.4/mattermost-5.38.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.38.4/mattermost-5.38.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `ffb0f544222550c8477bbb83df35379da6a0280d1d0501c2569c839db9cb22c6` +- GPG Signature: [https://releases.mattermost.com/5.38.4/mattermost-5.38.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.38.4/mattermost-5.38.4-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.37.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-37-extended-support-release) - [Download](https://releases.mattermost.com/5.37.10/mattermost-5.37.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.37.10/mattermost-5.37.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `ccaecdb70d49879fe4582456357ecfbc305d17e3aa847850389ad7d1f521caa7` +- GPG Signature: [https://releases.mattermost.com/5.37.10/mattermost-5.37.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.37.10/mattermost-5.37.10-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.36.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-36-feature-release) - [Download](https://releases.mattermost.com/5.36.2/mattermost-5.36.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.36.2/mattermost-5.36.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `fc5e03ada4f04290230e56411f3aecefa0d3a21317fc08b355193a1702bf1136` +- GPG Signature: [https://releases.mattermost.com/5.36.2/mattermost-5.36.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.36.2/mattermost-5.36.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.35.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-35-feature-release) - [Download](https://releases.mattermost.com/5.35.5/mattermost-5.35.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.35.5/mattermost-5.35.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `f7de6ad424498a68537b34f18c70cfbe89487f2700e83ee041aa33491719e31f` +- GPG Signature: [https://releases.mattermost.com/5.35.5/mattermost-5.35.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.35.5/mattermost-5.35.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.34.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-34-feature-release) - [Download](https://releases.mattermost.com/5.34.5/mattermost-5.34.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.34.5/mattermost-5.34.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `4af01d1a40f21c8b3ac4830f124713950a815f2dbb1ac1163d35d5c2aec8783b` +- GPG Signature: [https://releases.mattermost.com/5.34.5/mattermost-5.34.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.34.5/mattermost-5.34.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.33.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-33-feature-release) - [Download](https://releases.mattermost.com/5.33.5/mattermost-5.33.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.33.5/mattermost-5.33.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `6b4fef57213a73832e97430daba1d2faf211c5ee5fad127944dc35af2d31823d` +- GPG Signature: [https://releases.mattermost.com/5.33.5/mattermost-5.33.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.33.5/mattermost-5.33.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.32.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-32-feature-release) - [Download](https://releases.mattermost.com/5.32.1/mattermost-5.32.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.32.1/mattermost-5.32.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `9117ab9777d8453ae8b63f3a008152a2bdc6a638400640a67a0a359acf479a44` +- GPG Signature: [https://releases.mattermost.com/5.32.1/mattermost-5.32.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.32.1/mattermost-5.32.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.31.9 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-31-esr) - [Download](https://releases.mattermost.com/5.31.9/mattermost-5.31.9-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.31.9/mattermost-5.31.9-linux-amd64.tar.gz` +- SHA-256 Checksum: `95cc8744dd162ad16add85e76231494153473810f9a3a72d30d283466d73f949` +- GPG Signature: [https://releases.mattermost.com/5.31.9/mattermost-5.31.9-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.31.9/mattermost-5.31.9-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.30.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-30) - [Download](https://releases.mattermost.com/5.30.3/mattermost-5.30.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.30.3/mattermost-5.30.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `6502b01d966dca12443e4d397866651d236241373f2c3fb6fb8ce37ef136efc0` +- GPG Signature: [https://releases.mattermost.com/5.30.3/mattermost-5.30.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.30.3/mattermost-5.30.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.29.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-29-quality-release) - [Download](https://releases.mattermost.com/5.29.2/mattermost-5.29.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.29.2/mattermost-5.29.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `6e0741f06fbbe6c11707a18b9cfb1a80356d7ca32378b109657a0b29b3b246d0` +- GPG Signature: [https://releases.mattermost.com/5.29.2/mattermost-5.29.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.29.2/mattermost-5.29.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.28.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-28-feature-release) - [Download](https://releases.mattermost.com/5.28.2/mattermost-5.28.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.28.2/mattermost-5.28.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `399f3ad35ea0e0b109cdb714d18aaccf8571223d856ac2129a8cd0866f39ac20` +- GPG Signature: [https://releases.mattermost.com/5.28.2/mattermost-5.28.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.28.2/mattermost-5.28.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.27.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-27-quality-release) - [Download](https://releases.mattermost.com/5.27.2/mattermost-5.27.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.27.2/mattermost-5.27.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `067bfe08307580851c407ec43a6cb725f179aa3baf2c434a2bed9b03c69e15f0` +- GPG Signature: [https://releases.mattermost.com/5.27.2/mattermost-5.27.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.27.2/mattermost-5.27.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.26.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-26-feature-release) - [Download](https://releases.mattermost.com/5.26.2/mattermost-5.26.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.26.2/mattermost-5.26.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `aa671915f684d7daca2fed321ede89dd05c3d377b0beaaca9561b1d7e3c36970` +- GPG Signature: [https://releases.mattermost.com/5.26.2/mattermost-5.26.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.26.2/mattermost-5.26.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.25.7 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-25-esr) - [Download](https://releases.mattermost.com/5.25.7/mattermost-5.25.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.25.7/mattermost-5.25.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `89048fc2b4d4930927e4b92a508d8db3628d05059c7f271caffd05d9b50136c8` +- GPG Signature: [https://releases.mattermost.com/5.25.7/mattermost-5.25.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.25.7/mattermost-5.25.7-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.24.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-24-feature-release) - [Download](https://releases.mattermost.com/5.24.3/mattermost-5.24.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.24.3/mattermost-5.24.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `1a9a3200a3de242b4461df7bf58ff131ebf730cc242d7515ce101ad880b37fb8` +- GPG Signature: [https://releases.mattermost.com/5.24.3/mattermost-5.24.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.24.3/mattermost-5.24.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.23.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-23-quality-release) - [Download](https://releases.mattermost.com/5.23.2/mattermost-5.23.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.23.2/mattermost-5.23.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `a36f8de7fdc1b12c1b2b1a841e43a5f0604845b1c2bd4cff9318786964fcefae` +- GPG Signature: [https://releases.mattermost.com/5.23.2/mattermost-5.23.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.23.2/mattermost-5.23.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.22.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-22-feature-release) - [Download](https://releases.mattermost.com/5.22.3/mattermost-5.22.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.22.3/mattermost-5.22.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `24ce88ab151c873bcb107a2ff4fdbde7a06ef3d66fa172982ebd931211b2e7e0` +- GPG Signature: [https://releases.mattermost.com/5.22.3/mattermost-5.22.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.22.3/mattermost-5.22.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.21.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-21-quality-release) - [Download](https://releases.mattermost.com/5.21.0/mattermost-5.21.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.21.0/mattermost-5.21.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `909b17498139cd511d4e5483e2b7be0b757ac28ea5063be9c3d82cbe49b4a696` +- GPG Signature: [https://releases.mattermost.com/5.21.0/mattermost-5.21.0-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.21.0/mattermost-5.21.0-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.20.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-20-feature-release) - [Download](https://releases.mattermost.com/5.20.2/mattermost-5.20.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.20.2/mattermost-5.20.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `20fc3fdbeee5f13371b29c2016a3d42d5a8edf8c2508b43b295dd39c6cd57c90` +- GPG Signature: [https://releases.mattermost.com/5.20.2/mattermost-5.20.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.20.2/mattermost-5.20.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.19.3 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-19-esr) - [Download](https://releases.mattermost.com/5.19.3/mattermost-5.19.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.19.3/mattermost-5.19.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `9926f1ded2faedea9168a1ac84be77b9b4a66f038bbdc92297b653c3a0a04271` +- GPG Signature: [https://releases.mattermost.com/5.19.3/mattermost-5.19.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.19.3/mattermost-5.19.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.18.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-18-feature-release) - [Download](https://releases.mattermost.com/5.18.2/mattermost-5.18.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.18.2/mattermost-5.18.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `e61d6affca5bcf0e85b9152ff280b11135861f1b7b76dd30ad3ca96913c9f7a6` +- GPG Signature: [https://releases.mattermost.com/5.18.2/mattermost-5.18.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.18.2/mattermost-5.18.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.17.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-17-quality-release) - [Download](https://releases.mattermost.com/5.17.3/mattermost-5.17.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.17.3/mattermost-5.17.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `5b02c4e6c6c5735191bbdf46ee9af5aa08f2002e4b41d5ffb7cc39b4c838fadc` +- GPG Signature: [https://releases.mattermost.com/5.17.3/mattermost-5.17.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.17.3/mattermost-5.17.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.16.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-16-feature-release) - [Download](https://releases.mattermost.com/5.16.5/mattermost-5.16.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.16.5/mattermost-5.16.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `85dc0ec19fec3573c7331f25c17ad1a35a2db8f9bffa7ef9131dc6f9e00b51cc` +- GPG Signature: [https://releases.mattermost.com/5.16.5/mattermost-5.16.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.16.5/mattermost-5.16.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.15.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-15-quality-release) - [Download](https://releases.mattermost.com/5.15.5/mattermost-5.15.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.15.5/mattermost-5.15.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `9676cadb908891227d8bce784643506dd36ba05498c9b3c4ce9d9378eed2b071` +- GPG Signature: [https://releases.mattermost.com/5.15.5/mattermost-5.15.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.15.5/mattermost-5.15.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.14.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-14-feature-release) - [Download](https://releases.mattermost.com/5.14.5/mattermost-5.14.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.14.5/mattermost-5.14.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `d8f530ec5540dce20c3ff1a13beb54a8e065cb391247b4d92deb9f8c4adb3d7e` +- GPG Signature: [https://releases.mattermost.com/5.14.5/mattermost-5.14.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.14.5/mattermost-5.14.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.13.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-13-quality-release) - [Download](https://releases.mattermost.com/5.13.3/mattermost-5.13.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.13.3/mattermost-5.13.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `41f40fb7397309aeecdd9c8670e8f137a4892093ec658fc0346c732bca54e8f9` +- GPG Signature: [https://releases.mattermost.com/5.13.3/mattermost-5.13.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.13.3/mattermost-5.13.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.12.6 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-12-feature-release) - [Download](https://releases.mattermost.com/5.12.6/mattermost-5.12.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.12.6/mattermost-5.12.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `1464e3f970c3b55c9b3ce94925b8d6e4b3b291c05f181498e8ae23822cf1ade4` +- GPG Signature: [https://releases.mattermost.com/5.12.6/mattermost-5.12.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.12.6/mattermost-5.12.6-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.11.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-11-quality-release) - [Download](https://releases.mattermost.com/5.11.1/mattermost-5.11.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.11.1/mattermost-5.11.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `ad2db1a68103fb3ce9383f857eddc817848d548334b510b2dd2491f13f59ea4d` +- GPG Signature: [https://releases.mattermost.com/5.11.1/mattermost-5.11.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.11.1/mattermost-5.11.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.10.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-10-feature-release) - [Download](https://releases.mattermost.com/5.10.2/mattermost-5.10.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.10.2/mattermost-5.10.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `7212c63f94c0b3d44c9296e3f7907a2cb651e15f5ac2032f1092223867cdea90` +- GPG Signature: [https://releases.mattermost.com/5.10.2/mattermost-5.10.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.10.2/mattermost-5.10.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.9.8 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-9-esr) - [Download](https://releases.mattermost.com/5.9.8/mattermost-5.9.8-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.9.8/mattermost-5.9.8-linux-amd64.tar.gz` +- SHA-256 Checksum: `393a9803c2d1c28f592d52e43785899f787cccee1a12510a14f1d10e659792fe` +- GPG Signature: [https://releases.mattermost.com/5.9.8/mattermost-5.9.8-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.9.8/mattermost-5.9.8-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.8.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-8-feature-release) - [Download](https://releases.mattermost.com/5.8.2/mattermost-5.8.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.8.2/mattermost-5.8.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `d681b7a2de4711e39d961598dad3821114c94ff916ec84b7d9965c54ff48cdda` +- GPG Signature: [https://releases.mattermost.com/5.8.2/mattermost-5.8.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.8.2/mattermost-5.8.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.7.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-7-quality-release) - [Download](https://releases.mattermost.com/5.7.3/mattermost-5.7.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.7.3/mattermost-5.7.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `7775e6b38785f1838835fcdd0e64a1c8f718c0071232f31e9a70d83b09384955` +- GPG Signature: [https://releases.mattermost.com/5.7.3/mattermost-5.7.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.7.3/mattermost-5.7.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.6.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-6-feature-release) - [Download](https://releases.mattermost.com/5.6.5/mattermost-5.6.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.6.5/mattermost-5.6.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `9705f6befff80451228c12909eed7e36730ffc6a231bcacf1381b9807c7acb91` +- GPG Signature: [https://releases.mattermost.com/5.6.5/mattermost-5.6.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.6.5/mattermost-5.6.5-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.5.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-5-quality-release) - [Download](https://releases.mattermost.com/5.5.3/mattermost-5.5.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.5.3/mattermost-5.5.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `e568e23f1914b180665089dd711a154f03483bd127d2b037ab4dd35e50e6d567` +- GPG Signature: [https://releases.mattermost.com/5.5.3/mattermost-5.5.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.5.3/mattermost-5.5.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.4.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-4-feature-release) - [Download](https://releases.mattermost.com/5.4.0/mattermost-5.4.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.4.0/mattermost-5.4.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `dfbd4a76d640cf2b3fc1d78f3eddd6571669d3d0c27a4bc7166ac06c8d03af19` +- GPG Signature: [https://releases.mattermost.com/5.4.0/mattermost-5.4.0-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.4.0/mattermost-5.4.0-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.3.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-3-feature-release) - [Download](https://releases.mattermost.com/5.3.1/mattermost-5.3.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.3.1/mattermost-5.3.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `ebe59b38f0c7c1bed2dd94c0f5c64858dd316347418196199d871417747dcf97` +- GPG Signature: [https://releases.mattermost.com/5.3.1/mattermost-5.3.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.3.1/mattermost-5.3.1-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.2.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-2-feature-release) - [Download](https://releases.mattermost.com/5.2.2/mattermost-5.2.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.2.2/mattermost-5.2.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `91c383892e5072b798c828e6c4af19252a03d798bd42757c8a2369946f10ca8f` +- GPG Signature: [https://releases.mattermost.com/5.2.2/mattermost-5.2.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.2.2/mattermost-5.2.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.1.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-1-feature-release) - [Download](https://releases.mattermost.com/5.1.2/mattermost-5.1.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.1.2/mattermost-5.1.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `4646910788a177931e6a4c5a0d8751e3d4f10e8083c6078de348e3463b106bb3` +- GPG Signature: [https://releases.mattermost.com/5.1.2/mattermost-5.1.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.1.2/mattermost-5.1.2-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v5.0.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-0-feature-release) - [Download](https://releases.mattermost.com/5.0.3/mattermost-5.0.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.0.3/mattermost-5.0.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `35863bd376f949d1fd87a012d4f5676e5eb2bdaaccaec4dd9141cf88979af6a6` +- GPG Signature: [https://releases.mattermost.com/5.0.3/mattermost-5.0.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.0.3/mattermost-5.0.3-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v4.10.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-10) - [Download](https://releases.mattermost.com/4.10.10/mattermost-4.10.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.10.10/mattermost-4.10.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `57070578ec7580df1a1d28d6248b387ad8be72cb584fd8535483e853b4858b9e` +- GPG Signature: [https://releases.mattermost.com/4.10.10/mattermost-4.10.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/4.10.10/mattermost-4.10.10-linux-amd64.tar.gz.sig) + +Mattermost Enterprise Edition v4.9.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-9) - [Download](https://releases.mattermost.com/4.9.4/mattermost-4.9.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.9.4/mattermost-4.9.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `368419bc8301ae9823c42c2b5ae69a3135b1dc640c94b8280d46941bda1b7b0b` + +Mattermost Enterprise Edition v4.8.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-8) - [Download](https://releases.mattermost.com/4.8.2/mattermost-4.8.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.8.2/mattermost-4.8.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `61b218111ab336e1ef0dfaa5fa1dfec345b11f7af281fa7e8a76a5bd28ca9ca9` + +Mattermost Enterprise Edition v4.7.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-7) - [Download](https://releases.mattermost.com/4.7.4/mattermost-4.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.7.4/mattermost-4.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `6f616c02e6cab054acb80c6d949f12b1874f92a58690931cf3f1890a66c08bcc` + +Mattermost Enterprise Edition v4.6.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-6) - [Download](https://releases.mattermost.com/4.6.3/mattermost-4.6.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.6.3/mattermost-4.6.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `79763620c9a8b32a94193ae88d7fbab2899e3f525737b3e5c20cc5a0b96d19e2` + +Mattermost Enterprise Edition v4.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-5) - [Download](https://releases.mattermost.com/4.5.2/mattermost-4.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.5.2/mattermost-4.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `cb5b7d5729bb5abda3d89f0263ccb596feee4d4fd015c3c5e0de85792f700494` + +Mattermost Enterprise Edition v4.4.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-4-5) - [Download](https://releases.mattermost.com/4.4.5/mattermost-4.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.4.5/mattermost-4.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `54c268cb1ace376981ffc6845b18185c287783fad4dfb90969cd6bc459e306ae` + +Mattermost Enterprise Edition v4.3.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-3-4) - [Download](https://releases.mattermost.com/4.3.4/mattermost-4.3.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.3.4/mattermost-4.3.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `10a30776bfb1af34ab89657f0c77f96eb8be0e2998e8ea50bf3960cc1aacd383` + +Mattermost Enterprise Edition v4.2.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-2-2) - [Download](https://releases.mattermost.com/4.2.2/mattermost-4.2.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.2.2/mattermost-4.2.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `21d7fa761c2843ba69295cd10c7f4de8969acf57cb53b58be90d42eb6d0a71f7` + +Mattermost Enterprise Edition v4.1.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-1-2) - [Download](https://releases.mattermost.com/4.1.2/mattermost-4.1.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.1.2/mattermost-4.1.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `e13c33d92ab19e7448ec122925953ab4938a565d7775e237564ebb6e1025f8bd` + +Mattermost Enterprise Edition v4.0.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-0-5) - [Download](https://releases.mattermost.com/4.0.5/mattermost-4.0.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.0.5/mattermost-4.0.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `9b910bc0f1534852dead573bddcc13eccb3bbc51194cf64da92dadb662a480e8` + +Mattermost Enterprise Edition v3.10.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-10-3) - [Download](https://releases.mattermost.com/3.10.3/mattermost-3.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.10.3/mattermost-3.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `a70a29986f62fdced9195eeb6d26dd3f6dad2bb9fe8badef708f779043e6d438` + +Mattermost Enterprise Edition v3.9.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-9-2) - [Download](https://releases.mattermost.com/3.9.2/mattermost-3.9.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.9.2/mattermost-3.9.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `49097757a4e97b26339446754859f2589ab420d56a795a57c507fcc1b02ba91b` + +Mattermost Enterprise Edition v3.8.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-8-3) - [Download](https://releases.mattermost.com/3.8.3/mattermost-3.8.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.8.3/mattermost-3.8.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `c223320a82222ebff002071633c6331dce0da6ff6ac8e22d0ab0d7055356ff9c` + +Mattermost Enterprise Edition v3.7.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-7-5) - [Download](https://releases.mattermost.com/3.7.5/mattermost-3.7.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.7.5/mattermost-3.7.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `65e65da661edbc7b7b2b02411f13dbe498fd704d5ae1289789feca79fe00b58a` + +Mattermost Enterprise Edition v3.6.7 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-6-7) - [Download](https://releases.mattermost.com/3.6.7/mattermost-3.6.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.6.7/mattermost-3.6.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `8e666708fead5fbfcf1f20617b07fda21cc8cbc85f9690321cbf4a41bfc1dd89` + +Mattermost Enterprise Edition v3.5.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-5-1) - [Download](https://releases.mattermost.com/3.5.1/mattermost-3.5.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.5.1/mattermost-3.5.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `b972ac6f38f8b4c4f364e40a7c0e7819511315a81cb38c8a51c0622d7c5b14a1` + +Mattermost Enterprise Edition v3.4.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-4-0) - [Download](https://releases.mattermost.com/3.4.0/mattermost-3.4.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.4.0/mattermost-3.4.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `3329fe3ef4d6bd7bd156eec86903b5d9db30d8c62545e4f5ca63633a64559f16` + +Mattermost Enterprise Edition v3.3.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-3-0) - [Download](https://releases.mattermost.com/3.3.0/mattermost-3.3.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.3.0/mattermost-3.3.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `d12d567c270a0c163e07b38ff41ea1d7839991d31f7c10b6ad1b4ef0f05f4e14` + +Mattermost Enterprise Edition v3.2.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-2-0) - [Download](https://releases.mattermost.com/3.2.0/mattermost-3.2.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.2.0/mattermost-3.2.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `f66597ad2fa94d3f75f06135129aa91cddd35dd8b94acab4aa15dfa225596422` + +Mattermost Enterprise Edition v3.1.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-1-0) - [Download](https://releases.mattermost.com/3.1.0/mattermost-3.1.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.1.0/mattermost-3.1.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `9e29525199e25eca6b7fe6422b415f6371d21e22c344ca6febc5e64f69ec670b` + +Mattermost Enterprise Edition v3.0.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-0-3) - [Download](https://releases.mattermost.com/3.0.3/mattermost-enterprise-3.0.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.0.3/mattermost-enterprise-3.0.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `3c692f8532b1858aefd2f0c2c22721e6b18734580a84a8ae5d6ce891f0e16f07` + +Mattermost Enterprise Edition v2.2.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v2-2-0) - [Download](https://releases.mattermost.com/2.2.0/mattermost-enterprise-2.2.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/2.2.0/mattermost-enterprise-2.2.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `a7e997526d9204eab70c74a31d51eea693cca0d4bf0f0f71760f14f797fa5477` + +Mattermost Enterprise Edition v2.1.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v2-1-0) - [Download](https://releases.mattermost.com/2.1.0/mattermost-enterprise-2.1.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/2.1.0/mattermost-enterprise-2.1.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `9454c3daacae602025b03950590e3f1ecd540b85a4bb7ad73bdca212ba85cf7a` + +
+ +
+ +Mattermost Team Edition + +The open source Mattermost Team Edition is functionally identical to the commercial Mattermost Enterprise Edition in its free “team mode”, but there is no ability to unlock enterprise features. It deploys as single Linux binary with PostgreSQL or MySQL under an MIT license. + +We generally recommend installing Enterprise Edition, even if you don't currently need a license. This provides the flexibility to seamlessly unlock Enterprise features should you need them. However, if you only want to install software with a fully open source code base, then Team Edition is the best choice for you. + +Mattermost Team Edition v11.6.1 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-6-feature-release) - [Download](https://releases.mattermost.com/11.6.1/mattermost-team-11.6.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.6.1/mattermost-team-11.6.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `f988cc89d1885f3e9e6e1eeea92c9dbcc975ab53ffed70a01acd59b3fc657664` +- GPG Signature: [https://releases.mattermost.com/11.6.1/mattermost-team-11.6.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.6.1/mattermost-team-11.6.1-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.6.1/sbom-mattermost-v11.6.1.json](https://github.com/mattermost/mattermost/releases/download/v11.6.1/sbom-mattermost-v11.6.1.json) + +Mattermost Team Edition v11.5.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-5-feature-release) - [Download](https://releases.mattermost.com/11.5.4/mattermost-team-11.5.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.5.4/mattermost-team-11.5.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `42841fd586c27473968eeed0e50973e5f21cd2aec8083cd2999e7eac9e70735d` +- GPG Signature: [https://releases.mattermost.com/11.5.4/mattermost-team-11.5.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.5.4/mattermost-team-11.5.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.5.4/sbom-mattermost-v11.5.4.json](https://github.com/mattermost/mattermost/releases/download/v11.5.4/sbom-mattermost-v11.5.4.json) + +Mattermost Team Edition v11.4.5 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-4-feature-release) - [Download](https://releases.mattermost.com/11.4.5/mattermost-team-11.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.4.5/mattermost-team-11.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `3e36d64b2748afc98ea35767cb6a9e4df3b094b422606239206248cbedf36dd5` +- GPG Signature: [https://releases.mattermost.com/11.4.5/mattermost-team-11.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.4.5/mattermost-team-11.4.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.4.5/sbom-mattermost-v11.4.5.json](https://github.com/mattermost/mattermost/releases/download/v11.4.5/sbom-mattermost-v11.4.5.json) + +Mattermost Team Edition v11.3.3 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-3-feature-release) - [Download](https://releases.mattermost.com/11.3.3/mattermost-team-11.3.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.3.3/mattermost-team-11.3.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `f0e9d2664f8d5ce76f2c2480e4d11cb5793ed8438f529e3104c344d2f44f1dae` +- GPG Signature: [https://releases.mattermost.com/11.3.3/mattermost-team-11.3.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.3.3/mattermost-team-11.3.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.3.3/sbom-mattermost-v11.3.3.json](https://github.com/mattermost/mattermost/releases/download/v11.3.3/sbom-mattermost-v11.3.3.json) + +Mattermost Team Edition v11.2.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-2-feature-release) - [Download](https://releases.mattermost.com/11.2.4/mattermost-team-11.2.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.2.4/mattermost-team-11.2.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `29893c531162fc0a102a40b9dba4edfb098fde9ed411319fd828d29960f1872c` +- GPG Signature: [https://releases.mattermost.com/11.2.4/mattermost-team-11.2.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.2.4/mattermost-team-11.2.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.2.4/sbom-mattermost-v11.2.4.json](https://github.com/mattermost/mattermost/releases/download/v11.2.4/sbom-mattermost-v11.2.4.json) + +Mattermost Team Edition v11.1.3 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-1-feature-release) - [Download](https://releases.mattermost.com/11.1.3/mattermost-team-11.1.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.1.3/mattermost-team-11.1.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `5fa9d524d330454200edc9828ed5c2c3a1e90c3c4ba64b9985205b5980b0f482` +- GPG Signature: [https://releases.mattermost.com/11.1.3/mattermost-team-11.1.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.1.3/mattermost-team-11.1.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.1.3/sbom-mattermost-v11.1.3.json](https://github.com/mattermost/mattermost/releases/download/v11.1.3/sbom-mattermost-v11.1.3.json) + +Mattermost Team Edition v11.0.7 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v11-changelog.html#release-v11-0-major-release) - [Download](https://releases.mattermost.com/11.0.7/mattermost-team-11.0.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/11.0.7/mattermost-team-11.0.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `5cdb640b42e3ae670eccc1217dc63f7bf2c9a665536663f039d1d83ace04ea76` +- GPG Signature: [https://releases.mattermost.com/11.0.7/mattermost-team-11.0.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/11.0.7/mattermost-team-11.0.7-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v11.0.7/sbom-mattermost-v11.0.7.json](https://github.com/mattermost/mattermost/releases/download/v11.0.7/sbom-mattermost-v11.0.7.json) + +Mattermost Team Edition v10.12.4 - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-12-feature-release) - [Download](https://releases.mattermost.com/10.12.4/mattermost-team-10.12.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.12.4/mattermost-team-10.12.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `952f629cedcea017d9db43e622eaebb8aef66ac4dcd03e93a1b861a82433d9ea` +- GPG Signature: [https://releases.mattermost.com/10.12.4/mattermost-team-10.12.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.12.4/mattermost-team-10.12.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.12.4/sbom-mattermost-v10.12.4.json](https://github.com/mattermost/mattermost/releases/download/v10.12.4/sbom-mattermost-v10.12.4.json) + +Mattermost Team Edition v10.11.15 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/product-overview/mattermost-v10-changelog.html#release-v10-11-extended-support-release) - [Download](https://releases.mattermost.com/10.11.15/mattermost-team-10.11.15-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.11.15/mattermost-team-10.11.15-linux-amd64.tar.gz` +- SHA-256 Checksum: `31c2d3a1e0702214e44426ae8c9734ff9cf1a7d874a2e278e90dafc7b67d98f6` +- GPG Signature: [https://releases.mattermost.com/10.11.15/mattermost-team-10.11.15-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.11.15/mattermost-team-10.11.15-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.11.15/sbom-mattermost-v10.11.15.json](https://github.com/mattermost/mattermost/releases/download/v10.11.15/sbom-mattermost-v10.11.15.json) + +Mattermost Team Edition v10.10.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-10-feature-release) - [Download](https://releases.mattermost.com/10.10.3/mattermost-team-10.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.10.3/mattermost-team-10.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `12387834baeeecf824b6b5a18df39d83803d0964ae4907f9e944f60e086117a0` +- GPG Signature: [https://releases.mattermost.com/10.10.3/mattermost-team-10.10.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.10.3/mattermost-team-10.10.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.10.3/sbom-mattermost-v10.10.3.json](https://github.com/mattermost/mattermost/releases/download/v10.10.3/sbom-mattermost-v10.10.3.json) + +Mattermost Team Edition v10.9.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-9-feature-release) - [Download](https://releases.mattermost.com/10.9.5/mattermost-team-10.9.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.9.5/mattermost-team-10.9.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `f2c05dd29d92b12135c58cb766e21cab788004e03ab4c4652735e914bd9e8da7` +- GPG Signature: [https://releases.mattermost.com/10.9.5/mattermost-team-10.9.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.9.5/mattermost-team-10.9.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.9.5/sbom-mattermost-v10.9.5.json](https://github.com/mattermost/mattermost/releases/download/v10.9.5/sbom-mattermost-v10.9.5.json) + +Mattermost Team Edition v10.8.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-8-feature-release) - [Download](https://releases.mattermost.com/10.8.4/mattermost-team-10.8.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.8.4/mattermost-team-10.8.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `ccfbef2c3b0972bed04159c27bf2c10b529ec147b550c9f310ffdbb78eed8ea5` +- GPG Signature: [https://releases.mattermost.com/10.8.4/mattermost-team-10.8.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.8.4/mattermost-team-10.8.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.8.4/sbom-mattermost-v10.8.4.json](https://github.com/mattermost/mattermost/releases/download/v10.8.4/sbom-mattermost-v10.8.4.json) + +Mattermost Team Edition v10.7.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-7-feature-release) - [Download](https://releases.mattermost.com/10.7.4/mattermost-team-10.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.7.4/mattermost-team-10.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `a562d80fb84f63223a5dad9b56cabd0ed8f951677d3b9575bae677e757004431` +- GPG Signature: [https://releases.mattermost.com/10.7.4/mattermost-team-10.7.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.7.4/mattermost-team-10.7.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.7.4/sbom-mattermost-v10.7.4.json](https://github.com/mattermost/mattermost/releases/download/v10.7.4/sbom-mattermost-v10.7.4.json) + +Mattermost Team Edition v10.6.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-6-feature-release) - [Download](https://releases.mattermost.com/10.6.6/mattermost-team-10.6.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.6.6/mattermost-team-10.6.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `c829f301d3fc2fdd6061454a3ea3aa4f26d398340398a736c3402bd5eeb345f9` +- GPG Signature: [https://releases.mattermost.com/10.6.6/mattermost-team-10.6.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.6.6/mattermost-team-10.6.6-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.6.6/sbom-mattermost-v10.6.6.json](https://github.com/mattermost/mattermost/releases/download/v10.6.6/sbom-mattermost-v10.6.6.json) + +Mattermost Team Edition v10.5.14 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-5-extended-support-release) - [Download](https://releases.mattermost.com/10.5.14/mattermost-team-10.5.14-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.5.14/mattermost-team-10.5.14-linux-amd64.tar.gz` +- SHA-256 Checksum: `f2f45b188c5a88af43e03e25bc373f617fc376867fc64d34ffcc83a593761bd5` +- GPG Signature: [https://releases.mattermost.com/10.5.14/mattermost-team-10.5.14-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.5.14/mattermost-team-10.5.14-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.5.14/sbom-mattermost-v10.5.14.json](https://github.com/mattermost/mattermost/releases/download/v10.5.14/sbom-mattermost-v10.5.14.json) + +Mattermost Team Edition v10.4.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-4-feature-release) - [Download](https://releases.mattermost.com/10.4.5/mattermost-team-10.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.4.5/mattermost-team-10.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `31edebbc416c8978a81f40cffe7ed98f9b39f8a1f695b18bdf98dddc9edb650c` +- GPG Signature: [https://releases.mattermost.com/10.4.5/mattermost-team-10.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.4.5/mattermost-team-10.4.5-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.4.5/sbom-mattermost-v10.4.5.json](https://github.com/mattermost/mattermost/releases/download/v10.4.5/sbom-mattermost-v10.4.5.json) + +Mattermost Team Edition v10.3.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-3-feature-release) - [Download](https://releases.mattermost.com/10.3.4/mattermost-team-10.3.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.3.4/mattermost-team-10.3.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `17f8554512d6a79f865075dfd8f7d9fddae6c5f1af49ea9b3cfd713f7e652dfe` +- GPG Signature: [https://releases.mattermost.com/10.3.4/mattermost-team-10.3.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.3.4/mattermost-team-10.3.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.3.4/sbom-mattermost-v10.3.4.json](https://github.com/mattermost/mattermost/releases/download/v10.3.4/sbom-mattermost-v10.3.4.json) + +Mattermost Team Edition v10.2.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-2-feature-release) - [Download](https://releases.mattermost.com/10.2.3/mattermost-team-10.2.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.2.3/mattermost-team-10.2.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `b18ad8db0ae03c863fa4cb7f611584794776e9a1df52cf19c4bb90ce86938eef` +- GPG Signature: [https://releases.mattermost.com/10.2.3/mattermost-team-10.2.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.2.3/mattermost-team-10.2.3-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.2.3/sbom-mattermost-v10.2.3.json](https://github.com/mattermost/mattermost/releases/download/v10.2.3/sbom-mattermost-v10.2.3.json) + +Mattermost Team Edition v10.1.7 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-1-feature-release) - [Download](https://releases.mattermost.com/10.1.7/mattermost-team-10.1.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.1.7/mattermost-team-10.1.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `baf2f1ec86448938d1ed2879cb19e5034259090cd8282d5bebdb6d495de33a06` +- GPG Signature: [https://releases.mattermost.com/10.1.7/mattermost-team-10.1.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.1.7/mattermost-team-10.1.7-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.1.7/sbom-mattermost-v10.1.7.json](https://github.com/mattermost/mattermost/releases/download/v10.1.7/sbom-mattermost-v10.1.7.json) + +Mattermost Team Edition v10.0.4 - [View Changelog](https://docs.mattermost.com/about/mattermost-v10-changelog.html#release-v10-0-major-release) - [Download](https://releases.mattermost.com/10.0.4/mattermost-team-10.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/10.0.4/mattermost-team-10.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `ad7ace64160e17b352b6f0801c928eca8200f7bc71305d2e65ca296a535cee60` +- GPG Signature: [https://releases.mattermost.com/10.0.4/mattermost-team-10.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/10.0.4/mattermost-team-10.0.4-linux-amd64.tar.gz.sig) +- SBOM Download Link: [https://github.com/mattermost/mattermost/releases/download/v10.0.4/sbom.json](https://github.com/mattermost/mattermost/releases/download/v10.0.4/sbom.json) + +Mattermost Team Edition v9.11.18 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-11-extended-support-release) - [Download](https://releases.mattermost.com/9.11.18/mattermost-team-9.11.18-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.11.18/mattermost-team-9.11.18-linux-amd64.tar.gz` +- SHA-256 Checksum: `35682178506b8ee37074285e3d75280c076fa4ba9049c4d31f52ccb9a408a47e` +- GPG Signature: [https://releases.mattermost.com/9.11.18/mattermost-team-9.11.18-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.11.18/mattermost-team-9.11.18-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.10.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-10-feature-release) - [Download](https://releases.mattermost.com/9.10.3/mattermost-team-9.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.10.3/mattermost-team-9.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `d50e2d3352129f3eaa5271cb3031b0210f9283954e727f7dca959b4c277ea6fc` +- GPG Signature: [https://releases.mattermost.com/9.10.3/mattermost-team-9.10.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.10.3/mattermost-team-9.10.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.9.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-9-feature-release) - [Download](https://releases.mattermost.com/9.9.3/mattermost-team-9.9.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.9.3/mattermost-team-9.9.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `3920fec7e3d3242fe29f5ecce83d2829c7e25d7de1a3da44ac65596f76589f00` +- GPG Signature: [https://releases.mattermost.com/9.9.3/mattermost-team-9.9.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.9.3/mattermost-team-9.9.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.8.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-8-feature-release) - [Download](https://releases.mattermost.com/9.8.3/mattermost-team-9.8.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.8.3/mattermost-team-9.8.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `bc44d551031df256d23aef67f11ea4abeb39e91d24c151755ad17d31bbf0aced` +- GPG Signature: [https://releases.mattermost.com/9.8.3/mattermost-team-9.8.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.8.3/mattermost-team-9.8.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.7.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-7-feature-release) - [Download](https://releases.mattermost.com/9.7.6/mattermost-team-9.7.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.7.6/mattermost-team-9.7.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `e7633a3214543026fa3737cea3c2f42cad85d532de815991443941ab32d8592a` +- GPG Signature: [https://releases.mattermost.com/9.7.6/mattermost-team-9.7.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.7.6/mattermost-team-9.7.6-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.6.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-6-feature-release) - [Download](https://releases.mattermost.com/9.6.3/mattermost-team-9.6.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.6.3/mattermost-team-9.6.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `630a51a8c3228465914b318fd0caa634f1a0a39010482aa478f090efee4ca566` +- GPG Signature: [https://releases.mattermost.com/9.6.3/mattermost-team-9.6.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.6.3/mattermost-team-9.6.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.5.14 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-5-extended-support-release) - [Download](https://releases.mattermost.com/9.5.14/mattermost-team-9.5.14-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.5.14/mattermost-team-9.5.14-linux-amd64.tar.gz` +- SHA-256 Checksum: `db5730b44caadb647b09e593be38d808d35f9f67c9806b2e022d08675fa5257a` +- GPG Signature: [https://releases.mattermost.com/9.5.14/mattermost-team-9.5.14-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.5.14/mattermost-team-9.5.14-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.4.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-4-feature-release) - [Download](https://releases.mattermost.com/9.4.5/mattermost-team-9.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.4.5/mattermost-team-9.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `9ab357c21c5d786965f2dc622a109630908b6eacd6412e2d57990e9c92ae19fb` +- GPG Signature: [https://releases.mattermost.com/9.4.5/mattermost-team-9.4.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.4.5/mattermost-team-9.4.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.3.3 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-3-feature-release) - [Download](https://releases.mattermost.com/9.3.3/mattermost-team-9.3.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.3.3/mattermost-team-9.3.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `c5ff7e13935c11b88f9fa4e5ccd3f448cfd3e61d2917c6f51ef6a4065e315276` +- GPG Signature: [https://releases.mattermost.com/9.3.3/mattermost-team-9.3.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.3.3/mattermost-team-9.3.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.2.6 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-2-feature-release) - [Download](https://releases.mattermost.com/9.2.6/mattermost-team-9.2.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.2.6/mattermost-team-9.2.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `b5ba2edac3d547c2929e46a1dbdf7f7b0f5de826a30d1c59b268a79e9cb6804b` +- GPG Signature: [https://releases.mattermost.com/9.2.6/mattermost-team-9.2.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.2.6/mattermost-team-9.2.6-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.1.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-1-feature-release) - [Download](https://releases.mattermost.com/9.1.5/mattermost-team-9.1.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.1.5/mattermost-team-9.1.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `0e876e1ab71a2a2035881371e0098a032b4ac7ac6dc4cabd8b8082f4357d8053` +- GPG Signature: [https://releases.mattermost.com/9.1.5/mattermost-team-9.1.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.1.5/mattermost-team-9.1.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v9.0.5 - [View Changelog](https://docs.mattermost.com/about/mattermost-v9-changelog.html#release-v9-0-major-release) - [Download](https://releases.mattermost.com/9.0.5/mattermost-team-9.0.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/9.0.5/mattermost-team-9.0.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `2aa5abe8dc65d6083c719ee0824e87f76d49d68c8ba8b6937c24295bfcc43dfc` +- GPG Signature: [https://releases.mattermost.com/9.0.5/mattermost-team-9.0.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/9.0.5/mattermost-team-9.0.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v8.1.13 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v8-1-extended-support-release) - [Download](https://releases.mattermost.com/8.1.13/mattermost-team-8.1.13-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/8.1.13/mattermost-team-8.1.13-linux-amd64.tar.gz` +- SHA-256 Checksum: `024138ea4072245ec71ed90268799d63cb2776bbf89d590f1f014cd27dadbbf0` +- GPG Signature: [https://releases.mattermost.com/8.1.13/mattermost-team-8.1.13-linux-amd64.tar.gz.sig](https://releases.mattermost.com/8.1.13/mattermost-team-8.1.13-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v8.0.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v8-0-major-release) - [Download](https://releases.mattermost.com/8.0.4/mattermost-team-8.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/8.0.4/mattermost-team-8.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `2c1dbff642b429abf4af39d32ea047a42ada8c57ebbf3cd9a3617243e4807ccf` +- GPG Signature: [https://releases.mattermost.com/8.0.4/mattermost-team-8.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/8.0.4/mattermost-team-8.0.4-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.10.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-10-feature-release) - [Download](https://releases.mattermost.com/7.10.5/mattermost-team-7.10.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.10.5/mattermost-team-7.10.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `e09c4e7d7134e94fb06e92bda041dc8c9d122649052b27c380b20ac591faff95` +- GPG Signature: [https://releases.mattermost.com/7.10.5/mattermost-team-7.10.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.10.5/mattermost-team-7.10.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.9.6 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-9-feature-release) - [Download](https://releases.mattermost.com/7.9.6/mattermost-team-7.9.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.9.6/mattermost-team-7.9.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `cb4334bb355bc8a8471e66886e5332467c9e21f105514778072a142e6ab65a9e` +- GPG Signature: [https://releases.mattermost.com/7.9.6/mattermost-team-7.9.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.9.6/mattermost-team-7.9.6-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.8.15 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-8-extended-support-release) - [Download](https://releases.mattermost.com/7.8.15/mattermost-team-7.8.15-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.8.15/mattermost-team-7.8.15-linux-amd64.tar.gz` +- SHA-256 Checksum: `1a4351b1c2fdf65ca575f2a0d4df0d78f3aef17bb09ed16080e1afc4c74a33b6` +- GPG Signature: [https://releases.mattermost.com/7.8.15/mattermost-team-7.8.15-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.8.15/mattermost-team-7.8.15-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.7.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-7-feature-release) - [Download](https://releases.mattermost.com/7.7.4/mattermost-team-7.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.7.4/mattermost-team-7.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `74c86a5efa8b838f028ff8a435b4becaf46723c9b8f2d032de0ca15d128fb5cd` +- GPG Signature: [https://releases.mattermost.com/7.7.4/mattermost-team-7.7.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.7.4/mattermost-team-7.7.4-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-5-feature-release) - [Download](https://releases.mattermost.com/7.5.2/mattermost-team-7.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.5.2/mattermost-team-7.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `b2162bc12b0b8763809f0795f429bc59018c712b14461db63158b453710fa885` +- GPG Signature: [https://releases.mattermost.com/7.5.2/mattermost-team-7.5.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.5.2/mattermost-team-7.5.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.4.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-4-feature-release) - [Download](https://releases.mattermost.com/7.4.1/mattermost-team-7.4.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.4.1/mattermost-team-7.4.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `9950495ebebdbfc4905d794e5c021d9600dfe7345c5967cb4d2271dc50428808` +- GPG Signature: [https://releases.mattermost.com/7.4.1/mattermost-team-7.4.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.4.1/mattermost-team-7.4.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.3.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-3-feature-release) - [Download](https://releases.mattermost.com/7.3.1/mattermost-team-7.3.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.3.1/mattermost-team-7.3.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `26af2a6235261d5cb8b3d29b55a5c50b38c92f0b5e70e3ffac74729112d82c87` +- GPG Signature: [https://releases.mattermost.com/7.3.1/mattermost-team-7.3.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.3.1/mattermost-team-7.3.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.2.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-2-feature-release) - [Download](https://releases.mattermost.com/7.2.1/mattermost-team-7.2.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.2.1/mattermost-team-7.2.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `42030c3b892b9428a653bb9a0a52f12dcef9b81535a0181e0456f7848203fce5` +- GPG Signature: [https://releases.mattermost.com/7.2.1/mattermost-team-7.2.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.2.1/mattermost-team-7.2.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.1.9 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-1-extended-support-release) - [Download](https://releases.mattermost.com/7.1.9/mattermost-team-7.1.9-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.1.9/mattermost-team-7.1.9-linux-amd64.tar.gz` +- SHA-256 Checksum: `affd62133d3e3db55ae1b1ac723391dd7ed04a2f7814c98da8db3833ba61c0ff` +- GPG Signature: [https://releases.mattermost.com/7.1.9/mattermost-team-7.1.9-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.1.9/mattermost-team-7.1.9-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v7.0.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v7-0-major-release) - [Download](https://releases.mattermost.com/7.0.2/mattermost-team-7.0.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/7.0.2/mattermost-team-7.0.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `95725aa1950d1165ed671fbc855bee386422c95c0cdfc71940bab2200002fcbe` +- GPG Signature: [https://releases.mattermost.com/7.0.2/mattermost-team-7.0.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/7.0.2/mattermost-team-7.0.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.7.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-7-feature-release) - [Download](https://releases.mattermost.com/6.7.2/mattermost-team-6.7.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.7.2/mattermost-team-6.7.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `f5e6d1433a09380d2197fde4c6c04d4ad876178823bd6e5fb63301382806fd16` +- GPG Signature: [https://releases.mattermost.com/6.7.2/mattermost-team-6.7.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.7.2/mattermost-team-6.7.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.6.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-6-feature-release) - [Download](https://releases.mattermost.com/6.6.2/mattermost-team-6.6.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.6.2/mattermost-team-6.6.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `3e0b3240037fc81e52c168805734bb46dbac454c704429777b82f852ba0f5858` +- GPG Signature: [https://releases.mattermost.com/6.6.2/mattermost-team-6.6.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.6.2/mattermost-team-6.6.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-5-feature-release) - [Download](https://releases.mattermost.com/6.5.2/mattermost-team-6.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.5.2/mattermost-team-6.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `3c62748e5a7c0c78ad81b9b514d7a8eb88d19232707167b68a41757827736262` +- GPG Signature: [https://releases.mattermost.com/6.5.2/mattermost-team-6.5.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.5.2/mattermost-team-6.5.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.4.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-4-feature-release) - [Download](https://releases.mattermost.com/6.4.3/mattermost-team-6.4.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.4.3/mattermost-team-6.4.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `8a0297e875a78aa90e7c92a344dcc16dda9b80c3dd17e0085e00a005d3892ec8` +- GPG Signature: [https://releases.mattermost.com/6.4.3/mattermost-team-6.4.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.4.3/mattermost-team-6.4.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.3.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-3-extended-support-release) - [Download](https://releases.mattermost.com/6.3.10/mattermost-team-6.3.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.3.10/mattermost-team-6.3.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `00771ee7649f7a13a1598491ee5222509e85920271a12b3ae9683356b4d563ff` +- GPG Signature: [https://releases.mattermost.com/6.3.10/mattermost-team-6.3.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.3.10/mattermost-team-6.3.10-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.2.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-2-feature-release) - [Download](https://releases.mattermost.com/6.2.5/mattermost-team-6.2.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.2.5/mattermost-team-6.2.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `21e21b7ca6706816a30bdd4e12b4cfb2416eb07523f178b167bd19bb92316ee6` +- GPG Signature: [https://releases.mattermost.com/6.2.5/mattermost-team-6.2.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.2.5/mattermost-team-6.2.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.1.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-1-feature-release) - [Download](https://releases.mattermost.com/6.1.3/mattermost-team-6.1.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.1.3/mattermost-team-6.1.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `942f2a051b25a36e32e9b5da19bc8cf3ba54fb6febeffe71ba1db72dbf242520` +- GPG Signature: [https://releases.mattermost.com/6.1.3/mattermost-team-6.1.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.1.3/mattermost-team-6.1.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v6.0.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v6-0-feature-release) - [Download](https://releases.mattermost.com/6.0.4/mattermost-team-6.0.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/6.0.4/mattermost-team-6.0.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `11b26d3b2b1f6367118da3c21c7ab46e289c900a8860870a1b07b1a46c71fa24` +- GPG Signature: [https://releases.mattermost.com/6.0.4/mattermost-team-6.0.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/6.0.4/mattermost-team-6.0.4-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.39.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-39-quality-release) - [Download](https://releases.mattermost.com/5.39.3/mattermost-team-5.39.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.39.3/mattermost-team-5.39.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `77f77bcd73da8f449aba069108fafc694829cfa5ad0b5bcf289b52ee116c3d10` +- GPG Signature: [https://releases.mattermost.com/5.39.3/mattermost-team-5.39.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.39.3/mattermost-team-5.39.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.38.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-38-feature-release) - [Download](https://releases.mattermost.com/5.38.4/mattermost-team-5.38.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.38.4/mattermost-team-5.38.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `03d083280e8764010505a4f07810531907265335a0115745bf32cd7250fe858e` +- GPG Signature: [https://releases.mattermost.com/5.38.4/mattermost-team-5.38.4-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.38.4/mattermost-team-5.38.4-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.37.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-37-extended-support-release) - [Download](https://releases.mattermost.com/5.37.10/mattermost-team-5.37.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.37.10/mattermost-team-5.37.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `3d8efd53b900d5ffc19ce5af142bb6103371111f122040edeab3b72913ffc0b1` +- GPG Signature: [https://releases.mattermost.com/5.37.10/mattermost-team-5.37.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.37.10/mattermost-team-5.37.10-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.36.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-36-feature-release) - [Download](https://releases.mattermost.com/5.36.2/mattermost-team-5.36.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.36.2/mattermost-team-5.36.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `dff78b91a2c36b948470f0b6df247bbc9bb489cce531fa1d239367a1448afc74` +- GPG Signature: [https://releases.mattermost.com/5.36.2/mattermost-team-5.36.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.36.2/mattermost-team-5.36.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.35.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-35-feature-release) - [Download](https://releases.mattermost.com/5.35.5/mattermost-team-5.35.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.35.5/mattermost-team-5.35.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `3d5f3e529e0f4276c2ffb1a601fd778787913f689e2fc83e4c32e3703740fe8e` +- GPG Signature: [https://releases.mattermost.com/5.35.5/mattermost-team-5.35.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.35.5/mattermost-team-5.35.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.34.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-34-feature-release) - [Download](https://releases.mattermost.com/5.34.5/mattermost-team-5.34.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.34.5/mattermost-team-5.34.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `40c8e00dcbf3f6543e511e3c5dbc072af2e2aced0614e5c3f500a53c66395716` +- GPG Signature: [https://releases.mattermost.com/5.34.5/mattermost-team-5.34.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.34.5/mattermost-team-5.34.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.33.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-33-feature-release) - [Download](https://releases.mattermost.com/5.33.5/mattermost-team-5.33.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.33.5/mattermost-team-5.33.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `b2a14215bf33079c45892c387e48b7977e96ab2f7543def0f655096782f9277d` +- GPG Signature: [https://releases.mattermost.com/5.33.5/mattermost-team-5.33.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.33.5/mattermost-team-5.33.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.32.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-32-feature-release) - [Download](https://releases.mattermost.com/5.32.1/mattermost-team-5.32.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.32.1/mattermost-team-5.32.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `86fd99e49b6ed687004d46813e51fd91e761a87dff58fa2878e752728fac555a` +- GPG Signature: [https://releases.mattermost.com/5.32.1/mattermost-team-5.32.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.32.1/mattermost-team-5.32.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.31.9 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-31-esr) - [Download](https://releases.mattermost.com/5.31.9/mattermost-team-5.31.9-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.31.9/mattermost-team-5.31.9-linux-amd64.tar.gz` +- SHA-256 Checksum: `b5322d6187ca62b1b5725ae7162c8a2c7306a181afae6ebc508fc5de7308c808` +- GPG Signature: [https://releases.mattermost.com/5.31.9/mattermost-team-5.31.9-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.31.9/mattermost-team-5.31.9-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.30.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-30-feature-release) - [Download](https://releases.mattermost.com/5.30.3/mattermost-team-5.30.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.30.3/mattermost-team-5.30.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `9d9e3c5b4602749d111a569b5a597745450898dab6976c17b5b87d7b8f82d4b4` +- GPG Signature: [https://releases.mattermost.com/5.30.3/mattermost-team-5.30.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.30.3/mattermost-team-5.30.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.29.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-29-quality-release) - [Download](https://releases.mattermost.com/5.29.2/mattermost-team-5.29.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.29.2/mattermost-team-5.29.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `10dff87226298c22254f56825877c8639a882dc04c42e82bb34cfdbef8b06bae` +- GPG Signature: [https://releases.mattermost.com/5.29.2/mattermost-team-5.29.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.29.2/mattermost-team-5.29.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.28.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-28-feature-release) - [Download](https://releases.mattermost.com/5.28.2/mattermost-team-5.28.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.28.2/mattermost-team-5.28.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `a2bcc4aba7e2bfeb5b2b8d9f9793a3ae4882b457b60a40fe86c959769be182e8` +- GPG Signature: [https://releases.mattermost.com/5.28.2/mattermost-team-5.28.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.28.2/mattermost-team-5.28.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.27.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-27-quality-release) - [Download](https://releases.mattermost.com/5.27.2/mattermost-team-5.27.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.27.2/mattermost-team-5.27.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `9d1a1dd99a516c3aee64db44c9ef11a9dc33674928cdd570ca33ed8ae7837ee3` +- GPG Signature: [https://releases.mattermost.com/5.27.2/mattermost-team-5.27.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.27.2/mattermost-team-5.27.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.26.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-26-feature-release) - [Download](https://releases.mattermost.com/5.26.1/mattermost-team-5.26.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.26.2/mattermost-team-5.26.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `1d56a1b10ba3ea3ee89e48c5ca7dcbbc40704f4b541a26d9f7b7254193c320bd` +- GPG Signature: [https://releases.mattermost.com/5.26.2/mattermost-team-5.26.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.26.2/mattermost-team-5.26.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.25.7 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-25-esr) - [Download](https://releases.mattermost.com/5.25.7/mattermost-team-5.25.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.25.7/mattermost-team-5.25.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `9ee64a0e0bb09ef24f32aa3eea1a80b47cccf36339b7498e52e0d244422e13bb` +- GPG Signature: [https://releases.mattermost.com/5.25.7/mattermost-team-5.25.7-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.25.7/mattermost-team-5.25.7-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.24.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-24-feature-release) - [Download](https://releases.mattermost.com/5.24.3/mattermost-team-5.24.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.24.3/mattermost-team-5.24.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `c5328aca0e1f21b9d6dcb7ac9c58b96d56a107cbbbfe4cedbf38934b554bd82f` +- GPG Signature: [https://releases.mattermost.com/5.24.3/mattermost-team-5.24.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.24.3/mattermost-team-5.24.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.23.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-23-quality-release) - [Download](https://releases.mattermost.com/5.23.2/mattermost-team-5.23.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.23.2/mattermost-team-5.23.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `253da42ac5cadcce29342dcc576fe2b232f2f2a012503996edaa377596bb5aa4` +- GPG Signature: [https://releases.mattermost.com/5.23.2/mattermost-team-5.23.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.23.2/mattermost-team-5.23.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.22.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-22-feature-release) - [Download](https://releases.mattermost.com/5.22.3/mattermost-team-5.22.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.22.3/mattermost-team-5.22.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `05f956d2c2257b9bcbb9d8a4abdd8a41a63f040a790823f9612b5e7c7ad54fa7` +- GPG Signature: [https://releases.mattermost.com/5.22.3/mattermost-team-5.22.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.22.3/mattermost-team-5.22.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.21.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-21-quality-release) - [Download](https://releases.mattermost.com/5.21.0/mattermost-team-5.21.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.21.0/mattermost-team-5.21.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `4d81e27dd107ba3c66ad06b3e029c2e1b940a0f56b46250d9ebccb4edf3e50eb` +- GPG Signature: [https://releases.mattermost.com/5.21.0/mattermost-team-5.21.0-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.21.0/mattermost-team-5.21.0-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.20.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-20-feature-release) - [Download](https://releases.mattermost.com/5.20.2/mattermost-team-5.20.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.20.2/mattermost-team-5.20.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `ea8122b2c8839bfba25f8b4c56b7a17c88c12064ead70a9a43aa8c3681af9ba2` +- GPG Signature: [https://releases.mattermost.com/5.20.2/mattermost-team-5.20.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.20.2/mattermost-team-5.20.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.19.3 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-19-esr) - [Download](https://releases.mattermost.com/5.19.3/mattermost-team-5.19.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.19.3/mattermost-team-5.19.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `ec3b85032baccc5794e83cc134ca0114594ef69babb003c0a7fe96e22c7bcbd2` +- GPG Signature: [https://releases.mattermost.com/5.19.3/mattermost-team-5.19.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.19.3/mattermost-team-5.19.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.18.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-18-feature-release) - [Download](https://releases.mattermost.com/5.18.2/mattermost-team-5.18.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.18.2/mattermost-team-5.18.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `06db01d79b99f02b80d91e0e2af8907bc04b82d305fdf56d5b797062c023f10f` +- GPG Signature: [https://releases.mattermost.com/5.18.2/mattermost-team-5.18.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.18.2/mattermost-team-5.18.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.17.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-17-quality-release) - [Download](https://releases.mattermost.com/5.17.3/mattermost-team-5.17.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.17.3/mattermost-team-5.17.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `8189929e301017f384b89d40b3ef90b0355eddf59ed1c4a46fdf591f23c3e870` +- GPG Signature: [https://releases.mattermost.com/5.17.3/mattermost-team-5.17.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.17.3/mattermost-team-5.17.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.16.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-16-feature-release) - [Download](https://releases.mattermost.com/5.16.5/mattermost-team-5.16.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.16.5/mattermost-team-5.16.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `442f1faf85037cac187022f8acb362ba84b871f23185ad400fcee7dc07c71672` +- GPG Signature: [https://releases.mattermost.com/5.16.5/mattermost-team-5.16.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.16.5/mattermost-team-5.16.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.15.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-15-quality-release) - [Download](https://releases.mattermost.com/5.15.5/mattermost-team-5.15.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.15.5/mattermost-team-5.15.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `820dba42b593c000e3288b50ab929ab0107d31410e6b4d032d2c272b8a206b32` +- GPG Signature: [https://releases.mattermost.com/5.15.5/mattermost-team-5.15.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.15.5/mattermost-team-5.15.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.14.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-14-feature-release) - [Download](https://releases.mattermost.com/5.14.5/mattermost-team-5.14.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.14.5/mattermost-team-5.14.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `65401dacc38785b8735f8517849ca30a1972713c82eac3862ac1ac917e493d33` +- GPG Signature: [https://releases.mattermost.com/5.14.5/mattermost-team-5.14.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.14.5/mattermost-team-5.14.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.13.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-13-quality-release) - [Download](https://releases.mattermost.com/5.13.3/mattermost-team-5.13.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.13.3/mattermost-team-5.13.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `bfbcc5b0f56c97104f8e17bf7068225258fdd50ce2171cc16c4fd69cf4fc3e69` +- GPG Signature: [https://releases.mattermost.com/5.13.3/mattermost-team-5.13.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.13.3/mattermost-team-5.13.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.12.6 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-12-feature-release) - [Download](https://releases.mattermost.com/5.12.6/mattermost-team-5.12.6-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.12.6/mattermost-team-5.12.6-linux-amd64.tar.gz` +- SHA-256 Checksum: `080fc3644165c313d9ddc7ad83f8c5391fe83df30c7ce58cfbcbe3605351c4af` +- GPG Signature: [https://releases.mattermost.com/5.12.6/mattermost-team-5.12.6-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.12.6/mattermost-team-5.12.6-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.11.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-11-quality-release) - [Download](https://releases.mattermost.com/5.11.1/mattermost-team-5.11.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.11.1/mattermost-team-5.11.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `ae0435ec68d739ac68714b49325d2cd1b7c58524726871cc2cea191c7b3e4085` +- GPG Signature: [https://releases.mattermost.com/5.11.1/mattermost-team-5.11.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.11.1/mattermost-team-5.11.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.10.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-10-feature-release) - [Download](https://releases.mattermost.com/5.10.2/mattermost-team-5.10.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.10.2/mattermost-team-5.10.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `8359e0fadb923bdc904c72a7defd9a1f819a7fdc888e62da5c593e30bfb4314d` +- GPG Signature: [https://releases.mattermost.com/5.10.2/mattermost-team-5.10.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.10.2/mattermost-team-5.10.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.9.8 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-9-esr) - [Download](https://releases.mattermost.com/5.9.8/mattermost-team-5.9.8-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.9.8/mattermost-team-5.9.8-linux-amd64.tar.gz` +- SHA-256 Checksum: `74052a54c6b70a223ad2378484ebda7f7f80f855674987dcc2c510b142aa8432` +- GPG Signature: [https://releases.mattermost.com/5.9.8/mattermost-team-5.9.8-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.9.8/mattermost-team-5.9.8-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.8.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-8-feature-release) - [Download](https://releases.mattermost.com/5.8.2/mattermost-team-5.8.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.8.2/mattermost-team-5.8.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `be9499f24d4b7a38e2f390583a26071626fe8242d8e34fb382228c23012621c7` +- GPG Signature: [https://releases.mattermost.com/5.8.2/mattermost-team-5.8.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.8.2/mattermost-team-5.8.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.7.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-7-quality-release) - [Download](https://releases.mattermost.com/5.7.3/mattermost-team-5.7.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.7.3/mattermost-team-5.7.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `95e81c3764338df2eefec48a395dd6972877447309570b8843220b952a33fde2` +- GPG Signature: [https://releases.mattermost.com/5.7.3/mattermost-team-5.7.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.7.3/mattermost-team-5.7.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.6.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-6-feature-release) - [Download](https://releases.mattermost.com/5.6.5/mattermost-team-5.6.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.6.5/mattermost-team-5.6.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `9bd863f5f52d87ff792b98e67597f193d34969e682f562a40b1542a8f301f008` +- GPG Signature: [https://releases.mattermost.com/5.6.5/mattermost-team-5.6.5-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.6.5/mattermost-team-5.6.5-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.5.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-5-quality-release) - [Download](https://releases.mattermost.com/5.5.3/mattermost-team-5.5.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.5.3/mattermost-team-5.5.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `a47f941509d3b4191e60de487fd27eccc034a7196818ecba5022f09c7718fe09` +- GPG Signature: [https://releases.mattermost.com/5.5.3/mattermost-team-5.5.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.5.3/mattermost-team-5.5.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.4.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-4-feature-release) - [Download](https://releases.mattermost.com/5.4.0/mattermost-team-5.4.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.4.0/mattermost-team-5.4.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `6b6f3ea9e0faf3895d71f38cf90737468a8db07b12370762be6cf60c6983355a` +- GPG Signature: [https://releases.mattermost.com/5.4.0/mattermost-team-5.4.0-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.4.0/mattermost-team-5.4.0-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.3.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-3-feature-release) - [Download](https://releases.mattermost.com/5.3.1/mattermost-team-5.3.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.3.1/mattermost-team-5.3.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `047a78b45293479f69f1cb99169a1c01ee0f90ffaf9dbe145147638fb410526a` +- GPG Signature: [https://releases.mattermost.com/5.3.1/mattermost-team-5.3.1-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.3.1/mattermost-team-5.3.1-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.2.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-2-feature-release) - [Download](https://releases.mattermost.com/5.2.2/mattermost-team-5.2.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.2.2/mattermost-team-5.2.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `d51adb0f8611bb90641e6169f1a81ed9a43765c1b5d885c3dc98038355cd4429` +- GPG Signature: [https://releases.mattermost.com/5.2.2/mattermost-team-5.2.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.2.2/mattermost-team-5.2.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.1.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-1-feature-release) - [Download](https://releases.mattermost.com/5.1.2/mattermost-team-5.1.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.1.2/mattermost-team-5.1.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `2fa5c087b74a41017fc6f38fa1d8d2dbb59adb2b4a70efc38b624c564a572f22` +- GPG Signature: [https://releases.mattermost.com/5.1.2/mattermost-team-5.1.2-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.1.2/mattermost-team-5.1.2-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v5.0.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v5-0-feature-release) - [Download](https://releases.mattermost.com/5.0.3/mattermost-team-5.0.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/5.0.3/mattermost-team-5.0.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `b3711ebd0e0240876ba751b18bd7a7349ffbf3f8a02d63ff79303aba98ca02c9` +- GPG Signature: [https://releases.mattermost.com/5.0.3/mattermost-team-5.0.3-linux-amd64.tar.gz.sig](https://releases.mattermost.com/5.0.3/mattermost-team-5.0.3-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v4.10.10 *Extended Support Release (ESR)* - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-10-esr) - [Download](https://releases.mattermost.com/4.10.10/mattermost-team-4.10.10-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.10.10/mattermost-team-4.10.10-linux-amd64.tar.gz` +- SHA-256 Checksum: `c8a8569e3a65246ab4babc01ce61c52b0ac0b6bd4984ef9896d20ce0ade233c2` +- GPG Signature: [https://releases.mattermost.com/4.10.10/mattermost-team-4.10.10-linux-amd64.tar.gz.sig](https://releases.mattermost.com/4.10.10/mattermost-team-4.10.10-linux-amd64.tar.gz.sig) + +Mattermost Team Edition v4.9.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-9-feature-release) - [Download](https://releases.mattermost.com/4.9.4/mattermost-team-4.9.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.9.4/mattermost-team-4.9.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `7b8ed13dc08349bcd7e0886464e7c242f5905bb6685fb28e434a2bd3e3423cfc` + +Mattermost Team Edition v4.8.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-8-feature-release) - [Download](https://releases.mattermost.com/4.8.2/mattermost-team-4.8.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.8.2/mattermost-team-4.8.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `192d5b9ce2b1aeb3fc1c8a09ca53e7883b0977d7a37d63ea2f116a13ca5efaf8` + +Mattermost Team Edition v4.7.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-7-feature-release) - [Download](https://releases.mattermost.com/4.7.4/mattermost-team-4.7.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.7.4/mattermost-team-4.7.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `caac6f6a612fc50b230e0f77b3ba58c34e7bca86c2c6479e7732dece03cd69dc` + +Mattermost Team Edition v4.6.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-6-feature-release) - [Download](https://releases.mattermost.com/4.6.3/mattermost-team-4.6.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.6.3/mattermost-team-4.6.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `2583ece515ecd6f9f45f874aa009c8fa8970a273d5d2e3006ee47aad0bac0a3d` + +Mattermost Team Edition v4.5.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-5-feature-release) - [Download](https://releases.mattermost.com/4.5.2/mattermost-team-4.5.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.5.2/mattermost-team-4.5.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `756f30c7690c1c3d81470d73f18d87ff99869d130ca2528cb2a97a660ec9b73e` + +Mattermost Team Edition v4.4.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-4-5-feature-release) - [Download](https://releases.mattermost.com/4.4.5/mattermost-team-4.4.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.4.5/mattermost-team-4.4.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `c261384b2bd8e0472e22307368818eb84b0171e15bdacf7e926187aa846861d7` + +Mattermost Team Edition v4.3.4 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-3-4-feature-release) - [Download](https://releases.mattermost.com/4.3.4/mattermost-team-4.3.4-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.3.4/mattermost-team-4.3.4-linux-amd64.tar.gz` +- SHA-256 Checksum: `fbc2504cfe417b45ed957c2f45be654849c87fc0d46c14067b8febdbc626f4cc` + +Mattermost Team Edition v4.2.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-2-2-feature-release) - [Download](https://releases.mattermost.com/4.2.2/mattermost-team-4.2.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.2.2/mattermost-team-4.2.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `4353f7d77bf5a0bcc1bbce00f2ca60fd14f5fd8caa8b57f4c518dc3ef657c4d6` + +Mattermost Team Edition v4.1.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-1-2-feature-release) - [Download](https://releases.mattermost.com/4.1.2/mattermost-team-4.1.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.1.2/mattermost-team-4.1.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `1b43c5d1938d17f3ce5d9f90c958a8353639422df48488f002377a30a6d84ae1` + +Mattermost Team Edition v4.0.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v4-0-5-feature-release) - [Download](https://releases.mattermost.com/4.0.5/mattermost-team-4.0.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/4.0.5/mattermost-team-4.0.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `a7897c6027eb972c0e5d8039862308f1073f1a078e0aa28b3d67f7a5e519dc04` + +Mattermost Team Edition v3.10.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-10-3) - [Download](https://releases.mattermost.com/3.10.3/mattermost-team-3.10.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.10.3/mattermost-team-3.10.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `cdc8c706ccc169c143be87167077171bfcf4bec8d85cc42e2e78c45d483bf0a1` + +Mattermost Team Edition v3.9.2 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-9-2) - [Download](https://releases.mattermost.com/3.9.2/mattermost-team-3.9.2-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.9.2/mattermost-team-3.9.2-linux-amd64.tar.gz` +- SHA-256 Checksum: `f7f878c7d195e1f336b7025fbb4063c1796fa16296ac2d7437d2a5067750966e` + +Mattermost Team Edition v3.8.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-8-3) - [Download](https://releases.mattermost.com/3.8.3/mattermost-team-3.8.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.8.3/mattermost-team-3.8.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `1a5de4052c007c54fce6cd844ab3e89aabc8d1a05b8bac72ef58f6896760c4e1` + +Mattermost Team Edition v3.7.5 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-7-5) - [Download](https://releases.mattermost.com/3.7.5/mattermost-team-3.7.5-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.7.5/mattermost-team-3.7.5-linux-amd64.tar.gz` +- SHA-256 Checksum: `eaee6a57ab9e2924f71853cbebf465d63f7dbf1112716c0e4768984de39f83a2` + +Mattermost Team Edition v3.6.7 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-6-7) - [Download](https://releases.mattermost.com/3.6.7/mattermost-team-3.6.7-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.6.7/mattermost-team-3.6.7-linux-amd64.tar.gz` +- SHA-256 Checksum: `8378f15a6bd070386077798f36d8e521b63844bc838f6553915c6fd4fba3b01d` + +Mattermost Team Edition v3.5.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-5-1) - [Download](https://releases.mattermost.com/3.5.1/mattermost-team-3.5.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.5.1/mattermost-team-3.5.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `2c6bc8b1c25e48d1ac887cd6cbef77df1f80542127b4d98c4d7c0dfbfade04d5` + +Mattermost Team Edition v3.4.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-4-0) - [Download](https://releases.mattermost.com/3.4.0/mattermost-team-3.4.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.4.0/mattermost-team-3.4.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `c352f6c15466c35787bdb5207a6efe6b471513ccdd5b1f64a91a8bd09c3365da` + +Mattermost Team Edition v3.3.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-3-0) - [Download](https://releases.mattermost.com/3.3.0/mattermost-team-3.3.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.3.0/mattermost-team-3.3.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `09948edb32ebb940708e30a05c269e69568dfd2e0c05495392f353b26139b79a` + +Mattermost Team Edition v3.2.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-2-0) - [Download](https://releases.mattermost.com/3.2.0/mattermost-team-3.2.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.2.0/mattermost-team-3.2.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `14e5c1460a991791ef3dccd6b5aeab40ce903090c5f6c15e7974eb5e4571417a` + +Mattermost Team Edition v3.1.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-1-0) - [Download](https://releases.mattermost.com/3.1.0/mattermost-team-3.1.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.1.0/mattermost-team-3.1.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `dad164d2382428c36623b6d50e3290336a3be01bae278a465e0d8d94b701e3ff` + +Mattermost Team Edition v3.0.3 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v3-0-3) - [Download](https://releases.mattermost.com/3.0.3/mattermost-team-3.0.3-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/3.0.3/mattermost-team-3.0.3-linux-amd64.tar.gz` +- SHA-256 Checksum: `b60d26a13927b614e3245384559869ae31250c19790b1218a193d52599c09834` + +Mattermost Team Edition v2.2.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v2-2-0) - [Download](https://releases.mattermost.com/2.2.0/mattermost-team-2.2.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/2.2.0/mattermost-team-2.2.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `d723fe9bf18d2d2a419a8d2aa6ad94fc99f251f8382c4342f08a48813501ca06` + +Mattermost Team Edition v2.1.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v2-1-0) - [Download](https://releases.mattermost.com/2.1.0/mattermost-team-2.1.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/2.1.0/mattermost-team-2.1.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `2825434aad23db1181e03b036bd826e66d6d4f21d337d209679a095a3ed9a4d2` + +Mattermost Team Edition v2.0.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v2-0-0) - [Download](https://releases.mattermost.com/2.0.0/mattermost-team-2.0.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/2.0.0/mattermost-team-2.0.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `005687c6a8128e1e40d01933f09d7da1a1b70b149a6bef96d923166bc1e7ce8f` + +Mattermost Team Edition v1.4.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v1-4-0) - [Download](https://releases.mattermost.com/1.4.0/mattermost-team-1.4.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/1.4.0/mattermost-team-1.4.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `0874dad79415066466c22ac584e599897124106417e774818cf40864d202dbb0` + +Mattermost Team Edition v1.3.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v1-3-0) - [Download](https://releases.mattermost.com/1.3.0/mattermost-team-1.3.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/1.3.0/mattermost-team-1.3.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `57af87ae8a98743b5379ed70f93a923654f7b8547f89b7f99ef9a718f472364d` + +Mattermost Team Edition v1.2.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v1-2-1) - [Download](https://releases.mattermost.com/1.2.1/mattermost-team-1.2.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/1.2.1/mattermost-team-1.2.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `f4cc5b0e1026026ff0cea4cc915b92967f9dfdf497c249731dc804a9a2ff156d` + +Mattermost Team Edition v1.1.1 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v1-1-1) - [Download](https://releases.mattermost.com/1.1.1/mattermost-team-1.1.1-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/1.1.1/mattermost-team-1.1.1-linux-amd64.tar.gz` +- SHA-256 Checksum: `e6687b9d7f94538e1f4a9f93a0bcb8a66e293e2260433ed648964baa53c3e561` + +Mattermost Team Edition v1.0.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v1-0-0) - [Download](https://releases.mattermost.com/1.0.0/mattermost-team-1.0.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/1.0.0/mattermost-team-1.0.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `208b429cc29119b3d3c686b8973d6100eb02845b1da2f18744195f055521cbc8` + +Mattermost Team Edition v0.7.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v0-7-0-beta) - [Download](https://releases.mattermost.com/0.7.0/mattermost-team-0.7.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/0.7.0/mattermost-team-0.7.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `f0a0e5b5fab3aeb5dc638ab3059b3ea5bf7bc1ec5123db1199aa10db41bfffb1` + +Mattermost Team Edition v0.6.0 - [View Changelog](https://docs.mattermost.com/about/unsupported-legacy-releases.html#release-v0-6-0-alpha) - [Download](https://releases.mattermost.com/0.6.0/mattermost-team-0.6.0-linux-amd64.tar.gz?src=arc) +- `https://releases.mattermost.com/0.6.0/mattermost-team-0.6.0-linux-amd64.tar.gz` +- SHA-256 Checksum: `9eb364f7f963af32d4a9efe3bbb5abb2a21ca5d1a213b50ca461dab047a123b6` + +
diff --git a/docs/main/product-overview/whats-new-in-v11.mdx b/docs/main/product-overview/whats-new-in-v11.mdx new file mode 100644 index 000000000000..37f884f67086 --- /dev/null +++ b/docs/main/product-overview/whats-new-in-v11.mdx @@ -0,0 +1,42 @@ +--- +title: What's New in v11 +sidebar_position: 50 +description: Highlights, new features, deprecations, and breaking changes in Mattermost v11. +slug: /whats-new/whats-new-in-v11 +--- + + + + +# What's New in v11 + +Per-major-version "What's New" pages summarize highlights, new features, deprecations, and breaking changes for that major release. Detailed commit-level history lives in the [v11 Changelog](./mattermost-v11-changelog.mdx). + +URL convention: `/whats-new/whats-new-in-v{X.Y}/` (Grafana pattern). Each major version gets its own page with a stable, deep-linkable URL. + +:::note Status +This page is a stub seeded by the IA redesign Phase 1 (see `docs/_redesign/proposed-ia.md` §6 in the repo). Content authored by the release-management team. +::: + +## Highlights + +*Per-release highlights authored by release-management team.* + +## New features + +*Per-release feature list. Each entry should link to the canonical feature page in the End User Guide, Administration Guide, or Integrations Guide.* + +## Deprecations + +*Features marked deprecated in this major. Each entry should link to the [Deprecated Features](./deprecated-features.mdx) registry.* + +## Breaking changes + +*Behaviors changed in a backwards-incompatible way. Each entry should cross-link to the [Upgrade Guide v11](../administration-guide/upgrade/upgrade-v11.mdx) so operators see the same information from the operator-facing angle.* + +## Related + +- [v11 Changelog](./mattermost-v11-changelog.mdx) — commit-level release notes. +- [Upgrade Guide v11](../administration-guide/upgrade/upgrade-v11.mdx) — operator-facing upgrade procedure. +- [Important Upgrade Notes](../administration-guide/upgrade/important-upgrade-notes.mdx) — version-by-version notes for non-sequential upgrades. +- [Release Policy](./release-policy.mdx) — Mattermost's ESR cadence and support windows. diff --git a/docs/main/recipes/product-vulnerability-incident.mdx b/docs/main/recipes/product-vulnerability-incident.mdx new file mode 100644 index 000000000000..ebb1a7826baa --- /dev/null +++ b/docs/main/recipes/product-vulnerability-incident.mdx @@ -0,0 +1,78 @@ +--- +title: "Mattermost Recipe: How to use Mattermost for product vulnerability incidents" +--- +## Problem + +After getting access to your Mattermost instance, you’d like to set up a workflow for security incident handling using Mattermost. Visit our [deployment section](https://mattermost.com/download/) if you want to learn more about how to deploy your own Mattermost instance. + +## Solution + +This guide walks through the set up of a product security incident room using [Collaborative Playbooks](/end-user-guide/workflow-automation) and [Channels](/end-user-guide/messaging-collaboration) with voice calling and screen sharing functionalities. + +### 1. Workspace setup + +For Cloud customers, all the functionalities works out-of-the-box with no technical setup. Simply invite your team members to your workspace and move onto the next section. For self-hosted deployments, refer to the [calls configuration documentation](/administration-guide/configure/plugins-configuration-settings#calls) to configure voice calling and screen sharing. + +### 2. Playbooks setup + +Now that your [workspace](/end-user-guide/end-user-guide-index) and teammates are ready, the next step is to create a playbook for incident handling. For this recipe, we're using an adapted playbooks template used by the Mattermost Product Security team that's available for [download here](https://github.com/mattermost/mattermost-security/blob/master/product_security/playbooks/security_vulnerability_playbook.json). + +After downloading the template above, connect to your Mattermost [workspace](/end-user-guide/end-user-guide-index). Then open the product menu and select **Playbooks**. + +![From the product menu, select Playbooks.](/images/recipe/prod-vuln-incident1.png) + +Next, open the **Playbooks** menu, select **Import**, and navigate to the file you downloaded. + +![Select the Playbooks tab, select Import, and go to the template file you downloaded.](/images/recipe/prod-vuln-incident2.png) + +When you've imported the file, you should have a new playbook called **Security Vulnerability Playbook**. Select the three dots to edit the playbook. + +![Select the three dots next to the new Security Vulnerability Playbook you imported.](/images/recipe/prod-vuln-incident3.png) + +Modify any tasks or actions to suit your use case. In our scenario, we’ve assigned the playbook owner role by default to Alice and added three other team members to be automatically added in the **Actions** tab. We recommend changing these to the members of your security team. + +![Select Actions to assign a playbook owner role and add other team members from the security team](/images/recipe/prod-vuln-incident4.png) + +Select **Save**. Then, hit **Run**. + +![Save your changes then run the playbook by selecting Run.](/images/recipe/prod-vuln-incident5.png) + +Set the title on a scenario that makes sense for your environment and select **Start Run** to create a new channel and invite the members as you’ve predefined. + +![Give your playbook run a name. When you select Start Run, a new channel is created and members are invited based on how you set up the playbook.](/images/recipe/prod-vuln-incident6.png) + +### 3. Using calls for voice chat and screen sharing + +For Mattermost Enterprise and Professional customers, you can select **Start call** in the run channel header to kick-off a channel call. The call can only be joined by participants of the incident channel. + +![If you're running Mattermost Enterprise or Professional, select Start Call in the channel header that other channel participants can join.](/images/recipe/prod-vuln-incident7.png) + +In the bottom-left corner of Mattermost, select the expand icon to open a separate pop-out window for the call, with additional options to start presenting. + +![In a call, expand the call screen using the Expand icon. Expanding the call also provides you with additional options to share your screen.](/images/recipe/prod-vuln-incident8.png) + +For Mattermost Team Edition, only 1:1 calls are supported. Open a direct message with another incident responder and follow the same steps as above. + + + +Want to try out calls? Select **Start call** in the incident channel to start a free 30-day trial of Mattermost Enterprise to enable this functionality for all channels. + + + +## Discussion + +Using collaborative playbooks you can ensure a streamlined approach to incident resolution. Our playbook template walks through a typical product vulnerability remediation aims to provide a structure resolution and also keeping the right stakeholder informed. + +The playbook starts with a **Triage** stage that verifies the validity of the issue, continues with an **Investigation** of exploitation (if possible) and follows with an active **Remediation** of the issue. After the issue is mitigated, the incident can go into **Resolution** and be closed with an incident post-mortem. + +When running the playbook, you can add key events, such as messages, to the timeline for easier reporting. To do so, select the app icon when hovering over a message. + +![When running a playbook, add key events to the timeline by hovering over a message and selecting the App icon.](/images/recipe/prod-vuln-incident9.png) + +Give it a short summary that will be shown on the incident overview, with the ability to jump to the message linked. + +![Provide a short summary visible on the incident overview. When you publish the message to the timeline, other users will be able to jump to the linked message.](/images/recipe/prod-vuln-incident10.png) + +The timeline is a great feature to provide an overview of the most significant events for both active and previous events for both responders and for management. + +The process and playbook shared here is only the starting point for your unique environment. By [customizing the playbooks](https://mattermost.com/blog/getting-started-with-playbooks/) and [adding additional integrations](https://mattermost.com/blog/how-to-make-your-incident-response-plan-with-mattermost/) to automatically be notified about new incidents you can further accelerate your response times. Additional integrations with SIEM solutions and platforms such as HackerOne will be released in the next months. diff --git a/docs/main/samples/index.mdx b/docs/main/samples/index.mdx new file mode 100644 index 000000000000..ec380ec43f21 --- /dev/null +++ b/docs/main/samples/index.mdx @@ -0,0 +1,3 @@ +--- +--- + diff --git a/docs/main/security-guide/cmmc-compliance.mdx b/docs/main/security-guide/cmmc-compliance.mdx new file mode 100644 index 000000000000..47b2adae10c8 --- /dev/null +++ b/docs/main/security-guide/cmmc-compliance.mdx @@ -0,0 +1,86 @@ +--- +title: "CMMC Compliance" +--- +## Overview + +The [Cybersecurity Maturity Model Certification (CMMC) 2.0](https://dodcio.defense.gov/CMMC/) is a U.S. Department of Defense (DoD) program that requires all contractors, subcontractors, and suppliers who handle Federal Contract Information (FCI) or Controlled Unclassified Information (CUI) to achieve certification. Whether your organization works directly with the DoD or as part of the Defense Industrial Base (DIB) supply chain, demonstrating compliance is mandatory to maintain contract eligibility. + +Achieving CMMC compliance is not guaranteed as it depends on proper configuration, policies, and broader organizational practices outside the software’s scope. However, this document outlines how Mattermost’s features can help U.S. Department of Defense contractors and subcontractors address specific [Level 2 requirements](https://dodcio.defense.gov/Portals/0/Documents/CMMC/AssessmentGuideL2v2.pdf). + +## Access Control and Identity Management + +Mattermost supports robust identity and access management to ensure that only authorized users access the system and that they only see data permitted for their role. Key capabilities include: + +[Single Sign-On (SSO) Integration](/administration-guide/onboard/sso-saml): Mattermost integrates with enterprise identity providers via [SAML 2.0](/administration-guide/onboard/sso-saml), [OpenID Connect](/administration-guide/onboard/sso-openidconnect), and [AD/LDAP](/administration-guide/onboard/ad-ldap). This allows you to centrally manage user accounts and enforce enterprise authentication policies. Only users provisioned in your directory (and assigned to the Mattermost service) can log in. This helps satisfy access control requirements to “limit system access to authorized users” (AC 3.1.1) using vetted corporate identities. + +[Role-Based Access Control (RBAC)](/administration-guide/onboard/advanced-permissions): Granular permissions in Mattermost ensure users can perform only the actions permitted for their role. For example, regular users cannot perform administrative functions, and [guest accounts](/administration-guide/onboard/guest-accounts) have restricted access to specific channels. Administrators can configure [team-wide](/administration-guide/onboard/advanced-permissions#team-override-scheme) and [channel-specific roles/permissions](/administration-guide/configure/user-management-configuration-settings#advanced-access-control) so that users only access data and functions needed for their duties. This supports the principle of least privilege (AC 3.1.5) and limits users’ actions to authorized functions (AC 3.1.2, AC 3.1.7). + +[Group-Based Access Management](/administration-guide/onboard/ad-ldap-groups-synchronization): Mattermost [AD/LDAP Group Sync](/administration-guide/onboard/ad-ldap-groups-synchronization) automates user provisioning and de-provisioning. Users can be added or removed from Mattermost teams/channels based on their directory group membership. This ensures timely removal of access when personnel change roles or leave (addressing account management aspects of AC 3.1.1) and helps enforce separation of duties (AC 3.1.4) by aligning channel access with organizational roles. + +[Session Management and Timeout](/administration-guide/configure/environment-configuration-settings#session-lengths): Mattermost administrators can define session security settings, including session idle timeouts and session lifetime. Sessions can be automatically invalidated after a period of inactivity or on demand. By limiting session duration and requiring re-authentication, Mattermost reduces the risk of unauthorized access via unattended sessions (helps address AC 3.1.6 for session lock and IA 3.5.2 for session control). Failed login attempt thresholds can also be set (e.g. lock out after X failed attempts) to mitigate brute-force attacks, aligning with AC 3.1.8. + +**User Agreement and Access Approval**: Mattermost Enterprise supports a [Custom Terms of Service](/administration-guide/comply/custom-terms-of-service) banner that users must accept upon first login. This can be used to remind users of acceptable use policies or consent to monitoring, indirectly supporting training/awareness requirements and ensuring users acknowledge security terms before accessing CUI. + +## Authentication and Multi-Factor Authentication (MFA) + +Secure authentication is critical for protecting Controlled Unclassified Information (CUI). Mattermost offers several features to strengthen user authentication in alignment with CMMC requirements: + +**Unique User Identification**: Each Mattermost user has a unique account (username/email), satisfying the need for unique IDs (IA 3.5.1). Administrators can [deactivate accounts](/administration-guide/configure/user-management-configuration-settings#deactivate-users) that are found to be generic or shared, and when integrated with enterprise SSO or LDAP, organizational policies can prevent shared account use. + +**Password Policy Enforcement**: For built-in authentication, Mattermost administrators can [enforce strong password requirements](/administration-guide/configure/authentication-configuration-settings#password) (minimum length, complexity). This helps meet IA 3.5.2 by requiring robust passwords and reducing the risk of credential compromise. + +[Multi-Factor Authentication](/administration-guide/onboard/multi-factor-authentication): Mattermost supports MFA for all user accounts. In self-hosted deployments, admins can enable and enforce TOTP-based MFA (e.g. requiring a one-time code from Google Authenticator during login). When Mattermost is integrated with SSO (SAML/OIDC), you can leverage the IdP’s MFA policies (e.g. CAC/PIV or OTP) for Mattermost logins. Requiring two factors for authentication aligns with CMMC practice IA 3.5.3, adding an extra layer of verification to protect accounts even if passwords are compromised. + +**Account Lockout and Recovery**: Mattermost can limit failed login attempts and lock accounts after a specified number of failures, helping to thwart brute-force attacks (IA 3.5.3, additional aspect). It also provides options for [secure password reset](/end-user-guide/access/access-your-workspace#reset-your-password) or [administrator-issued password resets](/administration-guide/configure/user-management-configuration-settings#reset-user-s-password) to support account recovery while maintaining security controls. + +## Audit Logging and Accountability + +CMMC Level 2 (NIST 800-171) places heavy emphasis on audit logging and the ability to track and monitor system activity (Audit & Accountability, AU 3.3.x controls). Mattermost provides built-in logging and monitoring features that help meet these requirements: + +**System and Application Audit Logs**: Mattermost records server and application events in an [audit log](/administration-guide/manage/logging#audit-logging) ([JSON format](/administration-guide/comply/embedded-json-audit-log-schema)). This includes security-relevant events such as logins, account creations, permission changes, server configuration changes, and more. Enterprise editions can send logs to external [syslog or monitoring systems](/administration-guide/manage/logging#syslog-target-configuration-options) in real time. These logs provide the evidence needed for AU.3.3.1 (“generate audit records for user/activity”) and support analysis of incidents. + +**Message History Retention**: By default, Mattermost retains a complete history of all messages (including edits and deletions) and file uploads in the database. Even if a user deletes a message in the application, the data is still preserved in the backend (unless a retention policy is in place). This ensures actions are traceable to individuals (AU 3.3.2) and meets requirements to retain and archive audit data. Administrators can also [disable users’ ability to edit or delete messages](/administration-guide/onboard/advanced-permissions#system-scheme), guaranteeing an unalterable record of conversation content for compliance purposes (useful for investigations and meeting audit retention requirements). + +[Compliance Export](/administration-guide/comply/compliance-export) and [Electronic Discovery](/administration-guide/comply/electronic-discovery): Mattermost’s [Compliance Export](/administration-guide/comply/compliance-export) feature can automatically export message history and metadata on a scheduled basis. This helps organizations produce chat records for audits, e-discovery, or long-term archival outside the application (relevant to AU 3.3.3 on audit record retention and review). Additionally, integration with third-party archiving and e-discovery tools is supported (e.g. Smarsh/Global Relay), enabling centralized analysis of communications for compliance. + +**Automated Monitoring and Alerts**: Administrators can generate daily compliance reports of Mattermost activity or use the audit data for anomaly detection. Mattermost supports integration with Security Information and Event Management (SIEM) systems by sending logs to a [syslog](/administration-guide/manage/logging#syslog-target-configuration-options) or via the [API](https://developers.mattermost.com/api-documentation/). This allows organizations to correlate Mattermost events with other security data and receive alerts on suspicious behavior (e.g. multiple failed logins, unexpected user account changes), supporting AU 3.3.4 and RA 3.11.2 (continuous monitoring and risk assessment). Mattermost’s audit log can thus feed into your incident monitoring process for rapid detection of issues. + +**Protection of Audit Information**: Access to Mattermost logs is restricted to system administrators – regular users cannot view or tamper with audit records. Logs written to files on the server can be further protected by OS-level access controls. This aligns with AU 3.3.5 (prevent unauthorized access/modification of audit records). Additionally, if using Mattermost Cloud or an external log aggregator, you should apply appropriate controls to those environments to safeguard the logs. + +## Incident Response and Incident Collaboration + +Under CMMC Level 2, companies must establish and maintain an effective Incident Response (IR) capability (IR 3.6.1–3.6.3). Mattermost is a valuable tool for incident response planning, execution, and documentation: + +[Incident Playbooks](/end-user-guide/workflow-automation/learn-about-playbooks): Collaborative workflows managed through Mattermost Playbooks allow teams to codify their incident response plans and checklists directly in the platform. For example, you can create a playbook for “Cyber Incident Response” that automatically spins up a dedicated incident channel, assigns tasks to responders, notifies stakeholders, and tracks investigation steps when an incident is declared. This ensures a standardized response process, fulfilling the requirement to establish an operational incident-handling capability (IR 3.6.1) with defined preparation, detection, containment, and recovery steps. + +**Dedicated Incident Channels**: Mattermost enables the creation of [private, invite-only channels](/end-user-guide/collaborate/channel-types#private-channels) for incident responders. During an incident (e.g. a network breach or system outage), teams can coordinate in a secure Mattermost channel that is isolated from potentially compromised systems. Mattermost’s self-hosted or air-gapped deployment options allow it to serve as an [out-of-band communication](/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob)) platform if primary systems or networks are affected. This approach helps contain incidents by preventing adversaries from monitoring or disrupting incident comms, and supports IR 3.6.1’s requirement for effective coordination during an incident. + +**Real-Time Notifications and Integrations**: Mattermost can integrate with monitoring tools and security systems to streamline detection and response. For instance, a SIEM or IDS can post an alert to a Mattermost channel (via webhooks or integrations) to notify the team of a potential incident. Mattermost [Playbooks](/end-user-guide/workflow-automation/learn-about-playbooks) support [automated incident notifications](/end-user-guide/workflow-automation/notifications-and-updates) – triggering alerts to responders when certain conditions are met. This real-time alerting and centralization of incident communication assists with prompt detection and reporting of incidents (IR 3.6.2). Team members can discuss and analyze the threat in Mattermost, accelerating triage. + +**Task Tracking and Documentation**: With Mattermost [Playbooks](/end-user-guide/workflow-automation/learn-about-playbooks) and [Boards](/end-user-guide/project-management/work-with-boards), each incident response run can have an associated [checklist of tasks](/end-user-guide/workflow-automation/work-with-tasks) (e.g. Identify affected systems, Collect logs, Eradicate malware, etc.) and an owner for each task. Responders check off tasks as they are completed, and all actions are timestamped. This creates an auditable timeline of the incident. All discussion in the incident channel, file attachments (like forensic screenshots), and timeline of actions are preserved. This comprehensive documentation of incidents satisfies IR 3.6.2’s mandate to track and report incidents to appropriate officials, and helps during post-incident analysis. Mattermost also facilitates post-incident reviews by enabling teams to add [retrospective notes](/end-user-guide/workflow-automation/metrics-and-goals#configure-retrospectives-before-a-run) in the channel or Playbook run after resolution. These records can be exported as needed for reporting to DoD or other authorities. + +**Testing Incident Response**: Mattermost can be used to conduct incident response drills or tabletops. Teams can simulate incidents by [running playbooks](/end-user-guide/workflow-automation/work-with-runs) in Mattermost (e.g. a planned exercise) to verify that everyone receives notifications and follows the procedures. This helps meet IR 3.6.3 (test the incident response capability) by providing a platform to perform and document response tests. Over time, playbook analytics and metrics (e.g. average time to resolution) allow you to gauge improvements in IR performance. + +By leveraging Mattermost for incident response, organizations create a central hub for managing incidents from initial alert to post-mortem. This directly supports CMMC Level 2 requirements to have an established, tested incident response process and to document and report incidents in a timely manner. + +## Communications Protection and Data Security + +CMMC Level 2 includes controls to safeguard information during storage and transmission (System & Communications Protection, SC 3.13.x) and to limit unauthorized information flows. Mattermost offers multiple features to protect data and control communications: + +[Encryption in Transit](/deployment-guide/transport-encryption): All Mattermost client-server communication can be [encrypted](/deployment-guide/encryption-options) using TLS (Transport Layer Security). When configured with HTTPS, Mattermost encrypts data in transit between the server and clients (web, desktop, mobile), preventing eavesdropping on CUI being discussed or transferred. This meets the requirement to protect CUI on networks by encrypting it during transmission (SC 3.13.8). Mattermost supports modern TLS protocols and ciphers; administrators should configure TLS per DoD guidelines (e.g. FIPS 140-2 validated cryptographic modules where applicable) to fully satisfy this control. + +[Encryption at Rest](/deployment-guide/encryption-options#encryption-at-rest): Mattermost supports encryption of data at rest through enterprise database and storage configurations. The application can be deployed on encrypted file systems or use encrypted storage backends. For instance, if using Amazon S3 for file storage, Mattermost Enterprise can enable [server-side encryption with S3-managed keys](/administration-guide/configure/environment-configuration-settings#enable-server-side-encryption-for-amazon-s3). If using a self-hosted database, administrators can enable disk encryption or TDE on the database server. By encrypting the Mattermost database and storage drives, organizations add a layer of protection for CUI stored in chat messages and files, helping to meet SC 3.13.16 (protect confidentiality of CUI at rest) and MP 3.8.3 (media sanitization if disks are disposed). Mattermost documentation encourages regular key rotation and secure key management for encryption at rest. + +**Network Access Control and Segmentation**: Mattermost can be deployed in a manner that controls network access to the system. In self-hosted deployments, organizations often place Mattermost servers in a secure enclave or DMZ with firewalls controlling ingress/egress. For cloud deployments, Mattermost Cloud offers [IP allowlisting](/administration-guide/manage/cloud-ip-filtering) (Enterprise plan) to restrict access to known IP ranges. These configurations address SC 3.13.1 and SC 3.13.2 by allowing Mattermost to reside within a protected network segment and ensuring only trusted networks or VPN users can reach it. Additionally, within Mattermost, data is segmented by [Teams](/end-user-guide/collaborate/organize-using-teams) and [Channels](/end-user-guide/collaborate/channel-types) – you can create separate teams for different projects or clearance levels, and mark channels as private to restrict membership. This “micro-segmentation” of conversations ensures that sensitive discussions (e.g. about a specific CUI program) are isolated to authorized individuals, reducing inadvertent information exposure. + +[Self-Hosted](/deployment-guide/server/server-deployment-planning#deployment-options) and [Air-Gapped Deployment](/deployment-guide/deployment-guide-index): Unlike many collaboration tools, Mattermost can be fully self-hosted on-premises or in a sovereign cloud, giving organizations complete control over data locality. DoD contractors can [deploy Mattermost in an air-gapped environment](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) with no outside internet connectivity if required. This supports compliance when handling CUI that cannot be exposed to external systems. By keeping Mattermost within the same secured IT boundary as other CUI systems, contractors address concerns of SC 3.13.5 (isolate system components from external access). Mattermost’s deployment flexibility (on-prem, GovCloud, etc.) allows alignment with DoD requirements (e.g. hosting at IL4/IL5 for sensitive data, if using cloud infrastructure). All user data resides in the infrastructure you control, aiding data sovereignty and compliance with any [FedRAMP](https://www.fedramp.gov/) or [ITAR](https://www.pmddtc.state.gov/ddtc_public/ddtc_public?id=ddtc_public_portal_itar_landing) restrictions that may apply in addition to CMMC. + +**Data Loss Prevention Measures**: While Mattermost does not natively include a full DLP suite, administrators can enforce certain restrictions to prevent unauthorized sharing or retention of data. For example, [public link sharing](/administration-guide/configure/site-configuration-settings#public-links) (for files) can be disabled or restricted, ensuring that shared files are not exposed to untrusted users. [File Upload Settings](/administration-guide/configure/site-configuration-settings#file-sharing-and-downloads) and [Plugin Whitelisting](/administration-guide/configure/plugins-configuration-settings#enable-remote-marketplace) allow you to control what types of files can be shared or which integrations are allowed, supporting SC 3.13.4 (control of information flows). Additionally, the [Push Notification contents](/administration-guide/configure/site-configuration-settings#push-notification-contents) can be configured to omit message text, so that if mobile push notifications are used, they do not leak sensitive message content to device lock screens or external services. For more advanced DLP, Mattermost’s open [APIs](https://developers.mattermost.com/api-documentation/) and [webhooks](https://developers.mattermost.com/integrate/webhooks/) enable integration with external DLP solutions or content filtering systems (e.g. a script could detect and remove messages containing certain keywords or PII). These measures help fulfill AC 3.1.3 / SC 3.13.4 by controlling the flow of CUI and preventing it from leaving authorized channels. + +**Sensitive Information Controls**: [System-wide banners](/administration-guide/manage/system-wide-notifications) can display CUI handling notices such as "⚠️ This system contains CUI. Use authorized accounts only. All activity is monitored." Supports AC.L2-3.1.9, AT.L2-3.2.1, IR.L2-3.6.2, and MP.L2-3.8.2. As well as [channel-specific banners](/end-user-guide/collaborate/display-channel-banners) can be used to flag channels containing CUI or incident response data, reinforce workflow integrity, or restrict data sharing. Supports AC.L2-3.1.3, MP.L2-3.8.2, AU.L2-3.3.1/3.3.2, and SC.L2-3.13.4. + +**Antivirus Scanning**: To address system integrity requirements (SI 3.14.5 for scanning files for malware), Mattermost can integrate with antivirus tools. A [ClamAV plugin](https://mattermost.com/marketplace/antivirus-plugin/) is available that scans files uploaded to Mattermost for viruses and malware. When enabled, this helps ensure that malicious files are detected and quarantined, protecting users and meeting the intent of controls on detecting and protecting against malware (SI 3.14.4 and SI 3.14.5). Administrators should also keep the Mattermost server host up-to-date with security patches and monitor for vulnerabilities (SI 3.14.1/3.14.2), as part of overall system integrity maintenance. + +Register to our [Trust site](https://trust.mattermost.com/) to see a full listing of all controls mapped to Mattermost features. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization’s secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/security-guide/compliance-frameworks/disa-stig.mdx b/docs/main/security-guide/compliance-frameworks/disa-stig.mdx new file mode 100644 index 000000000000..78aae0151fa4 --- /dev/null +++ b/docs/main/security-guide/compliance-frameworks/disa-stig.mdx @@ -0,0 +1,137 @@ +--- +title: "DISA STIG" +sidebar_label: "DISA STIG" +description: Mattermost's posture against the DISA Security Technical Implementation Guide (STIG) and Security Requirements Guide (SRG) hardening framework. +--- + + + + + + +# DISA STIG + +This page documents Mattermost's posture against the DISA Security Technical Implementation Guides (STIG) and the underlying Security Requirements Guides (SRG) — the hardening framework DoD and federal civilian customers use to validate that a product is configured to known-secure defaults. + +:::important Status +Current status is **Roadmap** — see the `` badge above. Mattermost does not publish a dedicated Mattermost STIG today. The applicable framework for Mattermost configuration is the **Application Server SRG** and **Application Security and Development SRG**, with operating system hardening covered by the OS-specific STIG (RHEL 9, Ubuntu 22.04 LTS, Windows Server, etc.). + +This page documents the gap honestly: which SRG requirements are met by Mattermost's default and recommended configuration today, which require explicit customer configuration, and what's not addressed. +::: + +## Applicable STIGs and SRGs for a Mattermost deployment + +A Mattermost deployment crosses multiple STIG/SRG boundaries. The customer's authorization package typically references all of: + +| Layer | Document | Source | +|---|---|---| +| Operating system | RHEL 9 STIG / Ubuntu 22.04 LTS STIG / Windows Server STIG | [DISA STIG library](https://public.cyber.mil/stigs/downloads/) | +| Database | PostgreSQL 13+ STIG | [DISA STIG library](https://public.cyber.mil/stigs/downloads/) | +| Reverse proxy | NGINX is covered by the Web Server SRG (no NGINX-specific STIG) | DISA SRG library | +| Application server | Application Server SRG | DISA SRG library | +| Application | Application Security and Development SRG | DISA SRG library | +| Container runtime (if used) | Container Image SRG, Kubernetes STIG | DISA STIG library | + +Mattermost's contribution is the configuration at the application + application-server tiers. OS, database, and proxy layers are customer-hardened per their respective STIGs. + +## Application Security and Development SRG mapping + +The Application Security and Development SRG defines ~280 requirements. The summary below groups them by control family and identifies Mattermost's coverage. Full per-requirement mapping is a roadmap item. + +### Access Control (AC) — Application Security and Development SRG + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000033 — Application authentication | SAML 2.0, OIDC, AD/LDAP; PIV/CAC via IdP. See [Onboard Users](../../administration-guide/onboard/). | +| SRG-APP-000038 — Application access enforcement | RBAC (System / Team / Channel) + ABAC (Enterprise Advanced). See [Manage Permissions](../../administration-guide/manage/). | +| SRG-APP-000068 — Account lockout after unsuccessful login attempts | `ServiceSettings.MaximumLoginAttempts` config setting. | +| SRG-APP-000133 — Session timeout | `ServiceSettings.SessionLengthWebInHours` config setting. | +| SRG-APP-000148 — Multi-factor authentication enforcement | Enforced via the IdP. | +| SRG-APP-000164 — Account inactivity disabling | Customer-managed via the IdP. | + +### Audit and Accountability (AU) + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000091 — Audit record generation | JSON audit log emitted by default. See [Comply](../../administration-guide/comply/). | +| SRG-APP-000095 — Audit record content (who, what, when, where, source) | Audit log schema includes timestamp, user, action, resource, source IP, session ID. See Audit Log Reference (Phase 2). | +| SRG-APP-000099 — Audit record review and analysis | Customer-managed SIEM integration. | +| SRG-APP-000118 — Audit log capacity and overflow handling | Customer-managed at the SIEM tier; Mattermost emits to local files or remote endpoints. | +| SRG-APP-000119 — Audit log integrity protection | Customer-managed at the SIEM tier; Mattermost does not sign audit entries at emission today. | + +### Identification and Authentication (IA) + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000148 — User identity assurance | SAML federation to a STIG-compliant IdP. | +| SRG-APP-000164 — Account management | Provisioning via SCIM (Enterprise Advanced) + IdP-driven onboarding. | +| SRG-APP-000172 — Cryptographic identity protection | FIPS 140-3 validated module — see [Configure FIPS at Install Time](../../deployment-guide/server/configure-fips-at-install-time). | +| SRG-APP-000516 — Replay-resistant authentication | SAML with signed assertions + short-lived session tokens. | + +### System and Communications Protection (SC) + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000014 — Cryptographic protection of transmitted information | TLS 1.2+ enforced. See [Transport Encryption](../../deployment-guide/transport-encryption). | +| SRG-APP-000142 — Network access by default deny | NGINX-level configuration + System Console IP filtering (Cloud). | +| SRG-APP-000231 — Protection of information at rest | Database-tier + file-storage-tier encryption. See [Encryption Options](../../deployment-guide/encryption-options). | +| SRG-APP-000439 — Mobile device protection | EMM/MAM integration (Intune, etc.). See [Mobile Security](../mobile-security). | + +### Configuration Management (CM) + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000033 — Configuration baseline | `config.json` version-controlled by customer + Mattermost Operator CRDs for Kubernetes. | +| SRG-APP-000516 — Removal of unsupported components | Disable unused plugins, integrations, and features. See [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features). | + +### System and Information Integrity (SI) + +| Requirement category | Mattermost configuration | +|---|---| +| SRG-APP-000274 — Software integrity verification | Mattermost releases are PGP-signed; verify before install. | +| SRG-APP-000345 — Boundary protection (image proxy) | Image proxy disabled in air-gapped mode. See [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features). | +| SRG-APP-000456 — Flaw remediation cadence | Mattermost ESR cadence and security advisory feed — see [Release Policy](../../product-overview/release-policy). | + +## Roadmap items + +The following are not yet supported in product or documentation: + +- **Mattermost-specific STIG checklist** — a `.ckl`-format STIG checklist file mapping each SRG requirement to a Mattermost-specific finding. Roadmap. +- **Pre-hardened reference deployment** — an Ansible / Terraform module that applies the STIG-aligned configuration as a single deployable unit. Roadmap. +- **Audit log signing at emission** — cryptographic signing of audit log entries inside Mattermost (currently relies on the SIEM tier for tamper-evidence). Roadmap. +- **Automated SCAP scanning support** — emitting machine-readable configuration state for SCAP scanner ingestion. Not on roadmap. + +## Hardening checklist (interim) + +While the full STIG checklist is on the roadmap, customers can begin hardening today by: + +1. **Apply OS STIG** for the host OS (RHEL 9 / Ubuntu 22.04 / Windows Server). +2. **Apply PostgreSQL STIG** for the database tier. +3. **Apply Web Server SRG** to the NGINX reverse proxy. +4. **Apply Mattermost configuration** from the [Required configuration summary on the FedRAMP Moderate page](./fedramp-moderate#required-configuration) — this satisfies the majority of Application Security and Development SRG requirements applicable to Mattermost. +5. **Enable FIPS mode at install time** — see [Configure FIPS at Install Time](../../deployment-guide/server/configure-fips-at-install-time). +6. **Disable phone-home features** — see [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features). +7. **Configure audit log export** to a STIG-compliant SIEM. +8. **Configure IdP-side** policies for MFA, PIV/CAC, session lifetime, account lockout. + +## Customer responsibility + +DISA STIG compliance is **deployment-specific and customer-led**. Mattermost provides: + +- Default configurations aligned with SRG requirements where Mattermost owns the control. +- This mapping document for the controls Mattermost contributes to. +- Validated configuration guidance for the [FedRAMP Moderate](./fedramp-moderate) and [DoD IL4 / IL5](./dod-il-4-5) baselines that share many SRG requirements. + +Customers are responsible for OS-tier, database-tier, proxy-tier, and CAP-tier hardening, plus the assessment + authorization process. + +## References + +- [DISA STIG library](https://public.cyber.mil/stigs/downloads/) — canonical source. +- [Application Security and Development SRG](https://public.cyber.mil/stigs/srg-stig-tools/) — the primary applicable SRG. +- [DoD IL4 / IL5](./dod-il-4-5) — companion compliance page; STIG and IL4/IL5 are typically pursued together. +- [FedRAMP Moderate](./fedramp-moderate) — the underlying NIST 800-53 baseline that backs both IL and STIG requirements. diff --git a/docs/main/security-guide/compliance-frameworks/dod-il-4-5.mdx b/docs/main/security-guide/compliance-frameworks/dod-il-4-5.mdx new file mode 100644 index 000000000000..8ebe00d94cb0 --- /dev/null +++ b/docs/main/security-guide/compliance-frameworks/dod-il-4-5.mdx @@ -0,0 +1,121 @@ +--- +title: "DoD Impact Level 4 / Impact Level 5" +sidebar_label: "DoD IL4 / IL5" +description: Mattermost's posture against the DoD Cloud Computing Security Requirements Guide (CC SRG) Impact Level 4 and Impact Level 5 baselines. +--- + + + + + + +# DoD Impact Level 4 / Impact Level 5 + +This page documents Mattermost's posture against the DoD Cloud Computing Security Requirements Guide (CC SRG) Impact Level (IL) 4 and Impact Level 5 baselines. IL4 covers Controlled Unclassified Information (CUI) including export-controlled and mission-critical data. IL5 covers National Security Systems data and unclassified information requiring a higher level of protection than IL4. + +:::important Status +Current status is **Roadmap** — see the `` badge above. Mattermost is FedRAMP Moderate–aligned (see [FedRAMP Moderate](./fedramp-moderate)), which is the standard prerequisite for IL4 sponsorship. IL5 additionally requires US-citizen-only operational support and dedicated infrastructure. + +This page documents the gap honestly: what controls are met today via the FedRAMP Moderate baseline, what additional controls IL4/IL5 require beyond FedRAMP Moderate, and the customer's role in deploying Mattermost inside an authorized boundary. +::: + +## Authorization landscape + +| Level | Data classification | Network | Mattermost availability | +|---|---|---|---| +| **IL2** | Non-controlled, non-CUI | Internet-accessible | Standard Mattermost Cloud is suitable; no special configuration required. | +| **IL4** | CUI (including export-controlled, PHI, FOUO) | DISA NIPRNet boundary (CAP) | Self-Hosted Enterprise on AWS GovCloud (US) or Azure Government, customer-managed authorization boundary. | +| **IL5** | National Security Systems, mission-critical | DISA NIPRNet (dedicated) | Self-Hosted Enterprise on AWS GovCloud (US) or Azure Government, dedicated single-tenant infrastructure, US-citizen-only operational support, customer-managed authorization boundary. | +| **IL6** | Classified up to Secret | SIPRNet | Self-Hosted Enterprise in customer-managed enclave (out of scope for this page — see [Air-Gapped Operations](../../deployment-guide/air-gapped-operations/)). | + +## Baseline inheritance from FedRAMP Moderate + +A Mattermost deployment that meets the configuration on the [FedRAMP Moderate](./fedramp-moderate) page inherits the majority of the IL4 / IL5 control baseline. The CC SRG explicitly maps DoD impact levels to NIST 800-53 baselines: + +- **IL4** ≈ FedRAMP Moderate + DoD-specific overlays. +- **IL5** ≈ FedRAMP High + DoD-specific overlays, with the additional dedicated-infrastructure and US-person operational support requirements. + +Customers pursuing IL4 / IL5 authorization should start with the FedRAMP Moderate configuration as the baseline. + +## Additional controls beyond FedRAMP Moderate + +### Cryptography + +| Requirement | Mattermost support | +|---|---| +| FIPS 140-3 validated cryptographic modules in all data paths | See [Configure FIPS at Install Time](../../deployment-guide/server/configure-fips-at-install-time). Enable FIPS mode at install. | +| TLS 1.2+ exclusively; no TLS 1.0 / 1.1 | Configure in NGINX / reverse proxy per [Setup TLS](../../deployment-guide/server/setup-tls). | +| Data-at-rest encryption | See [Encryption Options](../../deployment-guide/encryption-options). | +| Key management aligned with NIST 800-57 | Customer-managed via HSM, AWS KMS, Azure Key Vault, or equivalent. | + +### Network boundary (Cloud Access Point — CAP) + +IL4 / IL5 require traffic to traverse a DISA CAP. Mattermost does not provide the CAP; customers deploy Mattermost behind their authorized CAP. + +- All inbound user traffic terminates at the CAP, not at the Mattermost reverse proxy. +- Outbound integrations (webhooks, push proxy egress, plugin marketplace) must be either disabled or routed through the CAP. Use [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features) as the inventory of outbound calls. + +### Audit and logging + +| Requirement | Mattermost support | +|---|---| +| Audit log immutability and retention ≥ 1 year (IL4) / ≥ 3 years (IL5) | JSON audit log + customer-managed SIEM export. Configure retention at the SIEM and the storage tier. | +| Audit log content includes all NIST 800-53 AU-3 fields | Documented in Audit Log Reference (Phase 2). | +| Real-time audit log monitoring | Customer-managed via SIEM integration (Splunk, ELK, OpenSearch, etc.). | +| Tamper-evident audit log integrity controls | Customer-managed at the SIEM tier; Mattermost does not sign audit log entries at emission. | + +### Authentication and identity + +| Requirement | Mattermost support | +|---|---| +| PIV / CAC smart-card authentication | Supported via SAML federation with a customer-managed IdP that supports CAC (Entra ID + ADFS with CAC, Okta with CAC, etc.). | +| Multi-factor authentication for all users | Enforced via the IdP. Mattermost honors the IdP's MFA assertion. | +| Account inactivity lockout | Configured via the IdP. | +| Privileged account separation | Custom roles + ABAC (Enterprise Advanced). | + +### Personnel + +**IL5 specifically**: Operational support personnel with access to Mattermost infrastructure must be US citizens. Mattermost provides Enterprise support tiers; for IL5 deployments, customers either: + +- Self-operate Mattermost (most common — Mattermost is self-hosted) and use Mattermost commercial support for product issues only, not for direct production access. +- Engage Mattermost professional services for a US-person-only engagement (contact Mattermost sales). + +### Dedicated infrastructure (IL5 only) + +IL5 requires dedicated, non-shared infrastructure. Mattermost Cloud (multi-tenant) is not suitable for IL5. Self-Hosted on customer-dedicated infrastructure (AWS GovCloud single-tenant, Azure Government single-tenant, or on-premises) is the supported path. + +## Required configuration summary + +A Mattermost deployment aligned with IL4 / IL5 requires, at minimum: + +1. **FIPS mode enabled at install time** — see [Configure FIPS at Install Time](../../deployment-guide/server/configure-fips-at-install-time). +2. **TLS 1.2+ exclusively** with FIPS-approved cipher suites. +3. **Audit log retention ≥ 1 year (IL4) / ≥ 3 years (IL5)** via customer SIEM. +4. **PIV / CAC authentication** via SAML federation to a customer-managed IdP. +5. **CAP-fronted network boundary** — Mattermost behind, not in front of, the CAP. +6. **Phone-home features disabled** — see [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features). +7. **Dedicated infrastructure (IL5 only)** — single-tenant AWS GovCloud / Azure Government / on-prem. +8. **US-person operational support (IL5 only)** — customer-controlled. + +## Customer responsibility + +DoD IL authorizations are **customer-led**. Mattermost provides the validated configuration and feature support documented on this page; customers are responsible for: + +- The authorization package (SSP, POA&M, ATO memo). +- Sponsorship by a DoD organization. +- Pen-testing within the authorization boundary. +- Continuous monitoring per the CC SRG. + +Mattermost will provide attestation letters, FIPS certificates, and configuration evidence to support a customer's authorization package on request via [https://mattermost.com/trust/](https://mattermost.com/trust/). + +## References + +- [DoD Cloud Computing Security Requirements Guide](https://public.cyber.mil/dccs/dccs-documents/) — the canonical CC SRG. +- [NIST SP 800-53 Rev. 5](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final) — the underlying control catalog. +- [FedRAMP Moderate](./fedramp-moderate) — the baseline Mattermost is aligned to today. +- [Mattermost Trust Portal](https://mattermost.com/trust/) — current attestation status and supporting evidence. diff --git a/docs/main/security-guide/compliance-frameworks/fedramp-moderate.mdx b/docs/main/security-guide/compliance-frameworks/fedramp-moderate.mdx new file mode 100644 index 000000000000..24edd92b95d7 --- /dev/null +++ b/docs/main/security-guide/compliance-frameworks/fedramp-moderate.mdx @@ -0,0 +1,137 @@ +--- +title: FedRAMP Moderate +sidebar_position: 1 +description: Mattermost's FedRAMP Moderate authorization posture, configuration guidance, and NIST 800-53 control mappings. +--- + + + + + + +# FedRAMP Moderate + +This page documents Mattermost's posture against the **FedRAMP Moderate** baseline (NIST 800-53 Rev. 5 Moderate control set). It is the primary entry surface for **Security Architects** and **Accreditors** (`docs/_redesign/personas.md` §5 in the repo) preparing System Security Plans (SSPs) or evaluating Mattermost for use in FedRAMP-bounded environments. + +:::important Status +Current authorization status is set by the `` badge above. Status updates require sign-off from Mattermost's compliance team — do not change in PRs without product + legal approval. See `docs/_redesign/proposed-ia.md` §5 risk 4 in the repo. +::: + +## Authorization scope + +When Mattermost achieves FedRAMP Moderate authorization, the authorization will apply to a specific deployment configuration. Customers using Mattermost in a FedRAMP-bounded environment **inherit** the authorization only when their deployment matches the authorized configuration. Deviations require customer-managed re-authorization. + +Documented in this page: + +- The authorized **edition** (Enterprise / Enterprise Advanced). +- The authorized **deployment mode** (Cloud Government or Self-Hosted in a FedRAMP-bounded enclave). +- The authorized **release version range**. +- The **shared responsibility model** — which controls Mattermost implements, which the customer implements, and which are shared. + +## NIST 800-53 control mapping + +The mapping below is organized by NIST 800-53 control family. Each row identifies the Mattermost feature, plugin, or configuration setting that implements the control. Where multiple controls share an implementation, the implementation is listed once and cross-referenced. + +This structure is modeled on [Teleport's FedRAMP page](https://goteleport.com/docs/zero-trust-access/compliance-frameworks/fedramp/), which organizes by NIST control family because that is the abstraction auditors cite in SSPs. + +### Access Control (AC) + +| Control | Implementation | Configuration | +|---|---|---| +| AC-2 (Account Management) | System Console → Users + SCIM provisioning | [Onboard Users](../../administration-guide/onboard/) | +| AC-3 (Access Enforcement) | Role-based access control (System / Team / Channel) + Advanced Permissions | [Manage Permissions](../../administration-guide/manage/) | +| AC-6 (Least Privilege) | Custom roles + ABAC (Enterprise Advanced) | [Manage Permissions](../../administration-guide/manage/) | +| AC-7 (Unsuccessful Login Attempts) | `ServiceSettings.MaximumLoginAttempts` + account lockout | System Console → Authentication | +| AC-11 (Session Lock) | `ServiceSettings.SessionLengthWebInHours` + session expiration | System Console → Session Lengths | +| AC-17 (Remote Access) | TLS enforcement + MFA | [Transport Encryption](../../deployment-guide/transport-encryption.mdx) | + +### Audit and Accountability (AU) + +| Control | Implementation | Configuration | +|---|---|---| +| AU-2 (Event Logging) | Audit log + JSON audit log schema | [Comply](../../administration-guide/comply/) | +| AU-3 (Content of Audit Records) | JSON audit log fields | Audit Log Reference (Phase 2) | +| AU-6 (Audit Review, Analysis, and Reporting) | SIEM integration via audit log export | *Audit Log Export to Air-Gapped SIEM* (Phase 2) | +| AU-9 (Protection of Audit Information) | Audit log immutability + offline export | Audit Log Reference (Phase 2) | +| AU-12 (Audit Record Generation) | Per-action audit emissions | Audit Log Reference (Phase 2) | + +### Identification and Authentication (IA) + +| Control | Implementation | Configuration | +|---|---|---| +| IA-2 (Identification and Authentication) | SAML 2.0, OIDC, AD/LDAP | [Onboard Users](../../administration-guide/onboard/) | +| IA-2(1) (MFA for Privileged Accounts) | MFA enforcement for system admins | System Console → MFA | +| IA-2(2) (MFA for Non-Privileged Accounts) | MFA enforcement for all users | System Console → MFA | +| IA-5 (Authenticator Management) | Password complexity policy + rotation | System Console → Password | +| IA-8 (Identification and Authentication, Non-Organizational Users) | Guest accounts with separate permission model | [Guest Accounts](../../administration-guide/manage/) | + +### Configuration Management (CM) + +| Control | Implementation | Configuration | +|---|---|---| +| CM-2 (Baseline Configuration) | `config.json` version control + Operator CR | [Configure](../../administration-guide/configure/) | +| CM-6 (Configuration Settings) | Hardening guide + STIG profile | [Hardening Guides](../../security-guide/) | +| CM-7 (Least Functionality) | Per-feature enable/disable flags + plugin gating | [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features) | +| CM-8 (Information System Component Inventory) | `mmctl system info` + Support Packet | [Maintain](../../administration-guide/) | + +### System and Communications Protection (SC) + +| Control | Implementation | Configuration | +|---|---|---| +| SC-7 (Boundary Protection) | NGINX reverse proxy + TLS + image proxy | [Setup NGINX Proxy](../../deployment-guide/server/setup-nginx-proxy.mdx) | +| SC-8 (Transmission Confidentiality and Integrity) | TLS 1.2+ enforcement | [Setup TLS](../../deployment-guide/server/setup-tls.mdx) | +| SC-13 (Cryptographic Protection) | FIPS 140-3 validated modules (when FIPS mode enabled at install time) | *Configure FIPS at Install Time* (Phase 1) and *Cryptography & FIPS* (Phase 2) | +| SC-28 (Protection of Information at Rest) | Database encryption at rest + file storage encryption | [Encryption Options](../../deployment-guide/encryption-options.mdx) | + +### System and Information Integrity (SI) + +| Control | Implementation | Configuration | +|---|---|---| +| SI-2 (Flaw Remediation) | Security advisory feed + ESR cadence | [ESR Support Policy](../../product-overview/) | +| SI-4 (Information System Monitoring) | Prometheus / Grafana / Loki integration | [Monitor & Operate](../../administration-guide/) | +| SI-7 (Software, Firmware, and Information Integrity) | Signed releases + checksum verification | Release verification — Phase 2 | + +### Other control families — Phase 2 + +The following control families will be added in Phase 2 as the Mattermost compliance team completes the authorization package: + +- **AT** — Awareness and Training (operator + user training references) +- **CA** — Assessment, Authorization, and Monitoring (ATO process documentation) +- **CP** — Contingency Planning (backup, DR, BCP) +- **IR** — Incident Response +- **MA** — Maintenance +- **MP** — Media Protection +- **PE** — Physical and Environmental Protection (deployment-context specific) +- **PL** — Planning +- **PS** — Personnel Security +- **RA** — Risk Assessment +- **SA** — System and Services Acquisition +- **SR** — Supply Chain Risk Management + +## Shared responsibility + +When Mattermost achieves FedRAMP Moderate authorization for the Cloud Government deployment mode, a formal shared responsibility model will be published here. Self-Hosted deployments operate entirely under the customer's authorization boundary — Mattermost's contribution is the validated configuration guidance on this page. + +## Required configuration + +For a Mattermost deployment to align with FedRAMP Moderate, the following configuration is required: + +1. **FIPS mode enabled at install time** — see *Configure FIPS at Install Time* (Phase 1). FIPS cannot be enabled post-deploy. +2. **TLS 1.2+ for all client and inter-service traffic** — see [Transport Encryption](../../deployment-guide/transport-encryption.mdx). +3. **Audit log retention ≥ 1 year** — configure via `LogSettings.FileLevel` and external SIEM export. +4. **MFA enforced for all users** — System Console → MFA. +5. **Phone-home features disabled** — see [Disable Phone-Home Features](../../deployment-guide/air-gapped-operations/disable-phone-home-features). +6. **Audit log offline export configured** — see *Audit Log Export to Air-Gapped SIEM* (Phase 2). + +## References + +- [NIST SP 800-53 Rev. 5](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final) — base control catalog. +- [FedRAMP Moderate baseline](https://www.fedramp.gov/baselines/) — the Moderate control selection. +- [Mattermost Trust Portal](https://mattermost.com/trust/) — formal attestation letters and authorization artifacts. +- [Teleport FedRAMP documentation](https://goteleport.com/docs/zero-trust-access/compliance-frameworks/fedramp/) — reference model for the NIST-control-family structure used on this page. +- [GitLab FedRAMP secure configuration guide](https://docs.gitlab.com/security/dedicated_for_government_secure_config_guide/) — reference model for numbered requirement / recommendation structure. diff --git a/docs/main/security-guide/compliance-frameworks/index.mdx b/docs/main/security-guide/compliance-frameworks/index.mdx new file mode 100644 index 000000000000..a78bff71d351 --- /dev/null +++ b/docs/main/security-guide/compliance-frameworks/index.mdx @@ -0,0 +1,32 @@ +--- +title: Compliance Frameworks +sidebar_position: 1 +description: Mattermost's posture and configuration guidance for FedRAMP, DoD IL, DISA STIG, FIPS, HIPAA, FINRA, CMMC, and related regulatory frameworks. +--- + +# Compliance Frameworks + +This section is the canonical home for **framework-specific** compliance documentation: FedRAMP, DoD IL4/IL5, DISA STIG, FIPS, HIPAA, FINRA, CMMC, and others. Each page below documents Mattermost's authorization posture, the configuration required to align with the framework, and (where applicable) the mapping from framework controls to specific Mattermost features and settings. + +:::note Operational vs. framework content +Compliance is documented in two places by design: +- **Frameworks** (here): authorization status, control mappings, configuration guidance. Target persona: **Security Architect / Accreditor** and **Compliance Officer**. +- **Operational machinery** ([Administration Guide → Comply](../../administration-guide/comply/)): step-by-step procedures for running compliance exports, eDiscovery searches, Legal Hold, data retention. Target persona: **Administrator** and **Compliance Officer**. + +Cross-link both ways when adding new content. +::: + +## Pages + +- [FedRAMP Moderate](./fedramp-moderate) — Authorization status, configuration guidance, and NIST 800-53 control mappings. +- [DoD IL4 / IL5](./dod-il-4-5) — Posture against DoD Cloud Computing Security Requirements Guide Impact Levels 4 and 5. +- [DISA STIG](./disa-stig) — Posture against the Application Security and Development SRG and applicable STIG layers. +- [CMMC Compliance](../cmmc-compliance) — preserved at parent level pending Phase 2 re-organization. +- [HIPAA Compliance](../hipaa-compliance) — preserved at parent level pending Phase 2 re-organization. +- [FINRA Compliance](../finra-compliance) — preserved at parent level pending Phase 2 re-organization. + +## How this section is organized + +Each framework page leads with an `` badge stating Mattermost's current authorization posture (Authorized / In Process / Roadmap / Not Pursued). Pages with "In Process" or "Roadmap" status document the **gap honestly** — what controls are met today, what's not, and the expected timeline. + +For legally citable attestation letters, see the [Mattermost Trust Portal](https://mattermost.com/trust/) (external). The pages in this section describe **configuration and control mappings** — they do not substitute for the formal attestation artifacts. diff --git a/docs/main/security-guide/dependency-vulnerability-analysis.mdx b/docs/main/security-guide/dependency-vulnerability-analysis.mdx new file mode 100644 index 000000000000..e6cc1289d313 --- /dev/null +++ b/docs/main/security-guide/dependency-vulnerability-analysis.mdx @@ -0,0 +1,51 @@ +--- +title: "Dependency Vulnerability Analysis" +--- +This document provides context on why certain third-party dependencies in Mattermost, although flagged as vulnerable by security scanners, do not pose a risk in Mattermost deployments. + +This analysis is regularly updated as new vulnerability reports are received and evaluated. + +## Overview + +Mattermost regularly scans its dependencies for known vulnerabilities. Some dependencies may be flagged as vulnerable by security scanners, but these vulnerabilities might not be applicable to Mattermost due to: + +- How the dependency is used in Mattermost +- The specific version or configuration implemented +- Mitigations already in place +- False positives in the scanning process + +## Dependency Analysis Table + +Below is a list of dependencies flagged as vulnerable by security scanners for our latest release, along with the justification for why each issue is not relevant to Mattermost deployments: + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Dependency / VersionVulnerabilityFalse Positive Justification
github.com/mattermost/ mattermost/server/v8Multiple CVE IDsMattermost uses Go module workspaces, which override go.mod dependency versions with local filesystem code at build time. The vulnerable versions are never included in final Docker images.
golang.org/x/crypto v0.44.0GHSA-f6x5-jh6r-wrfv CVE-2025-47914Mattermost doesn't utilize the vulnerable golang.org/x/crypto/ssh package. Upgrade is planned for v11.4
golang.org/x/crypto v0.44.0GGHSA-j5w8-q4qc-rx2x CVE-2025-58181Mattermost doesn't utilize the vulnerable golang.org/x/crypto/ssh package. Upgrade is planned for v11.4
diff --git a/docs/main/security-guide/finra-compliance.mdx b/docs/main/security-guide/finra-compliance.mdx new file mode 100644 index 000000000000..8a37a79aa4f6 --- /dev/null +++ b/docs/main/security-guide/finra-compliance.mdx @@ -0,0 +1,19 @@ +--- +title: "FINRA Compliance" +--- +Mattermost Enterprise and Enterprise Advanced features help users to meet the [cybersecurity requirements of the United States Financial Industry Regulatory Authority (FINRA)](https://www.finra.org/rules-guidance/key-topics/cybersecurity) as part of a customer's existing operational systems, including technology governance, system change management, risk assessments, technical controls, incident response, vendor management, data loss prevention, and staff training. + +FINRA reviews a firm’s ability to protect the confidentiality, integrity, and availability of sensitive customer information. This includes reviewing each firm’s compliance with SEC regulations, including: + +- Regulation [S-P (17 CFR §248.30)](https://www.ecfr.gov/current/title-17/chapter-II/part-248/subpart-A/subject-group-ECFR83262a0bce5ffaa/section-248.30), which requires firms to adopt written policies and procedures to protect customer information against cyber-attacks and other forms of unauthorized access. +- Regulation [S-ID (17 CFR §248.201-202)](https://www.ecfr.gov/current/title-17/chapter-II/part-248), which outlines a firm's duties regarding the detection, prevention, and mitigation of identity theft. +- The [Securities Exchange Act of 1934 (17 CFR §240.17a-4(f))](https://www.ecfr.gov/current/title-17/chapter-II/part-240), which requires firms to preserve electronically stored records in a non-rewriteable, non-erasable format. + +Mattermost supports FINRA compliance as part of a customer's integrated operations in the following ways: + +- **Continuous archiving:** Configuration as a non-rewriteable, non-erasable system of record for all messages and files entered into the system. Moreover, automated compliance exports and integration support for Smarsh/Actiance and Global Relay provide third-party eDiscovery options. +- **Secure deployment:** Deployment within private, public, and on-premises networks with existing FINRA-compliant safeguards and infrastructure to protect customer information from cyber attack. +- **Support for intrusion detection:** Ability to support multi-layered intrusion detection from authentication systems to application servers to database access, including configuration of proxy, application, and database logging to deeply audit system interactions. +- **Multi-layered disaster recovery:** High Availability configuration, automated data back up, and enterprise information archiving integration to prevent data loss and recover from disaster. + +**\*DISCLAIMER:** MATTERMOST DOES NOT POSITION ITS PRODUCTS AS "GUARANTEED COMPLIANCE SOLUTIONS". WE MAKE NO GUARANTEE THAT YOU WILL ACHIEVE REGULATORY COMPLIANCE USING MATTERMOST PRODUCTS. YOUR LEVEL OF SUCCESS IN ACHIEVING REGULATORY COMPLIANCE DEPENDS ON YOUR INTERPRETATION OF THE APPLICABLE REGULATION, AND THE ACTIONS YOU TAKE TO COMPLY WITH THEIR REQUIREMENTS. SINCE THESE FACTORS DIFFER ACCORDING TO INDIVIDUALS AND BUSINESSES, WE CANNOT GUARANTEE YOUR SUCCESS, NOR ARE WE RESPONSIBLE FOR ANY OF YOUR ACTIONS. NO GUARANTEES ARE MADE THAT YOU WILL ACHIEVE ANY SPECIFIC COMPLIANCE RESULTS FROM THE USE OF MATTERMOST OR FROM ANY RECOMMENDATIONS CONTAINED ON OUR WEBSITES, AND AS SUCH, THIS SHOULD NOT BE A SUBSTITUTE TO CONSULTING WITH YOUR OWN LEGAL AND COMPLIANCE REPRESENTATIVES ON THESE MATTERS. diff --git a/docs/main/security-guide/hipaa-compliance.mdx b/docs/main/security-guide/hipaa-compliance.mdx new file mode 100644 index 000000000000..8b30dba9ca52 --- /dev/null +++ b/docs/main/security-guide/hipaa-compliance.mdx @@ -0,0 +1,16 @@ +--- +title: "HIPAA Compliance" +--- +Deploying Mattermost as part of a HIPAA-compliant IT infrastructure requires a deployment team trained on [HIPAA-compliance requirements and standards](https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/). + +HIPAA-compliant deployments commonly consider the following: + +- Omitting the contents of messages from mobile push and email notifications: + - If your [Push Notifications Contents](/administration-guide/configure/site-configuration-settings#push-notification-contents) option is set to `Send full message snippet` there is a chance Personal Health Information (PHI) contained in messages could be displayed on a user's locked phone as a notification. To avoid this, set the option to `Send generic description with user and channel names` or `Send generic description with only sender name`. + - Similarly, setting [Email Notifications Contents](/administration-guide/configure/site-configuration-settings#email-notification-contents) to `Send generic description with only sender name` will only send the team name and name of the person who sent the message, with no information about channel name or message contents included in email notifications. +- Beyond Technical Safeguards, HIPAA compliance deployments also require: + - Administrative Safeguards + - Physical Safeguards + - Organizational requirements and other standards. + +To learn more, please review [HIPAA requirements from the US Department of Health and Human Services](https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/). diff --git a/docs/main/security-guide/mobile-security.mdx b/docs/main/security-guide/mobile-security.mdx new file mode 100644 index 000000000000..ea11ee52cd3c --- /dev/null +++ b/docs/main/security-guide/mobile-security.mdx @@ -0,0 +1,84 @@ +--- +title: "Mobile Security" +--- +Mattermost mobile is built with a robust security framework to protect user data and prevent unauthorized access. The Mattermost Mobile app's comprehensive security framework ensures that user data remains protected against unauthorized access. + +Continuous compliance through [secure SDLC practices and proactive vulnerability management](/deployment-guide/mobile/mobile-security-features#security-compliance) further reinforces the platform’s resilience. + +## Mobile Device Management (MDM) + +Mattermost supports the ability for an EMM provider to push Mattermost Mobile apps to EMM-enrolled devices. This approach is recommended for organizations that typically use EMM solutions to deploy Mobile apps to meet security and compliance policies. Learn more about [deploying Mattermost mobile using an EMM provider](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider). + +### Remote wipe capability + +Administrators can remotely wipe Mattermost data from mobile devices in case of loss or theft. This capability prevents unauthorized access to sensitive information by ensuring that data is erased from compromised devices. + +### Compliance policies + +Mattermost can be integrated with mobile device management solutions to enforce compliance policies. These policies ensure that mobile devices accessing the application adhere to security standards, such as encryption, password complexity, and device integrity. Learm more about [compliance with Mattermost](/administration-guide/compliance-with-mattermost). + +### Mobile access platforms + +Mattermost mobile applications can be operated under the protection of mobile access platforms like [Hypori](https://www.hypori.com/). These platforms provide an additional layer of security by creating a virtualized environment for mobile applications, ensuring that sensitive data is isolated from the device's operating system. This approach enhances data protection and minimizes the risk of data leakage or unauthorized access. + +## Microsoft Intune Mobile Application Management (MAM) + +Mattermost supports Microsoft Intune Mobile Application Management (MAM) to enforce app-level data protection on **iOS** devices without requiring full device enrollment in a mobile device management (MDM) solution. Intune MAM applies security policies directly to the Mattermost mobile app based on user identity, enabling organizations to protect corporate or mission-sensitive data on Bring Your Own Device (BYOD) and mixed-use devices while preserving user privacy. + +Intune MAM for Mattermost is currently supported on iOS only. For Android deployments, we recommend using **Android Enterprise work profiles** as an alternative approach until Mattermost adds support for Intune MAM on Android. + +Intune MAM enforcement is applied per Mattermost workspace and is evaluated continuously at runtime. If a device becomes non-compliant or enrollment fails, access to protected content is blocked automatically. This approach allows organizations to extend zero-trust and data loss prevention (DLP) controls to mobile users without assuming ownership of the underlying device. + +Learn more about the [security capabilities enabled through Intune MAM](/deployment-guide/mobile/mobile-security-features#microsoft-intune-mobile-application-management-mam)). + +## Jailbreak and root detection + +Jailbreaking or rooting a device disables many built-in security measures, making the device prone to malware and unauthorized access. This protection enables Mattermost administrators to deny access from any mobile device that appears to have been tampered with or is running a non-standard version of the operating system. Additionally, a rooted device may stop checking for software updates and security patches, and it might not be able to install them because the kernel is no longer properly signed. + +By detecting such devices, Mattermost ensures that only secure, uncompromised devices can access sensitive data. When enabled by the system admin, this proactive measure ensures the underlying mobile platform operates reliably and performs the expected kernel and operating system security protections before sending any customer data to the Mattermost application, and minimizes risk in environments where personal device security cannot be guaranteed. Learn more about Mattermost [mobile jailbreak and root detection](/deployment-guide/mobile/mobile-security-features#jailbreak-and-root-detection). + +## Biometric authentication + +Native biometric authentication ensures only the authorized device owner can access the Mattermost application. By utilizing hardware-level security, biometrics significantly enhance data protection, especially in cases of lost or stolen devices. This advanced security measure is far more robust and user-friendly compared to traditional passwords, adding a resilient layer of protection against unauthorized access. + +Administrators can mandate biometric authentication each time users attempt to open the Mattermost application, further safeguarding customer data and mitigating risks. Learn more about Mattermost [mobile biometric authentication](/deployment-guide/mobile/mobile-security-features#biometric-authentication), and the [user workflows in which users must authenticate](/administration-guide/configure/environment-configuration-settings#enable-biometric-authentication), when biometric authentication is enabled. + +## Screenshot and screen recording prevention + +Preventing screenshots and screen recordings protects sensitive information from being inadvertently or maliciously shared. This control is essential in ensuring that confidential communications and data remain within the secure confines of the app. By blocking unauthorized screen captures, Mattermost significantly reduces the risk of data leakage via visual content by preventing users from taking screenshots or recording their screens on the mobile device. This feature ensures that users can not intentionally or inadvertently capture an image of any information shared in Mattermost. Learn more about Mattermost [mobile screenshot and screen recording prevention](/deployment-guide/mobile/mobile-security-features#screenshot-and-screen-recording-prevention). + +## App sandboxing and secure data storage + +Sandboxing is a critical defense that isolates the application’s data from other apps—even if malicious software is present on the device. This isolation helps maintain user privacy and data integrity by ensuring that only Mattermost has access to its stored data. Learn more about Mattermost [mobile app sandboxing and secure data storage](/deployment-guide/mobile/mobile-security-features#mobile-data-isolation). + +Learn more about how Mattermost leverages robust sandboxing mechanisms on both iOS and Android to [securely store files](/deployment-guide/mobile/secure-mobile-file-storage) in its cache folder within the application container, ensuring isolation from unauthorized third-party apps. + +## Push notification message visibility + +Push notifications are a convenient way to stay updated, but they can also pose security risks if sensitive information is displayed. Mattermost provides options to [control the visibility of message content in push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications), ensuring that sensitive information is not inadvertently exposed through locked mobile screens and via relay servers from Apple and Google when sending notifications to iOS or Android mobile apps. + +## Disable downloads + +Environments with strict data loss prevention (DLP) policies or where sensitive information must not be stored on mobile devices can benefit from disabling file uploads and downloads on mobile devices. + +Disabling file uploads adds an additional layer of security by reducing the risk of malware or malicious files being introduced into the system, ensuring tighter control over sensitive corporate data, and preventing accidental leaks from unsecure mobile networks. + +Similarly, by disabling downloads, Mattermost ensures that files cannot be saved locally on the device, reducing the risk of unauthorized access or data leakage. Learn more about [disabling mobile uploads](/administration-guide/configure/site-configuration-settings#allow-file-downloads-on-mobile) and [disabling mobile downloads](/administration-guide/configure/site-configuration-settings#allow-file-uploads-on-mobile) in the Mattermost mobile app. + +## Secure file preview + +For organizations requiring even stricter control over file access on mobile devices, Mattermost provides secure file preview capabilities from Mattermost v10.11. This advanced security feature allows administrators to prevent file downloads, previews, and sharing for most file types while still enabling in-app viewing of essential content such as PDFs, videos, and images. + +When secure file preview is enabled, files are stored temporarily in the app's cache and cannot be exported or shared externally. This approach provides a balance between security and usability, ensuring that users can view necessary content without creating potential data leakage pathways. + +Additionally, administrators can control link navigation within PDF files when secure file preview mode is active, allowing links to open in the device browser or supported applications as needed. + +Learn more about [enabling secure file preview on mobile](/administration-guide/configure/environment-configuration-settings#enable-secure-file-preview-on-mobile) and [allow PDF link navigation on mobile](/administration-guide/configure/environment-configuration-settings#allow-pdf-link-navigation-on-mobile) in the Mattermost mobile app. + +## Burn-on-read messages + +Burn-on-read messages reduce the window of exposure for sensitive content by automatically deleting messages after they are revealed. This approach supports secure, time-bound communication by ensuring that sensitive information doesn't persist on the device longer than necessary. + +Administrators can enable burn-on-read messaging and set the burn-on-read duration to align with organizational policies. Learn more about [sending burn-on-read messages](/end-user-guide/collaborate/send-messages#send-burn-on-read-messages) and [enabling burn-on-read messages](/administration-guide/configure/site-configuration-settings#enable-burn-on-read-messages). + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/security-guide/secure-mattermost.mdx b/docs/main/security-guide/secure-mattermost.mdx new file mode 100644 index 000000000000..18151875084d --- /dev/null +++ b/docs/main/security-guide/secure-mattermost.mdx @@ -0,0 +1,19 @@ +--- +title: "Secure Mattermost" +--- +Mattermost ships with several security features that can help organizations safeguard their data. Mattermost Enterprise Edition includes features designed to offer extra layers of security protection. + +- [Encryption options](/deployment-guide/encryption-options) - Setup encryption for data in transit and at rest. +- [Transport encryption](/deployment-guide/transport-encryption) - Secure data in transit between Mattermost and other services. +- [Multi-factor authentication](/administration-guide/onboard/multi-factor-authentication) - Require users to provide a secure one-time code in addition to their username and password to log in to Mattermost. +- [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications) - Enable fully private mobile notifications to protect against iOS and Android notification infrastructure breaches. +- [Enterprise mobility management](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) - Secure mobile endpoints with management application configuration. +- [Delegated granular administration](/administration-guide/onboard/delegated-granular-administration) - Grant user access to specific areas of the Mattermost System Console. +- [Custom terms of service](/administration-guide/comply/custom-terms-of-service) - Increase clarity on legal Mattermost expectations for internal employees and guests. +- [Manage session length](/administration-guide/configure/environment-configuration-settings#session-lengths) - Control how long user sessions remain active. +- [User and group provisioning via AD/LDAP](/administration-guide/onboard/ad-ldap-groups-synchronization) - Provision and synchronize users and groups to pre-defined roles. +- [SAML-based single sign-on (SSO)](/administration-guide/onboard/sso-saml) - Enable login using a single user ID and password managed through a SAML 2.0 Service Provider. +- [SAML SSO technical documentation](/administration-guide/onboard/sso-saml-technical) - Technical details on SAML SSO. +- [Certificate-based authentication](/administration-guide/onboard/certificate-based-authentication) - Identify a user or a device before granting access to Mattermost. +- [Manage file sharing and downloads](/administration-guide/configure/site-configuration-settings#file-sharing-and-downloads) - Control file sharing and downloads in Mattermost. +- [Log path restrictions](/administration-guide/manage/logging#log-path-restrictions) - Restrict log file locations to authorized directories for enhanced access control and configuration integrity. diff --git a/docs/main/security-guide/security-guide-index.mdx b/docs/main/security-guide/security-guide-index.mdx new file mode 100644 index 000000000000..0340fc98ceef --- /dev/null +++ b/docs/main/security-guide/security-guide-index.mdx @@ -0,0 +1,180 @@ +--- +title: "Security Guide" +--- +Mattermost offers a comprehensive set of security features to protect information in its mobile applications. These features, ranging from encryption and authentication to device management and user education, provide a secure environment for team collaboration and communication. By prioritizing security, Mattermost ensures that customers can trust the mobile application to safeguard their data and privacy. + +## Data-in-Transit Encryption + +Mattermost can be configured to use Transport Layer Security (TLS) to encrypt data transmitted over the network. TLS provides a secure channel for data exchange, protecting it from eavesdropping and tampering during transmission. This encryption ensures that only the intended recipients can access the content, preventing unauthorized parties from intercepting or reading the information. + +Mattermost administrators who wish to configure access settings for private and public networks can do so with 3rd party infrastructure using a [reverse proxy](/deployment-guide/server/setup-tls). This ensures that devices connected to secure networks can safely access the application while restricting access from untrusted networks. Learn more about Mattermost [data-in-transit encryption](/deployment-guide/encryption-options#encryption-in-transit). + +## Data-at-Rest Encryption + +Encryption-at-rest ensures that messages, files, and other data stored in the Mattermost database and file storage are protected from unauthorized access by safeguarding data on physical storage media (e.g., disks) by encrypting it, making it inaccessible without the appropriate encryption keys. Learn more about Mattermost [data-at-rest encryption](/deployment-guide/encryption-options#encryption-at-rest). + +Encryption-at-rest also available for files stored in Amazon's proprietary S3 system using server-side encryption with [Amazon S3-managed keys](/administration-guide/configure/environment-configuration-settings#enable-server-side-encryption-for-amazon-s3) (Mattermost Enterprise) when users choose not to use open source options. + +We strongly recommend regularly rotating and securely storing encryption keys using tools, enabling logging and monitoring for access to encrypted data, and ensuring that backup data is encrypted. + +## Authentication and Access Control + +### Single Sign-On (SSO) + +The mobile application integrates with Single Sign-On providers, allowing users to authenticate using their existing credentials from other trusted systems. This reduces the risk of password-related security breaches and streamlines the login process. Learn more about Mattermost [SSO](/administration-guide/manage/admin/user-provisioning). + +### Multi-Factor Authentication (MFA) + +An additional layer of security beyond username and password. Customers can [enable and enforce MFA](/administration-guide/onboard/multi-factor-authentication) to protect accounts from unauthorized access, even if login credentials are compromised. + +### User Password Requirements + +System administrators can configure user password settings to help safeguard the platform against a range of common attack vectors while maintaining usability and compliance with enterprise security policies: + +- Enforcing longer passwords ensures a baseline level of strength for every user's credentials. Learn more about configuring a [minimum password length](/administration-guide/configure/authentication-configuration-settings#minimum-password-length). +- Enforcing character complexity protects against attackers exploiting weak or overly simple passwords by enforcing passwords that resist dictionary attacks and common password vulnerabilities. Learn more about configuring [password requirements](/administration-guide/configure/authentication-configuration-settings#password-requirements). +- Limiting the number of failed authentication attempts before locking the account temporarily or permanently mitigates brute-force, where attackers attempt to guess passwords by repeatedly entering potential combinations. Learn more about configuring the [maximum number of login attempts](/administration-guide/configure/authentication-configuration-settings#maximum-login-attempts). +- Enabling the forgot password flow adds a layer of convenience by ensuring users can reset their password when needed while preventing users from being locked out due to legitimate loss of credentials. Learn more about [enabling a password reset workflow](/administration-guide/configure/authentication-configuration-settings#enable-forgot-password-link). + +### Session Management + +System administrators can configure session management settings, including session length, session cache, and idle timeout to ensure user sessions are managed effectively and securely. Session fixation attacks are mitigated as Mattermost sets a new session cookie with each login. Learn more about [session management configuration settings](/administration-guide/configure/environment-configuration-settings#session-lengths). + +### Protection Against Brute Force Attacks + +System administrators can [rate limit Mattermost APIs](/administration-guide/configure/environment-configuration-settings) based on query frequency, memory store size, remote address, and headers. + +### Remote Session Revocation & Password Reset + +System administrators can remotely [revoke user sessions](/end-user-guide/preferences/manage-your-security-preferences) across web, mobile devices, and desktop apps. User passwords can be remotely [reset](/administration-guide/configure/user-management-configuration-settings#reset-user-s-password) to enhance security. + +Admins can also enforce re-login after a specified period of time by defining [session lengths](/administration-guide/configure/environment-configuration-settings#session-lengths) and by [revoking user sessions](/administration-guide/configure/user-management-configuration-settings#revoke-a-user-s-session) to force users to log back into the system immediately. + +### Role-Based Access Control (ABAC) + +Administrators can set granular permissions to control access to sensitive information within the application. This feature ensures that users only have access to the data necessary for their roles, minimizing the risk of accidental or intentional data exposure. Learn more about Mattermost [role-based access control](/end-user-guide/collaborate/learn-about-roles). + +### Cross-Origin Requests Control + +Choose whether to restrict or enable [cross-origin requests](/administration-guide/configure/integrations-configuration-settings#enable-cross-origin-requests-from) for enhanced control. + +## Public Link Management + +Public links for account creation, file, and image shares can be invalidated by [regenerating salts](/administration-guide/configure/site-configuration-settings#public-link-salt) to ensure security. + +Public links can also be disabled by setting the [public link salt](/administration-guide/configure/site-configuration-settings#public-link-salt) to an empty string. This prevents the creation of new public links and invalidates existing ones. + +## LLM Context Management + +Mattermost Agents are designed to ensure that only necessary information is sent to the Large Language Model (LLM) for generating accurate responses in Mattermost. Learn how Mattermost [Agents manages LLM context](/end-user-guide/collaborate/agents-context-management) and how to ensure data privacy. + +## Audit Logs and Monitoring + +Mattermost writes logs to both the console and to a log file in a machine-readable JSON format. Customers with a Mattermost subscription can additionally log directly to syslog and TCP socket destination targets. Learn more about [Mattermost logging](/administration-guide/manage/logging). + +### Activity Monitoring + +Mattermost stores a complete history of messages, including edits and deletes, along with all files uploaded. User interface actions for deleting messages and channels only remove the data from the user interface; the data is retained within your database. If your compliance guidelines require it, you can disable users' ability to edit and delete their messages after they are posted. Learn more about [Mattermost permissions](/administration-guide/onboard/advanced-permissions). + +The Mattermost mobile app generates audit logs that record user activities and system events. These logs enable administrators to monitor access and identify potential security threats, ensuring timely detection and response to suspicious behavior. + +## Regular Security Updates + +### Patch Management + +Mattermost regularly releases security updates to address vulnerabilities and enhance the application's security posture. Users are encouraged to keep their mobile applications up to date to benefit from the latest security improvements. Learn more about Mattermost [releases and the release life cycle](/product-overview/releases-lifecycle). + +### Community and Expert Contributions + +Being an open-core platform, Mattermost benefits from contributions from the security community and experts. These contributions help identify and mitigate potential security risks, ensuring that the mobile application remains robust and secure. Learn more about [contributing to Mattermost](https://mattermost.com/contribute/). + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. + +## Compliance Considerations + +Mattermost can be deployed as part of regulated environments where compliance with industry standards is essential. + +- HIPAA: Review our guidance on [deploying Mattermost as part of a HIPAA-compliant IT infrastructure](/security-guide/hipaa-compliance), with key considerations for protecting electronic protected health information (ePHI). +- FINRA: Learn how [Mattermost supports organizations in meeting the cybersecurity requirements of FINRA](/security-guide/finra-compliance). + +## Frequently Asked Questions + +### What are the trust benefits of Mattermost compared to third-party SaaS systems that let customers manage their own encryption keys? + +**Encryption doesn't mean a third-party SaaS vendor can't read your data.** A third-party vendor who provides encryption keys to the database that stores a customer's data at rest may still be able to read a customer's data while its in transit. + +For example, performing a search on message histories requires access to unencrypted messages in order to match the search term to words in your unencrypted message history. + +As another example, a customer's data encryption key is unlikely to be deployed to the mobile devices of end users; therefore, when a third-party system sends a push notification to an end user's mobile device, the unencrypted text is available to the third party. + +In contrast, Mattermost is hosted by the customer. Not only can data be encrypted at rest and in-transit with keys generated by the customer (which no vendors ever touch), unencrypted data for search and mobile notifications is handled by systems under your IT team's control. + +If it’s unclear from the vendor’s documentation whether or not your data can be read, ask them directly. + +**Moreover, high trust enterprises need more than encryption - they need privacy, total data ownership, auditability, and control of their infrastructure.** + +*Privacy* means a third-party service cannot monitor the identity, IP address, location, or access patterns of your employees, nor their activity on your system, nor provide that information either intentionally through a court order (which you may never be informed about) or unintentionally through a data breach. + +*Total data ownership* means a third party cannot prevent you from accessing your data at any time. It means no third party can read your data, analyze it or monetize it. It means that should you end your commercial relationship, you maintain your records with any backups. It also means you can delete your data at any time and verify that no additional copies remain. + +*Audibility* means being able to fully observe, monitor, and trace the operations of your systems. + +*Control of infrastructure* means being able to operate and customize your system to the specific needs of your business, including the ability to run on public and private networks, as well as on-prem, and interoperate with critical legacy systems with full observability and transparency down to reading the source code. + +As an open source self-hosted system, Mattermost provides privacy, total data ownership, and control of infrastructure required by high trust teams. + +### What are the fundamental security challenges with Massive, Multi-Tenant Applications (MMTA)? + +The key risk of allowing confidential data to enter a Massively Multi-Tenant Applications (MMTA) is having the system breached, never knowing your data has been compromised, and having stolen data used to breach your other systems. + +Marketers from MMTA vendors pay highly credentialed security professionals to offer "Death Star Logic" to gain a customer’s trust: "MMTA's SaaS offering is the most secure system in the galaxy because it outspends its customers on security investments, therefore the MMTA is more secure than a customer's self-hosted infrastructure." + +The problem with Death Star Logic is that it omits the fact that hosting confidential data from thousands of enterprise customers makes it the prime target for cyber attacks, which increases risk to customers for four key reasons: + +**1) Over time, MMTA vendors become Nation State Targets** + +The effort behind a cyber attack is proportional to the value of breaching the system. As the value of the data held by an MMTA vendor increases, so does the scale of its cyber threats. + +Vendors become "Nation State Targets" when the value of the breaching their system is so high it attracts the attention of the cyberwarfare branches of hostile nations. From there, even the smallest errors in system security can result in a significant breach. + +**2) MMTA systems can't protect customers from unknown vulnerabilities** + +A single bug in an MMTA system can put all customers at risk. For example, [Slack reported a bug that exposed message histories and files for nearly four million users](https://www.wired.com/2017/03/hack-brief-slack-bug-everyones-worst-office-nightmare/) (2017), and [a bug left 400 million Microsoft accounts exposed to account takeover](https://hackread.com/critical-bug-in-microsoft-left-400m-accounts-exposed/) (2018). + +For multi-tenant systems, bugs in infrastructure can present vulnerabilities as well. For example, in 2018 researchers discovered that chip-level exploits like [Meltdown and Spectre](https://www.wired.com/story/intel-meltdown-spectre-storm/), which had been around for decades, could make it possible for malicious code run by one tenant to affect the operations of another tenant that shared the same CPU. + +Keeping MMTA systems secure depends on the ability of internal and external security researches to continually stay ahead of cyber-attackers. + +**3) Customers don't know when breaches occur** + +When an MMTA is breached, it is most likely from an unknown bug or an unknown vulnerability. Because of this, it may not be clear that a system has been breached, and customers may not be notified. Moreover, following a breach, there's often no way for the customer's security team to audit the MMTA vendor and understand how their confidential data may have been accessed or stolen. + +The end result is confidential information passing through an MMTA may be used to exploit other systems the customer operates, with no way to trace the root of the breach to mitigate it in future. + +As an example, when [OneLogin reported a security breach that allowed the attacker to decrypt encrypted data impacting 2000 customers and 70 SaaS apps](https://krebsonsecurity.com/2017/06/onelogin-breach-exposed-ability-to-decrypt-data/) (2017), details were vague and there was little customers could do to analyze their risk or reduce risk in future. + +In contrast, an open source, self-hosted collaboration solution remains within the layers of physical security and network security enterprises use to protect their most valuable assets, with full access to logging and system histories to know when, where and how an attack might have occurred. + +Moreover, as a single-tenant solution, the strength of cyberattacks is typically limited to the breach value of just your confidential data and not the aggregate breach value of all customer data held by an MMTA. Plus, the sum of security investments your company makes to protect systems in its private networks accrues to your collaboration system - and for banks, this could be hundreds of millions of dollars a year. + +**4) MMTA systems risk cross-bleeding your data** + +MMTA also runs the risk of bugs or misconfigurations in a vendor’s multi-tenant system bleeding your data into another customer’s space, or vice versa. Bleeds can occur via logging systems, in application logic, middleware, and data layer errors. In 2019, [Facebook admitted to accidentally storing hundreds of millions of user passwords in clear text for years due to a configuration oversight](https://krebsonsecurity.com/2019/03/facebook-stored-hundreds-of-millions-of-user-passwords-in-plain-text-for-years/). + +### Why does Mattermost disclose whether or not an account exists when a user enters an incorrect password? + +Mattermost's core design principle is to be "fast, obvious, forgiving" and, telling users that they made a mistake in entering their password, is in service of our principle of prioritizing user interests. + +When using username-password authentication, especially with AD/LDAP, there's the possibility of usernames being email addresses, Mattermost username, AD/LDAP username and ID, or other AD/LDAP attributes and our design principle intends to help end users understand whether their login error came from having the wrong password or the wrong email/username. + +We believe this design increases productivity, speeds up user adoption, and reduces help desk tickets and support costs - and that these benefits outweigh the trade-offs. + +The trade-off with this design is that if physical security is not in effect, network security is not in effect (i.e., no VPN or a malicious user within the private network), and username-password authentication is used, an attacker may be able to enumerate email addresses or usernames by sending HTTP requests to the system, up to the maximum number of requests per second defined in Mattermost's [API rate limiting settings](/administration-guide/configure/environment-configuration-settings). + +For organizations who choose to deploy in such a configuration, please consider the following mitigations: + +1. Instead of username-password, use a Single Sign-On (SSO) provider in Mattermost Enterprise Edition like OneLogin, Okta, or ADFS, or use the open source GitLab SSO option available with Mattermost Team Edition. +2. Per the recommended install instructions, use a VPN client to apply network security to your deployment. +3. Enable monitoring and alerting from your proxy server to detect and isolate malicious behavior reaching your deployment. + +Above all, make sure to subscribe to the [Mattermost Security Bulletin](https://mattermost.com/security-updates/#sign-up) and apply security patches as recommended. diff --git a/docs/main/security-guide/zero-trust.mdx b/docs/main/security-guide/zero-trust.mdx new file mode 100644 index 000000000000..52685d7c2701 --- /dev/null +++ b/docs/main/security-guide/zero-trust.mdx @@ -0,0 +1,124 @@ +--- +title: "Zero Trust with Mattermost" +--- +Mattermost helps organizations adopt and implement Zero Trust principles to safeguard their mission-critical communications and collaboration. + +For security teams, Mattermost’s zero-trust-first approach ensures consistent compliance with organizational risk policies by automating key governance processes like incident response or data lifecycle management. + +Unlike traditional security approaches, Zero Trust assumes every user and system may be a potential threat. Mattermost implements this paradigm by offering customizable, secure solutions that protect sensitive communication workflows from both internal and external risks. + +This document outlines how Mattermost supports the core tenets of Zero Trust, for organizations of different sizes, including [Identity and access management](#identity-and-access-management), [Continuous monitoring](#continuous-monitoring), [Deployment and host control](#deployment-and-host-control), [Encryption](#encryption), [Micro-segmentation](#micro-segmentation), [Multi-factor authentication](#multi-factor-authentication-mfa), [Data management](#data-management), and [Incident response](#incident-response). Links to detailed documentation resources are provided below. + +## Identity and access management + +Mattermost integrates seamlessly with enterprise identity providers (IdPs), enabling strong identity verification and strict access control. + +By using one of the secure identity mechanisms listed below and enforcing least-privilege access via roles and groups, Mattermost ensures that only verified individuals gain access to the platform and its resources: + +- [SAML](/administration-guide/onboard/sso-saml): Enables seamless Single Sign-On, ensuring centralized authentication to continuously enforce user verification. +- [LDAP](/administration-guide/onboard/ad-ldap): Facilitates integration with enterprise directories to tightly control user access, adhering to granular identity verification. +- [OpenID Connect](/administration-guide/configure/authentication-configuration-settings#openid-connect): Provides secure, standards-based user authentication to verify identities and enforce secure access. +- [Session Management](/administration-guide/configure/environment-configuration-settings#session-lengths): Strengthens continuous authentication by controlling session lengths and automatically revoking sessions based on inactivity or policy violations, ensuring constant identity verification. By limiting session lifetimes and enforcing strict session policies, Mattermost mitigates the risk of stolen session tokens or extended unauthorized access. + +Authorized users can seamlessly be added and removed from channels utilizing the native AD/LDAP integration based on group memberships: + +- [LDAP Synchronized User Groups](/administration-guide/onboard/ad-ldap-groups-synchronization): Automates user management and access control by dynamically syncing with organizational directories to minimize risks and enforce policies. + +## Continuous monitoring + +Mattermost offers tools for monitoring activity, identifying suspicious behavior, session management, and real-time incident response. Audit trails and performance monitoring ensure the proactive detection of potential issues or breaches, delivering visibility into the activity across the platform. + +- [Audit Logging](/administration-guide/manage/logging): Tracks detailed activity logs for monitoring and identifying real-time anomaly-detection use cases, such as detecting anomalous behavior from compromised accounts or insider threats, or responding to unusual file-sharing activity within sensitive channels. +- [SIEM Integrations](https://developers.mattermost.com/integrate/webhooks/): Streamlines monitoring within existing security systems to detect and respond to lateral movement threats or policy violations consistently. +- [Performance Monitoring](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring): Protects against potential threats by analyzing system and user behaviors via proactive monitoring. + +## Deployment and host control + +Flexibility and control to host Mattermost securely to minimize the risk of vulnerabilities, downtime, and unauthorized modifications by ensuring secure, efficient, and reliable deployment of applications while maintaining strict control over the hosting environment. + +Mattermost's self-hosting enables tailored configurations for on-premises systems with specialized security needs, while cloud IP filtering ensures scalable control for remote or hybrid teams operating across distributed environments: + +- [Self-hosting Mattermost](/deployment-guide/deployment-guide-index): Enforces stricter data sovereignty requirements, and complete control over deployment environments, enabling organizations to implement custom Zero Trust security measures. +- [Cloud IP Filtering](/administration-guide/manage/cloud-ip-filtering#cloud-ip-filtering): Prevents untrusted entities from gaining initial access, restricting platform access to trusted network ranges, enforcing an evaluation of every connection. + +## Encryption + +Encryption protects both data at rest and data in transit, ensuring end-to-end security for sensitive communications. Encryption mitigates the risk of data theft in both storage and transfer, while granular permissions limit access to sensitive files and data to only authorized users. + +- [Database Encryption](/deployment-guide/encryption-options#database): Protects user and organizational data at rest, safeguarding sensitive information from unauthorized access. +- [Transport Layer Security (TLS) Encryption](/deployment-guide/encryption-options#encryption-in-transit): Secures data in transit by encrypting communications. +- [Policy Enforcement](/deployment-guide/encryption-options#file-storage): Ensures strict compliance through automated enforcement, protecting data integrity. + +## Micro-segmentation + +Segmenting and isolating sensitive resources is vital in minimizing lateral movement during an attack. Mattermost supports micro-segmentation through its organizational and role-based capabilities. Micro-segmentation enables organizations to restrict access to sensitive conversations, ensuring secure communication channels tailored to individual teams or missions. + +To achieve comprehensive micro-segmentation, the following areas of Mattermost functionality play a critical role. + +### Access control and permissions + +Ensure precise and role-based access to sensitive resources in order to minimize the risk of unauthorized access and potential data breaches: + +- [Advanced Access Controls](/administration-guide/manage/team-channel-members#advanced-access-controls): Enforces specific permissions configurations to restrict access based on roles. +- [Playbook-Specific Permissions](/end-user-guide/workflow-automation/share-and-collaborate): Controls access to sensitive workflows, ensuring resources are available only to authorized team members. + +### Organizational design and user management + +Establish a structured and scalable framework for managing user identities, roles, and access workflows to ensure accountability, facilitate collaboration, and enforce security policies: + +- [Teams](/end-user-guide/collaborate/organize-using-teams): Enables segmentation of access and collaboration, fostering compartmentalization and limiting exposure to unauthorized users. +- [Private Channels](/end-user-guide/collaborate/channel-types#private-channels): Restricts conversations to authorized participants, protecting sensitive data and adhering to need-to-know principles. +- [Guest Accounts](/administration-guide/onboard/guest-accounts): Enables secure, scoped access for external parties, ensuring least privilege principles are maintained. +- [Custom User Groups](/end-user-guide/collaborate/organize-using-custom-user-groups): Allows precise administrative control of access and permissions for specific user sets, enhancing access segmentation. + +### Administrative controls + +Enforce logical segmentation through team-level and group-level management, enhancing productivity and security by aligning user access with their specific roles: + +- [Delegated Granular Administration](/administration-guide/onboard/delegated-granular-administration): Ensures operational security by enabling controlled management access based on responsibilities. +- [Custom Terms of Service](/administration-guide/comply/custom-terms-of-service): Requires users to acknowledge organization-specific Terms of Service before access ensures alignment with security policies and strengthens compliance, particularly in regulated industries where custom terms may reflect specific mandates. +- [Granular Permissions](/administration-guide/onboard/delegated-granular-administration): Facilitates precise control over user and system permissions, adhering to the principle of least privilege. +- [Read-Only Permissions for Files](/administration-guide/configure/site-configuration-settings#file-sharing-and-downloads): Limits file-sharing capabilities to safeguard sensitive information from unauthorized alterations. + +### Security policies and tokens + +Enhance security with tailored authentication tools to protect systems and data from unauthorized API usage and credential misuse by establishing and enforcing secure, consistent, and scalable authentication mechanisms: + +- [Personal Access Tokens](https://developers.mattermost.com/integrate/reference/personal-access-token/): Enables secure API access with identity verification aligned to least privilege. + +## Multi-factor authentication (MFA) + +Mattermost supports MFA to strengthen authentication practices by adding an extra layer of protection for high-risk workflows beyond passwords: + +- [MFA](/administration-guide/onboard/multi-factor-authentication): Enhances user identity verification by requiring multiple factors for authentication. MFA ensures that unauthorized users are denied access even if passwords are compromised, reducing the risk of account breaches. + +Alternatively, often enforced through the identity provider (IDP). + +## Data management + +Data management directly addresses how sensitive information is managed, controlled, and safeguarded at every stage of the data lifecycle. Proper data retention practices ensure that data is not only securely stored but also that it is not retained longer than necessary, thereby reducing risks. + +By retaining data only for the duration that it is needed and then securely disposing of it, the exposure to malicious activity or unauthorized access is significantly reduced. Even if attackers gain access, their exposure is minimized. The less data stored, the smaller the "footprint" for potential exploitation: + +- [Data Retention Policies](/administration-guide/comply/data-retention-policy): Enforces strict retention controls to reduce data exposure and help comply with governance standards. +- [Compliance Export](/administration-guide/comply/compliance-export): Ensures data portability for audit and compliance purposes in a secure and controlled manner. +- [Compliance Monitoring](/administration-guide/comply/compliance-monitoring): Offers visibility into adherence to security and compliance policies, supporting compliance mandates. +- [E-Discovery](/administration-guide/comply/electronic-discovery): Boosts organizational oversight by ensuring discoverability of stored data for legal and compliance audits under secure protocols. E-Discovery capabilities help organizations meet compliance expectations for legal audits under frameworks like GDPR or HIPAA without sacrificing secure collaboration workflows. +- [Archiving Inactive Teams or Channels](/administration-guide/manage/team-channel-members#archive-a-team) & [Unarchive Channels](/end-user-guide/collaborate/archive-unarchive-channels): Reduces the potential attack surface by securely deactivating and storing inactive resources, minimizing both live data exposure and the likelihood of exploitation. This approach ensures adherence to security best practices while maintaining the ability to securely restore resources if needed. + +## Incident response + +Incident response ensures that organizations can effectively detect, investigate, and respond to security threats within a framework that assumes no entity, whether inside or outside the network, should be trusted by default. Incident response is the operational arm that ensures that organizations are vigilant, prepared, and capable of protecting themselves in a dynamic and evolving threat landscape. + +Mattermost Playbooks reduce the time to respond to threats and ensure compliancy-aligned documentation through automated incident notifications by empowering organizations to predefine and automate incident response workflows, ensuring that responses are consistent, documented, and transparent: + +- [Incident-Specific Channels for Secure Collaboration](/end-user-guide/workflow-automation/work-with-playbooks#actions): Maintains secure collaboration workflows across broader incident response workflows involving external tools, enforcing a centralized control model for operational continuity during incidents. Incident-specific channels reduce the time to assemble expert response teams, ensuring faster mitigation of active threats like phishing or ransomware attacks. +- [Automated Incident Notifications](/end-user-guide/workflow-automation/notifications-and-updates): Streamlines response workflows with authenticated alerts. + +Enhance learning from incidents, ensure historical accountability, reduce future attack surfaces, and meet compliance expectations by securely centralizing documentation to improve future response processes: + +- [Post-Incident Documentation](/end-user-guide/workflow-automation/metrics-and-goals): Enables secure storage and access for learnings, ensuring compliance with attack surface minimization principles. + +By embedding Zero Trust principles across access, monitoring, data management, and incident response, Mattermost equips organizations with the tools needed to safeguard collaboration workflows in today's evolving threat landscape. + +Discover how Mattermost can transform your Zero Trust strategy today. Book a live demo with a [Mattermost Zero Trust Expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization’s secure collaboration needs. diff --git a/docs/main/use-case-guide/devops-collaboration.mdx b/docs/main/use-case-guide/devops-collaboration.mdx new file mode 100644 index 000000000000..e8c7ab931e94 --- /dev/null +++ b/docs/main/use-case-guide/devops-collaboration.mdx @@ -0,0 +1,58 @@ +--- +title: "Real-Time DevSecOps Collaboration" +--- +Modern mission-driven software teams—ranging from critical infrastructure operators to government software factories—face the challenge of delivering and defending complex systems at speed. From CI/CD pipelines to incident response, secure collaboration is essential to ensure resilience, compliance, and operational success in environments where failure is not an option. + +Traditional messaging platforms, designed for commercial office settings, often introduce friction, fragmentation, and risk into DevSecOps workflows. These multi-purpose tools are optimized for generic team chat or water-cooler conversation—not for secure, structured collaboration in high-stakes delivery environments. As a result, critical signals get lost in noisy channels, response times slow down, and sensitive workflows are exposed to tools that lack operational control. + +Mattermost provides a secure, real-time ChatOps platform designed for DevSecOps collaboration in high-assurance environments. Whether supporting sovereign software supply chains, regulated platforms, or air-gapped operational environments, Mattermost unifies delivery, security, and platform teams into a single, extensible system built for mission velocity and compliance. + +The following mission-ready DevSecOps capabilities are available: + +## Continuous Integration & Delivery (CI/CD) Coordination + +Coordinating secure software delivery requires tight integration between code commits, testing pipelines, release workflows, and stakeholder approval. + +**Benefits** + +- **Automate pipeline visibility and alerting** by integrating with CI/CD tools like GitLab, Jenkins, and GitHub Actions using the [Mattermost integrations platform](/integrations-guide/integrations-guide-index). +- **Coordinate secure releases and hotfixes** using [Collaborative Playbooks](/end-user-guide/workflow-automation) to manage rollout steps, validation gates, and team notifications. +- **Enable traceable delivery communications** through [channel-based collaboration](/end-user-guide/messaging-collaboration), ensuring build logs, changelogs, and approvals remain accessible and audit-ready. +- **Support deployments in regulated and sovereign environments** using [self-hosted Kubernetes deployment models](/deployment-guide/server/deploy-kubernetes) for full control over CI/CD communications. + +## Platform Engineering & Internal Developer Platforms (IDPs) + +Platform teams need streamlined, secure ways to deliver services and enable developers while maintaining governance and uptime. + +**Benefits** + +- **Centralize platform requests and updates** in [dedicated channels](/end-user-guide/messaging-collaboration) that organize provisioning, support, and environment status discussions. +- **Automate ticket triage and escalation workflows** using [Playbooks](/end-user-guide/workflow-automation) to track response SLAs and ownership across platform operations. +- **Monitor infrastructure health and changes** with integrated feeds from [Prometheus, Grafana](/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring), or custom observability tools—supporting faster feedback loops. +- **Support hybrid cloud and edge operations** through [deployment flexibility](/deployment-guide/server/server-deployment-planning#deployment-options) across public, private, and disconnected environments. + +## Secure Incident Response for Production Systems + +Real-time visibility and structured collaboration are critical during service degradations, outages, or suspected intrusions. + +**Benefits** + +- **Automate incident handling** with [Playbooks](/end-user-guide/workflow-automation) to track diagnostics, assign tasks, and issue updates—supporting NOC, SRE, and AppSec workflows. +- **Accelerate containment and recovery** by [integrating alerting tools](/integrations-guide/integrations-guide-index#webhooks) like PagerDuty, Opsgenie, and custom webhooks into secure Mattermost channels. +- **Ensure communication continuity** during outages using [high availability architecture](/administration-guide/scale/high-availability-cluster-based-deployment) and [support for disconnected environments](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment). +- **Enable forensic review and audit** with [logging and export capabilities](/administration-guide/manage/logging#audit-logging) that preserve all incident-related communications. + +## Policy-Driven Collaboration in Regulated Environments + +Critical infrastructure DevSecOps must align with strict security, audit, and compliance requirements—including supply chain controls and Zero Trust architecture. + +**Benefits** + +- **Apply granular role-based access controls** using [advanced permissions](/administration-guide/onboard/advanced-permissions) and [channel-specific configurations](/administration-guide/manage/team-channel-members#advanced-access-controls) to protect sensitive workflows. +- **Support supply chain security coordination** by using [Playbooks](/end-user-guide/workflow-automation) to manage SBOM reviews, vendor risk analysis, and software intake workflows across internal and external teams. +- **Enforce secure collaboration behavior** through [custom Terms of Service](/administration-guide/comply/custom-terms-of-service), [data retention policies](/administration-guide/comply/data-retention-policy), and user authentication tied to [SSO and Entra ID](/administration-guide/onboard/sso-entraid). +- **Deploy in line** with [Zero Trust](/security-guide/zero-trust) principles with [self-managed, segmented deployments](/deployment-guide/server/server-deployment-planning#deployment-options) that enforce identity, access, and policy boundaries—suitable for classified or sovereign cloud environments. + +## Get Started + +[Talk to an Expert](https://mattermost.com/contact-sales/) to modernize your DevSecOps collaboration stack. Whether you're building secure CI/CD pipelines, enabling platform self-service, or responding to production incidents under regulatory pressure, Mattermost keeps your teams connected, compliant, and mission-ready. diff --git a/docs/main/use-case-guide/integrated-security-operations.mdx b/docs/main/use-case-guide/integrated-security-operations.mdx new file mode 100644 index 000000000000..7d1172d7ab2e --- /dev/null +++ b/docs/main/use-case-guide/integrated-security-operations.mdx @@ -0,0 +1,52 @@ +--- +title: "Integrated Security Operations" +--- +**Fragmented security operations create the blind spots attackers exploit. Deploy unified collaboration that coordinates your entire security ecosystem in real-time.** + +In today's evolving threat landscape, fragmented workflows, isolated teams, and disjointed tools create delays and blind spots in organizational defense. As threats scale across geopolitical, cyber, and supply chain domains, security operations must become more integrated,unifying monitoring, simulation, response, and intelligence into a continuous, coordinated system. + +Mattermost provides a secure, extensible platform for integrated security operations,built to support real-time coordination, mission-specific tooling, and sensitive communications. Whether deployed as a self-hosted Kubernetes instance, Linux server in your local data center, or in sovereign hosting environments, Mattermost empowers security teams to accelerate detection, decision-making, and coordinated response while maintaining full operational control. Built for security-conscious teams across commercial, government, and regulated industries, Mattermost supports integrated incident workflows and enterprise-level access control. + +![Augments security platform investments with collaborative, AI-powered security operations workflow.](/images/Intelligent-RT-Incident-Response.png) + +Mattermost supports security workflows across: + +## Security Operations Centers (SOCs) + +SOCs are the front lines of real-time monitoring, triage, and escalation. Coordinating across analysts, tools, and environments requires fast, structured communication and secure data handling. + +**Benefits** + +- **Accelerate triage and response workflows** with [Collaborative Playbooks](/end-user-guide/workflow-automation) that automate escalations, task assignment, and ticket updates for consistent response execution. +- **Integrate detection pipelines and observability tools** using the [Mattermost integrations platform](/integrations-guide/integrations-guide-index) to surface alerts from SIEM, SOAR, and log analysis systems into dedicated response channels. +- **Maintain operational security and compliance** through [role-based permissions](/administration-guide/onboard/advanced-permissions) and [audit logging](/administration-guide/manage/logging#audit-logging) to safeguard sensitive incident data. +- **Operate in secure, classified, or hybrid environments** using Kubernetes or Linux on the infrastructure of your choice: Public cloud, organization data center, or fully air-gapped. [Explore deployment options](/deployment-guide/server/server-deployment-planning#deployment-options). +- **Meet regulatory compliance requirements** with a solution that adapts to your organization's security posture and regulatory requirements, incl. GDPR, FedRAMP, ISO 27001, and more. + +## Computer Emergency Response Teams (CERTs) + +CERTs serve as rapid-response teams during high-risk events, requiring tight coordination, reliable workflows, and cross-unit information flow. + +**Benefits** + +- **Orchestrate high-stakes incident response** through [Collaborative Playbooks](/end-user-guide/workflow-automation) tailored for malware outbreaks, data exfiltration events, and zero-day exploits. +- **Centralize and structure communication** with [channel-based collaboration](/end-user-guide/messaging-collaboration), including [file sharing](/end-user-guide/collaborate/share-files-in-messages), [threaded updates](/end-user-guide/collaborate/organize-conversations), and task-tracking across affected teams. +- **Enable coordination across geographies** using [multi-device access](/deployment-guide/deployment-guide-index) and [mobile EMM support](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) for secure participation across locations and devices. +- **Preserve evidentiary and compliance data** through [audit logs](/administration-guide/manage/logging#audit-logging) and configurable [exports](/administration-guide/manage/bulk-export-tool) for legal review or forensic handoff. +- **Ensure data sovereignty** with flexible hosting options including EU-resident infrastructure, on-premises deployments, and air-gapped environments that maintain full control over sensitive communications. + +## Federated Threat Intelligence & Information Sharing + +Cross-organizational threat intelligence teams,spanning sectors, regions, and public-private partnerships,require secure, policy-driven platforms for sharing indicators, coordinating alerts, and supporting collective defense efforts. + +**Benefits** + +- **Collaborate securely across agencies or organizations** using [Connected Workspaces](/administration-guide/onboard/connected-workspaces) to synchronize alerts, discussions, and file sharing with trusted external partners. +- **Support multinational and sectoral collaboration** with [custom terms of service enforcement](/administration-guide/comply/custom-terms-of-service) and [localized UI settings](/end-user-guide/preferences/manage-your-display-options#language) for global partner access. +- **Preserve operational trust and compliance** through [role-based access controls](/administration-guide/onboard/advanced-permissions) and [channel-specific permissions](/administration-guide/manage/team-channel-members#advanced-access-controls) that enforce jurisdictional and information-sharing agreements. +- **Operationalize shared threat intelligence** by integrating IOCs, threat actor profiles, and shared playbooks into your Mattermost instance via the [integrations platform](/integrations-guide/integrations-guide-index). +- **Scale communication globally** with Mattermost's [high availability and horizontal scalability architecture](/administration-guide/scale/scaling-for-enterprise),supporting tens of thousands of users across enterprise, field, government, or classified environments. + +## Get Started + +Whether you're coordinating a global SOC, simulating threats, responding to incidents, or exchanging intelligence across borders, Mattermost ensures your teams are secure, synchronized, and mission-ready. Experience integrated security operations with pre-configured alerts, channels, and playbooks [in a live sandbox environment](https://mattermost.com/sign-up/?usecase=integrated-sec-ops) or [talk to an expert](https://mattermost.com/contact-sales/) to unify your security operations. diff --git a/docs/main/use-case-guide/maximize-microsoft-investments.mdx b/docs/main/use-case-guide/maximize-microsoft-investments.mdx new file mode 100644 index 000000000000..8a3812071611 --- /dev/null +++ b/docs/main/use-case-guide/maximize-microsoft-investments.mdx @@ -0,0 +1,86 @@ +--- +title: "Maximize Your Microsoft Investments" +--- +Unlock the full potential of your Microsoft Teams, M365, and Entra ID investment with Mattermost. Designed for operational teams that require advanced customization, secure workflows, and seamless deployment on segregated networks, Mattermost enhances your existing Microsoft solutions for critical mission success. + +Mattermost complements Microsoft solutions with tailored capabilities designed to meet the unique needs of high-security environments, inter-agency collaboration, and external workflows, enabling teams to maximize their Microsoft investment. + +The following mission-ready collaboration capabilities are available: + +## Sovereign Communication in Microsoft Teams + +Agencies and critical infrastructure organizations must often comply with strict data sovereignty rules that restrict cloud usage for sensitive collaboration. + +**Benefits** + +- **Deploy Mattermost on-premise or in sovereign clouds**, fully integrated with Microsoft Teams and Outlook (See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365)) to maintain workflow continuity and secure data storage. +- **Store messages, recordings, and transcriptions in compliance-approved systems**, with [data-at-rest encryption](/security-guide/security-guide-index#data-at-rest-encryption) ensuring no leakage of sensitive data to third-party platforms. +- **Enable secure Microsoft Teams interactions via embedded Mattermost collaboration**, supporting operations within familiar interfaces while enforcing regulatory compliance. See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365). +- **Enforce agency-specific policies** with [legal hold](/administration-guide/comply/legal-hold), [retention policies](/administration-guide/comply/data-retention-policy), and [user access controls](/administration-guide/onboard/advanced-permissions) that align with national or sectoral mandates. + +## On-Premises Skype for Business Replacement + +As Skype for Business reaches end-of-life, secure organizations require an alternative that preserves on-premises control, integrates into Microsoft workflows, and meets the security standards of air-gapped and classified environments. Cloud-first replacements like Microsoft Teams are not always viable due to network segmentation, compliance restrictions, or data sovereignty mandates. + +![Extend Microsoft Enterprise IT investments for edge-based, highly tailored Mission IT workflows with Mattermost.](/images/On-Prem-Skype-for-Business-replace.png) + +- **Preserve mission-critical communication workflows** with a self-hosted Mattermost deployment that supports [1:1 calls](/end-user-guide/collaborate/make-calls), [screen sharing](/end-user-guide/collaborate/make-calls#share-your-screen), and [threaded messaging](/end-user-guide/collaborate/organize-conversations) within secure environments. +- **Integrate Mattermost with Microsoft tools** such as Outlook, Teams, and [Entra ID Single Sign-On](/administration-guide/onboard/sso-entraid) to retain user workflows while centralizing identity and access control. See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365). +- **Deploy in sovereign, air-gapped, or private cloud environments** such as [Azure Deployment](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/mattermost.mattermost-operator?tab=overview) or **Azure Local** (formerly Azure Stack HCI) for on-premises hybrid cloud scenarios while maintaining compliance with STIG, FedRAMP, and NIST 800-53 standards. For Azure Local deployments, we recommend engaging **Mattermost Professional Services** for deployment support. [Talk to an Expert](https://mattermost.com/contact-sales/) to learn more. + +[Learn more](/use-case-guide/on-prem-skype-for-business-replacement) about replacing Skype for Business with Mattermost. + +## Out-of-Band Incident Response for Microsoft-Centric Environments + +During high-stakes incidents, Microsoft 365 tools can be limited or unavailable, slowing down response times and jeopardizing mission continuity. + +![Self-hosted Mattermost collaboration embeds in Microsoft Teams and Outlook user experience, while storing data all messaging, audio and screen share recordings, transcriptions, file sharing and AI interactions in fully on-premise data stores.](/images/Fully-Sovereign-Communication-Inside-MSTeams.png) + +**Benefits** + +- **Maintain operational continuity during M365 outages** with a dedicated, out-of-band Mattermost instance for secure incident response, communication, and collaboration. See [Mattermost Mission Collaboration for Microsoft](/integrations-guide/mattermost-mission-collaboration-for-m365) +- **Accelerate responses** with [AI-powered workflows](/administration-guide/configure/agents-admin-guide), enabling structured playbooks for triage, escalation, and resolution even when primary systems are compromised. +- **Integrate with Microsoft Security Suite** and [Entra ID](/administration-guide/onboard/sso-entraid) to preserve centralized identity management while keeping sensitive data in a secure secondary system. [Learn more](/integrations-guide/integrations-guide-index) about Mattermost's integration capabilities. +- **Protect breach-sensitive notifications** using [ID-only push alerts](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications) and enhanced mobile security, enabling secure communication without cloud exposure. + +## Enterprise to Tactical Edge + +Operational teams need to extend Microsoft capabilities to mission environments where bandwidth is limited, systems are segregated, and speed is critical. + +![Secure, Mission-Focused Collaboration to Enable Faster, Informed Decision-Making across Environments.](/images/Enterprise-to-Tactical-Edge.png) + +**Benefits** + +- **Enable mission-critical coordination at the edge** by [deploying Mattermost in secure, on-prem or air-gapped environments](/deployment-guide/server/server-deployment-planning#deployment-options) [integrated with Microsoft Teams and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365). +- **Fuse data and decision-making across platforms** with support for [toolchain integration](/integrations-guide/integrations-guide-index), [audio/screen share](/end-user-guide/collaborate/make-calls), and [workflow automation](/end-user-guide/workflow-automation) embedded into a dedicated Mission Operations Platform. +- **Maintain coalition and partner alignment** through [interoperable Connected Workspaces](/administration-guide/onboard/connected-workspaces) supporting collaboration across mission partner networks. +- **Accelerate action with mission-tuned AI** using secure Azure AI and [Mattermost Copilot](/end-user-guide/agents) to summarize context, guide decisions, and automate operational tasks. +- **Secure every communication path** with built-in [Zero Trust controls](/security-guide/zero-trust) and deploy on Azure or sovereign environments for maximum flexibility and compliance. + +## External Collaboration with Full Control + +Managing external collaboration within Microsoft Teams can be complex, often requiring numerous configurations and administration that lead to security risks like usage of consumer-grade chat tools. + +![Mattermost replaces Signal, Discord and other free personal apps with secure external messaging controlled by IT.](/images/External-Collaboration-with-Enterprise-Control.png) + +**Benefits** + +- **Integrate Mattermost with Microsoft Teams and Outlook** to enable secure external collaboration with encryption, audit trails, and role-based permissions—without compromising compliance. (See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365)). +- **Eliminate shadow IT** by providing [Connected Workspaces](/administration-guide/onboard/connected-workspaces) for sanctioned, policy-enforced engagement with external partners—reducing reliance on consumer-grade tools. +- **Apply granular policy enforcement for external users**, including [granular user permissions](/administration-guide/manage/team-channel-members#advanced-access-controls), [legal hold](/administration-guide/comply/legal-hold), [retention policies](/administration-guide/comply/data-retention-policy), and [custom Terms of Service](/administration-guide/comply/custom-terms-of-service). +- **Synchronize user identity** using [Entra ID](/administration-guide/onboard/sso-entraid) to maintain scalable, centralized access control across both internal and external collaborators. + +## Cross-Instance Collaboration Hub + +Multi-agency, multi-tenant Microsoft 365 environments often hinder seamless collaboration and increase complexity for inter-organization workflows. + +**Benefits** + +- **Centralize communication across M365 instances** using Mattermost as a neutral, embedded hub for messaging, file sharing, and playbook coordination (See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365)). +- **Bridge segmented Teams deployments** with [Connected Workspaces](/administration-guide/onboard/connected-workspaces) and Microsoft presence integration to ensure continuity without duplicative configuration. +- **Deploy flexibly across hybrid, private, or air-gapped environments** such as [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365) to ensure operational consistency no matter the deployment complexity. +- **Secure external communications and maintain control** with segmentation, data governance, and compliance automation across Teams ecosystems. + +## Get Started + +We can help you maximize your Microsoft investment while extending its capabilities into the most demanding mission contexts. [Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to discover how your organization can enhance Microsoft-based workflows with secure, extensible collaboration tailored for operational and compliance-sensitive environments. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/main/use-case-guide/mission-ready-mobile.mdx b/docs/main/use-case-guide/mission-ready-mobile.mdx new file mode 100644 index 000000000000..310ddcb8e372 --- /dev/null +++ b/docs/main/use-case-guide/mission-ready-mobile.mdx @@ -0,0 +1,54 @@ +--- +title: "Mission-Ready Mobile" +--- +Mission environments demand secure, reliable mobile collaboration, from intelligence briefings and operational coordination to incident response in disconnected regions. Traditional mobile communication tools fail to meet the demands of field-forward operations, exposing sensitive data to third-party systems, and increasing the risk of data leakage, non-compliance, and operational compromise. + +Mattermost provides a secure, mission-ready mobile platform built for defense, law enforcement, and public sector operations. Optimized for low-bandwidth and disconnected conditions, Mattermost ensures secure communication on government-issued devices while enabling compliant collaboration on personal phones—without reliance on consumer apps or invasive controls. + +With protections including ID-only push notifications, biometric authentication, jailbreak detection, and full MDM/EMM support, Mattermost delivers control, compliance, and usability across a range of challenging field conditions. + +![An infographic illustrating "Security-Optimized Mobility" with two devices side-by-side: A Mattermost server (on the left) and a mobile device (on the right). The Mattermost server displays a list of security features, including "Zero Trust Security (Channel ABAC, Files ABAC)," "Secure File Viewer," "TLS Data in Transit (Post Quantum)," "Authentication and Access Control (MFA, SSO)," "Data Spillage Handling," and more, with asterisks (\*) indicating functionality scheduled for release later in 2025. On the right, the mobile device mirrors corresponding security features, such as "Secure File Viewer," "TLS," "Burn on Read," "End-to-End Encryption," "Biometric Authentication," and others, with blue arrows connecting the related features on the server and the mobile device, signifying seamless integration and support for advanced security across these endpoints.](/images/mission-ready-mobile.png) + +The following mobile-first operational capabilities are available. + +## Secure Mobile Access on Government Devices + +Mission teams require trusted mobile access to secure collaboration, ensuring operational integrity during deployments, transit, and high-tempo operations. Government-issued or EMM-enrolled devices offer a fully controlled, secure mobile environment. + +**Benefits** + +- **Deploy securely with enterprise mobility management (EMM)** using [AppConfig integrations](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider#manage-app-configuration-using-appconfig) to manage application policies, access controls, and encrypted communication channels. +- **Maintain control over mission-critical data**: Enable safe delivery of notifications via [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications) that prevent exposure of sensitive content to third-party systems like Apple or Google. +- **Mitigate data compromise risk in personnel transitions**: Protect data with [remote wipe and deactivation](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) capabilities in the event of device loss, theft, or personnel separation. +- **Enforce strong identity assurance** through [native biometric authentication](/deployment-guide/mobile/mobile-security-features#biometric-authentication) and [multi-factor authentication (MFA)](/administration-guide/onboard/multi-factor-authentication) tied to [SSO](/administration-guide/onboard/sso-entraid) or [AD/LDAP](/administration-guide/onboard/ad-ldap) provisioning . +- **Comply with classified mobility mandates** by using [secure data storage](/deployment-guide/mobile/mobile-security-features#mobile-data-isolation), [sandboxing](/deployment-guide/mobile/mobile-security-features#security-measures), and FIPS 140-3-validated TLS in transit\* to meet defense-grade standards. + +## Secure Government Communications on Personal Devices + +When personal devices are the only available channel—whether in partner nations, rural patrol units, or disconnected deployments—Mattermost provides a secure alternative to consumer messaging apps like Signal or WhatsApp, enabling policy-compliant collaboration without compromising field effectiveness. + +**Benefits** + +- **Enable trusted communications on BYOD** using lightweight AppConfig policies with [EMM optionality](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider) that avoids intrusive control while ensuring essential security baselines. +- **Prevent unauthorized data sharing**: Mitigate leakage with [screenshot and screen recording prevention](/deployment-guide/mobile/mobile-security-features#screenshot-and-screen-recording-prevention) and [jailbreak/root detection](/deployment-guide/mobile/mobile-security-features#jailbreak-and-root-detection) that block high-risk mobile behaviors. +- **Secure access without cloud dependency** via [self-hosted deployments](/deployment-guide/server/server-deployment-planning#deployment-options) or [air-gapped infrastructures](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) that prevent sensitive data from touching public networks. +- **Deliver rapid alerts with low bandwidth impact** using [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications), ideal for DDIL (disconnected, intermittent, low-bandwidth) conditions. +- **Support interagency or coalition workflows** in mission-partner environments through [Connected Workspaces](/administration-guide/onboard/connected-workspaces) with [role-based](/administration-guide/onboard/delegated-granular-administration) and [attribute-based access controls (ABAC)](/administration-guide/manage/admin/attribute-based-access-control). + +## Built for Field-Forward Security + +Mattermost on mobile is hardened to operate under mission-grade security expectations, whether it's used by intelligence teams in transit, patrol officers in the field, or coalition operators in disconnected regions. + +**Features** + +- **Zero Trust security architecture** with channel- and file-level [attribute-based access control (ABAC)](/administration-guide/manage/admin/attribute-based-access-control). +- **TLS with post-quantum readiness** and end-to-end\* [encryption options](/security-guide/security-guide-index) for high-assurance deployments. +- **Burn-on-read messaging**: Use [secure file viewers](/security-guide/mobile-security#secure-file-preview), [burn on read messaging](/end-user-guide/collaborate/send-messages#send-burn-on-read-messages), and advanced data spillage controls\* to protect sensitive information and minimize persistent data exposure. +- **DoD STIG container support** with FIPS 140-3 validation\*, and [audit logging](/administration-guide/manage/logging#audit-logging) to ensure deployment compliance in regulated missions. +- **Isolated mobile sessions** from host operating systems by partnering with platforms like Hypori in high-assurance BYOD scenarios. + +Features marked with an asterisk above `*` will be available in a future 2025 release. + +## Get Started + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore how Mattermost can support mission-ready mobile collaboration. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. Whether you're securing communications on government-issued devices or enabling compliant collaboration on personal phones, Mattermost provides the control, trust, and extensibility needed to stay connected—without compromise. diff --git a/docs/main/use-case-guide/on-prem-skype-for-business-replacement.mdx b/docs/main/use-case-guide/on-prem-skype-for-business-replacement.mdx new file mode 100644 index 000000000000..7ecf369da262 --- /dev/null +++ b/docs/main/use-case-guide/on-prem-skype-for-business-replacement.mdx @@ -0,0 +1,52 @@ +--- +title: "On-Premises Skype for Business Replacement" +--- +With Skype for Business reaching end-of-life, security-conscious organizations face a critical inflection point. Many operate in air-gapped or classified environments where cloud-based alternatives are not viable due to compliance restrictions, risk exposure, or data sovereignty mandates. Without a secure, modern, on-premises collaboration platform, these organizations risk operational disruption, mission misalignment, and non-compliance with stringent regulatory frameworks. + +Mattermost provides a secure, self-hosted communication and collaboration platform purpose-built for air-gapped environments, classified networks, and regulated industries. Designed to meet NIST 800-53, FedRAMP, and DISA STIG compliance requirements, Mattermost replaces legacy tools with modern capabilities—secure messaging, file sharing, workflow automation, and integrated video collaboration—while maintaining full enterprise control. Organizations can operate at scale, enable external collaboration without policy violations, and modernize their digital workflows without compromising security. + +![Extend Microsoft Enterprise IT investments for edge-based, highly tailored Mission IT workflows with Mattermost.](/images/On-Prem-Skype-for-Business-replace.png) + +The following mission-ready collaboration capabilities are available: + +## Air-Gapped and Classified Operations + +Organizations operating in fully disconnected or classified environments require secure communication platforms that function entirely within their own infrastructure. + +**Benefits** + +- **Ensure secure communication in fully disconnected networks** using Mattermost's support for private on-premise deployments, including FIPS 140-3 validated and DISA STIG-hardened container images. [Learn more](/deployment-guide/reference-architecture/application-architecture) about Mattermost's architecture, components, and backend infrastructure. +- **Maintain operational continuity** with enterprise-grade [channel-based collaboration](/end-user-guide/messaging-collaboration)— including [1:1 audio calls](/end-user-guide/collaborate/make-calls), [screen sharing](/end-user-guide/collaborate/make-calls#share-your-screen), [threaded messaging](/end-user-guide/collaborate/organize-conversations), and [file sharing](/end-user-guide/collaborate/share-files-in-messages)—entirely within air-gapped systems. +- **Scale to mission requirements** with a [high-availability, horizontally scalable architecture](/administration-guide/scale/scaling-for-enterprise) that supports tens of thousands of users in secure on-prem environments. +- **Preserve data sovereignty and eliminate external dependencies** with a self-hosted [Kubernetes deployment model](/deployment-guide/server/deploy-kubernetes) that integrates into classified networks, sovereign data centers, or **Azure Local** (formerly Azure Stack HCI) for hybrid cloud on-premises scenarios. + +## Modernize Secure Collaboration Workflows + +Legacy communication tools lack the flexibility, automation, and usability demanded by modern operational teams. Mattermost introduces modern collaboration workflows without compromising compliance or deployment control. + +**Benefits** + +- **Enable dynamic, cross-platform messaging and coordination** with a unified interface across web, desktop, and mobile—featuring [threaded discussions](/end-user-guide/collaborate/organize-conversations), [file previews](/end-user-guide/collaborate/share-files-in-messages#preview-file-attachments), and [screen sharing](/end-user-guide/collaborate/make-calls#share-your-screen). +- **Streamline mission-critical processes** with [Collaborative Playbooks](/end-user-guide/workflow-automation) that automate and track workflows like incident response, shift turnover, and logistics planning. +- **Embed secure video conferencing into daily operations** using the [Pexip integration](https://mattermost.com/marketplace/pexip-video-connect/), allowing real-time video engagement from within your air-gapped or secure infrastructure. +- **Support operational task management** through optional Kanban-style [Boards](https://github.com/mattermost/mattermost-plugin-boards) for structured, accountable planning—hosted securely within your own network. +- **Align the user experience with your operational identity** using [custom branding](/administration-guide/configure/custom-branding-tools), [theming](/end-user-guide/preferences/customize-your-theme), and [product localization](/end-user-guide/preferences/manage-your-display-options#language) across more than 20 languages to support multinational teams. + +## Enterprise-Controlled External Collaboration + +Collaborating across organizational boundaries must not compromise compliance or IT governance. Mattermost enables secure external engagement while keeping control centralized within the enterprise. + +![Mattermost replaces Signal, Discord and other free personal apps with secure external messaging controlled by IT.](/images/External-Collaboration-with-Enterprise-Control.png) + +**Benefits** + +- **Collaborate securely with third parties** via Connected Workspaces that allow messaging, [file sharing](/end-user-guide/collaborate/share-files-in-messages), and [thread-based discussions](/end-user-guide/collaborate/organize-conversations) with external teams—without exposing internal systems. +- **Apply fine-grained access controls and retention policies** to external users through enterprise-managed [permissions](/administration-guide/onboard/advanced-permissions), [audit logging](/administration-guide/manage/logging#audit-logging), and [channel-specific configurations](/administration-guide/manage/team-channel-members#advanced-access-controls). +- **Integrate with Microsoft Teams, Exchange, and M365** to maintain centralized workflows and extend secure communication to external stakeholders without leaving policy-aligned platforms. See [Mattermost for M365, Teams, and Outlook](/integrations-guide/mattermost-mission-collaboration-for-m365). +- **Manage user identity and access** across internal and external roles using Microsoft [Entra ID](/administration-guide/onboard/sso-entraid) (Azure AD) synchronization for scalable and compliant provisioning. + +## Get Started + +With Mattermost, your organization gains a self-hosted, scalable, and compliant solution tailored for classified operations, secure external engagement, and operational modernization. + +[Talk to an Expert](https://mattermost.com/contact-sales/) to learn more about transitioning from Skype for Business to a secure, modern collaboration platform built for mission-critical environments, or to discuss your Azure Local deployment needs. Organizations deploying Mattermost on Azure Local (formerly Azure Stack HCI) for on-premises hybrid cloud scenarios can engage **Mattermost Professional Services** for deployment support to ensure optimal configuration and compliance with your security requirements. diff --git a/docs/main/use-case-guide/out-of-band-incident-response.mdx b/docs/main/use-case-guide/out-of-band-incident-response.mdx new file mode 100644 index 000000000000..45bf747b2a80 --- /dev/null +++ b/docs/main/use-case-guide/out-of-band-incident-response.mdx @@ -0,0 +1,49 @@ +--- +title: "Out-of-Band Incident Response" +--- +**Don't let attackers silence your incident response team. Deploy sovereign, encrypted collaboration that operates completely outside your compromised infrastructure.** + +When cyberattacks, infrastructure failures, or security breaches disrupt primary systems, organizations must maintain the ability to coordinate securely and act decisively. Traditional communication tools often become liabilities under these conditions, prone to compromise, unavailable during outages, or unable to support secure workflows. The operational and financial consequences of downtime can be catastrophic, underscoring the need for an independent collaboration environment. + +Mattermost provides a secure, mission-resilient out-of-band (OOB) collaboration platform that operates outside your primary infrastructure. Whether deployed as a self-hosted Kubernetes instance, Linux server in your local data center, or in sovereign hosting environments, the platform ensures real-time coordination remains available during network outages, security incidents, or critical decision windows. Built for security-conscious teams across commercial, government, and regulated industries, Mattermost supports integrated incident workflows and enterprise-level access control to enable business continuity, even under duress. + +![Secure and sovereign out-of-band incident response communication operates independently from compromised enterprise infrastructure.](/images/secure-out-of-band.png) + +Mattermost supports the following mission-critical OOB collaboration requirements: + +## Always-Available Backup Communications + +Out-of-band collaboration provides a persistent, independent channel for coordinating during crises, separate from compromised or degraded primary systems. + +**Benefits** + +- **Preserve communication during infrastructure failures** with secure, dedicated OOB deployments using Kubernetes Or Linux on the infrastructure of your choice: Public cloud, organization data center, or fully air-gapped. [Explore deployment options](/deployment-guide/server/server-deployment-planning#deployment-options). +- **Meet regulatory compliance requirements** with a solution that adapts to your organization's security posture and regulatory requirements, incl. GDPR, FedRAMP, ISO 27001, and more. +- **Ensure data sovereignty** with flexible hosting options including EU-resident infrastructure, on-premises deployments, and air-gapped environments that maintain full control over sensitive communications. +- **Maintain continuity across platforms** with [multi-device access](/deployment-guide/deployment-guide-index), including web, desktop, and mobile experiences, even when primary tools are offline. +- **Enforce strict access controls** using [role-based permissions](/administration-guide/onboard/advanced-permissions) and [audit logging](/administration-guide/manage/logging#audit-logging) to limit risk exposure during high-stakes operations. + +## Business Continuity at Scale + +Outages and downtime threaten both productivity and revenue. In large enterprises, the cost of outages can be measured in hundreds of thousands of dollars per minute, while government operations face national security implications. + +**Benefits** + +- **Scale communication globally** with Mattermost's [high availability and horizontal scalability architecture](/administration-guide/scale/scaling-for-enterprise), supporting tens of thousands of users across enterprise, field, government, or classified environments. +- **Accelerate outage recovery** using [Collaborative Playbooks](/end-user-guide/workflow-automation) that automate response steps and ensure team accountability during time-critical events, reducing mean time to recovery (MTTR) by up to 50%. +- **Demonstrate ROI through measurable outcomes** with built-in metrics tracking incident response times, team coordination efficiency, and compliance audit trails. + +## Incident Response in Crisis Conditions + +Cyber breaches demand swift, coordinated action across affected teams. Every delay in communication heightens risk and potential regulatory penalties. + +**Benefits** + +- **Ensure secure response coordination** through [private 1:1 calling and screen sharing](/end-user-guide/collaborate/make-calls) for uninterrupted incident discussions within an isolated Mattermost environment. +- **Integrate with your existing security stack** including ServiceNow, Grafana, Splunk, and other SOC tools via the [Mattermost integrations platform](/integrations-guide/integrations-guide-index). +- **Reduce mean time to resolution (MTTR)** by executing [structured incident playbooks](/end-user-guide/workflow-automation) that handle triage, task assignment, and escalation with full visibility and auditability. +- **Support compliance reporting** with automated documentation and audit trails helping organizations to meet NIS2, HIPAA, PCI DSS, GDPR, and government security requirements. + +## Get Started + +Whether protecting national security, managing global infrastructure, ensuring regulatory compliance, or recovering from outages, Mattermost ensures your teams remain connected, coordinated, and compliant, no matter the crisis. Experience out-of-band incident response with pre-configured alerts, channels, and playbooks in a [live sandbox environment](https://mattermost.com/sign-up/?usecase=out-of-band), a [live demo](https://mattermost.com/request-demo/), or [talk to an expert](https://mattermost.com/contact-sales/) to build your out-of-band incident response environment. diff --git a/docs/main/use-case-guide/purpose-built-collaboration.mdx b/docs/main/use-case-guide/purpose-built-collaboration.mdx new file mode 100644 index 000000000000..6fb2631a7acb --- /dev/null +++ b/docs/main/use-case-guide/purpose-built-collaboration.mdx @@ -0,0 +1,50 @@ +--- +title: "Purpose-Built Collaboration" +--- +From large-scale logistics operations to critical infrastructure defense, organizations are under pressure to act faster, with fewer resources and greater operational complexity. But legacy chat platforms and multi-purpose messaging tools can't keep pace with dynamic, high-stakes workflows. They lack the integration depth, security controls, and mission-specific configurability needed for real-time operational success. + +Mattermost provides a purpose-built collaboration platform designed for technical, operational, and industrial teams. It brings people, tools, and workflows together in a secure, extensible environment—streamlining coordination, improving decision velocity, and increasing resilience. Whether coordinating a global logistics chain, managing operational technology (OT) in the field, or running a security operations center, Mattermost adapts to your environment—not the other way around. + +![Secure, Mission-Focused Collaboration to Enable Faster, Informed Decision-Making across Environments.](/images/Enterprise-to-Tactical-Edge.png) + +The following mission-ready collaboration capabilities are available: + +## Global Logistics Coordination + +Coordinating logistics across continents, agencies, and time zones requires a secure, unified platform that centralizes communications and aligns stakeholders. + +**Benefits** + +- **Enable real-time coordination** across supply chains, procurement, and field units with [channel-based messaging](/end-user-guide/messaging-collaboration) and [playbook-driven workflows](/end-user-guide/workflow-automation) that standardize communication and reduce friction. +- **Connect systems across logistics networks** by integrating ERP, fleet tracking, maintenance management, and transportation tools via [webhooks, APIs, and plugins](/integrations-guide/integrations-guide-index). +- **Preserve operational continuity** during outages or disruptions using [self-hosted deployments](/deployment-guide/server/server-deployment-planning#deployment-options) and [high availability architecture](/administration-guide/scale/high-availability-cluster-based-deployment) that eliminate reliance on third-party cloud services. +- **Support multilingual coordination** with [localized UI options](/end-user-guide/preferences/manage-your-display-options#language) in 20+ languages to ensure inclusive collaboration across global teams. + +## Operational Technology and ICS Collaboration + +OT and field operations in energy, utilities, manufacturing, and transportation sectors demand secure, real-time communication across widely distributed assets and personnel. From remote substations and industrial facilities to on-site emergency repair teams, teams must coordinate without exposing sensitive control systems or violating compliance standards. + +Mattermost enables secure collaboration across OT environments and field operations, even under disconnected, air-gapped, or constrained network conditions. + +**Benefits** + +- **Enable compliant, real-time OT communications** across operational zones and facilities using [secure, on-prem collaboration](/deployment-guide/server/server-deployment-planning#deployment-options) that keeps data within your control perimeter. +- **Support field teams with hardened mobile access** using [EMM-based app provisioning](/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider), [biometric authentication](/deployment-guide/mobile/mobile-security-features#biometric-authentication), [jailbreak detection](/deployment-guide/mobile/mobile-security-features#jailbreak-and-root-detection), and [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications)—ensuring that only authorized, uncompromised devices can access operational data. +- **Integrate with industrial monitoring systems** like SCADA, PI historians, and plant analytics using [alert-driven webhook and plugin integrations](/integrations-guide/integrations-guide-index) that push system events to relevant mobile or desktop channels. +- **Ensure system and network isolation** with [air-gapped deployment support](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) that allows full collaboration within OT enclaves and disconnected environments. +- **Prevent mobile data leakage** via [remote wipe capabilities](/security-guide/mobile-security#mobile-device-management-mdm)) and [screenshot/screen recording prevention](/deployment-guide/mobile/mobile-security-features#screenshot-and-screen-recording-prevention) for mobile devices used in the field. + +## Technical Operational Command Centers + +Engineering, infrastructure, and security teams manage increasingly complex environments. Whether responding to incidents, deploying software, or monitoring infrastructure, they need customizable workspaces that reduce cognitive load and integrate the tools they trust. + +**Benefits** + +- **Accelerate decision-making and incident response** using [Collaborative Playbooks](/end-user-guide/workflow-automation) to automate workflows for triage, patching, code releases, and security alerts. +- **Customize your collaboration environment** with [theming](/end-user-guide/preferences/customize-your-theme), [custom branding](/administration-guide/configure/custom-branding-tools), and [channel templates](/end-user-guide/messaging-collaboration) to mirror internal teams and operational domains. +- **Extend platform capabilities** with [slash commands, bots, and custom plugins](/integrations-guide/integrations-guide-index) that connect Mattermost to CI/CD systems, alerting frameworks, ticketing platforms, and internal tools. +- **Increase usability and team cohesion** with [custom emojis](/end-user-guide/collaborate/react-with-emojis-gifs#upload-custom-emojis), shared terminology, and [real-time messaging](/end-user-guide/messaging-collaboration) optimized for platform engineers, DevSecOps teams, and field service managers. + +## Get Started + +[Talk to an Expert](https://mattermost.com/contact-sales/) to create a secure, purpose-built collaboration environment aligned with your mission. Whether supporting distributed logistics, managing ICS environments, or running an operational command center, Mattermost adapts to your workflows—so your teams can move faster, respond smarter, and deliver with confidence. diff --git a/docs/main/use-case-guide/secure-command-and-control.mdx b/docs/main/use-case-guide/secure-command-and-control.mdx new file mode 100644 index 000000000000..d17ad4a71f92 --- /dev/null +++ b/docs/main/use-case-guide/secure-command-and-control.mdx @@ -0,0 +1,67 @@ +--- +title: "Secure Command and Control" +--- +Expanding adversarial risk across cyber and kinetic domains requires faster, more secure, and better-informed coordination across mission environments. Traditional communication systems often fall short in high-stakes operational contexts—where minutes matter, information must remain contained, and decision advantage is critical to mission success. In an age of contested networks, personal device sprawl, and fragmented toolsets, organizations need a unified, secure platform to bridge communication and coordination gaps. + +Mattermost provides a secure, extensible Command & Control platform that accelerates decision advantage through real-time collaboration and mission-aligned workflows. It enables operational units, contractors, and mission partners to work together in tightly controlled environments—whether connected, disconnected, or degraded. With support for secure mobility, ChatOps, classified deployment models, and sovereign AI integrations, Mattermost empowers organizations to act faster, coordinate securely, and maintain operational resilience across the full mission lifecycle. + +![Secure, Mission-Focused Collaboration to Enable Faster, Informed Decision-Making across Environments.](/images/Enterprise-to-Tactical-Edge.png) + +The following mission-ready coordination capabilities are available: + +## Mission-Critical ChatOps + +In high-stakes missions—including classified operations—real-time collaboration and secure workflows are essential for operational success. Mattermost unifies teams, toolchains, and decision-makers into a single secure environment. + +**Benefits** + +- **Surface essential context faster for decisive action** using [threaded messaging](/end-user-guide/collaborate/organize-conversations), [file previews](/end-user-guide/collaborate/share-files-in-messages), and [channel-based discussion](/end-user-guide/messaging-collaboration) to consolidate signals and reduce noise. +- **Integrate mission tooling and automation** via the [Mattermost integrations platform](/integrations-guide/integrations-guide-index)—connecting alerting, workflow engines, and tactical systems directly into operational channels. +- **Strengthen mobile communication channels** through [enterprise mobility security](/security-guide/mobile-security) that reduce reliance on personal messaging apps, control data exposure, and ensure secure, compliant access. +- **Coordinate operations with structured workflows** using [Collaborative Playbooks](/end-user-guide/workflow-automation) that standardize task execution, streamline decision-making, and maintain continuity across teams and mission roles. +- **Deploy sovereign AI for operational intelligence** using [air-gapped and private AI operations](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment) to power decision support and automation in disconnected or classified settings. + +## Disconnected, Intermittent, and Low-Bandwidth (DDIL) Collaboration + +Disconnected environments demand resilient tools that work without cloud access, persistent connectivity, or conventional device infrastructure. + +![Mattermost's Self-Hosted Kubernetes-based Collaborative Workflow platform installs on edge, cloud and custom data center platforms.](/images/DDIL-disconnected-secure-communication-collaboration.png) + +**Benefits** + +- **Operate in air-gapped and disconnected networks** using [self-hosted Kubernetes deployments](/deployment-guide/server/deploy-kubernetes) and STIG-hardened container images for secure offline operations. +- **Ensure secure mobile access on managed or BYOD devices** with [mobile security features](/deployment-guide/mobile/mobile-security-features), Zero Trust enforcement, and [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications) for sensitive alerts. +- **Integrate with legacy and mission-specific systems** to maintain decision advantage in disconnected environments through [custom-built, self-hosted integrations](/integrations-guide/integrations-guide-index) tailored to your operational infrastructure. +- **Maintain command resilience** using [high availability cluster-based deployment](/administration-guide/scale/scaling-for-enterprise) and [horizontal scalability](/administration-guide/scale/scaling-for-enterprise) to support operational continuity at scale. +- **Automate field workflows** with [Collaborative Playbooks](/end-user-guide/workflow-automation) that track tasks, manage field updates, and orchestrate responses under DDIL constraints. +- **Enable secure real-time collaboration with headquarters** using [Connected Workspaces](/administration-guide/onboard/connected-workspaces) to synchronize discussions, files, and reactions if connectivity is restored. + +## Bring Your Own Device (BYOD) with Sensitive Information Protections + +Modern operations often require users—such as field personnel, mission partners, or remote contractors—to access critical communication tools from personal or unmanaged mobile devices. However, this flexibility introduces new risks when sensitive information or other protected data is involved. Without strong protections, mobile access becomes a liability in contested or regulated environments. + +Mattermost provides enterprise-grade mobile protections to enable secure BYOD access without compromising security or compliance. From mobile application management and encryption enforcement to biometric authentication and jailbreak detection, Mattermost ensures that data remains protected, access is governed, and sensitive information stays within authorized boundaries. + +**Benefits** + +- **Mitigate unauthorized access** with [biometric authentication](/deployment-guide/mobile/mobile-security-features#biometric-authentication) and [jailbreak/root detection](/deployment-guide/mobile/mobile-security-features#jailbreak-and-root-detection), ensuring only secure and uncompromised devices can access mission data. +- **Control information sharing** with [screenshot and screen recording prevention](/deployment-guide/mobile/mobile-security-features#screenshot-and-screen-recording-prevention), blocking unauthorized capture of sensitive content during classified or time-sensitive discussions. +- **Protect data at rest and in motion** using encrypted mobile storage, [secure sandboxing](/deployment-guide/mobile/mobile-security-features#mobile-data-isolation), and [ID-only push notifications](/administration-guide/configure/environment-configuration-settings#id-only-push-notifications) that never expose message content to third-party cloud services. +- **Segment mission access by role or project** with [attribute-based access controls (ABAC)](/administration-guide/manage/team-channel-members#advanced-access-controls) and scoped channel access, ensuring users only see data aligned with their permissions and operational role. +- **Ensure continuous mobile compliance** with secure SDLC practices and proactive vulnerability management baked into the Mattermost mobile application lifecycle. + +## Mission-Partner Environments + +Coordinating across departments, agencies, and external stakeholders—especially in multinational or coalition contexts—requires secure boundaries, role separation, and deployment flexibility. + +**Benefits** + +- **Unify mission stakeholders on a common-use platform** that supports [hybrid deployments](/deployment-guide/server/server-deployment-planning#deployment-options) across private cloud, edge environments, and [air-gapped infrastructure](/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment). +- **Maintain data sovereignty and mission alignment** with deployments that avoid consumer infrastructure and retain control over all communications and file transfers—even in classified operations. +- **Apply role-based separation of access** through [advanced permissions](/administration-guide/onboard/advanced-permissions) and [channel-level controls](/administration-guide/manage/team-channel-members#advanced-access-controls) to protect mission integrity across organizational boundaries. +- **Enable secure real-time collaboration across entities** using [Connected Workspaces](/administration-guide/onboard/connected-workspaces) to synchronize discussions, files, and reactions between teams without compromising internal governance. +- **Reduce personal device risk** by offering secure enterprise communication options that eliminate the need for unauthorized messaging apps. + +## Get Started + +[Talk to an Expert](https://mattermost.com/contact-sales/) to explore how Mattermost supports secure, real-time Command and Control collaboration. Whether you're coordinating joint operations, managing disconnected mission environments, or securing tactical communications in classified settings, Mattermost provides the control, scalability, and resilience your teams need to operate with speed, confidence, and compliance. diff --git a/docs/main/use-case-guide/self-sovereign-collaboration.mdx b/docs/main/use-case-guide/self-sovereign-collaboration.mdx new file mode 100644 index 000000000000..3ac578a9079e --- /dev/null +++ b/docs/main/use-case-guide/self-sovereign-collaboration.mdx @@ -0,0 +1,61 @@ +--- +title: "Self-Sovereign Collaboration" +--- +As data privacy laws tighten and geopolitical risk escalates, organizations must rethink how they control and protect communications. Cloud-centric collaboration platforms often introduce legal exposure, third-party monitoring, and cross-border compliance conflicts—putting operations and data at risk. Whether driven by internal policy, regulatory mandates, or national data sovereignty requirements, more organizations are moving toward self-sovereign collaboration models. + +Mattermost provides a secure, extensible collaboration platform that delivers full control over data, infrastructure, and compliance posture. Built on a self-hosted, open core foundation, Mattermost supports localized deployments across air-gapped, private cloud, and sovereign environments—ensuring organizations can future-proof operations, meet global compliance demands, and maintain continuous operational continuity without third-party dependencies. + +![Secure, Mission-Focused Collaboration to Enable Faster, Informed Decision-Making across Environments.](/images/Enterprise-to-Tactical-Edge.png) + +The following mission-ready sovereign collaboration capabilities are available: + +## Localized Compliance and Data Control + +Managing global operations means adhering to regional regulations—without compromising productivity or communication security. + +**Benefits** + +- **Meet global compliance mandates** like GDPR and data localization laws by deploying Mattermost in [public, private, or sovereign cloud environments](/product-overview/cloud-subscriptions) tailored to national regulatory frameworks. +- **Ensure full data control and transparency** with [self-hosted deployment options](/deployment-guide/server/server-deployment-planning#deployment-options) that eliminate exposure to vendor-controlled infrastructure or telemetry. +- **Audit and enforce compliance behavior** with [role-based access controls](/administration-guide/manage/team-channel-members#advanced-access-controls), [custom Terms of Service](/administration-guide/comply/custom-terms-of-service), and [audit logging](/administration-guide/manage/logging#audit-logging) to align with internal and regulatory standards. +- **Protect identity and access** using [SSO integrations](/administration-guide/onboard/sso-entraid), [AD/LDAP synchronization](/administration-guide/onboard/ad-ldap-groups-synchronization), and [MFA enforcement](/administration-guide/onboard/multi-factor-authentication) for secure authentication across geographies and operational roles. + +## Secure, Sovereign Deployment at Any Scale + +From national critical infrastructure to defense-grade networks, Mattermost offers flexible deployment models that preserve sovereignty and continuity. + +**Benefits** + +- **Deploy in classified, air-gapped, or disconnected environments** using [Kubernetes-based deployments](/deployment-guide/server/deploy-kubernetes) and STIG-hardened container images to support classified operations and sensitive data workflows. +- **Eliminate third-party monitoring** with full control over infrastructure, encryption keys, access policies, and system-level logging. +- **Scale to meet operational growth** with [horizontal scalability architecture](/administration-guide/scale/scaling-for-enterprise) that supports tens of thousands of users in sovereign environments without degrading performance or control. +- **Maintain operational continuity under cyber or supply chain disruption** using fully self-managed infrastructure that ensures collaboration continues even during cloud outages or external service failures. + +## Interoperable Mission-Partner Collaboration + +Cross-agency, multinational, or coalition collaboration requires sovereignty without isolation—supporting joint operations while preserving organizational boundaries. + +**Benefits** + +- **Create secure shared workspaces** with [Connected Workspaces Channels](/administration-guide/onboard/connected-workspaces) that synchronize discussions, reactions, and file sharing across trusted organizations—without exposing internal systems. +- **Control access across organizations** with [attribute-based permissions](/administration-guide/onboard/advanced-permissions) and scoped identity policies to ensure mission alignment and sensitive information segmentation. +- **Deploy sovereign AI and workflow automation** in isolated environments using [air-gapped AI operations](/end-user-guide/agents) and [Collaborative Playbooks](/end-user-guide/workflow-automation)—enabling intelligence and speed without compromising data control. +- **Upgrade legacy platforms** like Skype for Business with modern, compliant tools for secure messaging, screen sharing, and team coordination. [See Skype for Business replacement options](/use-case-guide/on-prem-skype-for-business-replacement). + +## Unified Collaboration for Secure Workflows + +Legacy collaboration tools—such as Skype for Business and other end-of-life platforms—can no longer meet the demands of modern, high-assurance environments. These tools often lack support for mobile security, extensibility, and integration with mission-critical workflows, creating gaps in continuity, control, and user experience. + +Mattermost replaces legacy, on-premises communication systems with a modern, sovereign collaboration platform built to support today's security, compliance, and operational agility requirements. + +**Benefits** + +- **Modernize secure messaging and team coordination** with [channel-based collaboration](/end-user-guide/messaging-collaboration), [threaded discussions](/end-user-guide/collaborate/organize-conversations), and [file sharing](/end-user-guide/collaborate/share-files-in-messages) that work across web, desktop, and mobile. +- **Replace outdated platforms** like Skype for Business with a scalable, [self-hosted architecture](/deployment-guide/server/server-deployment-planning#deployment-options) that delivers enhanced user experience, compliance, and cross-organizational flexibility. +- **Protect sensitive information on mobile** using [enterprise-grade mobile security](/security-guide/mobile-security) including [biometric access](/deployment-guide/mobile/mobile-security-features#biometric-authentication), [jailbreak detection](/deployment-guide/mobile/mobile-security-features#jailbreak-and-root-detection), [screenshot prevention](/deployment-guide/mobile/mobile-security-features#screenshot-and-screen-recording-prevention), and remote wipe—ensuring secure access from personal or field-issued devices. +- **Extend collaboration capabilities** using [integrated workflows and automations](/end-user-guide/workflow-automation) to replace manual coordination with policy-driven processes. +- **Unify teams around a secure, customizable platform** that evolves with your mission and integrates with internal systems via [webhooks, plugins, and APIs](/integrations-guide/integrations-guide-index). + +## Get Started + +[Talk to an Expert](https://mattermost.com/contact-sales/) to deploy a sovereign collaboration platform that gives you full control over your data, infrastructure, and compliance. Whether operating in a national defense context, regulated enterprise, or multinational coalition, Mattermost provides the control, transparency, and resilience required to stay mission-ready. diff --git a/docs/main/use-case-guide/use-cases-index.mdx b/docs/main/use-case-guide/use-cases-index.mdx new file mode 100644 index 000000000000..dd8436810f86 --- /dev/null +++ b/docs/main/use-case-guide/use-cases-index.mdx @@ -0,0 +1,16 @@ +--- +title: "Use Case Guide" +--- +Learn how operational teams use Mattermost to accelerate mission-critical work across a wide variety of disciplines. + +- [Integrated Security Operations](/integrated-security-operations) - Accelerate detection, decision-making, and coordinated response while maintaining full operational control in Security Operations Centers (SOCs), red team engagements, CERT responses, and cross-organizational intelligence hubs. +- [Maximize your Microsoft investments](/maximize-microsoft-investments) - Speed mission-critical outcomes by supplementing existing investments in Microsoft Teams, M365, and Entra ID for everyday collaboration with Mattermost's specialized workflow platform for technical and operational teams needing advanced customization, toolchain integration, and deployment to segregated networks. +- [Mission-Ready Mobile](/mission-ready-mobile) - Secure mobile collaboration for defense, law enforcement, and public sector operations optimized for low-bandwidth and disconnected conditions with protections including ID-only push notifications, biometric authentication, jailbreak detection, and full MDM/EMM support. +- [On-Premises Skype for Business replacement](/on-prem-skype-for-business-replacement) - Replace Skype for Business with Mattermost in classified operations. +- [Out-of-Band Incident Response](/out-of-band-incident-response) - Ensure real-time coordination remains available during network outages, security incidents, or critical decision windows when primary communication channels are unavailable. +- [Purpose-Built Collaboration](/purpose-built-collaboration) - Streamline coordination, improve decision velocity, and increase resilience across mission-critical workflows. +- [Real-Time DevSecOps collaboration](/devops-collaboration) - Support sovereign software supply chains, regulated platforms, or air-gapped operational environments to accelerate software development and deployment processes and reduce costs. +- [Secure Command and Control](/secure-command-and-control) - Accelerate decision advantage through real-time collaboration and mission-aligned workflows to enable operational units, contractors, and mission partners to work together in tightly controlled environments whether connected, disconnected, or degraded. +- [Self-Sovereign Collaboration](/self-sovereign-collaboration) - Maintain control over your data and communications with Mattermost's self-hosted, on-premises deployment options that ensure compliance, security, and operational continuity across all mission environments. + +[Book a live demo](https://mattermost.com/request-demo/) or [talk to a Mattermost expert](https://mattermost.com/contact-sales/) to explore tailored solutions for your organization's secure collaboration needs. Or try Mattermost yourself with a [1-hour preview](https://mattermost.com/sign-up/) for instant access to a live sandbox environment. diff --git a/docs/pdf/README.md b/docs/pdf/README.md new file mode 100644 index 000000000000..f55e7ce4b055 --- /dev/null +++ b/docs/pdf/README.md @@ -0,0 +1,124 @@ +# Phase 2 — PDF pipeline + +Builds brand-aligned PDF books from the docs site using headless Chromium + a print-only stylesheet. + +## What's here + +``` +pdf/ +├── books/ # Spine config: ordered list of URLs per book +│ └── api.json +├── scripts/ +│ ├── build-page-pdf.mjs # Capture a single page → PDF (the on-demand primitive) +│ └── build-book-pdf.mjs # Concatenate a section's pages → branded book PDF +├── styles/ +│ └── print.css # Brand-aligned print stylesheet (cover, headers, page numbers) +├── build/ # Output (gitignored) +└── package.json # Puppeteer +``` + +## Pipeline + +``` +docs site (npm start | npm run serve) + │ + │ HTTP fetches per spine entry + ▼ +build-book-pdf.mjs + │ + ├── fetches each
via Puppeteer page navigation + ├── prepends a brand-aligned cover (denim + marigold + Mission in Motion) + ├── composes static HTML, includes Google Fonts + the docs site's bundled CSS + ├── overrides everything for paper via styles/print.css (only thing the print pass cares about) + ▼ +Puppeteer page.pdf({ format: 'A4', preferCSSPageSize: true }) + │ + ▼ +build/mattermost-api.pdf +``` + +The print stylesheet does: +- `@page` rules for A4 size, margins, and running headers/footers +- `string-set: chapter content()` on h1 → fed into `@top-right` for chapter names +- `counter(page) " / " counter(pages)` in `@bottom-right` for page numbers +- Hides every site-chrome element (navbar, sidebar, footer, breadcrumbs, edit-this-page, OpenAPI right panel) +- Brand-aligned typography (Archivo Black headlines, Inter body, JetBrains Mono code) +- Page-break controls (`page-break-before: always` on h1, `page-break-inside: avoid` on figures/code/tables) +- Print-mode treatments for every branded MDX component (Hero flattens, Callouts get a thin denim left bar, StatStrip becomes a 4-up grid, CardGrid becomes a list) + +## Usage + +### Single-page (on-demand) PDF + +```bash +# Pre-req: docs site is running on port 3000 (npm start in docs-site/) +node pdf/scripts/build-page-pdf.mjs http://localhost:3000/api pdf/build/api-overview.pdf +``` + +Suitable as the unit primitive for the eventual "Download PDF" button on every page (CF Worker calls this against the production URL). + +### Multi-page book + +```bash +node pdf/scripts/build-book-pdf.mjs --book api +# → pdf/build/mattermost-api.pdf +``` + +Spine controlled by `pdf/books/api.json` — add/remove URL paths to change what's in the book. Future work auto-generates the spine from the OpenAPI tag list. + +## Current state + +| Capability | Status | +| --- | --- | +| Single-page PDF capture | ✓ Working | +| Multi-page book with cover | ✓ Working | +| Brand-aligned cover (denim + marigold + Mission in Motion + version + date) | ✓ Working | +| Running header (chapter name on right) | ✓ Working | +| Running footer (page X / N) | ✓ Working | +| Page-break-before on each chapter (h1) | ✓ Working | +| Branded typography (Archivo Black headlines) | ✓ Working | +| Branded MDX components in print mode | ✓ Working | + +| Coming in v1.1 / future | | +| --- | --- | +| Auto-generated TOC with page numbers | Needs Paged.js (target-counter) — see §below | +| Cross-reference page numbers ("see chapter X on page N") | Needs Paged.js | +| Watermarked customer PDFs (per-buyer "Provided to …") | CF Worker injecting watermark via page.evaluate before page.pdf | +| Auto-generated index | Needs Paged.js + index plugin | +| All sections, all versions (per PLAN.md §6.1) | Needs spine generators per OpenAPI / per RST tree | + +## Paged.js — when to add + +Puppeteer's native `page.pdf()` covers the basic book layout (cover, headers, footers, page breaks) using just `@page` rules. We use that today. + +Paged.js adds: +- TOC generation via `target-counter()` (the printed page number a heading lands on) +- "Continued on page N" bridges +- Automatic figure / table cross-references +- Better break-balancing across columns + +Add Paged.js when we hit a real need for any of those — likely Phase 5 (main docs migration, where the admin guide is 100+ pages and a good TOC matters more). For now, the cover + chapter breaks + page numbers are sufficient. + +To add: load `pagedjs` from npm or CDN, mount it via `Paged.Previewer().preview(content, stylesheets, container)` before calling `page.pdf`. + +## On-demand Worker (deferred) + +The on-demand per-page "Download PDF" button (PLAN.md §6.2) is the same `build-page-pdf.mjs` primitive, hosted on a Cloudflare Worker: + +``` +User clicks "Download PDF" on /docs/11.0/admin/saml-config + ▼ +CF Worker /api/pdf?url=… + ▼ +Browser Rendering API loads the URL, applies print.css, returns PDF stream + ▼ +Worker streams PDF back with Content-Disposition: attachment +``` + +This is straightforward to add once production is up (Browser Rendering API needs a domain). Defer to Phase 6 (cut first release branch) or later. + +## Costs + +Local: free. Headless Chromium runs on your machine. + +Production (CF Browser Rendering API): ~$0.001–0.005 per render. At 1000 PDFs/day (per PLAN.md §6.2), ~$50–150/mo. diff --git a/docs/pdf/books/administration-guide.json b/docs/pdf/books/administration-guide.json new file mode 100644 index 000000000000..2ef6070c0560 --- /dev/null +++ b/docs/pdf/books/administration-guide.json @@ -0,0 +1,136 @@ +{ + "title": "Mattermost Administration Guide", + "subtitle": "Configure, manage, scale, secure, and comply.", + "eyebrow": "ADMINISTRATION", + "version": "unreleased", + "spine": [ + "/administration-guide/administration-guide-index", + "/administration-guide/cloud-workspace-management", + "/administration-guide/compliance-with-mattermost", + "/administration-guide/upgrade-mattermost", + "/administration-guide/comply/compliance-export", + "/administration-guide/comply/custom-terms-of-service", + "/administration-guide/comply/data-retention-policy", + "/administration-guide/comply/electronic-discovery", + "/administration-guide/comply/export-mattermost-channel-data", + "/administration-guide/comply/legal-hold", + "/administration-guide/configure/agents-admin-guide", + "/administration-guide/configure/bleve-search", + "/administration-guide/configure/calls-deployment-guide", + "/administration-guide/configure/calls-kubernetes", + "/administration-guide/configure/calls-logging", + "/administration-guide/configure/calls-offloader-setup", + "/administration-guide/configure/cloud-billing-account-settings", + "/administration-guide/configure/configuration-in-your-database", + "/administration-guide/configure/configuration-settings", + "/administration-guide/configure/custom-branding-tools", + "/administration-guide/configure/customize-mattermost", + "/administration-guide/configure/enabling-chinese-japanese-korean-search", + "/administration-guide/configure/environment-variables", + "/administration-guide/configure/install-boards", + "/administration-guide/configure/manage-user-surveys", + "/administration-guide/configure/self-hosted-account-settings", + "/administration-guide/configure/smtp-email", + "/administration-guide/configure/system-attributes", + "/administration-guide/manage/cloud-byok", + "/administration-guide/manage/cloud-data-residency", + "/administration-guide/manage/cloud-ip-filtering", + "/administration-guide/manage/code-signing-custom-builds", + "/administration-guide/manage/command-line-tools", + "/administration-guide/manage/configure-health-check-probes", + "/administration-guide/manage/feature-labels", + "/administration-guide/manage/in-product-notices", + "/administration-guide/manage/mmctl-command-line-tool", + "/administration-guide/manage/product-limits", + "/administration-guide/manage/request-server-health-check", + "/administration-guide/manage/statistics", + "/administration-guide/manage/system-wide-notifications", + "/administration-guide/manage/team-channel-members", + "/administration-guide/manage/telemetry", + "/administration-guide/manage/user-satisfaction-surveys", + "/administration-guide/manage/admin/abac-channel-access-rules", + "/administration-guide/manage/admin/abac-system-wide-policies", + "/administration-guide/manage/admin/attribute-based-access-control", + "/administration-guide/manage/admin/autotranslation", + "/administration-guide/manage/admin/content-flagging", + "/administration-guide/manage/admin/customize-branding", + "/administration-guide/manage/admin/error-codes", + "/administration-guide/manage/admin/installing-license-key", + "/administration-guide/manage/admin/migration", + "/administration-guide/manage/admin/monitoring-and-performance", + "/administration-guide/manage/admin/self-hosted-billing", + "/administration-guide/manage/admin/server-configuration", + "/administration-guide/manage/admin/server-maintenance", + "/administration-guide/manage/admin/user-attributes", + "/administration-guide/manage/admin/user-management", + "/administration-guide/manage/admin/user-provisioning", + "/administration-guide/onboard/ad-ldap", + "/administration-guide/onboard/advanced-permissions", + "/administration-guide/onboard/certificate-based-authentication", + "/administration-guide/onboard/common-converting-oauth-to-openidconnect", + "/administration-guide/onboard/connected-workspaces", + "/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect", + "/administration-guide/onboard/guest-accounts", + "/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups", + "/administration-guide/onboard/migrate-from-slack", + "/administration-guide/onboard/migrate-gitlab-omnibus", + "/administration-guide/onboard/migrating-to-mattermost", + "/administration-guide/onboard/migration-announcement-email", + "/administration-guide/onboard/multi-factor-authentication", + "/administration-guide/onboard/ssl-client-certificate", + "/administration-guide/onboard/sso-entraid", + "/administration-guide/onboard/sso-gitlab", + "/administration-guide/onboard/sso-google", + "/administration-guide/onboard/sso-openidconnect", + "/administration-guide/onboard/sso-saml-adfs-msws2016", + "/administration-guide/onboard/sso-saml-adfs", + "/administration-guide/onboard/sso-saml-before-you-begin", + "/administration-guide/onboard/sso-saml-entraid", + "/administration-guide/onboard/sso-saml-faq", + "/administration-guide/onboard/sso-saml-keycloak", + "/administration-guide/onboard/sso-saml-ldapsync", + "/administration-guide/onboard/sso-saml-okta", + "/administration-guide/onboard/sso-saml-technical", + "/administration-guide/onboard/sso-saml", + "/administration-guide/onboard/user-provisioning-workflows", + "/administration-guide/scale/additional-ha-considerations", + "/administration-guide/scale/collect-performance-metrics", + "/administration-guide/scale/common-configure-mattermost-for-enterprise-search", + "/administration-guide/scale/deploy-grafana-loki-for-centralized-logging", + "/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring", + "/administration-guide/scale/elasticsearch-setup", + "/administration-guide/scale/ensuring-releases-perform-at-scale", + "/administration-guide/scale/enterprise-search", + "/administration-guide/scale/estimated-storage-per-user-per-month", + "/administration-guide/scale/high-availability-cluster-based-deployment", + "/administration-guide/scale/lifetime-storage", + "/administration-guide/scale/opensearch-setup", + "/administration-guide/scale/performance-alerting", + "/administration-guide/scale/performance-monitoring-metrics", + "/administration-guide/scale/push-notification-health-targets", + "/administration-guide/scale/redis", + "/administration-guide/scale/scale-to-100000-users", + "/administration-guide/scale/scale-to-15000-users", + "/administration-guide/scale/scale-to-200-users", + "/administration-guide/scale/scale-to-2000-users", + "/administration-guide/scale/scale-to-200000-users", + "/administration-guide/scale/scale-to-30000-users", + "/administration-guide/scale/scale-to-50000-users", + "/administration-guide/scale/scale-to-80000-users", + "/administration-guide/scale/scale-to-90000-users", + "/administration-guide/scale/scaling-for-enterprise", + "/administration-guide/scale/server-architecture", + "/administration-guide/upgrade/admin-onboarding-tasks", + "/administration-guide/upgrade/communicate-scheduled-maintenance", + "/administration-guide/upgrade/downgrading-mattermost-server", + "/administration-guide/upgrade/enterprise-install-upgrade", + "/administration-guide/upgrade/enterprise-roll-out-checklist", + "/administration-guide/upgrade/notify-admin", + "/administration-guide/upgrade/open-source-components", + "/administration-guide/upgrade/prepare-to-upgrade-mattermost", + "/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha", + "/administration-guide/upgrade/upgrading-mattermost-server", + "/administration-guide/upgrade/upgrading-postgres", + "/administration-guide/upgrade/welcome-email-to-end-users" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/api.json b/docs/pdf/books/api.json new file mode 100644 index 000000000000..f876826e1032 --- /dev/null +++ b/docs/pdf/books/api.json @@ -0,0 +1,22 @@ +{ + "title": "Mattermost API", + "subtitle": "REST API v4 — every endpoint, generated from the canonical OpenAPI specification.", + "eyebrow": "API REFERENCE", + "version": "v4", + "spine": [ + "/api/", + "/api/examples", + "/api/reference/login", + "/api/reference/create-user", + "/api/reference/get-users", + "/api/reference/create-channel", + "/api/reference/add-channel-member", + "/api/reference/get-channels-for-team", + "/api/reference/create-post", + "/api/reference/get-post", + "/api/reference/update-post", + "/api/reference/delete-post", + "/api/reference/upload-file", + "/api/reference/save-reaction" + ] +} diff --git a/docs/pdf/books/deployment-guide.json b/docs/pdf/books/deployment-guide.json new file mode 100644 index 000000000000..002672436800 --- /dev/null +++ b/docs/pdf/books/deployment-guide.json @@ -0,0 +1,72 @@ +{ + "title": "Mattermost Deployment Guide", + "subtitle": "Plan, provision, and ship a production Mattermost deployment.", + "eyebrow": "DEPLOYMENT", + "version": "unreleased", + "spine": [ + "/deployment-guide/deployment-guide-index", + "/deployment-guide/quick-start-evaluation", + "/deployment-guide/reference-architecture/deployment-scenarios/deployment-scenarios-index", + "/deployment-guide/reference-architecture/deployment-scenarios/air-gapped-deployment", + "/deployment-guide/reference-architecture/deployment-scenarios/deploy-ddil-operations", + "/deployment-guide/reference-architecture/deployment-scenarios/deploy-mission-partner", + "/deployment-guide/reference-architecture/deployment-scenarios/deploy-oob", + "/deployment-guide/reference-architecture/deployment-scenarios/deploy-sovereign-collaboration", + "/deployment-guide/server/server-deployment-planning", + "/deployment-guide/reference-architecture/application-architecture", + "/deployment-guide/software-hardware-requirements", + "/deployment-guide/server/preparations", + "/deployment-guide/server/orchestration", + "/deployment-guide/server/deploy-linux", + "/deployment-guide/server/linux/deploy-ubuntu", + "/deployment-guide/server/linux/deploy-rhel", + "/deployment-guide/server/linux/deploy-tar", + "/deployment-guide/server/deploy-kubernetes", + "/deployment-guide/server/kubernetes/deploy-k8s", + "/deployment-guide/server/kubernetes/deploy-k8s-aks", + "/deployment-guide/server/kubernetes/deploy-k8s-oke", + "/deployment-guide/server/deploy-containers", + "/deployment-guide/server/containers/install-docker", + "/deployment-guide/server/containers/fips-stig", + "/deployment-guide/server/configure-fips-at-install-time", + "/deployment-guide/server/setup-nginx-proxy", + "/deployment-guide/server/setup-tls", + "/deployment-guide/server/pre-authentication-secrets", + "/deployment-guide/server/image-proxy", + "/deployment-guide/server/prepare-mattermost-mysql-database", + "/deployment-guide/desktop/desktop-app-deployment", + "/deployment-guide/desktop/desktop-app-managed-resources", + "/deployment-guide/desktop/desktop-custom-dictionaries", + "/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install", + "/deployment-guide/desktop/desktop-troubleshooting", + "/deployment-guide/desktop/distribute-a-custom-desktop-app", + "/deployment-guide/desktop/linux-desktop-install", + "/deployment-guide/desktop/silent-windows-desktop-distribution", + "/deployment-guide/mobile/consider-mobile-vpn-options", + "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider", + "/deployment-guide/mobile/distribute-custom-mobile-apps", + "/deployment-guide/mobile/host-your-own-push-proxy-service", + "/deployment-guide/mobile/mobile-app-deployment", + "/deployment-guide/mobile/mobile-faq", + "/deployment-guide/mobile/mobile-security-features", + "/deployment-guide/mobile/mobile-troubleshooting", + "/deployment-guide/mobile/secure-mobile-file-storage", + "/deployment-guide/air-gapped-operations/index", + "/deployment-guide/air-gapped-operations/quick-start-runbook", + "/deployment-guide/air-gapped-operations/mirror-package-repositories", + "/deployment-guide/air-gapped-operations/offline-license-activation", + "/deployment-guide/air-gapped-operations/disable-phone-home-features", + "/deployment-guide/backup-disaster-recovery", + "/deployment-guide/disaster-recovery-aws", + "/deployment-guide/postgres-migration", + "/deployment-guide/postgres-migration-assist-tool", + "/deployment-guide/manual-postgres-migration", + "/deployment-guide/encryption-options", + "/deployment-guide/transport-encryption", + "/deployment-guide/deployment-troubleshooting", + "/deployment-guide/server/troubleshooting", + "/deployment-guide/server/docker-troubleshooting", + "/deployment-guide/server/trouble_mysql", + "/deployment-guide/server/trouble-postgres" + ] +} diff --git a/docs/pdf/books/end-user-guide.json b/docs/pdf/books/end-user-guide.json new file mode 100644 index 000000000000..28f09921b2b4 --- /dev/null +++ b/docs/pdf/books/end-user-guide.json @@ -0,0 +1,94 @@ +{ + "title": "Mattermost End User Guide", + "subtitle": "Everything users need to know to collaborate in Mattermost.", + "eyebrow": "END USER GUIDE", + "version": "unreleased", + "spine": [ + "/end-user-guide/agents", + "/end-user-guide/end-user-guide-index", + "/end-user-guide/messaging-collaboration", + "/end-user-guide/preferences", + "/end-user-guide/project-task-management", + "/end-user-guide/workflow-automation", + "/end-user-guide/access/access-your-workspace", + "/end-user-guide/access/install-android-app", + "/end-user-guide/access/install-desktop-app", + "/end-user-guide/access/install-ios-app", + "/end-user-guide/access/log-out", + "/end-user-guide/collaborate/agents-context-management", + "/end-user-guide/collaborate/archive-unarchive-channels", + "/end-user-guide/collaborate/audio-and-screensharing", + "/end-user-guide/collaborate/autotranslate-messages", + "/end-user-guide/collaborate/browse-channels", + "/end-user-guide/collaborate/channel-header-purpose", + "/end-user-guide/collaborate/channel-naming-conventions", + "/end-user-guide/collaborate/channel-types", + "/end-user-guide/collaborate/collaborate-within-channels", + "/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams", + "/end-user-guide/collaborate/communicate-with-messages", + "/end-user-guide/collaborate/convert-group-messages", + "/end-user-guide/collaborate/convert-public-channels", + "/end-user-guide/collaborate/create-channels", + "/end-user-guide/collaborate/display-channel-banners", + "/end-user-guide/collaborate/extend-mattermost-with-integrations", + "/end-user-guide/collaborate/favorite-channels", + "/end-user-guide/collaborate/flag-messages", + "/end-user-guide/collaborate/forward-messages", + "/end-user-guide/collaborate/invite-people", + "/end-user-guide/collaborate/join-leave-channels", + "/end-user-guide/collaborate/learn-about-roles", + "/end-user-guide/collaborate/manage-channel-bookmarks", + "/end-user-guide/collaborate/manage-channel-members", + "/end-user-guide/collaborate/mark-channels-unread", + "/end-user-guide/collaborate/mark-messages-unread", + "/end-user-guide/collaborate/mention-people", + "/end-user-guide/collaborate/message-priority", + "/end-user-guide/collaborate/message-reminders", + "/end-user-guide/collaborate/navigate-between-channels", + "/end-user-guide/collaborate/organize-conversations", + "/end-user-guide/collaborate/organize-using-custom-user-groups", + "/end-user-guide/collaborate/organize-using-teams", + "/end-user-guide/collaborate/react-with-emojis-gifs", + "/end-user-guide/collaborate/rename-channels", + "/end-user-guide/collaborate/reply-to-messages", + "/end-user-guide/collaborate/save-pin-messages", + "/end-user-guide/collaborate/schedule-messages", + "/end-user-guide/collaborate/search-for-messages", + "/end-user-guide/collaborate/send-messages", + "/end-user-guide/collaborate/share-files-in-messages", + "/end-user-guide/collaborate/share-links", + "/end-user-guide/collaborate/team-settings", + "/end-user-guide/collaborate/view-system-information", + "/end-user-guide/preferences/connect-multiple-workspaces", + "/end-user-guide/preferences/customize-desktop-app-experience", + "/end-user-guide/preferences/customize-your-channel-sidebar", + "/end-user-guide/preferences/customize-your-theme", + "/end-user-guide/preferences/manage-advanced-options", + "/end-user-guide/preferences/manage-your-channel-specific-notifications", + "/end-user-guide/preferences/manage-your-desktop-notifications", + "/end-user-guide/preferences/manage-your-display-options", + "/end-user-guide/preferences/manage-your-mentions-keywords-notifications", + "/end-user-guide/preferences/manage-your-mobile-notifications", + "/end-user-guide/preferences/manage-your-plugin-preferences", + "/end-user-guide/preferences/manage-your-sidebar-options", + "/end-user-guide/preferences/manage-your-thread-reply-notifications", + "/end-user-guide/preferences/manage-your-web-notifications", + "/end-user-guide/preferences/troubleshoot-notifications", + "/end-user-guide/project-management/boards-settings", + "/end-user-guide/project-management/calculations", + "/end-user-guide/project-management/groups-filter-sort", + "/end-user-guide/project-management/migrate-to-boards", + "/end-user-guide/project-management/navigate-boards", + "/end-user-guide/project-management/work-with-boards", + "/end-user-guide/project-management/work-with-cards", + "/end-user-guide/project-management/work-with-views", + "/end-user-guide/workflow-automation/interact-with-playbooks", + "/end-user-guide/workflow-automation/learn-about-playbooks", + "/end-user-guide/workflow-automation/metrics-and-goals", + "/end-user-guide/workflow-automation/notifications-and-updates", + "/end-user-guide/workflow-automation/share-and-collaborate", + "/end-user-guide/workflow-automation/work-with-playbooks", + "/end-user-guide/workflow-automation/work-with-runs", + "/end-user-guide/workflow-automation/work-with-tasks" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/get-help.json b/docs/pdf/books/get-help.json new file mode 100644 index 000000000000..c3b89be5a6bc --- /dev/null +++ b/docs/pdf/books/get-help.json @@ -0,0 +1,12 @@ +{ + "title": "Mattermost Get Help", + "subtitle": "Channels for help, escalation, and feedback.", + "eyebrow": "SUPPORT", + "version": "unreleased", + "spine": [ + "/get-help/community-chat", + "/get-help/community-for-mattermost", + "/get-help/contribute-to-documentation", + "/get-help/get-help-index" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/integrations-guide.json b/docs/pdf/books/integrations-guide.json new file mode 100644 index 000000000000..a3cbffce9493 --- /dev/null +++ b/docs/pdf/books/integrations-guide.json @@ -0,0 +1,28 @@ +{ + "title": "Mattermost Integrations Guide", + "subtitle": "Bring your tools into Mattermost — from webhooks to platform plugins.", + "eyebrow": "INTEGRATIONS", + "version": "unreleased", + "spine": [ + "/integrations-guide/built-in-slash-commands", + "/integrations-guide/faq", + "/integrations-guide/github", + "/integrations-guide/gitlab", + "/integrations-guide/incoming-webhooks", + "/integrations-guide/integrations-guide-index", + "/integrations-guide/jira", + "/integrations-guide/mattermost-mission-collaboration-for-m365", + "/integrations-guide/microsoft-calendar", + "/integrations-guide/microsoft-teams-meetings", + "/integrations-guide/microsoft-teams-sync", + "/integrations-guide/no-code-automation", + "/integrations-guide/outgoing-webhooks", + "/integrations-guide/plugins", + "/integrations-guide/restful-api", + "/integrations-guide/run-slash-commands", + "/integrations-guide/servicenow", + "/integrations-guide/slash-commands", + "/integrations-guide/webhook-integrations", + "/integrations-guide/zoom" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/product-overview.json b/docs/pdf/books/product-overview.json new file mode 100644 index 000000000000..42b4d4a58731 --- /dev/null +++ b/docs/pdf/books/product-overview.json @@ -0,0 +1,43 @@ +{ + "title": "Mattermost Product Overview", + "subtitle": "Editions, plans, releases, and the platform at a glance.", + "eyebrow": "PRODUCT OVERVIEW", + "version": "unreleased", + "spine": [ + "/product-overview/accessibility-compliance-policy", + "/product-overview/cloud-dedicated", + "/product-overview/cloud-shared", + "/product-overview/cloud-supported-integrations", + "/product-overview/cloud-vpc-private-connectivity", + "/product-overview/common-esr-support-rst", + "/product-overview/common-esr-support-upgrade", + "/product-overview/common-esr-support", + "/product-overview/corporate-directory-integration", + "/product-overview/deprecated-features", + "/product-overview/desktop-app-changelog", + "/product-overview/desktop", + "/product-overview/editions-and-offerings", + "/product-overview/faq-enterprise", + "/product-overview/faq-federal-procurement", + "/product-overview/faq-general", + "/product-overview/faq-mattermost-source-available-license", + "/product-overview/frequently-asked-questions", + "/product-overview/mattermost-desktop-releases", + "/product-overview/mattermost-mobile-releases", + "/product-overview/mattermost-server-releases", + "/product-overview/mattermost-v10-changelog", + "/product-overview/mattermost-v11-changelog", + "/product-overview/mobile-app-changelog", + "/product-overview/mobile", + "/product-overview/non-profit-subscriptions", + "/product-overview/product-overview-index", + "/product-overview/release-policy", + "/product-overview/releases-lifecycle", + "/product-overview/self-hosted-subscriptions", + "/product-overview/server", + "/product-overview/subscription", + "/product-overview/ui-ada-changelog", + "/product-overview/unsupported-legacy-releases", + "/product-overview/version-archive" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/security-guide.json b/docs/pdf/books/security-guide.json new file mode 100644 index 000000000000..6ff263df5849 --- /dev/null +++ b/docs/pdf/books/security-guide.json @@ -0,0 +1,16 @@ +{ + "title": "Mattermost Security Guide", + "subtitle": "Security architecture, threat model, and hardening guidance.", + "eyebrow": "SECURITY", + "version": "unreleased", + "spine": [ + "/security-guide/cmmc-compliance", + "/security-guide/dependency-vulnerability-analysis", + "/security-guide/finra-compliance", + "/security-guide/hipaa-compliance", + "/security-guide/mobile-security", + "/security-guide/secure-mattermost", + "/security-guide/security-guide-index", + "/security-guide/zero-trust" + ] +} \ No newline at end of file diff --git a/docs/pdf/books/use-case-guide.json b/docs/pdf/books/use-case-guide.json new file mode 100644 index 000000000000..395a8c0f8728 --- /dev/null +++ b/docs/pdf/books/use-case-guide.json @@ -0,0 +1,18 @@ +{ + "title": "Mattermost Use Case Guide", + "subtitle": "Mission-critical scenarios served by Mattermost.", + "eyebrow": "USE CASES", + "version": "unreleased", + "spine": [ + "/use-case-guide/devops-collaboration", + "/use-case-guide/integrated-security-operations", + "/use-case-guide/maximize-microsoft-investments", + "/use-case-guide/mission-ready-mobile", + "/use-case-guide/on-prem-skype-for-business-replacement", + "/use-case-guide/out-of-band-incident-response", + "/use-case-guide/purpose-built-collaboration", + "/use-case-guide/secure-command-and-control", + "/use-case-guide/self-sovereign-collaboration", + "/use-case-guide/use-cases-index" + ] +} \ No newline at end of file diff --git a/docs/pdf/package-lock.json b/docs/pdf/package-lock.json new file mode 100644 index 000000000000..f0ad6ba8ee7a --- /dev/null +++ b/docs/pdf/package-lock.json @@ -0,0 +1,1137 @@ +{ + "name": "pdf", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pdf", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "puppeteer": "^24.43.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.1.tgz", + "integrity": "sha512-zmS4RTK9fbrc++WlAJhxYbfz3IjDeOmkK/CwwbLmk7ydfS9e2CiEeRJHEPvjDVElO/bwXbidwGA37Bsm6LzCnQ==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.3", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.4", + "tar-fs": "^3.1.1", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", + "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~7.19.0" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.1.tgz", + "integrity": "sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz", + "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz", + "integrity": "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==", + "license": "Apache-2.0", + "dependencies": { + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.3.tgz", + "integrity": "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chromium-bidi": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz", + "integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1608973", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz", + "integrity": "sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ==", + "license": "BSD-3-Clause" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "24.43.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.43.0.tgz", + "integrity": "sha512-DRnMFz+J3s4lFUQcjqKl0/7h0jzlCZuUFU9lNjtKrnMl5WI1RwCaIItpHVu9empuPyUreYueN0sUW3/pnfdqsg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.13.1", + "chromium-bidi": "14.0.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1608973", + "puppeteer-core": "24.43.0", + "typed-query-selector": "^2.12.2" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "24.43.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.43.0.tgz", + "integrity": "sha512-cCRNXsUlhyPoKDz6+TiSpfZpRS3mD6Y1YFKhkdr6ik6TMfuJb7fAtXq9ThUFc4sphxObDk3BuAvdxc1Y6YOnqQ==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.13.1", + "chromium-bidi": "14.0.0", + "debug": "^4.4.3", + "devtools-protocol": "0.0.1608973", + "typed-query-selector": "^2.12.2", + "webdriver-bidi-protocol": "0.4.1", + "ws": "^8.20.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz", + "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamx": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", + "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", + "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", + "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typed-query-selector": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", + "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "license": "MIT", + "optional": true + }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", + "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/docs/pdf/package.json b/docs/pdf/package.json new file mode 100644 index 000000000000..d4ae376091ab --- /dev/null +++ b/docs/pdf/package.json @@ -0,0 +1,15 @@ +{ + "name": "pdf", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "puppeteer": "^24.43.0" + } +} diff --git a/docs/pdf/scripts/build-book-pdf.mjs b/docs/pdf/scripts/build-book-pdf.mjs new file mode 100644 index 000000000000..3d944beb4812 --- /dev/null +++ b/docs/pdf/scripts/build-book-pdf.mjs @@ -0,0 +1,215 @@ +#!/usr/bin/env node +/* + * Concatenate a section's pages into a single book PDF. + * + * Strategy: + * 1. Load the configured "spine" (an ordered list of URLs to include). + * 2. For each URL, fetch via Puppeteer and pull out just the article + * content (.theme-doc-markdown). + * 3. Inject a brand-aligned cover page at the top. + * 4. Inject the concatenated content into a single static HTML page. + * 5. Apply the print CSS, render to PDF. + * + * For Mattermost API v4, the spine is generated from the OpenAPI tags + * — overview + examples + each tag's landing + each endpoint within. + * For a smaller demo, the API "Overview" + "Examples" + the first + * tag's endpoints is a reasonable target. + * + * Usage: + * node pdf/scripts/build-book-pdf.mjs --book api # default + * node pdf/scripts/build-book-pdf.mjs --book api --base http://localhost:3000 + * + * Configurable via pdf/books/.json — see pdf/books/api.json. + */ + +import puppeteer from 'puppeteer'; +import {readFileSync, mkdirSync, statSync} from 'node:fs'; +import {dirname, resolve} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const PDF_ROOT = resolve(HERE, '..'); + +function arg(name, fallback) { + const i = process.argv.indexOf(`--${name}`); + if (i === -1) return fallback; + return process.argv[i + 1] ?? fallback; +} + +function loadSpine(book) { + const path = resolve(PDF_ROOT, 'books', `${book}.json`); + const cfg = JSON.parse(readFileSync(path, 'utf8')); + return cfg; +} + +function coverHtml(cfg) { + const buildDate = new Date().toISOString().slice(0, 10); + return ` +
+
+
${cfg.eyebrow}
+

${cfg.title}

+
${cfg.subtitle}
+
+
+
${cfg.version} · ${buildDate}
+
Mission in Motion
+
+
+ `; +} + +async function fetchArticle(page, url, index) { + await page.goto(url, {waitUntil: 'networkidle0', timeout: 60_000}); + await page.evaluateHandle('document.fonts.ready'); + // Pull just the article body so the book doesn't carry navbar / sidebar / footer. + // Also extract heading metadata so the book builder can compose a ToC. + return page.evaluate((idx) => { + const article = document.querySelector('article') || document.querySelector('.theme-doc-markdown'); + if (!article) { + return {html: '', title: 'Untitled', subsections: []}; + } + const clone = article.cloneNode(true); + const chapterId = `mm-chapter-${idx}`; + clone.setAttribute('id', chapterId); + const h1 = clone.querySelector('h1'); + const title = (h1 && h1.textContent.trim()) || document.title || 'Untitled'; + // Anchor the H1 itself so the ToC entry jumps to the start of the chapter. + if (h1 && !h1.id) h1.id = chapterId + '-title'; + const subsections = Array.from(clone.querySelectorAll('h2')).map((h, i) => { + if (!h.id) h.id = `${chapterId}-h2-${i}`; + return {text: h.textContent.trim().replace(/​/g, ''), id: h.id}; + }); + return {html: clone.outerHTML, title, subsections}; + }, index); +} + +function escapeHtml(s) { + return String(s).replace(/[&<>"']/g, (c) => ({'&': '&', '<': '<', '>': '>', '"': '"', "'": '''}[c])); +} + +function tocHtml(articles) { + const items = articles.map((a, i) => { + const sub = a.subsections.length + ? `
    ${a.subsections + .map((s) => `
  1. ${escapeHtml(s.text)}
  2. `) + .join('')}
` + : ''; + return `
  • + + ${String(i + 1).padStart(2, '0')} + ${escapeHtml(a.title)} + + + + ${sub} +
  • `; + }).join(''); + return ` +
    +
    +
    Contents
    +

    Table of Contents

    +
    +
      ${items}
    +
    + `; +} + +async function main() { + const bookName = arg('book', 'api'); + const base = arg('base', 'http://localhost:3000'); + const output = arg('out', resolve(PDF_ROOT, 'build', `mattermost-${bookName}.pdf`)); + + const cfg = loadSpine(bookName); + console.log(`[book] ${cfg.title} · ${cfg.spine.length} pages from ${base}`); + + const printCss = readFileSync(resolve(PDF_ROOT, 'styles', 'print.css'), 'utf8'); + mkdirSync(dirname(resolve(output)), {recursive: true}); + + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--font-render-hinting=none'], + }); + + try { + const fetcher = await browser.newPage(); + fetcher.on('pageerror', (e) => console.error(`[book:browser-error] ${e.message}`)); + + const articles = []; + for (let i = 0; i < cfg.spine.length; i++) { + const path = cfg.spine[i]; + const url = base + path; + console.log(`[book] ${path}`); + articles.push(await fetchArticle(fetcher, url, i)); + } + + // Compose the book document. We let Docusaurus's built CSS load too + // (so MDX components keep their layout); the print CSS overrides + // what's needed for paper. + const stylesUrl = `${base}/assets/css/styles.css`; + const htmlPath = resolve(PDF_ROOT, 'build', `${bookName}-book.html`); + const html = ` + + + + ${cfg.title} + + + + + + ${coverHtml(cfg)} + ${tocHtml(articles)} + ${articles.map((a) => a.html).join('\n
    \n')} + +`; + const fs = await import('node:fs/promises'); + await fs.writeFile(htmlPath, html); + + const printer = await browser.newPage(); + printer.on('console', (m) => { + if (m.type() === 'error') console.error(`[book:browser-error] ${m.text()}`); + }); + await printer.goto(`file://${htmlPath}`, {waitUntil: 'networkidle0'}); + await printer.emulateMediaType('print'); + await printer.evaluateHandle('document.fonts.ready'); + + // Rewrite the OpenAPI dev-server URL prefix to a generic example + // so the printed reference doesn't carry "http://localhost:8065" + // through to readers. This applies only to print captures; the + // live dev site keeps the localhost default for "Send API Request" + // testing convenience. + await printer.evaluate(() => { + const REPLACEMENT = 'https://your-mattermost-server.com'; + const PATTERN = /https?:\/\/localhost:\d+/g; + const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); + let n; + while ((n = walker.nextNode())) { + if (n.nodeValue && PATTERN.test(n.nodeValue)) { + n.nodeValue = n.nodeValue.replace(PATTERN, REPLACEMENT); + } + } + }); + + console.log(`[book] rendering → ${output}`); + await printer.pdf({ + path: resolve(output), + format: 'A4', + printBackground: true, + preferCSSPageSize: true, + displayHeaderFooter: false, + }); + + const {size} = statSync(resolve(output)); + const pages = Math.ceil(size / 25_000); // very rough estimate — replace with PDF probe later + console.log(`[book] done — ${(size / 1024).toFixed(1)} KB (~${pages} pages estimated)`); + } finally { + await browser.close(); + } +} + +main().catch((e) => { + console.error('[book] fatal:', e); + process.exit(1); +}); diff --git a/docs/pdf/scripts/build-page-pdf.mjs b/docs/pdf/scripts/build-page-pdf.mjs new file mode 100644 index 000000000000..0e9f4775b274 --- /dev/null +++ b/docs/pdf/scripts/build-page-pdf.mjs @@ -0,0 +1,75 @@ +#!/usr/bin/env node +/* + * Capture a single docs page to PDF, applying the brand-aligned print + * stylesheet. Used both for on-demand single-page PDF (the per-page + * "Download PDF" button) and as the unit primitive that the book + * builder concatenates. + * + * Usage: + * node pdf/scripts/build-page-pdf.mjs + * node pdf/scripts/build-page-pdf.mjs http://localhost:3000/api pdf/build/api-overview.pdf + * + * Pre-req: the docs site is built (npm run build) and being served + * either by `npm run serve` or some other static server. Pass the URL + * the page is reachable at. + */ + +import puppeteer from 'puppeteer'; +import {readFileSync, mkdirSync, existsSync} from 'node:fs'; +import {dirname, resolve} from 'node:path'; + +async function main() { + const [url, output] = process.argv.slice(2); + if (!url || !output) { + console.error('usage: build-page-pdf.mjs '); + process.exit(2); + } + + const printCss = readFileSync(new URL('../styles/print.css', import.meta.url), 'utf8'); + mkdirSync(dirname(resolve(output)), {recursive: true}); + + console.log(`[pdf] launching headless Chromium…`); + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--font-render-hinting=none'], + }); + + try { + const page = await browser.newPage(); + page.on('console', (m) => console.log(`[pdf:browser] ${m.type()}: ${m.text()}`)); + page.on('pageerror', (e) => console.error(`[pdf:browser-error] ${e.message}`)); + + console.log(`[pdf] loading ${url}`); + await page.goto(url, {waitUntil: 'networkidle0', timeout: 60_000}); + + // Apply the print stylesheet (so it lays out for paper while still + // running with media:screen — works around quirks where some + // Docusaurus chrome only renders for screen). + await page.addStyleTag({content: printCss}); + await page.emulateMediaType('print'); + + // Give web fonts time to settle so headlines don't fall back. + await page.evaluateHandle('document.fonts.ready'); + + console.log(`[pdf] rendering PDF → ${output}`); + await page.pdf({ + path: resolve(output), + format: 'A4', + printBackground: true, + preferCSSPageSize: true, + margin: {top: '22mm', right: '18mm', bottom: '24mm', left: '18mm'}, + displayHeaderFooter: false, // headers/footers come from @page in print.css + }); + + const fs = await import('node:fs/promises'); + const {size} = await fs.stat(resolve(output)); + console.log(`[pdf] done — ${(size / 1024).toFixed(1)} KB`); + } finally { + await browser.close(); + } +} + +main().catch((e) => { + console.error('[pdf] fatal:', e); + process.exit(1); +}); diff --git a/docs/pdf/scripts/gen-main-docs-books.mjs b/docs/pdf/scripts/gen-main-docs-books.mjs new file mode 100644 index 000000000000..399572690ae2 --- /dev/null +++ b/docs/pdf/scripts/gen-main-docs-books.mjs @@ -0,0 +1,124 @@ +#!/usr/bin/env node +// Generate book spines for each main-docs section from the Documentation +// sidebar config. One JSON per section under pdf/books/, consumable by +// build-book-pdf.mjs. +// +// Sources: +// docs-site/sidebars/documentation.generated.json (already authoritative) +// +// Outputs: +// pdf/books/product-overview.json +// pdf/books/use-case-guide.json +// ... etc. (one per top-level section that exists) +// +// Usage: node pdf/scripts/gen-main-docs-books.mjs + +import {readFileSync, writeFileSync, mkdirSync} from 'node:fs'; +import {resolve, dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const PDF_ROOT = resolve(HERE, '..'); +const REPO_ROOT = resolve(PDF_ROOT, '..'); +const SIDEBAR = resolve(REPO_ROOT, 'docs-site/sidebars/documentation.generated.json'); +const BOOKS_DIR = resolve(PDF_ROOT, 'books'); + +// Mapping from sidebar category label → book metadata (eyebrow/version). +// The label must match the top-level category's `label` in the sidebar JSON. +const BOOK_META = { + 'Product Overview': { + file: 'product-overview', + eyebrow: 'PRODUCT OVERVIEW', + subtitle: 'Editions, plans, releases, and the platform at a glance.', + }, + 'Use Case Guide': { + file: 'use-case-guide', + eyebrow: 'USE CASES', + subtitle: 'Mission-critical scenarios served by Mattermost.', + }, + 'Deployment Guide': { + file: 'deployment-guide', + eyebrow: 'DEPLOYMENT', + subtitle: 'Plan, provision, and ship a production Mattermost deployment.', + }, + 'Administration Guide': { + file: 'administration-guide', + eyebrow: 'ADMINISTRATION', + subtitle: 'Configure, manage, scale, secure, and comply.', + }, + 'Security Guide': { + file: 'security-guide', + eyebrow: 'SECURITY', + subtitle: 'Security architecture, threat model, and hardening guidance.', + }, + 'End User Guide': { + file: 'end-user-guide', + eyebrow: 'END USER GUIDE', + subtitle: 'Everything users need to know to collaborate in Mattermost.', + }, + 'Integrations Guide': { + file: 'integrations-guide', + eyebrow: 'INTEGRATIONS', + subtitle: 'Bring your tools into Mattermost — from webhooks to platform plugins.', + }, + 'Get Help': { + file: 'get-help', + eyebrow: 'SUPPORT', + subtitle: 'Channels for help, escalation, and feedback.', + }, +}; + +function collectDocIds(node, out = []) { + if (!node) return out; + if (Array.isArray(node)) { node.forEach((n) => collectDocIds(n, out)); return out; } + if (node.type === 'doc') out.push(node.id); + if (node.type === 'category') { + // Prepend the category's link if it points at a doc (the IA's landing + // page for that branch — naturally first in print order). + if (node.link && node.link.type === 'doc') out.push(node.link.id); + if (node.items) collectDocIds(node.items, out); + } + return out; +} + +function spineFromCategory(cat) { + return collectDocIds(cat).map((id) => '/' + id.replace(/^\/+/, '')); +} + +function getVersion() { + // Try to read from a VERSION file or fall back to today's date. + try { + return readFileSync(resolve(REPO_ROOT, 'VERSION'), 'utf8').trim() || 'unreleased'; + } catch { + return 'unreleased'; + } +} + +function main() { + const sidebar = JSON.parse(readFileSync(SIDEBAR, 'utf8')); + mkdirSync(BOOKS_DIR, {recursive: true}); + const version = getVersion(); + + let written = 0; + for (const node of sidebar) { + if (node.type !== 'category') continue; + const meta = BOOK_META[node.label]; + if (!meta) continue; + const spine = spineFromCategory(node); + if (!spine.length) continue; + const config = { + title: `Mattermost ${node.label}`, + subtitle: meta.subtitle, + eyebrow: meta.eyebrow, + version, + spine, + }; + const out = resolve(BOOKS_DIR, `${meta.file}.json`); + writeFileSync(out, JSON.stringify(config, null, 2)); + console.log(`[book] ${out} (${spine.length} pages)`); + written++; + } + console.log(`\n[book] wrote ${written} book configs to ${BOOKS_DIR}`); +} + +main(); diff --git a/docs/pdf/styles/print.css b/docs/pdf/styles/print.css new file mode 100644 index 000000000000..2c59e16cac56 --- /dev/null +++ b/docs/pdf/styles/print.css @@ -0,0 +1,712 @@ +/* + * Print stylesheet for Mattermost docs PDF capture. + * + * Loaded by the PDF builder (pdf/scripts/build-*.mjs) via: + * page.addStyleTag({ path: 'pdf/styles/print.css' }) + * before printing. + * + * Why this lives here instead of docs-site/src/css: + * The docs site is media-screen first; print is a publishing artifact + * produced by a separate pipeline. Keeping the print CSS next to the + * PDF builder makes the dependency obvious and lets us iterate on + * pagination without touching the live site CSS. + * + * If you need to move it back into the docs site (e.g., to enable a + * "Download PDF" button that does in-browser print-preview), drop it + * into docs-site/src/css/ and add a `` reference. + */ + +/* ============================================================ + * @page rules + * ========================================================== */ + +@page { + size: A4; + margin: 22mm 18mm 24mm 18mm; + @bottom-left { content: "Mattermost · API v4"; font-family: 'Inter', system-ui, sans-serif; font-size: 8pt; color: #5B77B1; } + @bottom-right { content: counter(page) " / " counter(pages); font-family: 'Inter', system-ui, sans-serif; font-size: 8pt; color: #5B77B1; } + @top-right { content: string(chapter); font-family: 'Archivo Black', 'Trade Gothic Next Heavy', system-ui, sans-serif; font-size: 8pt; letter-spacing: 0.1em; text-transform: uppercase; color: #1E325C; } +} + +@page :first { + margin: 0; + @top-right { content: none; } + @bottom-left { content: none; } + @bottom-right { content: none; } +} + +/* ============================================================ + * Hide on print: non-content site chrome + * ========================================================== */ + +.navbar, +.theme-doc-sidebar-container, +.theme-doc-toc-mobile, +.theme-doc-toc-desktop, +.table-of-contents, +.theme-doc-breadcrumbs, +.theme-edit-this-page, +.pagination-nav, +.theme-back-to-top-button, +nav[aria-label="Breadcrumbs"], +.footer, +button[aria-label*="navigation"], +button[aria-label*="theme"], +.openapi-tabs__container, +.openapi-right-panel__container, +.mm-cta { + display: none !important; +} + +/* ============================================================ + * Article container — reset to print-friendly column + * ========================================================== */ + +html, body { + background: #FFFFFF !important; + color: #1B1D22 !important; + font-family: 'Inter', system-ui, -apple-system, sans-serif; + font-size: 10pt; + line-height: 1.55; +} + +main, +.docMainContainer_TBSr, +[class*='docMainContainer'], +.docItemContainer_Djhp, +[class*='docItemContainer'], +article, +.theme-doc-markdown { + display: block !important; + width: 100% !important; + max-width: none !important; + margin: 0 !important; + padding: 0 !important; + background: transparent !important; +} + +.theme-doc-markdown > * { max-width: none !important; } + +/* ============================================================ + * Headings — Trade Gothic Heavy in denim, with running-header binding + * ========================================================== */ + +h1, h2, h3, h4 { + font-family: 'Archivo Black', 'Trade Gothic Next Heavy', 'Helvetica Neue', system-ui, sans-serif; + color: #1E325C; + letter-spacing: -0.015em; + line-height: 1.1; + page-break-after: avoid; + break-after: avoid; +} + +h1 { + font-size: 26pt; + margin: 0 0 8pt; + padding-bottom: 6pt; + border-bottom: 2pt solid #FFBC1F; + string-set: chapter content(); /* feeds @top-right via @page */ + page-break-before: always; + break-before: page; +} + +h1:first-of-type { + page-break-before: avoid; + break-before: avoid; +} + +h2 { + font-size: 16pt; + margin: 18pt 0 6pt; + padding-top: 8pt; + border-top: 1pt solid #D6DDEC; +} + +h3 { font-size: 12pt; margin: 12pt 0 4pt; color: #182849; } +h4 { font-size: 10.5pt; margin: 10pt 0 3pt; color: #182849; text-transform: uppercase; letter-spacing: 0.06em; } + +/* ============================================================ + * Body type + * ========================================================== */ + +p, li { + orphans: 3; + widows: 3; +} +p { margin: 0 0 6pt; } +ul, ol { margin: 0 0 8pt 18pt; padding: 0; } +li { margin-bottom: 2pt; } + +a { + color: #1E325C; + text-decoration: underline; + text-underline-offset: 2px; +} + +strong, b { color: #182849; } + +/* ============================================================ + * Code blocks + * ========================================================== */ + +code { + background: #EEF1F8; + border: 0.5pt solid #D6DDEC; + border-radius: 2pt; + padding: 0.5pt 3pt; + font-family: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace; + font-size: 8.5pt; + color: #182849; +} + +pre, .theme-code-block { + background: #EEF1F8 !important; + border: 0.5pt solid #D6DDEC !important; + border-radius: 3pt; + padding: 8pt 10pt; + margin: 6pt 0 10pt; + font-size: 8.5pt; + line-height: 1.45; + overflow: visible !important; + white-space: pre-wrap; + word-break: break-word; + page-break-inside: avoid; + break-inside: avoid; +} + +pre code, .theme-code-block code { + background: transparent !important; + border: none !important; + padding: 0 !important; + color: #1B1D22; +} + +.copyButton, .clean-btn { display: none !important; } + +/* ============================================================ + * Tables + * ========================================================== */ + +table { + width: 100% !important; + border-collapse: collapse; + margin: 8pt 0 12pt; + page-break-inside: auto; + font-size: 9pt; +} +thead { background: #1E325C; color: #FFFFFF; } +thead th { + font-family: 'Archivo Black', 'Trade Gothic Next Heavy', system-ui, sans-serif; + font-size: 7.5pt; + letter-spacing: 0.08em; + text-transform: uppercase; + text-align: left; + padding: 5pt 7pt; + border: none !important; +} +tbody td { padding: 4pt 7pt; border-bottom: 0.4pt solid #D6DDEC; vertical-align: top; } +tbody tr:nth-child(even) { background: #F8FAFD; } +tbody tr { page-break-inside: avoid; } + +/* ============================================================ + * Branded MDX components + * ========================================================== */ + +/* Hero — flatten in print (no full-bleed band, no hex camo). The hero + * was a screen marketing surface; in print it just becomes a section + * intro. */ +.mm-hero { + background: transparent !important; + color: #1B1D22 !important; + padding: 0 !important; + margin: 0 0 8pt !important; + border: none !important; + border-bottom: 2pt solid #FFBC1F !important; +} +.mm-hero * { color: #1B1D22 !important; } +.mm-hero [class*="ctaPrimary"], +.mm-hero [class*="ctaGhost"] { display: none !important; } +.mm-hero [class*="pillars"] { border-top-color: #D6DDEC !important; } + +/* Eyebrow — use as a section marker. Stays small, marigold-bordered. */ +[class*="eyebrow"] { + display: inline-block; + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 7.5pt; + letter-spacing: 0.18em; + text-transform: uppercase; + color: #B27F00 !important; + border-bottom: 1pt solid #FFBC1F; + padding-bottom: 1pt; + margin-bottom: 6pt; +} + +/* Callouts — denim left bar + label, no shadow, page-break-avoid */ +[class*="callout"] { + border: 0.5pt solid #D6DDEC !important; + border-left: 4pt solid #1E325C !important; + border-radius: 2pt; + padding: 6pt 9pt; + margin: 6pt 0 10pt; + page-break-inside: avoid; + break-inside: avoid; + background: #F8FAFD; +} +[class*="callout"] [class*="bar"] { display: none !important; } +[class*="callout"] [class*="label"] { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 7.5pt; + letter-spacing: 0.16em; + text-transform: uppercase; + color: #1E325C; + margin-bottom: 3pt; +} + +/* StatStrip — wrap as a 4-up grid in print */ +[class*="strip"] { + display: grid !important; + grid-template-columns: repeat(4, 1fr); + gap: 6pt 12pt; + margin: 8pt 0 12pt; + padding: 8pt 0; + border-top: 1pt solid #FFBC1F; + border-bottom: 0.5pt solid #D6DDEC; + list-style: none !important; +} +[class*="strip"] [class*="stat"] { display: flex !important; flex-direction: column; } +[class*="strip"] [class*="value"] { font-family: 'Archivo Black', system-ui, sans-serif; font-size: 18pt; color: #1E325C; } +[class*="strip"] [class*="label"] { font-family: 'Archivo Black', system-ui, sans-serif; font-size: 7pt; letter-spacing: 0.16em; text-transform: uppercase; color: #5B77B1; margin-top: 2pt; } +[class*="strip"] [class*="hint"] { font-size: 7.5pt; color: #5B77B1; margin-top: 1pt; } + +/* MethodLegend — render flat in print */ +[class*="legend"] { + list-style: none; + padding: 0; + margin: 4pt 0 10pt; + display: flex; + flex-wrap: wrap; + gap: 4pt 10pt; + font-size: 8pt; +} +[class*="legend"] [class*="badge"] { + display: inline-block; + font-family: 'JetBrains Mono', monospace; + font-size: 7pt; + font-weight: 600; + padding: 1pt 4pt; + border-radius: 2pt; + color: #FFF; + margin-right: 3pt; +} + +/* CardGrid — collapse to a clean list in print */ +[class*="grid"] { + display: block !important; +} +[class*="card"] { + display: block !important; + margin: 4pt 0 !important; + padding: 6pt 8pt !important; + border: 0.5pt solid #D6DDEC !important; + border-left: 3pt solid #FFBC1F !important; + border-radius: 2pt !important; + background: #FFFFFF !important; + box-shadow: none !important; + page-break-inside: avoid; +} +[class*="card"] [class*="title"] { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 10pt; + color: #1E325C !important; +} +[class*="card"] [class*="description"] { + font-size: 9pt; + color: #1B1D22 !important; + margin: 2pt 0; +} +[class*="card"] [class*="meta"] { + font-family: 'JetBrains Mono', monospace; + font-size: 7.5pt; + color: #B27F00 !important; + background: transparent !important; +} +[class*="card"] [class*="arrow"] { display: none !important; } +[class*="card"] [class*="icon"] { display: none !important; } + +/* ============================================================ + * OpenAPI plugin — print-specific overrides + * ========================================================== */ + +/* Method endpoint header: render the verb badge + path inline. + * (On screen the plugin uses a
     with a block-level 

    child, + * which stacks vertically when print CSS resets. Force a flex row.) */ +pre.openapi__method-endpoint { + display: flex !important; + align-items: baseline; + flex-wrap: wrap; + gap: 8pt; + background: transparent !important; + border: none !important; + padding: 0 !important; + margin: 0 0 12pt !important; + font-family: 'Inter', sans-serif !important; + white-space: normal !important; + page-break-inside: avoid; +} +.openapi__method-endpoint .badge { + flex: 0 0 auto; + display: inline-block; + padding: 2pt 7pt !important; + border-radius: 2pt !important; + font-family: 'JetBrains Mono', monospace !important; + font-size: 8pt !important; + font-weight: 600 !important; + letter-spacing: 0.06em !important; + color: #FFFFFF !important; + border: none !important; +} +.openapi__method-endpoint .badge--success { background: #2C7A4F !important; } +.openapi__method-endpoint .badge--info, +.openapi__method-endpoint .badge--primary { background: #2D7BD2 !important; } +.openapi__method-endpoint .badge--warning { background: #A86A1F !important; } +.openapi__method-endpoint .badge--danger { background: #8B1F1F !important; } +.openapi__method-endpoint .badge--secondary { background: #6B4FA0 !important; } + +.openapi__method-endpoint-path { + flex: 1 1 auto !important; + font-family: 'JetBrains Mono', monospace !important; + font-size: 11pt !important; + font-weight: 600 !important; + color: #1B1D22 !important; + margin: 0 !important; + padding: 0 !important; + border: none !important; + /* This is an h2; break my generic h2 styling. */ + padding-top: 0 !important; + border-top: none !important; + page-break-before: avoid !important; + break-before: avoid !important; +} +.openapi__method-endpoint-path::before { + display: none !important; /* kill the h2::before marigold rule */ +} +.openapi__divider { display: none; } + +/* Hide tab pickers — interactive only. The tab CONTENT below them + * stays visible (we just don't show the buttons since you can't click + * in a PDF). */ +ul[role="tablist"], +.openapi-tabs__mime-list-container, +.openapi-tabs__schema-list-container, +.openapi-tabs__response-list-container, +.openapi-tabs__code-list-container { + display: none !important; +} + +/* Tab panels: show only the active one (others stay rendered as DOM + * but are aria-hidden). The plugin sets `hidden` attribute on + * inactive panels — we just lean on that. */ +[role="tabpanel"][hidden] { + display: none !important; +} + +/* The right-side interactive panel ("Authorization", "Request" form, + * "Send API Request" button) — meaningless in print. */ +.openapi-right-panel__container { + display: none !important; +} + +/* Schema parameter rows — add spacing between name / type / required */ +.openapi-schema__container { + display: block !important; + padding: 4pt 0 !important; + border-bottom: 0.4pt dotted #D6DDEC; + margin-bottom: 0 !important; + page-break-inside: avoid; +} +.openapi-schema__property { + font-family: 'JetBrains Mono', monospace !important; + font-size: 9pt !important; + font-weight: 600 !important; + color: #1B1D22 !important; +} +.openapi-schema__name { + display: inline-block; + margin-left: 6pt !important; + font-family: 'Inter', sans-serif !important; + font-size: 8.5pt !important; + font-style: italic !important; + color: #5B77B1 !important; + font-weight: 400 !important; +} +.openapi-schema__required { + display: inline-block; + margin-left: 6pt !important; + font-family: 'Archivo Black', system-ui, sans-serif !important; + font-size: 7pt !important; + letter-spacing: 0.08em; + text-transform: uppercase; + color: #8B1F1F !important; + font-weight: 900 !important; +} +.openapi-schema__divider { display: none !important; } + +/* The expandable "▼" caret next to nested schemas — irrelevant on paper */ +[class*='collapsibleHeader'] svg, +.openapi-schema__list-item button svg, +[class*='SchemaItem'] svg { display: none !important; } + +/* The collapsible content is always visible in print (no toggling) */ +[class*='collapsibleContent'] { + height: auto !important; + overflow: visible !important; + display: block !important; +} + +/* Section headings inside endpoint pages (Request, Responses) — make + * them stand out with a marigold underline like other content h2s, + * but tighter. */ +.openapi-tabs__heading, +.openapi-tabs__response-header { + font-family: 'Archivo Black', system-ui, sans-serif !important; + font-size: 13pt !important; + color: #1E325C !important; + margin: 14pt 0 6pt !important; + padding: 0 0 3pt !important; + border-bottom: 1pt solid #D6DDEC !important; + border-top: none !important; + page-break-before: avoid; + page-break-after: avoid; + break-after: avoid; +} +.openapi-tabs__heading::before, +.openapi-tabs__response-header::before { display: none !important; } + +/* Response code chips (200, 400, 401) when shown in body */ +.openapi-tabs__response-code-item.active { + font-family: 'JetBrains Mono', monospace !important; + font-weight: 600 !important; + font-size: 8pt !important; + color: #FFFFFF !important; + background: #2C7A4F; + padding: 1pt 6pt !important; + border-radius: 2pt !important; + margin-right: 6pt; +} + +/* Each endpoint page's h1 should start a new page (already covered by + * the generic h1 rule) — but we make the h1 itself tighter for endpoints. */ +.docs-doc-id-reference h1:first-child, +.docs-doc-id-reference\/login h1:first-child, +[class*='docs-doc-id-reference'] h1:first-child { + font-size: 22pt !important; + margin-bottom: 4pt !important; + padding-bottom: 4pt !important; +} + +/* ============================================================ + * Cover page (rendered as the first .mm-print-cover element on the page) + * ========================================================== */ + +.mm-print-cover { + width: 100vw; + height: 100vh; + page-break-after: always; + break-after: page; + background: #1E325C; + color: #FFFFFF; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 30mm 24mm; + box-sizing: border-box; + margin: -22mm -18mm 22mm -18mm; +} +.mm-print-cover .cover-meta { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 9pt; + letter-spacing: 0.18em; + text-transform: uppercase; + color: #FFBC1F; +} +.mm-print-cover .cover-title { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 56pt; + line-height: 0.95; + letter-spacing: -0.025em; + color: #FFFFFF; +} +.mm-print-cover .cover-subtitle { + font-size: 14pt; + line-height: 1.4; + color: rgba(255,255,255,0.75); + margin-top: 10mm; + max-width: 60ch; +} +.mm-print-cover .cover-bottom { + border-top: 2pt solid #FFBC1F; + padding-top: 6mm; + display: flex; + justify-content: space-between; + align-items: flex-end; +} +.mm-print-cover .cover-version { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 12pt; + letter-spacing: 0.05em; + text-transform: uppercase; +} +.mm-print-cover .cover-tagline { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 9pt; + letter-spacing: 0.18em; + text-transform: uppercase; + color: #FFBC1F; +} + +/* ============================================================ + * Table of Contents (rendered after the cover, before chapter 1) + * ========================================================== */ + +.mm-print-toc { + page-break-before: always; + page-break-after: always; + break-before: page; + break-after: page; + padding: 0; + margin: 0; + /* Suppress the running chapter title until the first real article. */ + string-set: chapter ""; +} + +.mm-print-toc .toc-header { + margin-bottom: 14mm; + padding-bottom: 6pt; + border-bottom: 2pt solid #FFBC1F; +} + +.mm-print-toc .toc-eyebrow { + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 8pt; + letter-spacing: 0.18em; + text-transform: uppercase; + color: #B27F00; + margin-bottom: 4pt; +} + +.mm-print-toc .toc-heading { + font-family: 'Archivo Black', 'Trade Gothic Next Heavy', system-ui, sans-serif; + font-size: 32pt; + color: #1E325C; + margin: 0; + padding: 0; + border: none; + letter-spacing: -0.02em; + /* Override the article H1 rules so the ToC heading doesn't force a new page + * or feed the running header with "Table of Contents". */ + page-break-before: avoid !important; + break-before: avoid !important; + string-set: chapter ""; +} + +.mm-print-toc .toc-list { + list-style: none; + margin: 0; + padding: 0; + counter-reset: toc-chapter; +} + +.mm-print-toc .toc-chapter { + margin: 0 0 8pt; + padding: 0; + page-break-inside: avoid; + break-inside: avoid; +} + +.mm-print-toc .toc-chapter > a { + display: flex; + align-items: baseline; + gap: 6pt; + text-decoration: none; + color: #1E325C; + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 11pt; + line-height: 1.3; + padding: 3pt 0; + border-bottom: 0.4pt solid #EEF1F8; +} + +.mm-print-toc .toc-num { + flex: 0 0 auto; + font-family: 'Archivo Black', system-ui, sans-serif; + font-size: 9pt; + color: #B27F00; + letter-spacing: 0.08em; + min-width: 22pt; +} + +.mm-print-toc .toc-text { + flex: 0 1 auto; + color: #1E325C; +} + +.mm-print-toc .toc-leader { + flex: 1 1 auto; + border-bottom: 0.4pt dotted #B9C3D9; + position: relative; + top: -2pt; + margin: 0 4pt; + min-width: 12pt; +} + +.mm-print-toc .toc-page { + flex: 0 0 auto; + font-family: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace; + font-size: 9pt; + color: #5B77B1; + min-width: 18pt; + text-align: right; +} + +.mm-print-toc .toc-page::after { + content: target-counter(attr(data-href), page); +} + +.mm-print-toc .toc-sub { + list-style: none; + margin: 2pt 0 4pt 28pt; + padding: 0; +} + +.mm-print-toc .toc-sub li { + margin: 0; +} + +.mm-print-toc .toc-sub a { + display: flex; + align-items: baseline; + gap: 6pt; + text-decoration: none; + font-family: 'Inter', system-ui, sans-serif; + font-size: 9.5pt; + color: #182849; + padding: 1.5pt 0; +} + +.mm-print-toc .toc-sub .toc-text { color: #182849; font-weight: 500; } +.mm-print-toc .toc-sub .toc-page { color: #5B77B1; } +.mm-print-toc .toc-sub .toc-leader { border-bottom-color: #D6DDEC; } + +/* ============================================================ + * Page-break helpers + * ========================================================== */ + +img, figure, .mm-no-break { + page-break-inside: avoid; + break-inside: avoid; + max-width: 100% !important; + height: auto; +} + +hr { display: none; } /* most hr's are visual section breaks; redundant in print */ diff --git a/docs/site/.gitignore b/docs/site/.gitignore new file mode 100644 index 000000000000..b9846fb3465d --- /dev/null +++ b/docs/site/.gitignore @@ -0,0 +1,22 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader +sidebars/documentation.generated.json +sidebars/developers.generated.json + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/docs/site/.nvmrc b/docs/site/.nvmrc new file mode 100644 index 000000000000..209e3ef4b624 --- /dev/null +++ b/docs/site/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/docs/site/README.md b/docs/site/README.md new file mode 100644 index 000000000000..30f706583698 --- /dev/null +++ b/docs/site/README.md @@ -0,0 +1,38 @@ +# Mattermost Docs Site + +Built with [Docusaurus](https://docusaurus.io/). + +## Local development + +```bash +# 1. Install dependencies +cd docs/site && npm ci + +# 2. Generate the OpenAPI YAML bundle (reads api/v4/source/*.yaml) +node scripts/build-openapi.mjs + +# 3. Generate the documentation and developer sidebars +# These produce sidebars/documentation.generated.json and +# sidebars/developers.generated.json, which are .gitignored and must be +# regenerated locally after adding or removing doc pages. +# TODO: move these steps into the CI/CD build pipeline so they run automatically. +node scripts/gen-documentation-sidebar.mjs +node scripts/gen-developer-sidebar.mjs + +# 4. Generate the API reference MDX + sidebar (~2 min) +npx docusaurus gen-api-docs all + +# 5. Start dev server +npm start +``` + +## Build + +```bash +npm run build +``` + +## Notes + +- `sidebars/documentation.generated.json` and `sidebars/developers.generated.json` are generated by the sidebar scripts and are not committed. Re-run step 3 whenever you add or remove pages under `docs/` or `develop/`. +- `scripts/migrate-*.mjs` are one-time migration scripts kept locally only; they are not committed. diff --git a/docs/site/docusaurus.config.ts b/docs/site/docusaurus.config.ts new file mode 100644 index 000000000000..fb99e30ae112 --- /dev/null +++ b/docs/site/docusaurus.config.ts @@ -0,0 +1,233 @@ +import {themes as prismThemes} from 'prism-react-renderer'; +import type {Config} from '@docusaurus/types'; +import type * as Preset from '@docusaurus/preset-classic'; +// Active redirects (legacy Sphinx URLs → migrated MDX paths). Regenerated +// by `node docs-site/scripts/gen-active-redirects.mjs` after content +// changes; only entries whose target exists end up here. +import activeRedirects from './sidebars/active-redirects.json'; + +// Multi-instance docs setup with three top-level navigations: +// / → Documentation (admin / end-user) sources: ../docs +// /developers → Developers (contribute / integrate) sources: ../develop +// /api → API Reference (OpenAPI-generated) sources: ../api +// See PLAN.md §3.1 for the IA, §3.2 for design tokens. + +const config: Config = { + title: 'Mattermost Documentation', + tagline: 'Mission in Motion', + favicon: 'img/brand/icon-denim.svg', + + future: { + v4: true, + }, + + url: 'https://docs.mattermost.com', + baseUrl: '/', + + organizationName: 'mattermost', + projectName: 'mattermost', + + // Broken-link / broken-image policy. During the Phase 4 (developer docs) + // and Phase 5 (main docs) migrations, content references images and + // anchors that haven't been migrated yet — `warn` keeps the build green + // while the unconverted set shows up as warnings we can grep for. + // Tighten to `throw` after each migration phase completes. + onBrokenLinks: 'warn', + + markdown: { + hooks: { + onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownImages: 'warn', + }, + }, + + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + // Google Fonts: Inter (body) + Archivo Black (headings, free Trade Gothic Heavy fallback). + // Replace with Adobe Fonts kit once Trade Gothic Next licensing is confirmed + // — see PLAN.md §12 open items. + stylesheets: [ + { + href: 'https://fonts.googleapis.com/css2?family=Archivo+Black&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap', + type: 'text/css', + }, + ], + headTags: [ + {tagName: 'link', attributes: {rel: 'preconnect', href: 'https://fonts.googleapis.com'}}, + {tagName: 'link', attributes: {rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: 'anonymous'}}, + ], + + // Use the classic preset for the default Documentation instance. + // Developers and API are added as separate plugin instances below + // to give each its own routeBasePath and sidebar. + presets: [ + [ + 'classic', + { + docs: { + id: 'documentation', + path: '../main', + routeBasePath: '/', + sidebarPath: './sidebars/documentation.ts', + editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/main/', + }, + blog: false, + theme: { + customCss: ['./src/css/tokens.css', './src/css/custom.css'], + }, + } satisfies Preset.Options, + ], + ], + + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + id: 'developers', + path: '../develop', + routeBasePath: '/developers', + sidebarPath: './sidebars/developers.ts', + editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/develop/', + }, + ], + [ + '@docusaurus/plugin-content-docs', + { + id: 'api', + path: '../api', + routeBasePath: '/api', + sidebarPath: './sidebars/api.ts', + editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/api/', + // Required for endpoint pages generated by docusaurus-plugin-openapi-docs. + docItemComponent: '@theme/ApiItem', + }, + ], + [ + '@docusaurus/plugin-client-redirects', + { + // Legacy URL → migrated MDX path. Pre-filtered to entries whose + // target exists, so the build never breaks on a missing target. + redirects: activeRedirects.redirects, + }, + ], + [ + 'docusaurus-plugin-openapi-docs', + { + id: 'api-generator', + docsPluginId: 'api', + config: { + mattermost: { + specPath: 'openapi/mattermost-openapi-v4.yaml', + outputDir: '../api/reference', + sidebarOptions: { + groupPathsBy: 'tag', + categoryLinkSource: 'tag', + }, + }, + }, + }, + ], + ], + + // Theme for the API endpoint pages (parameter tables, request/response + // schemas, code-sample picker). Layered on the classic preset theme. + themes: ['docusaurus-theme-openapi-docs'], + + themeConfig: { + image: 'img/brand/logo-horizontal-denim.svg', + colorMode: { + defaultMode: 'light', + respectPrefersColorScheme: true, + }, + navbar: { + title: '', + logo: { + alt: 'Mattermost', + // Navbar is denim in both light and dark mode, so white logo always. + src: 'img/brand/logo-horizontal-white.svg', + srcDark: 'img/brand/logo-horizontal-white.svg', + }, + items: [ + { + type: 'docSidebar', + docsPluginId: 'documentation', + sidebarId: 'documentation', + position: 'left', + label: 'Documentation', + }, + { + type: 'docSidebar', + docsPluginId: 'developers', + sidebarId: 'developers', + position: 'left', + label: 'Developers', + }, + { + type: 'docSidebar', + docsPluginId: 'api', + sidebarId: 'api', + position: 'left', + label: 'API', + }, + { + href: 'https://github.com/mattermost/mattermost', + label: 'GitHub', + position: 'right', + }, + ], + }, + footer: { + style: 'dark', + logo: { + alt: 'Mattermost — Mission in Motion', + src: 'img/brand/logo-horizontal-white.svg', + width: 180, + }, + links: [ + { + title: 'Documentation', + items: [ + {label: 'Product Overview', to: '/'}, + {label: 'Deployment Guide', to: '/'}, + {label: 'Administration Guide', to: '/'}, + ], + }, + { + title: 'Developers', + items: [ + {label: 'Contribute', to: '/developers'}, + {label: 'Integrate & Extend', to: '/developers'}, + {label: 'API Reference', to: '/api'}, + ], + }, + { + title: 'Community', + items: [ + {label: 'GitHub', href: 'https://github.com/mattermost/mattermost'}, + {label: 'Forum', href: 'https://forum.mattermost.com/'}, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} Mattermost, Inc. All rights reserved.`, + }, + prism: { + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + additionalLanguages: ['bash', 'powershell', 'json', 'yaml', 'go', 'python'], + }, + // Code-sample tabs shown on every endpoint page, in display order. + // First entry is the default selected tab (curl). + languageTabs: [ + {highlight: 'bash', language: 'curl', logoClass: 'curl'}, + {highlight: 'powershell', language: 'powershell', logoClass: 'powershell'}, + {highlight: 'python', language: 'python', logoClass: 'python'}, + {highlight: 'javascript', language: 'nodejs', logoClass: 'nodejs', label: 'Node'}, + {highlight: 'go', language: 'go', logoClass: 'go'}, + ], + } satisfies Preset.ThemeConfig, +}; + +export default config; diff --git a/docs/site/package-lock.json b/docs/site/package-lock.json new file mode 100644 index 000000000000..0c34946fe048 --- /dev/null +++ b/docs/site/package-lock.json @@ -0,0 +1,21620 @@ +{ + "name": "docs-site", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "docs-site", + "version": "0.0.0", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/faster": "3.10.1", + "@docusaurus/plugin-client-redirects": "^3.10.1", + "@docusaurus/preset-classic": "3.10.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "docusaurus-plugin-openapi-docs": "^5.0.2", + "docusaurus-theme-openapi-docs": "^5.0.2", + "prism-react-renderer": "^2.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "yaml": "^2.8.4" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/tsconfig": "3.10.1", + "@docusaurus/types": "3.10.1", + "@types/react": "^19.0.0", + "typescript": "~6.0.2" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.18.1.tgz", + "integrity": "sha512-aehCadlWOGvrT91KUIZpC0MbB8KBW9yUuvTJFd2xesR7le/IsT4nJUnjCCZ4ZqZCeTcPHPV5mo//fZ5oxcSVYw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.8.tgz", + "integrity": "sha512-3YEorYg44niXcm7gkft3nXYItHd44e8tmh4D33CTszPgP0QWkaLEaFywiNyJBo7UL/mqObA/G9RYuU7R8tN1IA==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.19.8", + "@algolia/autocomplete-shared": "1.19.8" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.8.tgz", + "integrity": "sha512-ZvJWO8ZZJDpc1LNM2TTBdmQsZBLMR4rU5iNR2OYvEeFBiaf/0ESnRSSLQbryarJY4SVxtoz6A2ZtDMNM+iQEAA==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.19.8" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.8.tgz", + "integrity": "sha512-h5hf2t8ejF6vlOgvLaZzQbWs5SyH2z4PAWygNAvvD/2RI29hdQ54ldUGwqVuj9Srs+n8XUKTPUqb7fvhBhQrnQ==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.52.1.tgz", + "integrity": "sha512-HmXOGBOAOJPounpBzBpuY0zDYeiCpxgHnQmuA7JO6ScukcBdGp3/XM9zJk5pJx/xNGD68mbPGXWpDxGtl6BwDQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.52.1.tgz", + "integrity": "sha512-5oo4+I8iixie9vXhCyNFCzeIr8pqA3FQ//VsLHTDvZAV4ttYOPGvYHGQq5NSalrLx5Jc3dRro/5uDOlnUMcBJg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.52.1.tgz", + "integrity": "sha512-qCDoZfx5MpX7XQzvQ3bC4tSEMkQWQMaF/ABtLuoze03Y/flR563CCSws02qIJ23oX7lxl92LsilZjINVyTdtLw==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.52.1.tgz", + "integrity": "sha512-hnGs0/lsFJ2PWDxNBz7pxreXo/Xz7gxYRcfePBUjsH26ad0kU/sgnVZd9LwWBpsQv65z2jlb5dkyaB9WE9M9FQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.52.1.tgz", + "integrity": "sha512-2VxxNc/uBysyKvGeBdSM5n9eIDKH8kWD7wd9/yqbJAiVwU4Yv6tU1LSJusHKrXV/aCu1KW7t9Gug9QyeEmtn/Q==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.52.1.tgz", + "integrity": "sha512-O6mPtsw3xEfNOe6gWFpYLeAZAIljNa4Hgna3bq15PwyN7nbjTY0wXJFRbzs/0YVf75Br+SbOQUmjKxXYjDiSiQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.52.1.tgz", + "integrity": "sha512-gA8oJOV1LnQQkDf91iebNnFInHuW0gRPEgLSOQ7EfipCEjYTHm5swm1DlH9H5RaRw4RrHuzHBegnlzc0MAstcg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "license": "MIT" + }, + "node_modules/@algolia/ingestion": { + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.52.1.tgz", + "integrity": "sha512-U9zZfc5xIu9wRxZkt+HceJUAD4VKHKbAyLSloJdEyMRmphXeibfrY9cxqIXBcmPeZzGhn3Imb35Dq8l19PkJhw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.52.1.tgz", + "integrity": "sha512-a3SGNceHmkQfq77iG8Ka+w1pvwfZa/0lzEIgse30fL0kD+yKnd/dg0dQvSfFPAEt2f21DMcGkDSSeJlO3KdQjQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.52.1.tgz", + "integrity": "sha512-z98QEguCFDpxb4S/PyrUK1igqF8tPsdbqOUUO6ON91vJ58w+Gwa6ncrI0oNXSFcrkxA5EqPKPQ2A1PBCn08TYQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.52.1.tgz", + "integrity": "sha512-CI7+/0I11QeZM59Uc8whd2or0kqzFVjpaPn9Qpwll/krHcBAxk24WkAQ6WX+IwDVMfpont4YGbKwAmCre3vE8Q==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.52.1.tgz", + "integrity": "sha512-S6bDuw9byfOvm3T71cgdoZgrgnZq6hpdMLkx52Louh57nUAmvGQESz2aojOynQHjbTiV55smvAFbgn0qT4tJrg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.52.1.tgz", + "integrity": "sha512-tqZXM+54rWo4mk5jL5Z/flE11nPmNEdXwFBM5py9DkOmbjeCNemfVd45FyM97XdzfZ0dl9uOJC6PYn1FpkeyQg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.5.tgz", + "integrity": "sha512-orNOYXw3hYXxxisXMldjzjBzqqTLBPbwOtHg7ovBPvfBHDue1qM9YJENZ3W2BQuS+7z4ThogMbEzEsov57Itkg==", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz", + "integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.29.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", + "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", + "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", + "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", + "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", + "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz", + "integrity": "sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz", + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-jsx": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", + "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz", + "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", + "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", + "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.29.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.5.tgz", + "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz", + "integrity": "sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/postcss-alpha-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-alpha-function/-/postcss-alpha-function-1.0.1.tgz", + "integrity": "sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.2.tgz", + "integrity": "sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.12.tgz", + "integrity": "sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-function-display-p3-linear": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function-display-p3-linear/-/postcss-color-function-display-p3-linear-1.0.1.tgz", + "integrity": "sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-function": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.12.tgz", + "integrity": "sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.2.tgz", + "integrity": "sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-content-alt-text": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.8.tgz", + "integrity": "sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-contrast-color-function": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-contrast-color-function/-/postcss-contrast-color-function-2.0.12.tgz", + "integrity": "sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-exponential-functions": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.9.tgz", + "integrity": "sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-4.0.0.tgz", + "integrity": "sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.11.tgz", + "integrity": "sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.12.tgz", + "integrity": "sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.12.tgz", + "integrity": "sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.4.tgz", + "integrity": "sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-initial": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-2.0.1.tgz", + "integrity": "sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.3.tgz", + "integrity": "sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-light-dark-function": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.11.tgz", + "integrity": "sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-3.0.0.tgz", + "integrity": "sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overflow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-2.0.0.tgz", + "integrity": "sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-2.0.0.tgz", + "integrity": "sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-3.0.0.tgz", + "integrity": "sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.4.tgz", + "integrity": "sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-minmax": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.9.tgz", + "integrity": "sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.5.tgz", + "integrity": "sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-4.0.0.tgz", + "integrity": "sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz", + "integrity": "sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.12.tgz", + "integrity": "sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-position-area-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-position-area-property/-/postcss-position-area-property-1.0.0.tgz", + "integrity": "sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.2.1.tgz", + "integrity": "sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-property-rule-prelude-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-property-rule-prelude-list/-/postcss-property-rule-prelude-list-1.0.0.tgz", + "integrity": "sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-random-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz", + "integrity": "sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.12.tgz", + "integrity": "sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-4.0.1.tgz", + "integrity": "sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-sign-functions": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz", + "integrity": "sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.9.tgz", + "integrity": "sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-syntax-descriptor-syntax-production": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-syntax-descriptor-syntax-production/-/postcss-syntax-descriptor-syntax-production-1.0.1.tgz", + "integrity": "sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-system-ui-font-family": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-system-ui-font-family/-/postcss-system-ui-font-family-1.0.0.tgz", + "integrity": "sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.3.tgz", + "integrity": "sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.9.tgz", + "integrity": "sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-4.0.0.tgz", + "integrity": "sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/utilities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", + "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.3.tgz", + "integrity": "sha512-rUOujwIpxJRgD7+kicVsI3D5sqBvdiRTquzWBpTEXZs8ZXfGbfzpus5HqumaNYTppN2HvH8E2yNuRwYdHJeOlA==", + "license": "MIT", + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@docsearch/css": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.3.tgz", + "integrity": "sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==", + "license": "MIT" + }, + "node_modules/@docsearch/react": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.3.tgz", + "integrity": "sha512-Bg2wdDsoQVlNCcEKuEJAU04tvHCqgx8rIu+uIoM4pRtcx3TBKJuXutJik3LTA8LRc9YEyHkrYUrmcC0D7BYf+g==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.19.2", + "@docsearch/core": "4.6.3", + "@docsearch/css": "4.6.3" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", + "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", + "@algolia/autocomplete-shared": "1.19.2" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", + "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.19.2" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", + "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@docusaurus/babel": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/bundler": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^7.0.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.7", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^5.2.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*", + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/faster": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/faster/-/faster-3.10.1.tgz", + "integrity": "sha512-XTZhE5C1gZ/DaYYMlSk02dwP5vhpQON5QHVz1s3892mSESAywgWanURpXEDAvt4GvGuq7s+XP8rTWHZvfaJmdQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "@rspack/core": "^1.7.10", + "@swc/core": "^1.7.39", + "@swc/html": "^1.13.5", + "browserslist": "^4.24.2", + "lightningcss": "^1.27.0", + "semver": "^7.5.4", + "swc-loader": "^0.2.6", + "tslib": "^2.6.0", + "webpack": "^5.95.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", + "integrity": "sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-client-redirects": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.10.1.tgz", + "integrity": "sha512-LHgd+YDvkhfOHMAE6XtUng3DQNzVM765RqVRrMJgHtzAvfopQhY6ieprqjxDVBdv21cLma6I0jHr+YCZH8fL9A==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", + "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "cheerio": "1.0.0-rc.12", + "combine-promises": "^1.1.0", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", + "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", + "integrity": "sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", + "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", + "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^2.3.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", + "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", + "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/gtag.js": "^0.0.20", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", + "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", + "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", + "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.1.tgz", + "integrity": "sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/plugin-css-cascade-layers": "3.10.1", + "@docusaurus/plugin-debug": "3.10.1", + "@docusaurus/plugin-google-analytics": "3.10.1", + "@docusaurus/plugin-google-gtag": "3.10.1", + "@docusaurus/plugin-google-tag-manager": "3.10.1", + "@docusaurus/plugin-sitemap": "3.10.1", + "@docusaurus/plugin-svgr": "3.10.1", + "@docusaurus/theme-classic": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-search-algolia": "3.10.1", + "@docusaurus/types": "3.10.1" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", + "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.5.4", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", + "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", + "integrity": "sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "^1.19.2", + "@docsearch/react": "^3.9.0 || ^4.3.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "algoliasearch": "^5.37.0", + "algoliasearch-helper": "^3.26.0", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/tsconfig": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.10.1.tgz", + "integrity": "sha512-rYvB7yqkdqWIpAbDzQljGfM4cDBkLTbhmagZBEcsyj6oPUsz47lmW2pYdN1j+7sGFgltbAmQH62xfbrij4Eh6Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docusaurus/types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "escape-string-regexp": "^4.0.0", + "execa": "^5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.10.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "license": "MIT" + }, + "node_modules/@faker-js/faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", + "deprecated": "Please update to a newer version.", + "license": "MIT" + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@hookform/error-message": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.1.tgz", + "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-hook-form": "^7.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.57.2", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@module-federation/error-codes": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.22.0.tgz", + "integrity": "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==", + "license": "MIT" + }, + "node_modules/@module-federation/runtime": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.22.0.tgz", + "integrity": "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==", + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.22.0", + "@module-federation/runtime-core": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@module-federation/runtime-core": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.22.0.tgz", + "integrity": "sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==", + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@module-federation/runtime-tools": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.22.0.tgz", + "integrity": "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.22.0", + "@module-federation/webpack-bundler-runtime": "0.22.0" + } + }, + "node_modules/@module-federation/sdk": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.22.0.tgz", + "integrity": "sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==", + "license": "MIT" + }, + "node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.22.0.tgz", + "integrity": "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", + "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.7.0.tgz", + "integrity": "sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.7.0.tgz", + "integrity": "sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.7.0.tgz", + "integrity": "sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.7.0.tgz", + "integrity": "sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-rsa": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.7.0.tgz", + "integrity": "sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.7.0.tgz", + "integrity": "sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pfx": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.7.0.tgz", + "integrity": "sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.7.0.tgz", + "integrity": "sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg==", + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.7.0.tgz", + "integrity": "sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.7.0.tgz", + "integrity": "sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", + "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.2.tgz", + "integrity": "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@redocly/ajv": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.18.3.tgz", + "integrity": "sha512-l42u0of3hY98sN2A+M4qTX1O/KrpgGH32Hu9kP2GtHyD5Dfqq86PKFLe5dwaD8DEnNmlOlll2BAmeEtf0DaySg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/config": { + "version": "0.48.1", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.48.1.tgz", + "integrity": "sha512-vq8GM3e0KiglqkwE5Lb9XayrmZY4dHCs21BsvV92yAZN68f1N9cZUuwY1SwnztPbH06dn9uLzubBl/JNfImqfA==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "2.7.2" + } + }, + "node_modules/@redocly/openapi-core": { + "version": "2.30.4", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-2.30.4.tgz", + "integrity": "sha512-23Mg0EPaczaxnbcLokUwY6fnzWhldc84XBvEMn4sOc6iV/TtroNmWx70WttT6Xs6dBUNeFUVZEI7MlKAmZRvcw==", + "license": "MIT", + "dependencies": { + "@redocly/ajv": "^8.18.1", + "@redocly/config": "^0.48.1", + "ajv": "npm:@redocly/ajv@8.18.1", + "ajv-formats": "^3.0.1", + "colorette": "^1.2.0", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "picomatch": "^4.0.4", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=22.12.0 || >=20.19.0 <21.0.0", + "npm": ">=10" + } + }, + "node_modules/@redocly/openapi-core/node_modules/ajv": { + "name": "@redocly/ajv", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.18.1.tgz", + "integrity": "sha512-Ifm/pP/tul1qmAecpbVxCBluVE32rKfjf8gYXH4xI2gCv9mRWFhJMHzkPDM4TXlxwPQYIFegymlsy8lXz7optA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/openapi-core/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@redocly/openapi-core/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "license": "MIT" + }, + "node_modules/@redocly/openapi-core/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", + "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@rspack/binding": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.7.11.tgz", + "integrity": "sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q==", + "license": "MIT", + "optionalDependencies": { + "@rspack/binding-darwin-arm64": "1.7.11", + "@rspack/binding-darwin-x64": "1.7.11", + "@rspack/binding-linux-arm64-gnu": "1.7.11", + "@rspack/binding-linux-arm64-musl": "1.7.11", + "@rspack/binding-linux-x64-gnu": "1.7.11", + "@rspack/binding-linux-x64-musl": "1.7.11", + "@rspack/binding-wasm32-wasi": "1.7.11", + "@rspack/binding-win32-arm64-msvc": "1.7.11", + "@rspack/binding-win32-ia32-msvc": "1.7.11", + "@rspack/binding-win32-x64-msvc": "1.7.11" + } + }, + "node_modules/@rspack/binding-darwin-arm64": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.11.tgz", + "integrity": "sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-darwin-x64": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.11.tgz", + "integrity": "sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-linux-arm64-gnu": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.11.tgz", + "integrity": "sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-arm64-musl": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.11.tgz", + "integrity": "sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-gnu": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.11.tgz", + "integrity": "sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-musl": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.11.tgz", + "integrity": "sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-wasm32-wasi": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.11.tgz", + "integrity": "sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "1.0.7" + } + }, + "node_modules/@rspack/binding-win32-arm64-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.11.tgz", + "integrity": "sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-ia32-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.11.tgz", + "integrity": "sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-x64-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.11.tgz", + "integrity": "sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/core": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.7.11.tgz", + "integrity": "sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime-tools": "0.22.0", + "@rspack/binding": "1.7.11", + "@rspack/lite-tapable": "1.1.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.1" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@rspack/lite-tapable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.1.0.tgz", + "integrity": "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==", + "license": "MIT" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.33.tgz", + "integrity": "sha512-jOlwnFV2xhuuZeAUILGFULeR6vDPfijEJ57evfocwznQldLU3w2cZ9bSDryY9ip+AsM3r1NJKzf47V2NXebkeQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.26" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.15.33", + "@swc/core-darwin-x64": "1.15.33", + "@swc/core-linux-arm-gnueabihf": "1.15.33", + "@swc/core-linux-arm64-gnu": "1.15.33", + "@swc/core-linux-arm64-musl": "1.15.33", + "@swc/core-linux-ppc64-gnu": "1.15.33", + "@swc/core-linux-s390x-gnu": "1.15.33", + "@swc/core-linux-x64-gnu": "1.15.33", + "@swc/core-linux-x64-musl": "1.15.33", + "@swc/core-win32-arm64-msvc": "1.15.33", + "@swc/core-win32-ia32-msvc": "1.15.33", + "@swc/core-win32-x64-msvc": "1.15.33" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.33.tgz", + "integrity": "sha512-N+L0uXhuO7FIfzqwgxmzv0zIpV0qEp8wPX3QQs2p4atjMoywup2JTeDlXPw+z9pWJGCae3JjM+tZ6myclI+2gA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.33.tgz", + "integrity": "sha512-/Il4QHSOhV4FekbsDtkrNmKbsX26oSysvgrRswa/RYOHXAkwXDbB4jaeKq6PsJLSPkzJ2KzQ061gtBnk0vNHfA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.33.tgz", + "integrity": "sha512-C64hBnBxq4viOPQ8hlx+2lJ23bzZBGnjw7ryALmS+0Q3zHmwO8lw1/DArLENw4Q18/0w5wdEO1k3m1wWNtKGqQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.33.tgz", + "integrity": "sha512-TRJfnJbX3jqpxRDRoieMzRiCBS5jOmXNb3iQXmcgjFEHKLnAgK1RZRU8Cq1MsPqO4jAJp/ld1G4O3fXuxv85uw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.33.tgz", + "integrity": "sha512-il7tYM+CpUNzieQbwAjFT1P8zqAhmGWNAGhQZBnxurXZ0aNn+5nqYFTEUKNZl7QibtT0uQXzTZrNGHCIj6Y1Og==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-ppc64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.33.tgz", + "integrity": "sha512-ZtNBwN0Z7CFj9Il0FcPaKdjgP7URyKu/3RfH46vq+0paOBqLj4NYldD6Qo//Duif/7IOtAraUfDOmp0PLAufog==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-s390x-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.33.tgz", + "integrity": "sha512-De1IyajoOmhOYYjw/lx66bKlyDpHZTueqwpDrWgf5O7T6d1ODeJJO9/OqMBmrBQc5C+dNnlmIufHsp4QVCWufA==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.33.tgz", + "integrity": "sha512-mGTH0YxmUN+x6vRN/I6NOk5X0ogNktkwPnJ94IMvR7QjhRDwL0O8RXEDhyUM0YtwWrryBOqaJQBX4zruxEPRGw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.33.tgz", + "integrity": "sha512-hj628ZkSEJf6zMf5VMbYrG2O6QqyTIp2qwY6VlCjvIa9lAEZ5c2lfPblCLVGYubTeLJDxadLB/CxqQYOQABeEQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.33.tgz", + "integrity": "sha512-GV2oohtN2/5+KSccl86VULu3aT+LrISC8uzgSq0FRnikpD+Zwc+sBlXmoKQ+Db6jI57ITUOIB8jRkdGMABC29g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.33.tgz", + "integrity": "sha512-gtyvzSNR8DHKfFEA2uqb8Ld1myqi6uEg2jyeUq3ikn5ytYs7H8RpZYC8mdy4NXr8hfcdJfCLXPlYaqqfBXpoEQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.33.tgz", + "integrity": "sha512-d6fRqQSkJI+kmMEBWaDQ7TMl8+YjLYbwRUPZQ9DY0ORBJeTzOrG0twvfvlZ2xgw6jA0ScQKgfBm4vHLSLl5Hqg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/html": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html/-/html-1.15.33.tgz", + "integrity": "sha512-PZIfmj5zYpAJ2eMptf0My2q9Bl8bkraW28+FD1pRnxOiYMrKrP5vL2tB2PdxMRjS0ziLFVM5HEuGFw8PxEDOaw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@swc/html-darwin-arm64": "1.15.33", + "@swc/html-darwin-x64": "1.15.33", + "@swc/html-linux-arm-gnueabihf": "1.15.33", + "@swc/html-linux-arm64-gnu": "1.15.33", + "@swc/html-linux-arm64-musl": "1.15.33", + "@swc/html-linux-ppc64-gnu": "1.15.33", + "@swc/html-linux-s390x-gnu": "1.15.33", + "@swc/html-linux-x64-gnu": "1.15.33", + "@swc/html-linux-x64-musl": "1.15.33", + "@swc/html-win32-arm64-msvc": "1.15.33", + "@swc/html-win32-ia32-msvc": "1.15.33", + "@swc/html-win32-x64-msvc": "1.15.33" + } + }, + "node_modules/@swc/html-darwin-arm64": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-darwin-arm64/-/html-darwin-arm64-1.15.33.tgz", + "integrity": "sha512-zyO6uMBfLyCh55wundAxKX+8P/f98ecuyir4VX6nTmn6y7x37ndB8f01LUrd9Tiq6eEAvDXLiqEUvuGjEc7Pmg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-darwin-x64": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-darwin-x64/-/html-darwin-x64-1.15.33.tgz", + "integrity": "sha512-MaGunsY/J5l7Rb5OmoztEWh+ikooydT7nWkjiDovj7UfkB9HLk5sLr9O7ZdNGJ2u9dD6FX89SzMdA0Psm9NJrQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-arm-gnueabihf": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-arm-gnueabihf/-/html-linux-arm-gnueabihf-1.15.33.tgz", + "integrity": "sha512-CrbUDjVl6/hQ1C5KPMiK4vxk/eOMjxkVELqwnOxsZ+aFVTv3L3YrGMaJ5H47vvIihkPhqiSOUPmMEFqxvqKmXg==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-arm64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.15.33.tgz", + "integrity": "sha512-7tZ0IgmUslI9Extu/TpxJS0GjJoDx0j9zeq2cIidPdM/njSBpyRB7n4B292Q5WFVh7PcZl7WXqqqMczibQ27aA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-arm64-musl": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-musl/-/html-linux-arm64-musl-1.15.33.tgz", + "integrity": "sha512-gYi2ainYZV2z+jwjp9UKuPVOf3c5q+NkH3QRDjqDrIPLagqDsYNjobi8p5oajGcPGFLNTcVw08VTcubJGChReA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-ppc64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-ppc64-gnu/-/html-linux-ppc64-gnu-1.15.33.tgz", + "integrity": "sha512-6CfzyVQSdD8ezFdxFve4J/b6qTgXIwYFWEvSdaJvXSgwTy976uUV5Ff1LOF86mt2zWMhZJX9DqmkGyIhepbyWw==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-s390x-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-s390x-gnu/-/html-linux-s390x-gnu-1.15.33.tgz", + "integrity": "sha512-Msx1eniw95lhMHUSe3D5FXweKHtkHtzJLsHJDj920uL4Dm7UHqzwaCuZdCmzbkHnO96YjjQvAm266djg8wupmQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-x64-gnu": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.15.33.tgz", + "integrity": "sha512-JDNb4Uq+7g+23QuOtwWnP0/EqztWIHFFdQdeBIS5zx83YBG2dYRMdPAjnHJWh2YRZxdepd8q6S9MUIxpSrouAg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-linux-x64-musl": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-linux-x64-musl/-/html-linux-x64-musl-1.15.33.tgz", + "integrity": "sha512-NSpZdbz4dj0pu1A0Z9l68Bll5HAzEMtBAeMe6jc4GEVfpIw6eeafQHm2/yMUEh09tgl8t9LzM9DycfdTZDjM4g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-win32-arm64-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-win32-arm64-msvc/-/html-win32-arm64-msvc-1.15.33.tgz", + "integrity": "sha512-w7iho3/zS3lCDqgUZMDLMBO0ElX7j+KgvMb8BOrKqLDOSTDDj3lY/BClNJ7vBpAliI2kPQs/mUikdZyzi4MBjQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-win32-ia32-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-win32-ia32-msvc/-/html-win32-ia32-msvc-1.15.33.tgz", + "integrity": "sha512-6hJ2pBweSfZ38trYHXmzTBDpRNvqJgFl2PkIWdy4IXbV/Fv0v9Dqe0t9Gi2ZVEBpgI7PD6pF42AT4HmrNTVFyQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/html-win32-x64-msvc": { + "version": "1.15.33", + "resolved": "https://registry.npmjs.org/@swc/html-win32-x64-msvc/-/html-win32-x64-msvc-1.15.33.tgz", + "integrity": "sha512-eaY/vNE7rkPKluJYjhOiQOA1tto5VbJOoD1C1xFTBmr9t7WsqYUfbQhYQy5A26/z83NNgtDwELM85rkMB+/vWA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/types": { + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.26.tgz", + "integrity": "sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.20.tgz", + "integrity": "sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "license": "MIT" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", + "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.19.0" + } + }, + "node_modules/@types/prismjs": { + "version": "1.26.6", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz", + "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "license": "MIT" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.52.1.tgz", + "integrity": "sha512-fHA8+kXTbjagw3jkLiaS7KKrH8qe2DyOsiUhGlN4cdT77PEsfqXZl7ewDk1hsg+pJnPlnE50XtLxjR91iJOpmg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.18.1", + "@algolia/client-abtesting": "5.52.1", + "@algolia/client-analytics": "5.52.1", + "@algolia/client-common": "5.52.1", + "@algolia/client-insights": "5.52.1", + "@algolia/client-personalization": "5.52.1", + "@algolia/client-query-suggestions": "5.52.1", + "@algolia/client-search": "5.52.1", + "@algolia/ingestion": "1.52.1", + "@algolia/monitoring": "1.52.1", + "@algolia/recommend": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.29.1.tgz", + "integrity": "sha512-6ck2YFudF2Pje7szQoPBiRFTGfd+1I+0I/WfLPGn0bj1kvrFoOQmNyedNiDxTk3/r4IfSLDYk+RA4G7u8H6+yA==", + "license": "MIT", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/allof-merge": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/allof-merge/-/allof-merge-0.6.8.tgz", + "integrity": "sha512-RJrHVDqITsU1kjE2L7s1hy4AYZSTlO1m9jTleYhVCEOfOpbbygRGfcEgrp+bW3oX/PcMUwVkt6MSJyXoyI6lRA==", + "license": "MIT", + "dependencies": { + "json-crawl": "^0.5.3" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.27", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz", + "integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz", + "integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-blank-pseudo": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-7.0.1.tgz", + "integrity": "sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.3.tgz", + "integrity": "sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-has-pseudo/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssdb": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.8.0.tgz", + "integrity": "sha512-QbLeyz2Bgso1iRlh7IpWk6OKa3lLNGXsujVjDMPl9rOZpxKeiG69icLpbLCFxeURwmcdIfZqQyhlooKJYM4f8Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ], + "license": "MIT-0" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "license": "MIT", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/detect-package-manager": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-3.0.2.tgz", + "integrity": "sha512-8JFjJHutStYrfWwzfretQoyNGoZVW1Fsrp4JO9spa7h/fBfwgTMEIy4/LBzRDGsxwVPHU0q+T9YvwLDJoOApLQ==", + "license": "MIT", + "dependencies": { + "execa": "^5.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/docusaurus-plugin-openapi-docs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-5.0.2.tgz", + "integrity": "sha512-WCC2m6PpylXZfNga+ScelTG0a7jUGtbB9+AmbR9lUj93FPryTs8VHTMJ3fKtO0senJTWgOU3MDvZw0v+mE3ztA==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.3.3", + "@redocly/openapi-core": "^2.25.2", + "allof-merge": "^0.6.6", + "chalk": "^5.6.2", + "clsx": "^2.1.1", + "fs-extra": "^11.3.0", + "json-pointer": "^0.6.2", + "json5": "^2.2.3", + "lodash": "^4.17.21", + "mustache": "^4.2.0", + "openapi-to-postmanv2": "^6.0.0", + "postman-collection": "^5.0.2", + "slugify": "^1.6.6", + "swagger2openapi": "^7.0.8", + "xml-formatter": "^3.6.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "^3.10.0", + "@docusaurus/utils": "^3.10.0", + "@docusaurus/utils-validation": "^3.10.0", + "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/docusaurus-plugin-sass": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.6.tgz", + "integrity": "sha512-2hKQQDkrufMong9upKoG/kSHJhuwd+FA3iAe/qzS/BmWpbIpe7XKmq5wlz4J5CJaOPu4x+iDJbgAxZqcoQf0kg==", + "license": "MIT", + "peer": true, + "dependencies": { + "sass-loader": "^16.0.2" + }, + "peerDependencies": { + "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha", + "sass": "^1.30.0" + } + }, + "node_modules/docusaurus-theme-openapi-docs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-5.0.2.tgz", + "integrity": "sha512-BD6WhbunR6kXqtoUUDlhxO4HlCNM2nYENGr/TbiTEknkgXYKQz+FEIhY4Hyz5GSLpuhPih0CDuNl7Xkfpcz0Yw==", + "license": "MIT", + "dependencies": { + "@hookform/error-message": "^2.0.1", + "@reduxjs/toolkit": "^2.8.2", + "allof-merge": "^0.6.6", + "buffer": "^6.0.3", + "clsx": "^2.1.1", + "copy-text-to-clipboard": "^3.2.0", + "crypto-js": "^4.2.0", + "file-saver": "^2.0.5", + "lodash": "^4.17.21", + "pako": "^2.1.0", + "path-browserify": "^1.0.1", + "postman-code-generators": "^2.0.0", + "postman-collection": "^5.0.2", + "prism-react-renderer": "^2.4.1", + "process": "^0.11.10", + "react-hook-form": "^7.59.0", + "react-live": "^4.1.8", + "react-magic-dropzone": "^1.0.1", + "react-markdown": "^10.1.0", + "react-modal": "^3.16.3", + "react-redux": "^9.2.0", + "rehype-raw": "^7.0.0", + "remark-gfm": "4.0.1", + "sass": "^1.89.2", + "sass-loader": "^16.0.5", + "unist-util-visit": "^5.0.0", + "url": "^0.11.4", + "xml-formatter": "^3.6.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@docusaurus/theme-common": "^3.10.0", + "docusaurus-plugin-openapi-docs": "^5.0.0", + "docusaurus-plugin-sass": "^0.2.3", + "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.352", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.352.tgz", + "integrity": "sha512-9wHk8x6dyuimoe18EdiDPWKExNdxYqo4fn4FwOVVper6RxT3cmpBwBkWWfSOCYJjQdIco/nPhJhNLmn4Ufg1Yg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.1.0.tgz", + "integrity": "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.21.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.1.tgz", + "integrity": "sha512-8p7DUVq6XJnZEz9W4oSwiwycxBIjHjRzYb3Je3zVN+geKTRQKzAkR/K4PBExlS0090d9nshak6phMUxr3PDjmQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "license": "MIT" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz", + "integrity": "sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==", + "license": "BSD-3-Clause" + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "license": "MIT", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "license": "MIT" + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "license": "ISC" + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz", + "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-reasons": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", + "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", + "license": "Apache-2.0" + }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "license": "MIT" + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", + "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", + "license": "MIT", + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/immer": { + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.7.tgz", + "integrity": "sha512-LFVFtAROHcDy1er5UI6nodRFnZ2SgdCXhfNSI+DpObO8N7Pur/muBGsjzH5wpnFHCYhYVQxZskCkV4koQ//3/Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.45", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.45.tgz", + "integrity": "sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.1.0.tgz", + "integrity": "sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-crawl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/json-crawl/-/json-crawl-0.5.3.tgz", + "integrity": "sha512-BEjjCw8c7SxzNK4orhlWD5cXQh8vCk2LqDr4WgQq4CV+5dvopeYwt1Tskg67SuSLKvoFH5g0yuYtg7rcfKV6YA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-pointer": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "license": "MIT", + "dependencies": { + "foreach": "^2.0.4" + } + }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "license": "MIT", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/json-schema-to-ts": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-2.7.2.tgz", + "integrity": "sha512-R1JfqKqbBR4qE8UyBR56Ms30LL62/nlhoz+1UkfI/VE7p54Awu919FZ6ZUPG8zIa3XB65usPJgr1ONVncUGSaQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@types/json-schema": "^7.0.9", + "ts-algebra": "^1.2.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "license": "MIT", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz", + "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/liquid-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", + "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "license": "CC0-1.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-format": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.2.tgz", + "integrity": "sha512-Y5ERWVcyh3sby9Fx2U5F1yatiTFjNsqF5NltihTWI9QgNtr5o3dbCZdcKa1l2wyfhnwwoP9HGNxga7LqZLA6gw==", + "license": "Apache-2.0", + "dependencies": { + "charset": "^1.0.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "license": "MIT", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/neotraverse": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.15.tgz", + "integrity": "sha512-HZpdkco+JeXq0G+WWpMJ4NsX3pqb5O7eR9uGz3FfoFt+LYzU8iRWp49nJtud6hsDoywM8tIrDo3gjgmOqJA8LA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "license": "MIT", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "license": "MIT", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/null-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", + "integrity": "sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/null-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/null-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/null-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/null-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "license": "BSD-3-Clause", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-linter/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver-browser": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver-browser/-/oas-resolver-browser-2.5.6.tgz", + "integrity": "sha512-Jw5elT/kwUJrnGaVuRWe1D7hmnYWB8rfDDjBnpQ+RYY/dzAewGXeTexXzt4fGEo6PUE4eqKqPWF79MZxxvMppA==", + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "path-browserify": "^1.0.1", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver-browser/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-resolver/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-to-postmanv2": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/openapi-to-postmanv2/-/openapi-to-postmanv2-6.0.1.tgz", + "integrity": "sha512-zAjaTwXo07az6jjvZTw4d26QMQsFxZBxTqjj3LQQMDCCuO6+peATQc9bSmAq3QbzvikP+h2WEjTphMcIrcSurg==", + "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.11.0", + "ajv-draft-04": "1.0.0", + "ajv-formats": "2.1.1", + "async": "3.2.6", + "commander": "2.20.3", + "graphlib": "2.1.8", + "js-yaml": "4.1.0", + "json-pointer": "0.6.2", + "json-schema-merge-allof": "0.8.1", + "lodash": "4.17.21", + "neotraverse": "0.6.15", + "oas-resolver-browser": "2.5.6", + "object-hash": "3.0.0", + "openapi-types": "^12.1.3", + "path-browserify": "1.0.1", + "postman-collection": "^5.0.0", + "swagger2openapi": "7.0.8", + "yaml": "1.10.2" + }, + "bin": { + "openapi2postmanv2": "bin/openapi2postmanv2.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/openapi-to-postmanv2/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/openapi-to-postmanv2/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/openapi-to-postmanv2/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/openapi-to-postmanv2/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT" + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz", + "integrity": "sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.12.tgz", + "integrity": "sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-10.0.0.tgz", + "integrity": "sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-10.0.0.tgz", + "integrity": "sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-custom-media": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.6.tgz", + "integrity": "sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-properties": { + "version": "14.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz", + "integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.5.tgz", + "integrity": "sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", + "integrity": "sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.4.tgz", + "integrity": "sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-10.0.1.tgz", + "integrity": "sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-focus-within": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", + "integrity": "sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-6.0.0.tgz", + "integrity": "sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-image-set-function": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-7.0.0.tgz", + "integrity": "sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-lab-function": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.12.tgz", + "integrity": "sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.1.0.tgz", + "integrity": "sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-merge-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-resolve-nested": "^3.1.0", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", + "integrity": "sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-6.0.0.tgz", + "integrity": "sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-10.0.0.tgz", + "integrity": "sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.6.1.tgz", + "integrity": "sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-alpha-function": "^1.0.1", + "@csstools/postcss-cascade-layers": "^5.0.2", + "@csstools/postcss-color-function": "^4.0.12", + "@csstools/postcss-color-function-display-p3-linear": "^1.0.1", + "@csstools/postcss-color-mix-function": "^3.0.12", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.2", + "@csstools/postcss-content-alt-text": "^2.0.8", + "@csstools/postcss-contrast-color-function": "^2.0.12", + "@csstools/postcss-exponential-functions": "^2.0.9", + "@csstools/postcss-font-format-keywords": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.11", + "@csstools/postcss-gradients-interpolation-method": "^5.0.12", + "@csstools/postcss-hwb-function": "^4.0.12", + "@csstools/postcss-ic-unit": "^4.0.4", + "@csstools/postcss-initial": "^2.0.1", + "@csstools/postcss-is-pseudo-class": "^5.0.3", + "@csstools/postcss-light-dark-function": "^2.0.11", + "@csstools/postcss-logical-float-and-clear": "^3.0.0", + "@csstools/postcss-logical-overflow": "^2.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", + "@csstools/postcss-logical-resize": "^3.0.0", + "@csstools/postcss-logical-viewport-units": "^3.0.4", + "@csstools/postcss-media-minmax": "^2.0.9", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", + "@csstools/postcss-nested-calc": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.1", + "@csstools/postcss-oklab-function": "^4.0.12", + "@csstools/postcss-position-area-property": "^1.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.2.1", + "@csstools/postcss-property-rule-prelude-list": "^1.0.0", + "@csstools/postcss-random-function": "^2.0.1", + "@csstools/postcss-relative-color-syntax": "^3.0.12", + "@csstools/postcss-scope-pseudo-class": "^4.0.1", + "@csstools/postcss-sign-functions": "^1.1.4", + "@csstools/postcss-stepped-value-functions": "^4.0.9", + "@csstools/postcss-syntax-descriptor-syntax-production": "^1.0.1", + "@csstools/postcss-system-ui-font-family": "^1.0.0", + "@csstools/postcss-text-decoration-shorthand": "^4.0.3", + "@csstools/postcss-trigonometric-functions": "^4.0.9", + "@csstools/postcss-unset-value": "^4.0.0", + "autoprefixer": "^10.4.23", + "browserslist": "^4.28.1", + "css-blank-pseudo": "^7.0.1", + "css-has-pseudo": "^7.0.3", + "css-prefers-color-scheme": "^10.0.0", + "cssdb": "^8.6.0", + "postcss-attribute-case-insensitive": "^7.0.1", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^7.0.12", + "postcss-color-hex-alpha": "^10.0.0", + "postcss-color-rebeccapurple": "^10.0.0", + "postcss-custom-media": "^11.0.6", + "postcss-custom-properties": "^14.0.6", + "postcss-custom-selectors": "^8.0.5", + "postcss-dir-pseudo-class": "^9.0.1", + "postcss-double-position-gradients": "^6.0.4", + "postcss-focus-visible": "^10.0.1", + "postcss-focus-within": "^9.0.1", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^6.0.0", + "postcss-image-set-function": "^7.0.0", + "postcss-lab-function": "^7.0.12", + "postcss-logical": "^8.1.0", + "postcss-nesting": "^13.0.2", + "postcss-opacity-percentage": "^3.0.0", + "postcss-overflow-shorthand": "^6.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^10.0.0", + "postcss-pseudo-class-any-link": "^10.0.1", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-10.0.1.tgz", + "integrity": "sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-8.0.1.tgz", + "integrity": "sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", + "license": "MIT", + "dependencies": { + "sort-css-media-queries": "2.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.23" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/postcss-zindex": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postman-code-generators": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postman-code-generators/-/postman-code-generators-2.1.1.tgz", + "integrity": "sha512-+egQK1Jf9a92QP23vRTKcDLOthIQmI7WI4czEsZq/wgguLMnVHJ26KlT8AVtpAdVw28hqUbHwicerYxRWCfjoA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.2", + "detect-package-manager": "^3.0.2", + "lodash": "^4.17.21", + "postman-collection": "^5.0.0", + "shelljs": "^0.8.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postman-collection": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.3.0.tgz", + "integrity": "sha512-PMa5vRheqDFfS1bkRg8WBidWxunRA80sT5YNLP27YC5+ycyfiLMCwPnqQd1zfvxkGk04Pr9UronWmmgsbpsVyQ==", + "license": "Apache-2.0", + "dependencies": { + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.23", + "mime": "3.0.0", + "mime-format": "2.0.2", + "postman-url-encoder": "3.0.8", + "semver": "7.7.1", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postman-collection/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postman-collection/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/postman-collection/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/postman-collection/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-url-encoder": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.8.tgz", + "integrity": "sha512-EOgUMBazo7JNP4TDrd64TsooCiWzzo4143Ws8E8WYGEpn2PKpq+S4XRTDhuRTYHm3VKOpUZs7ZYZq7zSDuesqA==", + "license": "Apache-2.0", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.1.tgz", + "integrity": "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==", + "license": "MIT", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.3.0.tgz", + "integrity": "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==", + "license": "MIT", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-helmet-async": { + "name": "@slorber/react-helmet-async", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@slorber/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-e9/OK8VhwUSc67diWI8Rb3I0YgI9/SBQtnhe9aEuK6MhZm7ntZZimXgwXnd8W96YTmSOb9M4d8LwhRZyhWr/1A==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-hook-form": { + "version": "7.75.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.75.0.tgz", + "integrity": "sha512-Ovv94H+0p3sJ7B9B5QxPuCP1u8V/cHuVGyH55cSwodYDtoJwK+fqk3vjfIgSX59I2U/bU4z0nRJ9HMLpNiWEmw==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-json-view-lite": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.5.0.tgz", + "integrity": "sha512-tk7o7QG9oYyELWHL8xiMQ8x4WzjCzbWNyig3uexmkLb54r8jO0yH3WCWx8UZS0c49eSA4QUmG5caiRJ8fAn58g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" + }, + "node_modules/react-live": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/react-live/-/react-live-4.1.8.tgz", + "integrity": "sha512-B2SgNqwPuS2ekqj4lcxi5TibEcjWkdVyYykBEUBshPAPDQ527x2zPEZg560n8egNtAjUpwXFQm7pcXV65aAYmg==", + "license": "MIT", + "dependencies": { + "prism-react-renderer": "^2.4.0", + "sucrase": "^3.35.0", + "use-editable": "^2.3.3" + }, + "engines": { + "node": ">= 0.12.0", + "npm": ">= 2.0.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz", + "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-magic-dropzone": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-magic-dropzone/-/react-magic-dropzone-1.0.1.tgz", + "integrity": "sha512-0BIROPARmXHpk4AS3eWBOsewxoM5ndk2psYP/JmbCq8tz3uR2LIV1XiroZ9PKrmDRMctpW+TvsBCtWasuS8vFA==", + "license": "MIT" + }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw==", + "license": "MIT", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^3.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", + "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rtlcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.99.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", + "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-loader": { + "version": "16.0.8", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.8.tgz", + "integrity": "sha512-hcov4ZwZJIGbEuyNr9EmiTmZueyrxSToE6GOzoZnq5JM7ecRO7ttyvilPn+VmRsqiP16+VYZzVnGZj/hzZgKBA==", + "license": "MIT", + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/schema-dts": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.5.tgz", + "integrity": "sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==", + "license": "Apache-2.0" + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "license": "MIT", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", + "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", + "license": "MIT", + "dependencies": { + "@peculiar/x509": "^1.14.2", + "pkijs": "^3.3.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.7.tgz", + "integrity": "sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg==", + "license": "MIT", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "mime-types": "2.1.18", + "minimatch": "3.1.5", + "path-is-inside": "1.0.2", + "path-to-regexp": "3.3.0", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" + }, + "node_modules/serve-index": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "license": "MIT" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.3.tgz", + "integrity": "sha512-tAjEd+wt/YwnEbfNB2ht51ybBJxbEWwe5ki/Z//Wh0rpBFTCUSj46GnxUKEWzhfuJTsee8x3lybHxFgUMig2hw==", + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slugify": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", + "license": "MIT", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svgo": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", + "license": "MIT", + "dependencies": { + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/swc-loader": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.7.tgz", + "integrity": "sha512-nwYWw3Fh9ame3Rtm7StS9SBLpHRRnYcK7bnpF3UKZmesAK0gw2/ADvlURFAINmPvKtDLzp+GBiP9yLoEjg6S9w==", + "license": "MIT", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.47.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", + "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thingies": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-algebra": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", + "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==", + "license": "MIT" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "license": "MIT" + }, + "node_modules/use-editable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/use-editable/-/use-editable-2.3.3.tgz", + "integrity": "sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16.8.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", + "license": "MIT" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.106.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", + "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.1", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.3.tgz", + "integrity": "sha512-9Gyu2F7+bg4Vv+pjbovuYDhHX+mqdqITykfzdM9UyKqKHlsE5aAjRhR+oOEfXW5vBeu8tarzlJFIZva4ZjAdrQ==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.25", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.8.1", + "connect-history-api-fallback": "^2.0.0", + "express": "^4.22.1", + "graceful-fs": "^4.2.6", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^5.5.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", + "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpackbar": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", + "license": "MIT", + "dependencies": { + "ansis": "^3.2.0", + "consola": "^3.2.3", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@rspack/core": "*", + "webpack": "3 || 4 || 5" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wsl-utils/node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-formatter": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.7.0.tgz", + "integrity": "sha512-+8qTc3zv2UcJ1v9IsSIce37Dl4MQG14Cp7tWrwmy202UaI1wqRukw5QMX1JHsV+DX64yw77EgGsj2s5wGvuMbQ==", + "license": "MIT", + "dependencies": { + "xml-parser-xo": "^4.1.5" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/xml-parser-xo": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.5.tgz", + "integrity": "sha512-TxyRxk9sTOUg3glxSIY6f0nfuqRll2OEF8TspLgh5mZkLuBgheCn3zClcDSGJ58TvNmiwyCCuat4UajPud/5Og==", + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", + "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "license": "Apache-2.0" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/site/package.json b/docs/site/package.json new file mode 100644 index 000000000000..67aa4c572f0b --- /dev/null +++ b/docs/site/package.json @@ -0,0 +1,53 @@ +{ + "name": "@mattermost/docs-site", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids", + "typecheck": "tsc" + }, + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/faster": "3.10.1", + "@docusaurus/plugin-client-redirects": "^3.10.1", + "@docusaurus/preset-classic": "3.10.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "docusaurus-plugin-openapi-docs": "^5.0.2", + "docusaurus-theme-openapi-docs": "^5.0.2", + "prism-react-renderer": "^2.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "yaml": "^2.8.4" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/tsconfig": "3.10.1", + "@docusaurus/types": "3.10.1", + "@types/react": "^19.0.0", + "typescript": "~6.0.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=20.0" + } +} diff --git a/docs/site/scripts/build-openapi.mjs b/docs/site/scripts/build-openapi.mjs new file mode 100644 index 000000000000..5ebe1608b352 --- /dev/null +++ b/docs/site/scripts/build-openapi.mjs @@ -0,0 +1,174 @@ +#!/usr/bin/env node +/* + * Bundles the Mattermost OpenAPI fragments into a single YAML document. + * + * Canonical source: mattermost/mattermost/api/v4/source/. The upstream + * Makefile uses naive `cat` concatenation which produces *invalid* YAML + * when fragments declare the same path key (currently + * /api/v4/sharedchannels/{channel_id}/remotes lives in both + * channels.yaml and sharedchannels.yaml). This script does a real + * YAML parse + merge with last-wins semantics so the bundle validates. + * + * Skips: + * - The Go-based x-codeSamples extractor (we use the plugin's + * auto-generated curl/Go/Node/Python samples for now). + * - The Playbooks merge (separate spec; integrate later if needed). + * + * Usage: node docs-site/scripts/build-openapi.mjs + * Output: docs-site/openapi/mattermost-openapi-v4.yaml + */ + +import {readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync} from 'node:fs'; +import {dirname, join, resolve} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {parse, stringify} from 'yaml'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SITE_ROOT = resolve(HERE, '..'); +// docs/site/ → docs/ → mattermost/ (monorepo root where api/v4/source lives) +const REPO_ROOT = resolve(SITE_ROOT, '../..'); + +const PRE_MERGE_PATH = join(REPO_ROOT, 'sources/mattermost-api-source/api/v4/source'); +const POST_MERGE_PATH = join(REPO_ROOT, 'api/v4/source'); +const SOURCE_DIR = (existsSync(POST_MERGE_PATH) && readdirSync(POST_MERGE_PATH).some((f) => f.endsWith('.yaml'))) + ? POST_MERGE_PATH + : PRE_MERGE_PATH; + +const OUT = join(SITE_ROOT, 'openapi/mattermost-openapi-v4.yaml'); + +// Order matches the upstream Makefile build-v4 target. Order is significant +// because the openapi-docs plugin renders sidebar groups in tag order, and +// tags are first-seen in the file order. +const PATH_FRAGMENTS = [ + 'users', 'status', 'teams', 'channels', 'posts', 'preferences', 'files', + 'recaps', 'ai', 'uploads', 'jobs', 'system', 'emoji', 'webhooks', 'saml', + 'compliance', 'ldap', 'groups', 'cluster', 'brand', 'commands', 'oauth', + 'elasticsearch', 'bleve', 'dataretention', 'plugins', 'roles', 'schemes', + 'service_terms', 'remoteclusters', 'sharedchannels', 'reactions', 'actions', + 'bots', 'cloud', 'usage', 'permissions', 'imports', 'exports', 'ip_filters', + 'bookmarks', 'views', 'reports', 'limits', 'logs', + 'outgoing_oauth_connections', 'metrics', 'scheduled_post', + 'custom_profile_attributes', 'audit_logging', 'access_control', + 'content_flagging', 'agents', 'properties', +]; + +function loadYaml(name) { + const file = join(SOURCE_DIR, `${name}.yaml`); + if (!existsSync(file)) { + console.warn(`[openapi] skip (missing): ${name}.yaml`); + return null; + } + return parse(readFileSync(file, 'utf8')); +} + +function mergePaths(base, fragment, fragmentName) { + if (!fragment || typeof fragment !== 'object') return; + for (const [pathKey, pathItem] of Object.entries(fragment)) { + if (base[pathKey]) { + console.warn(`[openapi] duplicate path "${pathKey}" — overwritten by ${fragmentName}.yaml`); + } + base[pathKey] = pathItem; + } +} + +function walkStrings(node, fn, key) { + if (typeof node === 'string') return fn(node, key); + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) node[i] = walkStrings(node[i], fn, key); + return node; + } + if (node && typeof node === 'object') { + for (const [k, v] of Object.entries(node)) node[k] = walkStrings(v, fn, k); + return node; + } + return node; +} + +function deepMerge(target, source) { + for (const [k, v] of Object.entries(source ?? {})) { + if (v && typeof v === 'object' && !Array.isArray(v) && target[k] && typeof target[k] === 'object' && !Array.isArray(target[k])) { + deepMerge(target[k], v); + } else { + target[k] = v; + } + } +} + +function main() { + if (!existsSync(SOURCE_DIR)) { + console.error(`OpenAPI source not found at ${SOURCE_DIR}`); + process.exit(1); + } + + console.log(`[openapi] source: ${SOURCE_DIR}`); + + const intro = loadYaml('introduction'); + if (!intro) { + console.error('introduction.yaml is required as the bundle base'); + process.exit(1); + } + // introduction.yaml ends with `paths:` (open). After parsing it yields + // a doc whose paths key is null — initialize as empty object so we can + // merge fragments into it. + intro.paths = intro.paths ?? {}; + console.log(`[openapi] base: introduction.yaml (info, tags=${(intro.tags ?? []).length}, servers=${(intro.servers ?? []).length})`); + + let endpointCount = 0; + for (const name of PATH_FRAGMENTS) { + const frag = loadYaml(name); + if (!frag) continue; + const before = Object.keys(intro.paths).length; + mergePaths(intro.paths, frag, name); + const added = Object.keys(intro.paths).length - before; + endpointCount += Object.keys(frag).length; + console.log(`[openapi] ${name.padEnd(28)} +${added.toString().padStart(3)} paths (${Object.keys(frag).length} declared, ${Object.keys(frag).length - added} duplicates)`); + } + + const defs = loadYaml('definitions'); + if (defs) { + deepMerge(intro, defs); + console.log(`[openapi] merged definitions.yaml (components.schemas: ${Object.keys(intro.components?.schemas ?? {}).length})`); + } + + // Sanitize description text so docusaurus-plugin-openapi-docs writes + // valid MDX/YAML. + // 1) Embedded double-quotes break the plugin's `description: "..."` + // frontmatter (it discards the closing quote of `("")`). + // → replace inner `"..."` with curly quotes. + // 2) Markdown autolinks like `` break MDX (` { + if (key !== 'description' && key !== 'summary' && key !== 'title') return value; + let v = value; + if (v.includes('"')) { + const fixed = v.replace(/"([^"]*)"/g, '“$1”'); + if (fixed !== v) { quoteFixes++; v = fixed; } + } + if (/<[^a-zA-Z!]/.test(v)) { + const fixed = v.replace(/<(?=[^a-zA-Z!])/g, '<'); + if (fixed !== v) { autolinkFixes++; v = fixed; } + } + return v; + }); + console.log(`[openapi] sanitized: quotes=${quoteFixes}, autolinks=${autolinkFixes}`); + + const totalPaths = Object.keys(intro.paths).length; + const totalOperations = Object.values(intro.paths) + .flatMap((p) => Object.keys(p ?? {})) + .filter((k) => ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'].includes(k)) + .length; + + const out = stringify(intro, {lineWidth: 0}); + mkdirSync(dirname(OUT), {recursive: true}); + writeFileSync(OUT, out); + + const sizeMb = (out.length / 1024 / 1024).toFixed(2); + console.log(`[openapi] wrote ${OUT}`); + console.log(`[openapi] ${sizeMb} MB · ${totalPaths} unique paths · ${totalOperations} operations`); +} + +main(); diff --git a/docs/site/scripts/gen-active-redirects.mjs b/docs/site/scripts/gen-active-redirects.mjs new file mode 100644 index 000000000000..d08ab197b92e --- /dev/null +++ b/docs/site/scripts/gen-active-redirects.mjs @@ -0,0 +1,104 @@ +#!/usr/bin/env node +// Filter the raw redirects.json (extracted from the legacy Sphinx +// redirects.py) to the subset whose target MDX page actually exists in +// the migrated `docs/` tree. Output: +// docs-site/sidebars/active-redirects.json +// (kept in the sidebars/ folder since that's already gitignore-aware and +// regenerated). Consumed by docusaurus.config.ts via +// @docusaurus/plugin-client-redirects. +// +// Internal redirects whose destination is still missing (target page not +// yet migrated, or marked draft) are dropped silently — they'll start +// working as soon as the destination lands. External redirects (to +// github.com, other-host) need server-side rules and aren't emitted here. +// +// Usage: node docs-site/scripts/gen-active-redirects.mjs + +import {readFileSync, writeFileSync, readdirSync, statSync, existsSync} from 'node:fs'; +import {join, resolve, basename, dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SITE_ROOT = resolve(HERE, '..'); +const REPO_ROOT = resolve(SITE_ROOT, '..'); +const DOCS = join(REPO_ROOT, 'docs'); +const SRC = join(SITE_ROOT, 'scripts', 'migrate-main-docs', 'redirects.json'); +const OUT = join(SITE_ROOT, 'sidebars', 'active-redirects.json'); + +function isDraft(filePath) { + try { + const head = readFileSync(filePath, 'utf8').slice(0, 800); + return /^draft:\s*true/m.test(head); + } catch { return false; } +} + +function urlFromMdx(absPath) { + // docs/foo/bar.mdx → /foo/bar (index.mdx → /foo) + let rel = absPath.slice(DOCS.length).replace(/\\/g, '/'); + rel = rel.replace(/\.mdx$/, ''); + if (rel.endsWith('/index')) rel = rel.slice(0, -'/index'.length); + return rel || '/'; +} + +function collectExistingUrls() { + const urls = new Set(); + (function walk(dir) { + for (const name of readdirSync(dir)) { + const p = join(dir, name); + const s = statSync(p); + if (s.isDirectory()) walk(p); + else if (p.endsWith('.mdx') && !isDraft(p)) urls.add(urlFromMdx(p)); + } + })(DOCS); + return urls; +} + +function main() { + const raw = JSON.parse(readFileSync(SRC, 'utf8')); + const existing = collectExistingUrls(); + const active = []; + const missing = []; + const droppedAnchoredFrom = []; + for (const r of raw.internal) { + // @docusaurus/plugin-client-redirects requires `from` paths without + // anchors. Sphinx allowed anchored sources for mid-page redirects — + // those need server-side rules, not client-side. Drop them. + if (r.from.includes('#')) { droppedAnchoredFrom.push(r); continue; } + // Strip anchor when checking existence; preserve it in the emitted to. + const target = r.to.split('#')[0]; + if (existing.has(target)) active.push({from: r.from, to: r.to}); + else missing.push(r); + } + // De-duplicate: the plugin refuses duplicate FROM values. + const seenFrom = new Map(); + const final = []; + for (const r of active) { + if (seenFrom.has(r.from)) continue; + seenFrom.set(r.from, true); + final.push(r); + } + writeFileSync( + OUT, + JSON.stringify( + { + _meta: { + source: 'docs-site/scripts/migrate-main-docs/redirects.json', + active: final.length, + missing_target: missing.length, + dropped_anchored_from: droppedAnchoredFrom.length, + total_internal: raw.internal.length, + }, + redirects: final, + }, + null, + 2, + ), + ); + console.log(`[redirects] wrote ${OUT}`); + console.log(` active: ${final.length}`); + console.log(` missing target: ${missing.length}`); + console.log(` dropped (anchored): ${droppedAnchoredFrom.length}`); + console.log(` total internal: ${raw.internal.length}`); +} + +main(); diff --git a/docs/site/scripts/gen-developer-sidebar.mjs b/docs/site/scripts/gen-developer-sidebar.mjs new file mode 100644 index 000000000000..50529fe008ca --- /dev/null +++ b/docs/site/scripts/gen-developer-sidebar.mjs @@ -0,0 +1,122 @@ +#!/usr/bin/env node +// Generate the Developers sidebar from the migrated content tree under +// develop/. Output: docs-site/sidebars/developers.generated.json +// +// Usage: node docs-site/scripts/gen-developer-sidebar.mjs + +import {readFileSync, writeFileSync, readdirSync, statSync, existsSync} from 'node:fs'; +import {join, resolve, basename, dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SITE_ROOT = resolve(HERE, '..'); +const REPO_ROOT = resolve(SITE_ROOT, '..'); +const SRC = join(REPO_ROOT, 'develop'); +const OUT = join(SITE_ROOT, 'sidebars', 'developers.generated.json'); + +const TOP_LEVEL = [ + {dir: 'contribute', label: 'Contribute'}, + {dir: 'integrate', label: 'Integrate & Extend'}, + {dir: 'internal', label: 'Internal'}, +]; + +function humanize(name) { + return name.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()); +} + +function readFm(filePath, key) { + try { + const text = readFileSync(filePath, 'utf8').slice(0, 2000); + const m = text.match(/^---\n([\s\S]*?)\n---/); + if (!m) return null; + const r = new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, 'm'); + const x = m[1].match(r); + return x ? x[1].trim().replace(/^"|"$/g, '') : null; + } catch { return null; } +} + +function pathToDocId(relPath) { return relPath.replace(/\.(md|mdx)$/, ''); } + +function buildCategory(absDir, devRelDir) { + const items = []; + const entries = readdirSync(absDir); + const indexFile = entries.find((e) => /^index\.(md|mdx)$/.test(e)); + let categoryLink = null; + if (indexFile) { + categoryLink = {type: 'doc', id: pathToDocId(join(devRelDir, indexFile))}; + } + + const subDirs = []; + const leafDocs = []; + for (const name of entries) { + if (/^index\.(md|mdx)$/.test(name)) continue; + const abs = join(absDir, name); + const st = statSync(abs); + if (st.isDirectory()) subDirs.push(name); + else if (st.isFile() && /\.(md|mdx)$/.test(name)) leafDocs.push(name); + } + + function key(name, abs) { + const p = readFm(abs, 'sidebar_position'); + return [p ? Number(p) : 9999, name.toLowerCase()]; + } + leafDocs.sort((a, b) => { + const ka = key(a, join(absDir, a)); + const kb = key(b, join(absDir, b)); + return ka[0] - kb[0] || ka[1].localeCompare(kb[1]); + }); + subDirs.sort((a, b) => { + const ka = key(a, join(absDir, a, 'index.md')); + const kb = key(b, join(absDir, b, 'index.md')); + return ka[0] - kb[0] || ka[1].localeCompare(kb[1]); + }); + + for (const name of leafDocs) { + const id = pathToDocId(join(devRelDir, name)); + const label = readFm(join(absDir, name), 'title') || humanize(basename(name, /\.(md|mdx)$/.exec(name)[0])); + items.push({type: 'doc', id, label}); + } + for (const name of subDirs) { + const sub = buildCategory(join(absDir, name), join(devRelDir, name)); + // Skip empty subcategories — Docusaurus refuses sidebar categories that + // have neither a link nor any items. + if (sub) items.push(sub); + } + + const label = + readFm(join(absDir, 'index.md'), 'title') || + readFm(join(absDir, 'index.mdx'), 'title') || + humanize(basename(absDir)); + + if (!categoryLink && items.length === 0) return null; + + return {type: 'category', label, collapsed: true, ...(categoryLink ? {link: categoryLink} : {}), items}; +} + +function main() { + if (!existsSync(SRC)) { console.error(`develop/ not found at ${SRC}`); process.exit(1); } + + const sidebar = [{type: 'doc', id: 'index', label: 'Welcome'}]; + for (const {dir, label} of TOP_LEVEL) { + const abs = join(SRC, dir); + if (!existsSync(abs)) { console.warn(`[sidebar] skip ${dir}: missing`); continue; } + const cat = buildCategory(abs, dir); + cat.label = label; + cat.collapsed = true; + sidebar.push(cat); + } + writeFileSync(OUT, JSON.stringify(sidebar, null, 2)); + + let cats = 0, docs = 0; + (function walk(n) { + if (Array.isArray(n)) n.forEach(walk); + else if (n && typeof n === 'object') { + if (n.type === 'category') cats++; + if (n.type === 'doc') docs++; + if (n.items) walk(n.items); + } + })(sidebar); + console.log(`[sidebar] wrote ${OUT}: ${cats} categories, ${docs} docs`); +} + +main(); diff --git a/docs/site/scripts/gen-documentation-sidebar.mjs b/docs/site/scripts/gen-documentation-sidebar.mjs new file mode 100644 index 000000000000..69f3d2220465 --- /dev/null +++ b/docs/site/scripts/gen-documentation-sidebar.mjs @@ -0,0 +1,562 @@ +#!/usr/bin/env node +// Generate the Documentation sidebar from the migrated content tree under +// docs/. Output: docs-site/sidebars/documentation.generated.json +// +// Mirrors gen-developer-sidebar.mjs in structure. Only differences are +// the source directory and the top-level section list (per PLAN.md 3.1). +// +// Usage: node docs-site/scripts/gen-documentation-sidebar.mjs + +import {readFileSync, writeFileSync, readdirSync, statSync, existsSync} from 'node:fs'; +import {join, resolve, basename, dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SITE_ROOT = resolve(HERE, '..'); +const REPO_ROOT = resolve(SITE_ROOT, '..'); +const SRC = join(REPO_ROOT, 'docs'); +const OUT = join(SITE_ROOT, 'sidebars', 'documentation.generated.json'); + +const TOP_LEVEL = [ + {dir: 'product-overview', label: 'Overview'}, + {dir: 'use-case-guide', label: 'Use Case Guide'}, + {dir: 'deployment-guide', label: 'Deployment Guide'}, + {dir: 'administration-guide', label: 'Administration Guide'}, + {dir: 'security-guide', label: 'Security & Compliance'}, + {dir: 'end-user-guide', label: 'End User Guide'}, + {dir: 'integrations-guide', label: 'Integrations Guide'}, + {dir: 'get-help', label: 'Get Help'}, + {dir: 'agents', label: 'Agents'}, + {dir: 'recipes', label: 'Recipes'}, + {dir: 'samples', label: 'Samples'}, +]; + +function humanize(name) { + return name.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()); +} + +function readFm(filePath, key) { + try { + const text = readFileSync(filePath, 'utf8').slice(0, 4000); + const m = text.match(/^---\n([\s\S]*?)\n---/); + if (!m) return null; + const r = new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, 'm'); + const x = m[1].match(r); + return x ? x[1].trim().replace(/^"|"$/g, '') : null; + } catch { return null; } +} + +function isDraft(filePath) { + return readFm(filePath, 'draft') === 'true'; +} + +function pathToDocId(relPath) { return relPath.replace(/\.(md|mdx)$/, ''); } + +function buildCategory(absDir, docsRelDir) { + const entries = readdirSync(absDir); + const indexFile = entries.find((e) => /^index\.(md|mdx)$/.test(e)); + let categoryLink = null; + if (indexFile && !isDraft(join(absDir, indexFile))) { + categoryLink = {type: 'doc', id: pathToDocId(join(docsRelDir, indexFile))}; + } + + const subDirs = []; + const leafDocs = []; + for (const name of entries) { + if (/^index\.(md|mdx)$/.test(name)) continue; + const abs = join(absDir, name); + const st = statSync(abs); + if (st.isDirectory()) subDirs.push(name); + else if (st.isFile() && /\.(md|mdx)$/.test(name) && !isDraft(abs)) leafDocs.push(name); + } + + function key(name, abs) { + const p = readFm(abs, 'sidebar_position'); + return [p ? Number(p) : 9999, name.toLowerCase()]; + } + leafDocs.sort((a, b) => { + const ka = key(a, join(absDir, a)); + const kb = key(b, join(absDir, b)); + return ka[0] - kb[0] || ka[1].localeCompare(kb[1]); + }); + subDirs.sort((a, b) => { + const ka = key(a, join(absDir, a, 'index.mdx')); + const kb = key(b, join(absDir, b, 'index.mdx')); + return ka[0] - kb[0] || ka[1].localeCompare(kb[1]); + }); + + const items = []; + for (const name of leafDocs) { + const id = pathToDocId(join(docsRelDir, name)); + const filePath = join(absDir, name); + const label = readFm(filePath, 'sidebar_label') || + readFm(filePath, 'title') || + humanize(basename(name, /\.(md|mdx)$/.exec(name)[0])); + items.push({type: 'doc', id, label}); + } + for (const name of subDirs) { + const sub = buildCategory(join(absDir, name), join(docsRelDir, name)); + if (sub) items.push(sub); + } + + const label = + readFm(join(absDir, 'index.md'), 'title') || + readFm(join(absDir, 'index.mdx'), 'title') || + humanize(basename(absDir)); + + if (!categoryLink && items.length === 0) return null; + + return {type: 'category', label, collapsed: true, ...(categoryLink ? {link: categoryLink} : {}), items}; +} + +// Files in docs/product-overview/ that are MDX snippet/partial includes, +// not standalone pages. Excluded from the auto-generated sidebar so they +// don't appear as orphan entries. They remain importable from other MDX. +const OVERVIEW_HIDDEN = new Set([ + 'common-esr-support', + 'common-esr-support-upgrade', + 'common-esr-support-rst', +]); + +// Manual grouping override for the Overview section. +// +// The Overview directory is flat (~40 .mdx files at one level) for URL-stability +// reasons — moving files into sub-directories would break the redirect table. +// This override applies a logical grouping at sidebar-render time only; the +// files themselves stay flat on disk and their URLs stay stable. +// +// Mirrors the live docs.mattermost.com Overview structure. +const OVERVIEW_GROUPS = { + // 'Subscription Overview' — paid subscription model: Self-Hosted, Cloud, Non-Profit. + subscription: { + label: 'Subscription Overview', + landing: 'subscription', + items: [ + 'self-hosted-subscriptions', + {label: 'Cloud', landing: 'cloud-subscriptions', items: [ + 'cloud-dedicated', + 'cloud-shared', + 'cloud-vpc-private-connectivity', + 'cloud-supported-integrations', + 'corporate-directory-integration', + ]}, + 'non-profit-subscriptions', + ], + }, + // 'Releases and Life Cycle' with Server / Desktop / Mobile sub-groups. + releases: { + label: 'Releases and Life Cycle', + landing: 'releases-lifecycle', + items: [ + 'release-policy', + {label: 'Server', landing: 'server', items: [ + 'mattermost-server-releases', + 'mattermost-v11-changelog', + 'mattermost-v10-changelog', + 'unsupported-legacy-releases', + 'version-archive', + 'ui-ada-changelog', + ]}, + {label: 'Desktop', landing: 'desktop', items: [ + 'mattermost-desktop-releases', + 'desktop-app-changelog', + ]}, + {label: 'Mobile', landing: 'mobile', items: [ + 'mattermost-mobile-releases', + 'mobile-app-changelog', + ]}, + 'deprecated-features', + ], + }, + // 'Frequently Asked Questions'. + faq: { + label: 'Frequently Asked Questions', + landing: 'frequently-asked-questions', + items: [ + 'faq-general', + 'faq-enterprise', + 'faq-federal-procurement', + 'faq-license', + 'faq-mattermost-source-available-license', + ], + }, +}; + +// Top-level items in the Overview section, in order. Strings are doc basenames; +// objects are group keys from OVERVIEW_GROUPS above. Mirrors the live site. +const OVERVIEW_ROOT_ORDER = [ + 'editions-and-offerings', + 'plans', + {group: 'subscription'}, + 'certifications-and-compliance', + 'accessibility-compliance-policy', + {group: 'releases'}, + {group: 'faq'}, + // Locally-added pages not present on live: + 'whats-new-in-v11', +]; + +function buildOverviewItem(spec, leafLabels) { + if (typeof spec === 'string') { + const id = `product-overview/${spec}`; + return {type: 'doc', id, label: leafLabels[id] || humanize(spec)}; + } + if (spec.group) { + const g = OVERVIEW_GROUPS[spec.group]; + if (!g) throw new Error(`unknown overview group: ${spec.group}`); + return buildOverviewGroup(g, leafLabels); + } + return buildOverviewGroup(spec, leafLabels); +} + +function buildOverviewGroup(g, leafLabels) { + const items = g.items.map((it) => buildOverviewItem(it, leafLabels)); + const cat = {type: 'category', label: g.label, collapsed: true, items}; + if (g.landing) { + cat.link = {type: 'doc', id: `product-overview/${g.landing}`}; + } + return cat; +} + +// Pull every doc label from the auto-generated Overview category so the +// manual ordering preserves the frontmatter-derived titles. +function collectLeafLabels(cat, acc = {}) { + if (!cat || !cat.items) return acc; + for (const it of cat.items) { + if (it.type === 'doc' && it.id && it.label) acc[it.id] = it.label; + else if (it.type === 'category') collectLeafLabels(it, acc); + } + return acc; +} + +// =========================================================================== +// Deployment Guide — manual grouping override. +// =========================================================================== +// +// The Deployment Guide directory has loose top-level files mixed with sub- +// directories (server/, desktop/, mobile/, air-gapped-operations/, reference- +// architecture/). The auto-generated sidebar ends up as 16 mostly-alphabetical +// items at the top level, with a 16-item kitchen-sink under Server. +// +// This override applies a progression-ordered grouping (Try → Plan → Install +// → Operate → Security → Troubleshoot) at sidebar-render time only; the +// files themselves stay flat on disk and their URLs stay stable. +// +// Server's internal structure is also restructured into Plan / Install-by- +// platform / Configure-at-install sub-groups, and the four troubleshooting +// pages that live under server/ are pulled up into the top-level +// "Deployment Troubleshooting" category. + +const DEPLOYMENT_GROUPS = { + // 'Deployment Scenarios' — promoted from inside Reference Architecture + // to a top-level group. DISC-relevant patterns (Air-Gapped, DDIL, Mission + // Partner, OOB, Sovereign-on-Microsoft) deserve prominence, not burial. + deploymentScenarios: { + label: 'Deployment Scenarios', + landing: 'reference-architecture/deployment-scenarios/deployment-scenarios-index', + items: [ + 'reference-architecture/deployment-scenarios/air-gapped-deployment', + 'reference-architecture/deployment-scenarios/deploy-ddil-operations', + 'reference-architecture/deployment-scenarios/deploy-mission-partner', + 'reference-architecture/deployment-scenarios/deploy-oob', + 'reference-architecture/deployment-scenarios/deploy-sovereign-collaboration', + ], + }, + + // Server — fully restructured. Reference Architecture's remaining pages + // (Application Architecture + Software & Hardware Requirements) fold in + // here as the "Plan" sub-group, alongside Preparations + Solution Programs. + // The standalone Reference Architecture top-level category is eliminated; + // its index page (reference-architecture-index) is hidden from the sidebar + // (URL still resolves directly). + server: { + label: 'Server', + landing: 'server/server-deployment-planning', + items: [ + {label: 'Plan', items: [ + 'reference-architecture/application-architecture', + 'software-hardware-requirements', + 'server/preparations', + 'server/orchestration', + ]}, + // Install methods, each with their sub-pages. + {label: 'Install on Linux', landing: 'server/deploy-linux', items: [ + 'server/linux/deploy-ubuntu', + 'server/linux/deploy-rhel', + 'server/linux/deploy-tar', + ]}, + {label: 'Install on Kubernetes', landing: 'server/deploy-kubernetes', items: [ + 'server/kubernetes/deploy-k8s', + 'server/kubernetes/deploy-k8s-aks', + 'server/kubernetes/deploy-k8s-oke', + ]}, + {label: 'Install with Containers', landing: 'server/deploy-containers', items: [ + 'server/containers/install-docker', + 'server/containers/fips-stig', + ]}, + // Configure at install time — install-blocking decisions like FIPS, + // TLS, NGINX reverse proxy, image proxy, MySQL setup, pre-auth secrets. + {label: 'Configure at install time', items: [ + 'server/configure-fips-at-install-time', + 'server/setup-nginx-proxy', + 'server/setup-tls', + 'server/pre-authentication-secrets', + 'server/image-proxy', + 'server/prepare-mattermost-mysql-database', + ]}, + ], + }, + + // Backup & Disaster Recovery — group the two related pages. + backupDr: { + label: 'Backup & Disaster Recovery', + landing: 'backup-disaster-recovery', + items: [ + 'disaster-recovery-aws', + ], + }, + + // PostgreSQL Migration — group the three migration pages. + postgresMig: { + label: 'PostgreSQL Migration', + landing: 'postgres-migration', + items: [ + 'postgres-migration-assist-tool', + 'manual-postgres-migration', + ], + }, + + // Encryption — at-rest + in-transit. + encryption: { + label: 'Encryption', + landing: 'encryption-options', + items: [ + 'transport-encryption', + ], + }, + + // Deployment Troubleshooting — pulls in the four troubleshooting pages + // currently scattered inside server/, plus the existing top-level page. + troubleshooting: { + label: 'Deployment Troubleshooting', + landing: 'deployment-troubleshooting', + items: [ + 'server/troubleshooting', + 'server/docker-troubleshooting', + 'server/trouble_mysql', + 'server/trouble-postgres', + ], + }, +}; + +// Top-level Deployment Guide order — Try → Plan → Install → Operate → Security +// → Troubleshoot. Strings are paths relative to docs/deployment-guide/; objects +// reference DEPLOYMENT_GROUPS keys or are inline sub-directories handled +// by the auto-generator (Desktop, Mobile, Air-Gapped Operations). +const DEPLOYMENT_ROOT_ORDER = [ + 'quick-start-evaluation', + {group: 'deploymentScenarios'}, + 'deployment-architecture', + {group: 'server'}, + // Desktop, Mobile, Air-Gapped Operations keep their auto-generated trees + // (each has its own index file + sub-pages). Referenced by the `__auto__` + // sentinel so we slot them in here, in the order we want. + {auto: 'desktop'}, + {auto: 'mobile'}, + {auto: 'air-gapped-operations'}, + {group: 'backupDr'}, + {group: 'postgresMig'}, + {group: 'encryption'}, + {group: 'troubleshooting'}, +]; + +// Files re-parented into other groups — exclude from the orphan check so they +// don't get re-appended at root level. +const DEPLOYMENT_HIDDEN = new Set([ + 'software-hardware-requirements', // → server Plan + 'reference-architecture/application-architecture', // → server Plan + 'reference-architecture/reference-architecture-index', // orphan after RA removal — URL still resolves directly + 'backup-disaster-recovery', // → backupDr (as landing) + 'disaster-recovery-aws', // → backupDr + 'postgres-migration', // → postgresMig (as landing) + 'postgres-migration-assist-tool', // → postgresMig + 'manual-postgres-migration', // → postgresMig + 'encryption-options', // → encryption (as landing) + 'transport-encryption', // → encryption + 'deployment-troubleshooting', // → troubleshooting (as landing) + 'server/troubleshooting', // → troubleshooting + 'server/docker-troubleshooting', // → troubleshooting + 'server/trouble_mysql', // → troubleshooting + 'server/trouble-postgres', // → troubleshooting +]); + +function buildDeploymentItem(spec, leafLabels, autoCats) { + if (typeof spec === 'string') { + const id = `deployment-guide/${spec}`; + return {type: 'doc', id, label: leafLabels[id] || humanize(spec.split('/').pop())}; + } + if (spec.doc) { + // Explicit doc leaf with an inline label override. + const id = `deployment-guide/${spec.doc}`; + return {type: 'doc', id, label: spec.label || leafLabels[id] || humanize(spec.doc.split('/').pop())}; + } + if (spec.auto) { + // Reference an auto-generated sub-category (e.g., Desktop, Mobile, Air-Gapped). + const cat = autoCats.get(spec.auto); + if (!cat) throw new Error(`auto-category not found: deployment-guide/${spec.auto}`); + return cat; + } + if (spec.group) { + const g = DEPLOYMENT_GROUPS[spec.group]; + if (!g) throw new Error(`unknown deployment group: ${spec.group}`); + return buildDeploymentGroup(g, leafLabels, autoCats); + } + return buildDeploymentGroup(spec, leafLabels, autoCats); +} + +function buildDeploymentGroup(g, leafLabels, autoCats) { + const items = g.items.map((it) => buildDeploymentItem(it, leafLabels, autoCats)); + const cat = {type: 'category', label: g.label, collapsed: true, items}; + if (g.landing) { + cat.link = {type: 'doc', id: `deployment-guide/${g.landing}`}; + } + return cat; +} + +function buildDeploymentSidebar(autoCat) { + // Index the auto-generated sub-categories by directory name so we can + // hand them off intact to the manual ordering. We look at the category's + // link target first, and fall back to the first doc child if the dir + // has no index.{md,mdx} (e.g., desktop/, mobile/). + const autoCats = new Map(); + function dirNameFromId(id) { + const parts = id.split('/'); + return parts.length >= 2 ? parts[1] : null; + } + for (const it of autoCat.items) { + if (it.type !== 'category') continue; + let dirName = null; + if (it.link && it.link.id) { + dirName = dirNameFromId(it.link.id); + } + if (!dirName && it.items) { + const firstDoc = it.items.find((c) => c.type === 'doc' && c.id); + if (firstDoc) dirName = dirNameFromId(firstDoc.id); + } + if (dirName) autoCats.set(dirName, it); + } + + const leafLabels = collectLeafLabels(autoCat); + + const items = DEPLOYMENT_ROOT_ORDER.map((spec) => buildDeploymentItem(spec, leafLabels, autoCats)); + + // Orphan detection: surface any leaf doc in the Deployment Guide that we + // didn't include in the manual order, so new files don't silently disappear. + // DEPLOYMENT_HIDDEN is files we KNOW are re-parented inside groups — they + // are referenced (so their labels need to stay in leafLabels) but they + // must not be re-emitted as orphans. + const hiddenIds = new Set(); + for (const h of DEPLOYMENT_HIDDEN) hiddenIds.add(`deployment-guide/${h}`); + const known = new Set(); + (function walk(n) { + if (Array.isArray(n)) n.forEach(walk); + else if (n && typeof n === 'object') { + if (n.type === 'doc' && n.id) known.add(n.id); + if (n.link && n.link.id) known.add(n.link.id); + if (n.items) walk(n.items); + } + })(items); + const orphans = []; + for (const id of Object.keys(leafLabels)) { + if (!known.has(id) && !hiddenIds.has(id) && id !== 'deployment-guide/deployment-guide-index') { + orphans.push(id); + } + } + if (orphans.length > 0) { + console.warn(`[sidebar] WARN: ${orphans.length} Deployment Guide file(s) missing from DEPLOYMENT_ROOT_ORDER — falling through to root:`); + for (const id of orphans) console.warn(` - ${id}`); + for (const id of orphans) items.push({type: 'doc', id, label: leafLabels[id]}); + } + + return { + type: 'category', + label: 'Deployment Guide', + collapsed: true, + link: {type: 'doc', id: 'deployment-guide/deployment-guide-index'}, + items, + }; +} + +function buildOverviewSidebar(autoCat) { + const leafLabels = collectLeafLabels(autoCat); + // Drop hidden snippet-include partials from the label map up front. + for (const hidden of OVERVIEW_HIDDEN) delete leafLabels[`product-overview/${hidden}`]; + + const items = OVERVIEW_ROOT_ORDER.map((spec) => buildOverviewItem(spec, leafLabels)); + + // Surface any flat docs we didn't include in the manual order so a new + // file dropped into docs/product-overview/ doesn't silently disappear. + const known = new Set(); + (function walk(n) { + if (Array.isArray(n)) n.forEach(walk); + else if (n && typeof n === 'object') { + if (n.type === 'doc' && n.id) known.add(n.id); + if (n.link && n.link.id) known.add(n.link.id); + if (n.items) walk(n.items); + } + })(items); + const orphans = []; + for (const id of Object.keys(leafLabels)) { + if (!known.has(id) && id !== 'product-overview/product-overview-index') orphans.push(id); + } + if (orphans.length > 0) { + console.warn(`[sidebar] WARN: ${orphans.length} Overview file(s) missing from OVERVIEW_ROOT_ORDER — falling through to root:`); + for (const id of orphans) console.warn(` - ${id}`); + for (const id of orphans) items.push({type: 'doc', id, label: leafLabels[id]}); + } + + return { + type: 'category', + label: 'Overview', + collapsed: true, + // Merged with the site landing — clicking "Overview" opens the + // root doc (docs/index.mdx, slug: /), which is the unified + // welcome / Overview page. + link: {type: 'doc', id: 'index'}, + items, + }; +} + +function main() { + if (!existsSync(SRC)) { console.error(`docs/ not found at ${SRC}`); process.exit(1); } + + const sidebar = []; + for (const {dir, label} of TOP_LEVEL) { + const abs = join(SRC, dir); + if (!existsSync(abs)) continue; + let cat = buildCategory(abs, dir); + if (!cat) continue; + cat.label = label; + cat.collapsed = true; + if (dir === 'product-overview') { + cat = buildOverviewSidebar(cat); + } else if (dir === 'deployment-guide') { + cat = buildDeploymentSidebar(cat); + } + sidebar.push(cat); + } + writeFileSync(OUT, JSON.stringify(sidebar, null, 2)); + + let cats = 0, docs = 0; + (function walk(n) { + if (Array.isArray(n)) n.forEach(walk); + else if (n && typeof n === 'object') { + if (n.type === 'category') cats++; + if (n.type === 'doc') docs++; + if (n.items) walk(n.items); + } + })(sidebar); + console.log(`[sidebar] wrote ${OUT}: ${cats} categories, ${docs} docs`); +} + +main(); diff --git a/docs/site/scripts/gen-hex-camo.mjs b/docs/site/scripts/gen-hex-camo.mjs new file mode 100644 index 000000000000..d002743ec6c9 --- /dev/null +++ b/docs/site/scripts/gen-hex-camo.mjs @@ -0,0 +1,99 @@ +#!/usr/bin/env node +/* + * Generates a tileable hexagonal camouflage SVG, matching the Mattermost + * brand book "Hexagonal Camouflage" pattern (denim variant, primary + * brand background). + * + * Output: docs-site/static/img/patterns/hex-camo-denim.svg + * + * Re-run if you want to tweak the shade mix / density / cell size. + */ + +import {writeFileSync, mkdirSync} from 'node:fs'; +import {dirname, join, resolve} from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const OUT = resolve(HERE, '../static/img/patterns/hex-camo-denim.svg'); + +// Tile dimensions. Side=9 → ~3x smaller cells than v1 (was side=24). +// Reads as fine grain / texture rather than chunky mosaic. +const SIDE = 9; +const HEX_W = 2 * SIDE; +const HEX_H = Math.sqrt(3) * SIDE; +const COL_STEP = 1.5 * SIDE; +const ROW_STEP = HEX_H; + +const COLS = 8; // 8 cols × 8 rows ≈ 108×125 tile +const ROWS = 8; +const TILE_W = COL_STEP * COLS; +const TILE_H = ROW_STEP * ROWS; + +// Tight shade band — every cell is within a narrow window of denim-500. +// The base color matches the hero's solid bg, so most cells visually +// disappear; only the slightly-lighter cells provide the texture beat. +// No marigold / no high-contrast outliers. +const SHADES = [ + {color: '#1E325C', weight: 14}, // denim-500 (matches hero bg — invisible cells) + {color: '#22386A', weight: 5}, // +4 lightness — faintly visible + {color: '#172A4F', weight: 3}, // -2 lightness — adds depth shadow +]; + +// Stable PRNG so the SVG is deterministic and reproducible across runs. +function mulberry32(seed) { + return () => { + seed |= 0; seed = (seed + 0x6D2B79F5) | 0; + let t = seed; + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} +const rand = mulberry32(0xCAFE); + +function pickShade() { + const total = SHADES.reduce((s, x) => s + x.weight, 0); + let r = rand() * total; + for (const s of SHADES) { + if (r < s.weight) return s.color; + r -= s.weight; + } + return SHADES[0].color; +} + +function hexPath(cx, cy) { + const pts = []; + for (let i = 0; i < 6; i++) { + const a = Math.PI / 3 * i; + pts.push(`${(cx + SIDE * Math.cos(a)).toFixed(2)},${(cy + SIDE * Math.sin(a)).toFixed(2)}`); + } + return `M${pts.join(' L')}Z`; +} + +const polygons = []; +// Render extra cells beyond the tile edge so the seam is hidden when tiled. +for (let col = -1; col <= COLS + 1; col++) { + for (let row = -1; row <= ROWS + 1; row++) { + const cx = col * COL_STEP; + const cy = row * ROW_STEP + (col % 2 ? ROW_STEP / 2 : 0); + polygons.push(``); + } +} + +const svg = ` + + + + + + + ${polygons.join('\n ')} + + +`; + +mkdirSync(dirname(OUT), {recursive: true}); +writeFileSync(OUT, svg); +console.log(`wrote ${OUT} (${TILE_W}×${TILE_H.toFixed(1)})`); diff --git a/docs/site/sidebars/active-redirects.json b/docs/site/sidebars/active-redirects.json new file mode 100644 index 000000000000..15f67abf4cf8 --- /dev/null +++ b/docs/site/sidebars/active-redirects.json @@ -0,0 +1,2779 @@ +{ + "_meta": { + "source": "docs-site/scripts/migrate-main-docs/redirects.json", + "active": 691, + "missing_target": 217, + "dropped_anchored_from": 1113, + "total_internal": 2021 + }, + "redirects": [ + { + "from": "/about/accessibility-compliance-policy", + "to": "/product-overview/accessibility-compliance-policy" + }, + { + "from": "/about/cloud-supported-integrations", + "to": "/product-overview/cloud-supported-integrations" + }, + { + "from": "/about/common-esr-support-rst", + "to": "/product-overview/common-esr-support-rst" + }, + { + "from": "/about/desktop", + "to": "/product-overview/desktop" + }, + { + "from": "/about/frequently-asked-questions", + "to": "/product-overview/frequently-asked-questions" + }, + { + "from": "/about/mobile", + "to": "/product-overview/mobile" + }, + { + "from": "/about/security/zero-trust", + "to": "/security-guide/zero-trust" + }, + { + "from": "/about/cloud-dedicated", + "to": "/product-overview/cloud-dedicated" + }, + { + "from": "/about/cloud-shared", + "to": "/product-overview/cloud-shared" + }, + { + "from": "/about/cloud-vpc-private-connectivity", + "to": "/product-overview/cloud-vpc-private-connectivity" + }, + { + "from": "/about/common-esr-support-upgrade", + "to": "/product-overview/common-esr-support-upgrade" + }, + { + "from": "/about/common-esr-support", + "to": "/product-overview/common-esr-support" + }, + { + "from": "/about/corporate-directory-integration", + "to": "/product-overview/corporate-directory-integration" + }, + { + "from": "/about/deprecated-features", + "to": "/product-overview/deprecated-features" + }, + { + "from": "/about/deployments-and-editions", + "to": "/product-overview/editions-and-offerings" + }, + { + "from": "/about/desktop-app-changelog", + "to": "/product-overview/desktop-app-changelog" + }, + { + "from": "/about/devops-collaboration", + "to": "/use-case-guide/devops-collaboration" + }, + { + "from": "/about/editions-and-offerings", + "to": "/product-overview/editions-and-offerings" + }, + { + "from": "/about/faq-community", + "to": "/get-help/contribute-to-documentation#frequently-asked-questions.html" + }, + { + "from": "/about/faq-enterprise", + "to": "/product-overview/faq-enterprise" + }, + { + "from": "/about/faq-federal-procurement", + "to": "/product-overview/faq-federal-procurement" + }, + { + "from": "/about/faq-general", + "to": "/product-overview/faq-general" + }, + { + "from": "/about/faq-integrations", + "to": "/integrations-guide/integrations-guide-index#frequently-asked-questions.html" + }, + { + "from": "/about/faq-mattermost-source-available-license", + "to": "/product-overview/faq-mattermost-source-available-license" + }, + { + "from": "/about/faq-notifications", + "to": "/end-user-guide/preferences/troubleshoot-notifications#frequently-asked-questions.html" + }, + { + "from": "/about/faq-video-audio-screensharing", + "to": "/end-user-guide/collaborate/audio-and-screensharing" + }, + { + "from": "/about/integrated-security-operations", + "to": "/use-case-guide/integrated-security-operations" + }, + { + "from": "/about/mattermost-desktop-releases", + "to": "/product-overview/mattermost-desktop-releases" + }, + { + "from": "/about/mattermost-mobile-releases", + "to": "/product-overview/mattermost-mobile-releases" + }, + { + "from": "/about/mattermost-server-releases", + "to": "/product-overview/mattermost-server-releases" + }, + { + "from": "/about/mattermost-v10-changelog", + "to": "/product-overview/mattermost-v10-changelog" + }, + { + "from": "/about/maximize-microsoft-investments", + "to": "/use-case-guide/maximize-microsoft-investments" + }, + { + "from": "/about/mission-ready-mobile", + "to": "/use-case-guide/mission-ready-mobile" + }, + { + "from": "/about/mobile-app-changelog", + "to": "/product-overview/mobile-app-changelog" + }, + { + "from": "/about/non-profit-subscriptions", + "to": "/product-overview/non-profit-subscriptions" + }, + { + "from": "/about/on-prem-skype-for-business-replacement", + "to": "/use-case-guide/on-prem-skype-for-business-replacement" + }, + { + "from": "/about/out-of-band-incident-response", + "to": "/use-case-guide/out-of-band-incident-response" + }, + { + "from": "/about/purpose-built-collaboration", + "to": "/use-case-guide/purpose-built-collaboration" + }, + { + "from": "/about/release-policy", + "to": "/product-overview/release-policy" + }, + { + "from": "/about/releases-lifecycle", + "to": "/product-overview/releases-lifecycle" + }, + { + "from": "/about/secure-command-and-control", + "to": "/use-case-guide/secure-command-and-control" + }, + { + "from": "/about/security", + "to": "/security-guide/security-guide-index" + }, + { + "from": "/about/security/dependency-vulnerability-analysis", + "to": "/security-guide/dependency-vulnerability-analysis" + }, + { + "from": "/about/security/mobile-security", + "to": "/security-guide/mobile-security" + }, + { + "from": "/about/self-hosted-subscriptions", + "to": "/product-overview/self-hosted-subscriptions" + }, + { + "from": "/about/self-sovereign-collaboration", + "to": "/use-case-guide/self-sovereign-collaboration" + }, + { + "from": "/about/server", + "to": "/product-overview/server" + }, + { + "from": "/about/subscription", + "to": "/product-overview/subscription" + }, + { + "from": "/about/unsupported-legacy-releases", + "to": "/product-overview/unsupported-legacy-releases" + }, + { + "from": "/about/version-archive", + "to": "/product-overview/version-archive" + }, + { + "from": "/boards/boards-settings", + "to": "/end-user-guide/project-management/boards-settings" + }, + { + "from": "/boards/calculations", + "to": "/end-user-guide/project-management/calculations" + }, + { + "from": "/boards/groups-filter-sort", + "to": "/end-user-guide/project-management/groups-filter-sort" + }, + { + "from": "/boards/migrate-to-boards", + "to": "/end-user-guide/project-management/migrate-to-boards" + }, + { + "from": "/boards/navigate-boards", + "to": "/end-user-guide/project-management/navigate-boards" + }, + { + "from": "/boards/work-with-boards", + "to": "/end-user-guide/project-management/work-with-boards" + }, + { + "from": "/boards/work-with-cards", + "to": "/end-user-guide/project-management/work-with-cards" + }, + { + "from": "/boards/work-with-views", + "to": "/end-user-guide/project-management/work-with-views" + }, + { + "from": "/collaborate/access-your-workspace", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/collaborate/agents-context-management", + "to": "/end-user-guide/collaborate/agents-context-management" + }, + { + "from": "/collaborate/archive-unarchive-channels", + "to": "/end-user-guide/collaborate/archive-unarchive-channels" + }, + { + "from": "/collaborate/audio-and-screensharing", + "to": "/end-user-guide/collaborate/audio-and-screensharing" + }, + { + "from": "/collaborate/browse-channels", + "to": "/end-user-guide/collaborate/browse-channels" + }, + { + "from": "/collaborate/built-in-slash-commands", + "to": "/integrations-guide/built-in-slash-commands" + }, + { + "from": "/collaborate/channel-header-purpose", + "to": "/end-user-guide/collaborate/channel-header-purpose" + }, + { + "from": "/collaborate/channel-naming-conventions", + "to": "/end-user-guide/collaborate/channel-naming-conventions" + }, + { + "from": "/collaborate/channel-types", + "to": "/end-user-guide/collaborate/channel-types" + }, + { + "from": "/collaborate/collaborate-within-connected-microsoft-teams", + "to": "/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams" + }, + { + "from": "/collaborate/convert-group-messages", + "to": "/end-user-guide/collaborate/convert-group-messages" + }, + { + "from": "/collaborate/convert-public-channels", + "to": "/end-user-guide/collaborate/convert-public-channels" + }, + { + "from": "/collaborate/create-channels", + "to": "/end-user-guide/collaborate/create-channels" + }, + { + "from": "/collaborate/display-channel-banners", + "to": "/end-user-guide/collaborate/display-channel-banners" + }, + { + "from": "/collaborate/extend-mattermost-with-integrations", + "to": "/end-user-guide/collaborate/extend-mattermost-with-integrations" + }, + { + "from": "/collaborate/favorite-channels", + "to": "/end-user-guide/collaborate/favorite-channels" + }, + { + "from": "/collaborate/forward-messages", + "to": "/end-user-guide/collaborate/forward-messages" + }, + { + "from": "/collaborate/install-android-app", + "to": "/end-user-guide/access/install-android-app" + }, + { + "from": "/collaborate/install-desktop-app", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/collaborate/install-ios-app", + "to": "/end-user-guide/access/install-ios-app" + }, + { + "from": "/collaborate/invite-people", + "to": "/end-user-guide/collaborate/invite-people" + }, + { + "from": "/collaborate/join-leave-channels", + "to": "/end-user-guide/collaborate/join-leave-channels" + }, + { + "from": "/collaborate/learn-about-roles", + "to": "/end-user-guide/collaborate/learn-about-roles" + }, + { + "from": "/collaborate/log-out", + "to": "/end-user-guide/access/log-out" + }, + { + "from": "/collaborate/manage-channel-bookmarks", + "to": "/end-user-guide/collaborate/manage-channel-bookmarks" + }, + { + "from": "/collaborate/manage-channel-members", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/collaborate/mark-channels-unread", + "to": "/end-user-guide/collaborate/mark-channels-unread" + }, + { + "from": "/collaborate/mark-messages-unread", + "to": "/end-user-guide/collaborate/mark-messages-unread" + }, + { + "from": "/collaborate/mention-people", + "to": "/end-user-guide/collaborate/mention-people" + }, + { + "from": "/collaborate/message-priority", + "to": "/end-user-guide/collaborate/message-priority" + }, + { + "from": "/collaborate/message-reminders", + "to": "/end-user-guide/collaborate/message-reminders" + }, + { + "from": "/collaborate/navigate-between-channels", + "to": "/end-user-guide/collaborate/navigate-between-channels" + }, + { + "from": "/collaborate/organize-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/collaborate/organize-using-custom-user-groups", + "to": "/end-user-guide/collaborate/organize-using-custom-user-groups" + }, + { + "from": "/collaborate/organize-using-teams", + "to": "/end-user-guide/collaborate/organize-using-teams" + }, + { + "from": "/collaborate/react-with-emojis-gifs", + "to": "/end-user-guide/collaborate/react-with-emojis-gifs" + }, + { + "from": "/collaborate/rename-channels", + "to": "/end-user-guide/collaborate/rename-channels" + }, + { + "from": "/collaborate/reply-to-messages", + "to": "/end-user-guide/collaborate/reply-to-messages" + }, + { + "from": "/collaborate/save-pin-messages", + "to": "/end-user-guide/collaborate/save-pin-messages" + }, + { + "from": "/collaborate/schedule-messages", + "to": "/end-user-guide/collaborate/schedule-messages" + }, + { + "from": "/collaborate/search-for-messages", + "to": "/end-user-guide/collaborate/search-for-messages" + }, + { + "from": "/collaborate/collaborate-within-channels", + "to": "/end-user-guide/collaborate/collaborate-within-channels" + }, + { + "from": "/collaborate/communicate-with-messages", + "to": "/end-user-guide/collaborate/communicate-with-messages" + }, + { + "from": "/collaborate/send-messages", + "to": "/end-user-guide/collaborate/send-messages" + }, + { + "from": "/collaborate/share-files-in-messages", + "to": "/end-user-guide/collaborate/share-files-in-messages" + }, + { + "from": "/collaborate/share-links", + "to": "/end-user-guide/collaborate/share-links" + }, + { + "from": "/collaborate/team-settings", + "to": "/end-user-guide/collaborate/team-settings" + }, + { + "from": "/collaborate/view-system-information", + "to": "/end-user-guide/collaborate/view-system-information" + }, + { + "from": "/administration/announcement-banner", + "to": "/administration-guide/manage/system-wide-notifications" + }, + { + "from": "/administration/backup", + "to": "/deployment-guide/backup-disaster-recovery" + }, + { + "from": "/administration/branding", + "to": "/administration-guide/manage/admin/customize-branding" + }, + { + "from": "/administration/changelog", + "to": "/product-overview/mattermost-server-releases" + }, + { + "from": "/administration/command-line-tools", + "to": "/administration-guide/manage/command-line-tools" + }, + { + "from": "/administration/compliance-export", + "to": "/administration-guide/comply/compliance-export" + }, + { + "from": "/administration/config-in-database", + "to": "/administration-guide/configure/configuration-in-your-database" + }, + { + "from": "/administration/data-retention", + "to": "/administration-guide/comply/data-retention-policy" + }, + { + "from": "/administration/downgrade", + "to": "/administration-guide/upgrade/downgrading-mattermost-server" + }, + { + "from": "/administration/ediscovery", + "to": "/administration-guide/comply/electronic-discovery" + }, + { + "from": "/administration/encryption", + "to": "/deployment-guide/encryption-options" + }, + { + "from": "/administration/extended-support-release", + "to": "/product-overview/release-policy#extended-support-releases" + }, + { + "from": "/administration/hipchat-migration-guidelines", + "to": "/administration-guide/onboard/migrating-to-mattermost" + }, + { + "from": "/administration/image-proxy", + "to": "/deployment-guide/server/image-proxy" + }, + { + "from": "/administration/legacy-upgrade", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/administration/light-install-hindi", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/administration/migrating", + "to": "/administration-guide/onboard/migrating-to-mattermost" + }, + { + "from": "/administration/migration-announcement-email-template", + "to": "/administration-guide/onboard/migration-announcement-email" + }, + { + "from": "/administration/mobile-changelog", + "to": "/product-overview/mobile-app-changelog" + }, + { + "from": "/administration/notices", + "to": "/administration-guide/manage/in-product-notices" + }, + { + "from": "/administration/open-source-components", + "to": "/administration-guide/upgrade/open-source-components" + }, + { + "from": "/administration/prev-config-settings", + "to": "/administration-guide/configure/configuration-settings" + }, + { + "from": "/administration/releases-lifecycle", + "to": "/product-overview/releases-lifecycle" + }, + { + "from": "/administration/statistics", + "to": "/administration-guide/manage/statistics" + }, + { + "from": "/administration/telemetry", + "to": "/administration-guide/manage/telemetry" + }, + { + "from": "/administration/upgrade", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/administration/upgrade-guide", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/administration/upgrading-to-2.0", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/administration/upgrading-to-3.0", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/administration/user-provisioning", + "to": "/administration-guide/onboard/user-provisioning-workflows" + }, + { + "from": "/administration/config-settings", + "to": "/administration-guide/configure/configuration-settings" + }, + { + "from": "/administration/version-archive", + "to": "/product-overview/version-archive" + }, + { + "from": "/administration/release-lifecycle", + "to": "/product-overview/releases-lifecycle" + }, + { + "from": "/administration-guide/configure/calls-deployment", + "to": "/administration-guide/configure/calls-deployment-guide" + }, + { + "from": "/administration-guide/configure/calls-overview", + "to": "/administration-guide/configure/calls-deployment-guide" + }, + { + "from": "/channels/find-channels", + "to": "/end-user-guide/collaborate/browse-channels" + }, + { + "from": "/channels/sign-in", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/channels/channel-types", + "to": "/end-user-guide/collaborate/channel-types" + }, + { + "from": "/channels/create-channels", + "to": "/end-user-guide/collaborate/create-channels" + }, + { + "from": "/channels/channel-naming-conventions", + "to": "/end-user-guide/collaborate/channel-naming-conventions" + }, + { + "from": "/channels/rename-channels", + "to": "/end-user-guide/collaborate/rename-channels" + }, + { + "from": "/channels/convert-public-channels", + "to": "/end-user-guide/collaborate/convert-public-channels" + }, + { + "from": "/channels/join-leave-channels", + "to": "/end-user-guide/collaborate/join-leave-channels" + }, + { + "from": "/channels/manage-channel-members", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/channels/browse-channels", + "to": "/end-user-guide/collaborate/browse-channels" + }, + { + "from": "/channels/navigate-between-channels", + "to": "/end-user-guide/collaborate/navigate-between-channels" + }, + { + "from": "/channels/favorite-channels", + "to": "/end-user-guide/collaborate/favorite-channels" + }, + { + "from": "/channels/mark-channels-unread", + "to": "/end-user-guide/collaborate/mark-channels-unread" + }, + { + "from": "/channels/customize-your-channel-sidebar", + "to": "/end-user-guide/preferences/customize-your-channel-sidebar" + }, + { + "from": "/channels/archive-unarchive-channels", + "to": "/end-user-guide/collaborate/archive-unarchive-channels" + }, + { + "from": "/channels/send-messages", + "to": "/end-user-guide/collaborate/send-messages" + }, + { + "from": "/channels/message-priority", + "to": "/end-user-guide/collaborate/message-priority" + }, + { + "from": "/channels/reply-to-messages", + "to": "/end-user-guide/collaborate/reply-to-messages" + }, + { + "from": "/channels/organize-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/channels/mention-people", + "to": "/end-user-guide/collaborate/mention-people" + }, + { + "from": "/channels/mark-messages-unread", + "to": "/end-user-guide/collaborate/mark-messages-unread" + }, + { + "from": "/channels/share-files-in-messages", + "to": "/end-user-guide/collaborate/share-files-in-messages" + }, + { + "from": "/channels/forward-messages", + "to": "/end-user-guide/collaborate/forward-messages" + }, + { + "from": "/channels/share-links", + "to": "/end-user-guide/collaborate/share-links" + }, + { + "from": "/channels/save-pin-messages", + "to": "/end-user-guide/collaborate/save-pin-messages" + }, + { + "from": "/channels/message-reminders", + "to": "/end-user-guide/collaborate/message-reminders" + }, + { + "from": "/channels/search-for-messages", + "to": "/end-user-guide/collaborate/search-for-messages" + }, + { + "from": "/channels/collaborate-using-mattermost-for-microsoft-teams", + "to": "/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams" + }, + { + "from": "/cloud/cloud-administration/cloud-changelog", + "to": "/product-overview/mattermost-server-releases" + }, + { + "from": "/cloud/cloud-administration/compliance-export", + "to": "/administration-guide/comply/compliance-export" + }, + { + "from": "/cloud/cloud-administration/custom-terms-of-service", + "to": "/administration-guide/comply/custom-terms-of-service" + }, + { + "from": "/cloud/cloud-administration/data-retention-policy", + "to": "/administration-guide/comply/data-retention-policy" + }, + { + "from": "/cloud/cloud-administration/sso-openid-connect", + "to": "/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect" + }, + { + "from": "/cloud/cloud-guest-accounts", + "to": "/administration-guide/onboard/guest-accounts" + }, + { + "from": "/cloud/cloud-mobile/cloud-app-config", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/cloud/cloud-mobile/troubleshooting-mobile", + "to": "/deployment-guide/mobile/mobile-faq" + }, + { + "from": "/cloud/cloud-reporting", + "to": "/administration-guide/manage/statistics" + }, + { + "from": "/cloud/mobile-apps-faq", + "to": "/deployment-guide/mobile/mobile-faq" + }, + { + "from": "/cloud/cloud-user-management", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/collaborate/collaborate-using-mattermost-for-microsoft-teams", + "to": "/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams" + }, + { + "from": "/collaborate-within-embedded-microsoft-teams", + "to": "/end-user-guide/collaborate/collaborate-within-connected-microsoft-teams" + }, + { + "from": "/comply/cloud-data-retention-policy", + "to": "/administration-guide/comply/data-retention-policy" + }, + { + "from": "/comply/compliance-export", + "to": "/administration-guide/comply/compliance-export" + }, + { + "from": "/comply/custom-terms-of-service", + "to": "/administration-guide/comply/custom-terms-of-service" + }, + { + "from": "/comply/data-retention-policy", + "to": "/administration-guide/comply/data-retention-policy" + }, + { + "from": "/comply/electronic-discovery", + "to": "/administration-guide/comply/electronic-discovery" + }, + { + "from": "/comply/export-mattermost-channel-data", + "to": "/administration-guide/comply/export-mattermost-channel-data" + }, + { + "from": "/comply/legal-hold", + "to": "/administration-guide/comply/legal-hold" + }, + { + "from": "/configure/agents-admin-guide", + "to": "/administration-guide/configure/agents-admin-guide" + }, + { + "from": "/configure/configuration-settings", + "to": "/administration-guide/configure/configuration-settings" + }, + { + "from": "/configure/bleve-search", + "to": "/administration-guide/configure/bleve-search" + }, + { + "from": "/configure/calls-deployment", + "to": "/administration-guide/configure/calls-deployment-guide" + }, + { + "from": "/configure/calls-log-collection", + "to": "/administration-guide/configure/calls-logging" + }, + { + "from": "/configure/calls-overview", + "to": "/administration-guide/configure/calls-deployment-guide" + }, + { + "from": "/configure/calls-troubleshooting", + "to": "/administration-guide/configure/calls-logging" + }, + { + "from": "/configure/cloud-billing-account-settings", + "to": "/administration-guide/configure/cloud-billing-account-settings" + }, + { + "from": "/configure/common-config-settings-notation", + "to": "/administration-guide/configure/configuration-settings" + }, + { + "from": "/configure/configuration-in-your-database", + "to": "/administration-guide/configure/configuration-in-your-database" + }, + { + "from": "/configure/custom-branding-tools", + "to": "/administration-guide/configure/custom-branding-tools" + }, + { + "from": "/configure/customize-mattermost", + "to": "/administration-guide/configure/customize-mattermost" + }, + { + "from": "/configure/customizing-mattermost", + "to": "/administration-guide/configure/customize-mattermost" + }, + { + "from": "/configure/enabling-chinese-japanese-korean-search", + "to": "/administration-guide/configure/enabling-chinese-japanese-korean-search" + }, + { + "from": "/configure/environment-variables", + "to": "/administration-guide/configure/environment-variables" + }, + { + "from": "/configure/install-boards", + "to": "/administration-guide/configure/install-boards" + }, + { + "from": "/configure/manage-user-surveys", + "to": "/administration-guide/configure/manage-user-surveys" + }, + { + "from": "/configure/self-hosted-account-settings", + "to": "/administration-guide/configure/self-hosted-account-settings" + }, + { + "from": "/configure/smtp-email", + "to": "/administration-guide/configure/smtp-email" + }, + { + "from": "/configure/system-attributes", + "to": "/administration-guide/configure/system-attributes" + }, + { + "from": "/configure/configuration-in-mattermost-database", + "to": "/administration-guide/configure/configuration-in-your-database" + }, + { + "from": "/configure/configuation-in-a-database", + "to": "/administration-guide/configure/configuration-in-your-database" + }, + { + "from": "/configure/configuration-in-the-database", + "to": "/administration-guide/configure/configuration-in-your-database" + }, + { + "from": "/deploy/backup-disaster-recovery", + "to": "/deployment-guide/backup-disaster-recovery" + }, + { + "from": "/deploy/bleve-search", + "to": "/administration-guide/configure/bleve-search" + }, + { + "from": "/deploy/build-custom-mobile-apps", + "to": "/deployment-guide/mobile/distribute-custom-mobile-apps" + }, + { + "from": "/deploy/client-side-data", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/deploy/consider-mobile-vpn-options", + "to": "/deployment-guide/mobile/consider-mobile-vpn-options" + }, + { + "from": "/deploy/deploy-mobile-apps-using-emm-provider", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/deploy/desktop/desktop-app-deployment", + "to": "/deployment-guide/desktop/desktop-app-deployment" + }, + { + "from": "/deploy/desktop/desktop-app-managed-resources", + "to": "/deployment-guide/desktop/desktop-app-managed-resources" + }, + { + "from": "/deploy/mobile/mobile-app-deployment", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/deploy/desktop/desktop-custom-dictionaries", + "to": "/deployment-guide/desktop/desktop-custom-dictionaries" + }, + { + "from": "/deploy/desktop/desktop-msi-installer-and-group-policy-install", + "to": "/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install" + }, + { + "from": "/deploy/desktop/desktop-troubleshooting", + "to": "/deployment-guide/desktop/desktop-troubleshooting" + }, + { + "from": "/deploy/desktop/distribute-a-custom-desktop-app", + "to": "/deployment-guide/desktop/distribute-a-custom-desktop-app" + }, + { + "from": "/deploy/desktop/linux-desktop-install", + "to": "/deployment-guide/desktop/linux-desktop-install" + }, + { + "from": "/deploy/desktop/silent-windows-desktop-distribution", + "to": "/deployment-guide/desktop/silent-windows-desktop-distribution" + }, + { + "from": "/deploy/encryption-options", + "to": "/deployment-guide/encryption-options" + }, + { + "from": "/deploy/image-proxy", + "to": "/deployment-guide/server/image-proxy" + }, + { + "from": "/deploy/manual-postgres-migration", + "to": "/deployment-guide/manual-postgres-migration" + }, + { + "from": "/deploy/mobile-appconfig", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/deploy/mobile-apps-faq", + "to": "/deployment-guide/mobile/mobile-faq" + }, + { + "from": "/deploy/mobile/consider-mobile-vpn-options", + "to": "/deployment-guide/mobile/consider-mobile-vpn-options" + }, + { + "from": "/deploy/mobile/deploy-mobile-apps-using-emm-provider", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/deploy/mobile/distribute-custom-mobile-apps", + "to": "/deployment-guide/mobile/distribute-custom-mobile-apps" + }, + { + "from": "/deploy/mobile/host-your-own-push-proxy-service", + "to": "/deployment-guide/mobile/host-your-own-push-proxy-service" + }, + { + "from": "/deploy/mobile/mobile-faq", + "to": "/deployment-guide/mobile/mobile-faq" + }, + { + "from": "/deploy/mobile/mobile-security-features", + "to": "/deployment-guide/mobile/mobile-security-features" + }, + { + "from": "/deploy/mobile/mobile-troubleshooting", + "to": "/deployment-guide/mobile/mobile-troubleshooting" + }, + { + "from": "/deploy/mobile/secure-mobile-file-storage", + "to": "/deployment-guide/mobile/secure-mobile-file-storage" + }, + { + "from": "/deploy/mobile-faq", + "to": "/deployment-guide/mobile/mobile-faq" + }, + { + "from": "/deploy/mobile-hpns", + "to": "/deployment-guide/mobile/host-your-own-push-proxy-service" + }, + { + "from": "/deploy/mobile-overview", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/deploy/mobile-troubleshoot-notifications", + "to": "/deployment-guide/mobile/mobile-troubleshooting" + }, + { + "from": "/deploy/mobile-troubleshoot", + "to": "/deployment-guide/mobile/mobile-troubleshooting" + }, + { + "from": "/deploy/postgres-migration-assist-tool", + "to": "/deployment-guide/postgres-migration-assist-tool" + }, + { + "from": "/deploy/postgres-migration", + "to": "/deployment-guide/postgres-migration" + }, + { + "from": "/deploy/quick-start-evaluation", + "to": "/deployment-guide/quick-start-evaluation" + }, + { + "from": "/deploy/server/containers/install-docker", + "to": "/deployment-guide/server/containers/install-docker" + }, + { + "from": "/deploy/server/deploy-containers", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/deploy/server/deploy-kubernetes", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/deploy/server/deploy-linux", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/deploy/server/docker-troubleshooting", + "to": "/deployment-guide/server/docker-troubleshooting" + }, + { + "from": "/deploy/server/image-proxy", + "to": "/deployment-guide/server/image-proxy" + }, + { + "from": "/deploy/server/kubernetes/deploy-k8s-aks", + "to": "/deployment-guide/server/kubernetes/deploy-k8s-aks" + }, + { + "from": "/deploy/server/kubernetes/deploy-k8s-oke", + "to": "/deployment-guide/server/kubernetes/deploy-k8s-oke" + }, + { + "from": "/deploy/server/kubernetes/deploy-k8s", + "to": "/deployment-guide/server/kubernetes/deploy-k8s" + }, + { + "from": "/deploy/server/orchestration", + "to": "/deployment-guide/server/orchestration" + }, + { + "from": "/deploy/server/prepare-mattermost-mysql-database", + "to": "/deployment-guide/server/prepare-mattermost-mysql-database" + }, + { + "from": "/deploy/server/setup-nginx-proxy", + "to": "/deployment-guide/server/setup-nginx-proxy" + }, + { + "from": "/deploy/server/setup-tls", + "to": "/deployment-guide/server/setup-tls" + }, + { + "from": "/deploy/server/trouble-postgres", + "to": "/deployment-guide/server/trouble-postgres" + }, + { + "from": "/deploy/server/trouble_mysql", + "to": "/deployment-guide/server/trouble_mysql" + }, + { + "from": "/deploy/server/troubleshooting", + "to": "/deployment-guide/server/troubleshooting" + }, + { + "from": "/deploy/transport-encryption", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/deploy/use-prebuilt-mobile-apps", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/deploy/desktop-app", + "to": "/deployment-guide/desktop/desktop-app-deployment" + }, + { + "from": "/deploy/deprecated-features", + "to": "/product-overview/deprecated-features" + }, + { + "from": "/deploy/desktop-app-changelog", + "to": "/product-overview/desktop-app-changelog" + }, + { + "from": "/deploy/legacy-self-hosted-changelog", + "to": "/product-overview/unsupported-legacy-releases" + }, + { + "from": "/deploy/mobile-app-changelog", + "to": "/product-overview/mobile-app-changelog" + }, + { + "from": "/deploy/mattermost-changelog", + "to": "/product-overview/server" + }, + { + "from": "/deploy/legacy-cloud-changelog", + "to": "/product-overview/mattermost-server-releases" + }, + { + "from": "/deploy/deploy-openfaas", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/deploy/package-aws", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/deploy/deploy-http", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/deploy/deploy-mattermost-apps", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/deploy/high-scale-troubleshoot", + "to": "/deployment-guide/server/troubleshooting#deployment-troubleshooting" + }, + { + "from": "/deploy/server/linux/deploy-rhel", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/deployment/advanced-permissions", + "to": "/administration-guide/onboard/advanced-permissions" + }, + { + "from": "/deployment/auth", + "to": "/administration-guide/onboard/multi-factor-authentication" + }, + { + "from": "/deployment/converting-oauth20-service-providers-to-openidconnect", + "to": "/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect" + }, + { + "from": "/deployment/certificate-based-authentication", + "to": "/administration-guide/onboard/certificate-based-authentication" + }, + { + "from": "/deployment/team-channel-management", + "to": "/administration-guide/manage/team-channel-members" + }, + { + "from": "/deployment/desktop-app-deployment", + "to": "/deployment-guide/desktop/desktop-app-deployment" + }, + { + "from": "/deployment/elasticsearch", + "to": "/administration-guide/scale/elasticsearch-setup" + }, + { + "from": "/deployment/enterprise-deployment-guide", + "to": "/administration-guide/scale/scaling-for-enterprise" + }, + { + "from": "/deployment/guest-accounts", + "to": "/administration-guide/onboard/guest-accounts" + }, + { + "from": "/deployment/ha", + "to": "/administration-guide/scale/high-availability-cluster-based-deployment" + }, + { + "from": "/deployment/metrics", + "to": "/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring" + }, + { + "from": "/deployment/mobile-app-deployment", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/deployment/on-boarding", + "to": "/administration-guide/upgrade/admin-onboarding-tasks" + }, + { + "from": "/deployment/push", + "to": "/deployment-guide/mobile/host-your-own-push-proxy-service" + }, + { + "from": "/deployment/scaling", + "to": "/administration-guide/scale/scaling-for-enterprise" + }, + { + "from": "/deployment/sso-ldap", + "to": "/administration-guide/onboard/ad-ldap" + }, + { + "from": "/deployment/sso-openidconnect", + "to": "/administration-guide/onboard/sso-openidconnect" + }, + { + "from": "/deployment/sso-gitlab", + "to": "/administration-guide/onboard/sso-gitlab" + }, + { + "from": "/deployment/sso-google", + "to": "/administration-guide/onboard/sso-google" + }, + { + "from": "/deployment/sso-office", + "to": "/administration-guide/onboard/sso-entraid" + }, + { + "from": "/deployment/sso-saml", + "to": "/administration-guide/onboard/sso-saml" + }, + { + "from": "/deployment/sso-saml-technical", + "to": "/administration-guide/onboard/sso-saml-technical" + }, + { + "from": "/deployment/sso-saml-troubleshooting", + "to": "/administration-guide/onboard/sso-saml" + }, + { + "from": "/deployment/ssl-client-certificate", + "to": "/administration-guide/onboard/ssl-client-certificate" + }, + { + "from": "/deployment/sso-saml-okta", + "to": "/administration-guide/onboard/sso-saml-okta" + }, + { + "from": "/deployment/sso-saml-adfs-msws2016", + "to": "/administration-guide/onboard/sso-saml-adfs-msws2016" + }, + { + "from": "/getting-started/feature-labels", + "to": "/administration-guide/manage/feature-labels" + }, + { + "from": "/getting-started/admin-onboarding-tasks", + "to": "/administration-guide/upgrade/admin-onboarding-tasks" + }, + { + "from": "/getting-started/enterprise-roll-out-checklist", + "to": "/administration-guide/upgrade/enterprise-roll-out-checklist" + }, + { + "from": "/getting-started/welcome-email-to-end-users", + "to": "/administration-guide/upgrade/welcome-email-to-end-users" + }, + { + "from": "/getting-started/light-install", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/getting-started/welcome_email", + "to": "/administration-guide/upgrade/welcome-email-to-end-users" + }, + { + "from": "/getting-started/organizing-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/guides/administrator", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/guides/deployment-guides", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/guides/deployment", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/guides/desktop-mobile-app-deployment", + "to": "/deployment-guide/desktop/desktop-app-deployment" + }, + { + "from": "/guides/messaging", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/guides/orchestration", + "to": "/use-case-guide/use-cases-index" + }, + { + "from": "/guides/cloud-admin-guide", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/guides/setup-onboard-manage-comply", + "to": "/administration-guide/administration-guide-index" + }, + { + "from": "/guides/user", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/guides/channels", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/guides/playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/guides/welcome-to-mattermost", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/guides/changelogs", + "to": "/product-overview/releases-lifecycle" + }, + { + "from": "/help/apps/desktop-changelog", + "to": "/product-overview/desktop-app-changelog" + }, + { + "from": "/help/apps/desktop-guide", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/help/messaging/attaching-files", + "to": "/end-user-guide/collaborate/share-files-in-messages" + }, + { + "from": "/help/getting-started/creating-teams", + "to": "/end-user-guide/collaborate/organize-using-teams#create-a-team" + }, + { + "from": "/help/getting-started/install-desktop-app", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/help/messaging/flagging-messages", + "to": "/end-user-guide/collaborate/save-pin-messages" + }, + { + "from": "/help/getting-started/light-install", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/help/getting-started/log-out", + "to": "/end-user-guide/access/log-out" + }, + { + "from": "/help/getting-started/managing-members", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/help/messaging/mentioning-teammates", + "to": "/end-user-guide/collaborate/mention-people" + }, + { + "from": "/help/getting-started/organizing", + "to": "/end-user-guide/collaborate/channel-naming-conventions" + }, + { + "from": "/help/getting-started/organizing-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/help/messaging/organizing-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/help/messaging/pinning-messages", + "to": "/end-user-guide/collaborate/save-pin-messages" + }, + { + "from": "/help/getting-started/signing-in", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/help/getting-started/searching", + "to": "/end-user-guide/collaborate/search-for-messages" + }, + { + "from": "/help/messaging/sending-messages", + "to": "/end-user-guide/collaborate/send-messages" + }, + { + "from": "/help/getting-started/switch-between-teams", + "to": "/end-user-guide/collaborate/organize-using-teams#team-sidebar" + }, + { + "from": "/help/getting-started/welcome-to-mattermost", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/help/settings/desktop-app-options", + "to": "/end-user-guide/preferences/customize-desktop-app-experience" + }, + { + "from": "/help/settings/manage-servers", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/help/settings/team-settings", + "to": "/end-user-guide/collaborate/team-settings" + }, + { + "from": "/help/settings/theme-colors", + "to": "/end-user-guide/preferences/customize-your-theme" + }, + { + "from": "/incident-collaboration/getting-started", + "to": "/end-user-guide/workflow-automation/learn-about-playbooks" + }, + { + "from": "/incident-collaboration/launching-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/incident-collaboration/overview", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/incident-collaboration/playbook-planning", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/incident-collaboration/review-and-refine", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/incident-collaboration/running-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/incident-collaboration/refining-and-improving", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/incident-collaboration/setting-up-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/install/desktop-app-managed-resources", + "to": "/deployment-guide/desktop/desktop-app-managed-resources" + }, + { + "from": "/install/desktop-custom-dictionaries", + "to": "/deployment-guide/desktop/desktop-custom-dictionaries" + }, + { + "from": "/install/desktop-msi-installer-and-group-policy-install", + "to": "/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install" + }, + { + "from": "/install/installing-mattermost-omnibus", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/prepare-mattermost-mysql-database", + "to": "/deployment-guide/server/prepare-mattermost-mysql-database" + }, + { + "from": "/install/setup-nginx-proxy", + "to": "/deployment-guide/server/setup-nginx-proxy" + }, + { + "from": "/install/setup-tls", + "to": "/deployment-guide/server/setup-tls" + }, + { + "from": "/install/setup-mattermost-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/trouble-postgres", + "to": "/deployment-guide/server/trouble-postgres" + }, + { + "from": "/install/trouble_mysql", + "to": "/deployment-guide/server/trouble_mysql" + }, + { + "from": "/install/troubleshooting", + "to": "/deployment-guide/server/troubleshooting" + }, + { + "from": "/install/install-rhel", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-tar", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-kubernetes", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/install-kubernetes-aks", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/cluster-transport-encryption", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/install/database-transport-encryption", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/install/config-tls-mattermost", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/install/proxy-to-mattermost-transport-encryption", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/install/transport-encryption", + "to": "/deployment-guide/transport-encryption" + }, + { + "from": "/install/deploy-bitnami", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/enterprise-install-upgrade", + "to": "/administration-guide/upgrade/enterprise-install-upgrade" + }, + { + "from": "/install/desktop", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/install/desktop-managed-resources", + "to": "/deployment-guide/desktop/desktop-app-managed-resources" + }, + { + "from": "/install/desktop-msi-gpo", + "to": "/deployment-guide/desktop/desktop-msi-installer-and-group-policy-install" + }, + { + "from": "/install/docker-ebs", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/install/i18n", + "to": "/administration-guide/configure/enabling-chinese-japanese-korean-search" + }, + { + "from": "/install/installing-mattermost-desktop-app", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/install/install-kubernetes-cluster", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/install-kubernetes-mattermost", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/install-ubuntu-2004", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/mattermost-omnibus", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/setting-up-local-machine-using-docker", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/install/smtp-email-setup", + "to": "/administration-guide/configure/smtp-email" + }, + { + "from": "/install/use-kubernetes-mattermost", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/cloud-changelog", + "to": "/product-overview/mattermost-server-releases" + }, + { + "from": "/install/desktop-app-install", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/install/install-ios-app", + "to": "/end-user-guide/access/install-ios-app" + }, + { + "from": "/install/install-android-app", + "to": "/end-user-guide/access/install-android-app" + }, + { + "from": "/install/desktop-app-changelog", + "to": "/product-overview/desktop-app-changelog" + }, + { + "from": "/install/deprecated-features", + "to": "/product-overview/deprecated-features" + }, + { + "from": "/install/install-mattermost-server-tarball", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-6-mattermost", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/mattermost-kubernetes-operator", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/install-ubuntu-2004-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-7-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-1804-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-1804-postgresql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-2004-mysql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-debian-mysql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-8-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-1804-mysql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-debian-server", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-8-mysql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-7-mysql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-debian-postgresql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-2004-postgresql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-8-postgresql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/installing-ubuntu-1804-LTS", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-1804-mattermost", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-8", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-ubuntu-2004-mattermost", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-7-mattermost", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-7-postgresql", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-8-mattermost", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-7", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/installing-ubuntu-2004-LTS", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-debian", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-centos-oracle-scientific", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-common-intro", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-latest-tarball", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/common-prod-deploy-docker", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/install/common-deploy-faq", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/install-rhel-nginx", + "to": "/deployment-guide/server/setup-nginx-proxy" + }, + { + "from": "/install/config-ssl-http2-nginx", + "to": "/deployment-guide/server/setup-nginx-proxy#configure-nginx-with-ssl-and-http-2" + }, + { + "from": "/install/config-proxy-nginx", + "to": "/deployment-guide/server/setup-nginx-proxy" + }, + { + "from": "/install/install-nginx", + "to": "/deployment-guide/server/setup-nginx-proxy" + }, + { + "from": "/install/faq_kubernetes", + "to": "/deployment-guide/server/kubernetes/deploy-k8s" + }, + { + "from": "/install/common-prod-deploy-tar", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/common-prod-deploy-omnibus", + "to": "/deployment-guide/server/deploy-linux" + }, + { + "from": "/install/common-local-deploy-docker", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/install/install-docker", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/install/manage_kubernetes", + "to": "/deployment-guide/server/deploy-kubernetes" + }, + { + "from": "/install/trial-mattermost-using-docker", + "to": "/deployment-guide/server/deploy-containers" + }, + { + "from": "/integrate/github", + "to": "/integrations-guide/github" + }, + { + "from": "/integrate/gitlab", + "to": "/integrations-guide/gitlab" + }, + { + "from": "/integrate/jira", + "to": "/integrations-guide/jira" + }, + { + "from": "/integrate/mattermost-mission-collaboration-for-m365", + "to": "/integrations-guide/mattermost-mission-collaboration-for-m365" + }, + { + "from": "/integrate/microsoft-calendar", + "to": "/integrations-guide/microsoft-calendar" + }, + { + "from": "/integrate/microsoft-calendar-interoperability", + "to": "/integrations-guide/microsoft-calendar" + }, + { + "from": "/integrate/microsoft-teams-meetings", + "to": "/integrations-guide/microsoft-teams-meetings" + }, + { + "from": "/integrate/microsoft-teams-meetings-interoperability", + "to": "/integrations-guide/microsoft-teams-meetings" + }, + { + "from": "/integrate/microsoft-teams-sync", + "to": "/integrations-guide/microsoft-teams-sync" + }, + { + "from": "/integrate/servicenow", + "to": "/integrations-guide/servicenow" + }, + { + "from": "/integrate/zoom", + "to": "/integrations-guide/zoom" + }, + { + "from": "/integrations/integration-faq", + "to": "/integrations-guide/integrations-guide-index#frequently-asked-questions" + }, + { + "from": "/integrations/net-promoter-score", + "to": "/administration-guide/manage/user-satisfaction-surveys" + }, + { + "from": "/manage/admin/attribute-based-access-control", + "to": "/administration-guide/manage/admin/attribute-based-access-control" + }, + { + "from": "/manage/admin/error-codes", + "to": "/administration-guide/manage/admin/error-codes" + }, + { + "from": "/manage/admin/installing-license-key", + "to": "/administration-guide/manage/admin/installing-license-key" + }, + { + "from": "/manage/admin/self-hosted-billing", + "to": "/administration-guide/manage/admin/self-hosted-billing" + }, + { + "from": "/manage/admin/customize-branding", + "to": "/administration-guide/manage/admin/customize-branding" + }, + { + "from": "/manage/admin/migration", + "to": "/administration-guide/manage/admin/migration" + }, + { + "from": "/manage/admin/monitoring-and-performance", + "to": "/administration-guide/manage/admin/monitoring-and-performance" + }, + { + "from": "/manage/admin/server-configuration", + "to": "/administration-guide/manage/admin/server-configuration" + }, + { + "from": "/manage/admin/server-maintenance", + "to": "/administration-guide/manage/admin/server-maintenance" + }, + { + "from": "/manage/admin/user-attributes", + "to": "/administration-guide/manage/admin/user-attributes" + }, + { + "from": "/manage/admin/user-management", + "to": "/administration-guide/manage/admin/user-management" + }, + { + "from": "/manage/admin/user-provisioning", + "to": "/administration-guide/manage/admin/user-provisioning" + }, + { + "from": "/manage/cloud-byok", + "to": "/administration-guide/manage/cloud-byok" + }, + { + "from": "/manage/cloud-data-residency", + "to": "/administration-guide/manage/cloud-data-residency" + }, + { + "from": "/manage/cloud-ip-filtering", + "to": "/administration-guide/manage/cloud-ip-filtering" + }, + { + "from": "/manage/code-signing-custom-builds", + "to": "/administration-guide/manage/code-signing-custom-builds" + }, + { + "from": "/manage/command-line-tools", + "to": "/administration-guide/manage/command-line-tools" + }, + { + "from": "/manage/configure-health-check-probes", + "to": "/administration-guide/manage/configure-health-check-probes" + }, + { + "from": "/manage/error-codes", + "to": "/administration-guide/manage/admin/error-codes" + }, + { + "from": "/manage/feature-labels", + "to": "/administration-guide/manage/feature-labels" + }, + { + "from": "/manage/in-product-notices", + "to": "/administration-guide/manage/in-product-notices" + }, + { + "from": "/manage/mmctl-command-line-tool", + "to": "/administration-guide/manage/mmctl-command-line-tool" + }, + { + "from": "/manage/request-server-health-check", + "to": "/administration-guide/manage/request-server-health-check" + }, + { + "from": "/manage/self-hosted-billing", + "to": "/administration-guide/manage/admin/self-hosted-billing" + }, + { + "from": "/manage/statistics", + "to": "/administration-guide/manage/statistics" + }, + { + "from": "/manage/system-wide-notifications", + "to": "/administration-guide/manage/system-wide-notifications" + }, + { + "from": "/manage/team-channel-members", + "to": "/administration-guide/manage/team-channel-members" + }, + { + "from": "/manage/telemetry", + "to": "/administration-guide/manage/telemetry" + }, + { + "from": "/manage/product-limits", + "to": "/administration-guide/manage/product-limits" + }, + { + "from": "/manage/user-satisfaction-surveys", + "to": "/administration-guide/manage/user-satisfaction-surveys" + }, + { + "from": "/manage/announcement-banner", + "to": "/administration-guide/manage/system-wide-notifications" + }, + { + "from": "/manage/heath-checks", + "to": "/administration-guide/manage/configure-health-check-probes" + }, + { + "from": "/manage/cloud-vpc-private-connectivity", + "to": "/product-overview/cloud-vpc-private-connectivity" + }, + { + "from": "/messaging/channels-basics", + "to": "/end-user-guide/collaborate/collaborate-within-channels" + }, + { + "from": "/messaging/creating-teams", + "to": "/end-user-guide/collaborate/organize-using-teams#create-a-team" + }, + { + "from": "/messaging/customizing-theme-colors", + "to": "/end-user-guide/preferences/customize-your-theme" + }, + { + "from": "/messaging/logging-out", + "to": "/end-user-guide/access/log-out" + }, + { + "from": "/messaging/managing-channels", + "to": "/end-user-guide/collaborate/collaborate-within-channels" + }, + { + "from": "/messaging/managing-desktop-app-options", + "to": "/end-user-guide/preferences/customize-desktop-app-experience" + }, + { + "from": "/messaging/managing-desktop-app-servers", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/messaging/managing-members", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/messaging/mentioning-teammates", + "to": "/end-user-guide/collaborate/mention-people" + }, + { + "from": "/messaging/messaging-basics", + "to": "/end-user-guide/collaborate/collaborate-within-channels" + }, + { + "from": "/messaging/navigating-between-teams", + "to": "/end-user-guide/collaborate/organize-using-teams#team-sidebar" + }, + { + "from": "/messaging/organizing-channels", + "to": "/end-user-guide/collaborate/channel-naming-conventions" + }, + { + "from": "/messaging/organizing-conversations", + "to": "/end-user-guide/collaborate/organize-conversations" + }, + { + "from": "/messaging/organizing-mattermost", + "to": "/end-user-guide/collaborate/channel-naming-conventions" + }, + { + "from": "/messaging/pinning-messages", + "to": "/end-user-guide/collaborate/save-pin-messages" + }, + { + "from": "/messaging/searching-in-mattermost", + "to": "/end-user-guide/collaborate/search-for-messages" + }, + { + "from": "/messaging/sending-messages", + "to": "/end-user-guide/collaborate/send-messages" + }, + { + "from": "/messaging/sending-receiving-messages", + "to": "/end-user-guide/collaborate/send-messages" + }, + { + "from": "/messaging/sharing-messages", + "to": "/end-user-guide/collaborate/share-links" + }, + { + "from": "/messaging/sharing-files", + "to": "/end-user-guide/collaborate/share-files-in-messages" + }, + { + "from": "/messaging/signing-in", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/messaging/switching-between-teams", + "to": "/end-user-guide/collaborate/organize-using-teams#team-sidebar" + }, + { + "from": "/messaging/team-settings", + "to": "/end-user-guide/collaborate/team-settings" + }, + { + "from": "/messaging/welcome-to-mattermost-channels", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/messaging/welcome-to-mattermost-messaging", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/messaging/cloud-user-management", + "to": "/end-user-guide/collaborate/manage-channel-members" + }, + { + "from": "/mobile/deploy-mobile-apps-using-emm-provider", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/mobile/mobile-appstore-install", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/mobile/mobile-blackberry", + "to": "/deployment-guide/mobile/deploy-mobile-apps-using-emm-provider" + }, + { + "from": "/mobile/mobile-compile yourself", + "to": "/deployment-guide/mobile/distribute-custom-mobile-apps" + }, + { + "from": "/mobile/mobile-hpns", + "to": "/deployment-guide/mobile/host-your-own-push-proxy-service" + }, + { + "from": "/mobile/mobile-mobileiron", + "to": "/deployment-guide/mobile/distribute-custom-mobile-apps" + }, + { + "from": "/mobile/mobile-overview", + "to": "/deployment-guide/mobile/mobile-app-deployment" + }, + { + "from": "/mobile/mobile-testing-notifications", + "to": "/deployment-guide/mobile/mobile-troubleshooting" + }, + { + "from": "/onboard/ad-ldap", + "to": "/administration-guide/onboard/ad-ldap" + }, + { + "from": "/onboard/advanced-permissions", + "to": "/administration-guide/onboard/advanced-permissions" + }, + { + "from": "/onboard/certificate-based-authentication", + "to": "/administration-guide/onboard/certificate-based-authentication" + }, + { + "from": "/onboard/common-converting-oauth-to-openidconnect", + "to": "/administration-guide/onboard/common-converting-oauth-to-openidconnect" + }, + { + "from": "/onboard/connected-workspaces", + "to": "/administration-guide/onboard/connected-workspaces" + }, + { + "from": "/onboard/convert-oauth20-service-providers-to-openidconnect", + "to": "/administration-guide/onboard/convert-oauth20-service-providers-to-openidconnect" + }, + { + "from": "/onboard/guest-accounts", + "to": "/administration-guide/onboard/guest-accounts" + }, + { + "from": "/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups", + "to": "/administration-guide/onboard/managing-team-channel-membership-using-ad-ldap-sync-groups" + }, + { + "from": "/onboard/migrate-from-slack", + "to": "/administration-guide/onboard/migrate-from-slack" + }, + { + "from": "/onboard/migrating-to-mattermost", + "to": "/administration-guide/onboard/migrating-to-mattermost" + }, + { + "from": "/onboard/migration-announcement-email", + "to": "/administration-guide/onboard/migration-announcement-email" + }, + { + "from": "/onboard/multi-factor-authentication", + "to": "/administration-guide/onboard/multi-factor-authentication" + }, + { + "from": "/onboard/ssl-client-certificate", + "to": "/administration-guide/onboard/ssl-client-certificate" + }, + { + "from": "/onboard/sso-entraid", + "to": "/administration-guide/onboard/sso-entraid" + }, + { + "from": "/onboard/sso-gitlab", + "to": "/administration-guide/onboard/sso-gitlab" + }, + { + "from": "/onboard/sso-google", + "to": "/administration-guide/onboard/sso-google" + }, + { + "from": "/onboard/sso-openidconnect", + "to": "/administration-guide/onboard/sso-openidconnect" + }, + { + "from": "/onboard/sso-saml-adfs-msws2016", + "to": "/administration-guide/onboard/sso-saml-adfs-msws2016" + }, + { + "from": "/onboard/sso-saml-adfs", + "to": "/administration-guide/onboard/sso-saml-adfs" + }, + { + "from": "/onboard/sso-saml-keycloak", + "to": "/administration-guide/onboard/sso-saml-keycloak" + }, + { + "from": "/onboard/sso-saml-ldapsync", + "to": "/administration-guide/onboard/sso-saml-ldapsync" + }, + { + "from": "/onboard/sso-saml-okta", + "to": "/administration-guide/onboard/sso-saml-okta" + }, + { + "from": "/onboard/sso-saml-technical", + "to": "/administration-guide/onboard/sso-saml-technical" + }, + { + "from": "/onboard/sso-saml", + "to": "/administration-guide/onboard/sso-saml" + }, + { + "from": "/onboard/user-provisioning-workflows", + "to": "/administration-guide/onboard/user-provisioning-workflows" + }, + { + "from": "/onboard/migrating-from-hipchat-to-mattermost", + "to": "/administration-guide/onboard/migrating-to-mattermost" + }, + { + "from": "/onboard/sso-office", + "to": "/administration-guide/onboard/sso-entraid" + }, + { + "from": "/onboard/guest-account-access", + "to": "/administration-guide/onboard/guest-accounts" + }, + { + "from": "/onboard/common-sso-openidconnect", + "to": "/administration-guide/onboard/sso-openidconnect" + }, + { + "from": "/onboard/common-disable-mfa", + "to": "/administration-guide/onboard/multi-factor-authentication" + }, + { + "from": "/onboard/common-sso-google", + "to": "/administration-guide/onboard/sso-google" + }, + { + "from": "/onboard/sso-saml-faq", + "to": "/administration-guide/onboard/sso-saml" + }, + { + "from": "/onboard/common-sso-entraid", + "to": "/administration-guide/onboard/sso-entraid" + }, + { + "from": "/onboard/shared-channels", + "to": "/administration-guide/onboard/connected-workspaces" + }, + { + "from": "/overview/auth", + "to": "/product-overview/corporate-directory-integration" + }, + { + "from": "/overview/authentication", + "to": "/administration-guide/onboard/multi-factor-authentication" + }, + { + "from": "/overview/faq", + "to": "/product-overview/frequently-asked-questions" + }, + { + "from": "/overview/license-and-subscription", + "to": "/product-overview/subscription" + }, + { + "from": "/playbooks/getting-started", + "to": "/end-user-guide/workflow-automation/learn-about-playbooks" + }, + { + "from": "/playbooks/setting-up-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/playbooks/running-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/playbooks/refining-and-improving", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/playbooks/customize-a-playbook", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/playbooks/customize-a-run", + "to": "/end-user-guide/workflow-automation/work-with-runs" + }, + { + "from": "/playbooks/reusing-and-sharing-playbooks", + "to": "/end-user-guide/workflow-automation/share-and-collaborate" + }, + { + "from": "/playbooks/playbook-permissions", + "to": "/end-user-guide/workflow-automation/share-and-collaborate#playbooks-permissions" + }, + { + "from": "/playbooks/overview", + "to": "/end-user-guide/workflow-automation/learn-about-playbooks" + }, + { + "from": "/playbooks/work-with-playbooks", + "to": "/end-user-guide/workflow-automation/work-with-playbooks" + }, + { + "from": "/playbooks/work-with-runs", + "to": "/end-user-guide/workflow-automation/work-with-runs" + }, + { + "from": "/playbooks/work-with-tasks", + "to": "/end-user-guide/workflow-automation/work-with-tasks" + }, + { + "from": "/playbooks/notifications-and-updates", + "to": "/end-user-guide/workflow-automation/notifications-and-updates" + }, + { + "from": "/playbooks/metrics-and-goals", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/playbooks/share-and-collaborate", + "to": "/end-user-guide/workflow-automation/share-and-collaborate" + }, + { + "from": "/playbooks/interact-with-playbooks", + "to": "/end-user-guide/workflow-automation/interact-with-playbooks" + }, + { + "from": "/playbooks/get-started-with-playbooks", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/preferences/manage-your-calls-preferences", + "to": "/end-user-guide/preferences/manage-your-plugin-preferences" + }, + { + "from": "/product-overview/mattermost-v9-changelog", + "to": "/product-overview/unsupported-legacy-releases" + }, + { + "from": "/preferences/connect-multiple-workspaces", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/preferences/customize-desktop-app-experience", + "to": "/end-user-guide/preferences/customize-desktop-app-experience" + }, + { + "from": "/preferences/customize-your-channel-sidebar", + "to": "/end-user-guide/preferences/customize-your-channel-sidebar" + }, + { + "from": "/preferences/customize-your-theme", + "to": "/end-user-guide/preferences/customize-your-theme" + }, + { + "from": "/preferences/manage-advanced-options", + "to": "/end-user-guide/preferences/manage-advanced-options" + }, + { + "from": "/preferences/manage-your-channel-specific-notifications", + "to": "/end-user-guide/preferences/manage-your-channel-specific-notifications" + }, + { + "from": "/preferences/manage-your-desktop-notifications", + "to": "/end-user-guide/preferences/manage-your-desktop-notifications" + }, + { + "from": "/preferences/manage-your-display-options", + "to": "/end-user-guide/preferences/manage-your-display-options" + }, + { + "from": "/preferences/manage-your-mentions-keywords-notifications", + "to": "/end-user-guide/preferences/manage-your-mentions-keywords-notifications" + }, + { + "from": "/preferences/manage-your-mobile-notifications", + "to": "/end-user-guide/preferences/manage-your-mobile-notifications" + }, + { + "from": "/preferences/manage-your-plugin-preferences", + "to": "/end-user-guide/preferences/manage-your-plugin-preferences" + }, + { + "from": "/preferences/manage-your-sidebar-options", + "to": "/end-user-guide/preferences/manage-your-sidebar-options" + }, + { + "from": "/preferences/manage-your-thread-reply-notifications", + "to": "/end-user-guide/preferences/manage-your-thread-reply-notifications" + }, + { + "from": "/preferences/manage-your-web-notifications", + "to": "/end-user-guide/preferences/manage-your-web-notifications" + }, + { + "from": "/preferences/troubleshoot-notifications", + "to": "/end-user-guide/preferences/troubleshoot-notifications" + }, + { + "from": "/repeatable-processes/interact-with-playbooks", + "to": "/end-user-guide/workflow-automation/interact-with-playbooks" + }, + { + "from": "/repeatable-processes/learn-about-playbooks", + "to": "/end-user-guide/workflow-automation/learn-about-playbooks" + }, + { + "from": "/repeatable-processes/metrics-and-goals", + "to": "/end-user-guide/workflow-automation/metrics-and-goals" + }, + { + "from": "/repeatable-processes/notifications-and-updates", + "to": "/end-user-guide/workflow-automation/notifications-and-updates" + }, + { + "from": "/repeatable-processes/share-and-collaborate", + "to": "/end-user-guide/workflow-automation/share-and-collaborate" + }, + { + "from": "/repeatable-processes/work-with-playbooks", + "to": "/end-user-guide/workflow-automation/work-with-playbooks" + }, + { + "from": "/repeatable-processes/work-with-runs", + "to": "/end-user-guide/workflow-automation/work-with-runs" + }, + { + "from": "/repeatable-processes/work-with-tasks", + "to": "/end-user-guide/workflow-automation/work-with-tasks" + }, + { + "from": "/scale/additional-ha-considerations", + "to": "/administration-guide/scale/additional-ha-considerations" + }, + { + "from": "/scale/collect-performance-metrics", + "to": "/administration-guide/scale/collect-performance-metrics" + }, + { + "from": "/scale/common-configure-mattermost-for-enterprise-search", + "to": "/administration-guide/scale/common-configure-mattermost-for-enterprise-search" + }, + { + "from": "/scale/deploy-prometheus-grafana-for-performance-monitoring", + "to": "/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring" + }, + { + "from": "/scale/elasticsearch-setup", + "to": "/administration-guide/scale/elasticsearch-setup" + }, + { + "from": "/scale/ensuring-releases-perform-at-scale", + "to": "/administration-guide/scale/ensuring-releases-perform-at-scale" + }, + { + "from": "/scale/enterprise-search", + "to": "/administration-guide/scale/enterprise-search" + }, + { + "from": "/scale/estimated-storage-per-user-per-month", + "to": "/administration-guide/scale/estimated-storage-per-user-per-month" + }, + { + "from": "/scale/high-availability-cluster-based-deployment", + "to": "/administration-guide/scale/high-availability-cluster-based-deployment" + }, + { + "from": "/scale/lifetime-storage", + "to": "/administration-guide/scale/lifetime-storage" + }, + { + "from": "/scale/opensearch-setup", + "to": "/administration-guide/scale/opensearch-setup" + }, + { + "from": "/scale/performance-alerting", + "to": "/administration-guide/scale/performance-alerting" + }, + { + "from": "/scale/performance-monitoring", + "to": "/administration-guide/scale/deploy-prometheus-grafana-for-performance-monitoring" + }, + { + "from": "/scale/performance-monitoring-metrics", + "to": "/administration-guide/scale/performance-monitoring-metrics" + }, + { + "from": "/scale/push-notification-health-targets", + "to": "/administration-guide/scale/push-notification-health-targets" + }, + { + "from": "/scale/redis", + "to": "/administration-guide/scale/redis" + }, + { + "from": "/scale/scale-to-100000-users", + "to": "/administration-guide/scale/scale-to-100000-users" + }, + { + "from": "/scale/scale-to-15000-users", + "to": "/administration-guide/scale/scale-to-15000-users" + }, + { + "from": "/scale/scale-to-200-users", + "to": "/administration-guide/scale/scale-to-200-users" + }, + { + "from": "/scale/scale-to-2000-users", + "to": "/administration-guide/scale/scale-to-2000-users" + }, + { + "from": "/scale/scale-to-200000-users", + "to": "/administration-guide/scale/scale-to-200000-users" + }, + { + "from": "/scale/scale-to-30000-users", + "to": "/administration-guide/scale/scale-to-30000-users" + }, + { + "from": "/scale/scale-to-50000-users", + "to": "/administration-guide/scale/scale-to-50000-users" + }, + { + "from": "/scale/scale-to-80000-users", + "to": "/administration-guide/scale/scale-to-80000-users" + }, + { + "from": "/scale/scale-to-90000-users", + "to": "/administration-guide/scale/scale-to-90000-users" + }, + { + "from": "/scale/scaling-for-enterprise", + "to": "/administration-guide/scale/scaling-for-enterprise" + }, + { + "from": "/scale/high-availability-cluster", + "to": "/administration-guide/scale/high-availability-cluster-based-deployment" + }, + { + "from": "/scale/scale-to-100-users", + "to": "/administration-guide/scale/scale-to-200-users" + }, + { + "from": "/scale/scale-to-1000-users", + "to": "/administration-guide/scale/scale-to-2000-users" + }, + { + "from": "/scale/scale-to-25000-users", + "to": "/administration-guide/scale/scale-to-30000-users" + }, + { + "from": "/scale/scale-to-70000-users", + "to": "/administration-guide/scale/scale-to-80000-users" + }, + { + "from": "/scale/scale-to-79000-users", + "to": "/administration-guide/scale/scale-to-80000-users" + }, + { + "from": "/scale/scale-to-88000-users", + "to": "/administration-guide/scale/scale-to-90000-users" + }, + { + "from": "/scale/elasticsearch", + "to": "/administration-guide/scale/elasticsearch-setup" + }, + { + "from": "/guides/agents", + "to": "/end-user-guide/agents" + }, + { + "from": "/guides/cloud-workspace-management", + "to": "/administration-guide/cloud-workspace-management" + }, + { + "from": "/guides/compliance-with-mattermost", + "to": "/administration-guide/compliance-with-mattermost" + }, + { + "from": "/guides/deployment-troubleshooting", + "to": "/deployment-guide/deployment-troubleshooting" + }, + { + "from": "/guides/messaging-collaboration", + "to": "/end-user-guide/messaging-collaboration" + }, + { + "from": "/guides/preferences", + "to": "/end-user-guide/preferences" + }, + { + "from": "/guides/project-task-management", + "to": "/end-user-guide/project-task-management" + }, + { + "from": "/guides/secure-mattermost", + "to": "/security-guide/secure-mattermost" + }, + { + "from": "/guides/upgrade-mattermost", + "to": "/administration-guide/upgrade-mattermost" + }, + { + "from": "/guides/workflow-automation", + "to": "/end-user-guide/workflow-automation" + }, + { + "from": "/guides/about-mattermost", + "to": "/" + }, + { + "from": "/overview/index", + "to": "/" + }, + { + "from": "/upgrade/admin-onboarding-tasks", + "to": "/administration-guide/upgrade/admin-onboarding-tasks" + }, + { + "from": "/upgrade/communicate-scheduled-maintenance", + "to": "/administration-guide/upgrade/communicate-scheduled-maintenance" + }, + { + "from": "/upgrade/downgrading-mattermost-server", + "to": "/administration-guide/upgrade/downgrading-mattermost-server" + }, + { + "from": "/upgrade/enterprise-install-upgrade", + "to": "/administration-guide/upgrade/enterprise-install-upgrade" + }, + { + "from": "/upgrade/enterprise-roll-out-checklist", + "to": "/administration-guide/upgrade/enterprise-roll-out-checklist" + }, + { + "from": "/upgrade/notify-admin", + "to": "/administration-guide/upgrade/notify-admin" + }, + { + "from": "/upgrade/open-source-components", + "to": "/administration-guide/upgrade/open-source-components" + }, + { + "from": "/upgrade/prepare-to-upgrade-mattermost", + "to": "/administration-guide/upgrade/prepare-to-upgrade-mattermost" + }, + { + "from": "/upgrade/upgrade-mattermost-kubernetes-ha", + "to": "/administration-guide/upgrade/upgrade-mattermost-kubernetes-ha" + }, + { + "from": "/upgrade/upgrading-mattermost-server", + "to": "/administration-guide/upgrade/upgrading-mattermost-server" + }, + { + "from": "/upgrade/welcome-email-to-end-users", + "to": "/administration-guide/upgrade/welcome-email-to-end-users" + }, + { + "from": "/upgrade/installing-license-key", + "to": "/administration-guide/manage/admin/installing-license-key" + }, + { + "from": "/upgrade/extended-support-release", + "to": "/product-overview/release-policy#extended-support-releases" + }, + { + "from": "/upgrade/releases-lifecycle", + "to": "/product-overview/releases-lifecycle" + }, + { + "from": "/upgrade/release-definitions", + "to": "/product-overview/release-policy#release-types" + }, + { + "from": "/upgrade/version-archive", + "to": "/product-overview/version-archive" + }, + { + "from": "/upgrade/release-lifecycle", + "to": "/product-overview/release-policy" + }, + { + "from": "/welcome/manage-desktop-app-server-connections", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/welcome/insights", + "to": "/product-overview/deprecated-features#mattermost-server-v9-0-0" + }, + { + "from": "/welcome/log-in", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/welcome/log-out", + "to": "/end-user-guide/access/log-out" + }, + { + "from": "/welcome/manage-custom-groups", + "to": "/end-user-guide/collaborate/organize-using-custom-user-groups" + }, + { + "from": "/welcome/about-teams", + "to": "/end-user-guide/collaborate/organize-using-teams" + }, + { + "from": "/welcome/team-settings", + "to": "/end-user-guide/collaborate/team-settings" + }, + { + "from": "/welcome/about-user-roles", + "to": "/end-user-guide/collaborate/learn-about-roles" + }, + { + "from": "/welcome/customize-your-theme", + "to": "/end-user-guide/preferences/customize-your-theme" + }, + { + "from": "/welcome/customize-desktop-app-experience", + "to": "/end-user-guide/preferences/customize-desktop-app-experience" + }, + { + "from": "/welcome/manage-multiple-server-connections", + "to": "/end-user-guide/preferences/connect-multiple-workspaces" + }, + { + "from": "/welcome/what-changed-in-v70", + "to": "/product-overview/mattermost-v10-changelog" + }, + { + "from": "/welcome/sign-in", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/guides/get-help", + "to": "/get-help/get-help-index" + }, + { + "from": "/guides/community-chat", + "to": "/get-help/community-chat" + }, + { + "from": "/guides/community-for-mattermost", + "to": "/get-help/community-for-mattermost" + }, + { + "from": "/guides/contribute-to-documentation", + "to": "/get-help/contribute-to-documentation" + }, + { + "from": "/about/integrations", + "to": "/integrations-guide/integrations-guide-index" + }, + { + "from": "/about/product", + "to": "/" + }, + { + "from": "/guides/deployment-guide", + "to": "/deployment-guide/deployment-guide-index" + }, + { + "from": "/guides/administration-guide", + "to": "/administration-guide/administration-guide-index" + }, + { + "from": "/end-user-guide/collaborate/access-your-workspace", + "to": "/end-user-guide/access/access-your-workspace" + }, + { + "from": "/end-user-guide/collaborate/install-android-app", + "to": "/end-user-guide/access/install-android-app" + }, + { + "from": "/end-user-guide/collaborate/install-desktop-app", + "to": "/end-user-guide/access/install-desktop-app" + }, + { + "from": "/end-user-guide/collaborate/install-ios-app", + "to": "/end-user-guide/access/install-ios-app" + }, + { + "from": "/end-user-guide/collaborate/log-out", + "to": "/end-user-guide/access/log-out" + }, + { + "from": "/guides/use-mattermost", + "to": "/end-user-guide/end-user-guide-index" + }, + { + "from": "/product-overview/product-overview-index", + "to": "/" + } + ] +} \ No newline at end of file diff --git a/docs/site/sidebars/api.ts b/docs/site/sidebars/api.ts new file mode 100644 index 000000000000..756bd5719c44 --- /dev/null +++ b/docs/site/sidebars/api.ts @@ -0,0 +1,29 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore — generated by `docusaurus gen-api-docs`. The default export +// is the apisidebar items array (not a full SidebarsConfig object). +import apiReference from '../../api/reference/sidebar'; + +// API tab sidebar. +// "Overview" → hand-authored intro page (api/index.mdx) +// "Examples" → curl quick-start (api/examples.mdx) +// "Reference" → 38 OpenAPI tag groups (~550 endpoints) generated by +// docusaurus-plugin-openapi-docs from +// openapi/mattermost-openapi-v4.yaml. +// +// See docs/site/README.md for local dev setup (includes regenerating this). + +const sidebars: SidebarsConfig = { + api: [ + {type: 'doc', id: 'index', label: 'Overview'}, + {type: 'doc', id: 'examples', label: 'Examples'}, + { + type: 'category', + label: 'Reference', + collapsed: false, + items: apiReference as any[], + }, + ], +}; + +export default sidebars; diff --git a/docs/site/sidebars/developers.ts b/docs/site/sidebars/developers.ts new file mode 100644 index 000000000000..3e594bc308e4 --- /dev/null +++ b/docs/site/sidebars/developers.ts @@ -0,0 +1,15 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore — generated by `node docs-site/scripts/gen-developer-sidebar.mjs` +// from the migrated content tree under develop/. +import generated from './developers.generated.json'; + +// Developers tab sidebar. Generated from the develop/ directory tree +// (Contribute, Integrate & Extend, Internal, with all sub-categories +// derived from sub-directories). + +const sidebars: SidebarsConfig = { + developers: generated as any[], +}; + +export default sidebars; diff --git a/docs/site/sidebars/documentation.ts b/docs/site/sidebars/documentation.ts new file mode 100644 index 000000000000..983ed8c2dfd2 --- /dev/null +++ b/docs/site/sidebars/documentation.ts @@ -0,0 +1,16 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore — generated by `node docs-site/scripts/gen-documentation-sidebar.mjs` +// from the migrated content tree under docs/. +import generated from './documentation.generated.json'; + +// Documentation tab sidebar. Generated from the docs/ directory tree +// (Product Overview, Use Case Guide, Deployment Guide, Administration +// Guide, Security Guide, End User Guide, Integrations Guide, Get Help, +// Agents, Recipes, Samples). + +const sidebars: SidebarsConfig = { + documentation: generated as any[], +}; + +export default sidebars; diff --git a/docs/site/src/components/AttestationStatus/index.tsx b/docs/site/src/components/AttestationStatus/index.tsx new file mode 100644 index 000000000000..8bb3ae4647c0 --- /dev/null +++ b/docs/site/src/components/AttestationStatus/index.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +// Compliance / authorization status badge for framework pages +// (FedRAMP, DoD IL, DISA STIG, HIPAA, FINRA, CMMC, Common Criteria…). +// +// Status semantics: +// authorized — formally authorized / certified; ATO or equivalent in place. +// in-process — actively pursuing authorization; documented gap exists. +// roadmap — committed for future authorization; no work in flight yet. +// not-pursued — not on the roadmap; framework documented for reference only. +// +// Usage: +// +// +// + +type Status = 'authorized' | 'in-process' | 'roadmap' | 'not-pursued'; + +const STATUS_LABEL: Record = { + 'authorized': 'Authorized', + 'in-process': 'In Process', + 'roadmap': 'Roadmap', + 'not-pursued': 'Not Pursued', +}; + +const STATUS_CLASS: Record = { + 'authorized': 'authorized', + 'in-process': 'inProcess', + 'roadmap': 'roadmap', + 'not-pursued': 'notPursued', +}; + +const KNOWN_STATUSES = Object.keys(STATUS_LABEL) as Status[]; + +export default function AttestationStatus({ + framework, + status, + certificate, + asOf, + detailsHref, +}: { + framework: string; + status: string; + certificate?: string; + asOf?: string; + detailsHref?: string; +}) { + if (!framework) { + return ( + + ); + } + if (!(KNOWN_STATUSES as string[]).includes(status)) { + return ( + + ); + } + + const s = status as Status; + return ( + + ); +} diff --git a/docs/site/src/components/AttestationStatus/styles.module.css b/docs/site/src/components/AttestationStatus/styles.module.css new file mode 100644 index 000000000000..c49e8fd18844 --- /dev/null +++ b/docs/site/src/components/AttestationStatus/styles.module.css @@ -0,0 +1,77 @@ +/* AttestationStatus — framework header + status pill + optional metadata. + * Distinct from edition/deployment badges: this is a full-width block at + * the top of compliance-framework pages, not an inline chip. */ + +.box { + display: block; + margin: 1rem 0; + padding: 0.75rem 1rem; + border-radius: 6px; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-left: 4px solid var(--mm-color-denim, #1E325C); + color: var(--mm-text-primary); +} + +[data-theme='dark'] .box { + background: rgba(255, 255, 255, 0.04); +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + flex-wrap: wrap; +} + +.framework { + font-weight: 700; + font-size: 1rem; + letter-spacing: 0.01em; +} + +.status { + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.75rem; + padding: 0.18rem 0.55rem; + border-radius: 999px; + border: 1px solid currentColor; + white-space: nowrap; +} + +.status[data-status='authorized'] { color: #1d6f42; background: rgba(29, 111, 66, 0.08); } +.status[data-status='in-process'] { color: #8a5d00; background: rgba(255, 188, 31, 0.18); } +.status[data-status='roadmap'] { color: #1E325C; background: rgba(30, 50, 92, 0.08); } +.status[data-status='not-pursued'] { color: #6c757d; background: rgba(108, 117, 125, 0.10); } + +[data-theme='dark'] .status[data-status='authorized'] { color: #6dd49b; } +[data-theme='dark'] .status[data-status='in-process'] { color: #FFBC1F; } +[data-theme='dark'] .status[data-status='roadmap'] { color: #9eb1da; } +[data-theme='dark'] .status[data-status='not-pursued'] { color: #b0b6bd; } + +/* Variant left-borders per status, for at-a-glance scanning. */ +.authorized { border-left-color: #1d6f42; } +.inProcess { border-left-color: #FFBC1F; } +.roadmap { border-left-color: #1E325C; } +.notPursued { border-left-color: #6c757d; } + +.meta { + margin-top: 0.55rem; + font-size: 0.88rem; + display: flex; + gap: 1.25rem; + flex-wrap: wrap; + color: var(--mm-text-secondary, var(--mm-text-primary)); +} + +.meta strong { + font-weight: 700; +} + +.unknown { + background: #fff3cd; + color: #664d03; + border-left-color: #ffc107; +} diff --git a/docs/site/src/components/Callout/index.tsx b/docs/site/src/components/Callout/index.tsx new file mode 100644 index 000000000000..12e2f2b6797d --- /dev/null +++ b/docs/site/src/components/Callout/index.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import styles from './styles.module.css'; + +type Kind = 'note' | 'tip' | 'important' | 'warning' | 'security'; + +const COPY: Record = { + note: {label: 'Note', icon: 'i'}, + tip: {label: 'Tip', icon: '+'}, + important: {label: 'Important', icon: '!'}, + warning: {label: 'Warning', icon: '!'}, + security: {label: 'Security', icon: 'S'}, +}; + +export default function Callout({ + kind = 'note', + title, + children, +}: { + kind?: Kind; + title?: string; + children: React.ReactNode; +}) { + const meta = COPY[kind]; + return ( + + ); +} + +// Convenience wrappers used like ... in MDX. +export const Note = (p: {title?: string; children: React.ReactNode}) => ; +export const Tip = (p: {title?: string; children: React.ReactNode}) => ; +export const Important = (p: {title?: string; children: React.ReactNode}) => ; +export const Warning = (p: {title?: string; children: React.ReactNode}) => ; +export const Security = (p: {title?: string; children: React.ReactNode}) => ; diff --git a/docs/site/src/components/Callout/styles.module.css b/docs/site/src/components/Callout/styles.module.css new file mode 100644 index 000000000000..9c97f0df5f4c --- /dev/null +++ b/docs/site/src/components/Callout/styles.module.css @@ -0,0 +1,82 @@ +/* Branded callouts. Denim-tinted surface with a colored left bar + * that signals the kind. Title in Trade Gothic Heavy uppercase. */ + +.callout { + display: grid; + grid-template-columns: 3.25rem 1fr; + gap: 0; + margin: 1.5rem 0; + border: 1px solid var(--mm-border-subtle); + border-radius: 4px; + background: var(--mm-bg-surface); + overflow: hidden; + box-shadow: 0 1px 2px rgba(30, 50, 92, 0.04); +} + +[data-theme='dark'] .callout { + background: var(--mm-denim-800); +} + +.bar { + display: flex; + align-items: flex-start; + justify-content: center; + padding-top: 0.95rem; + background: var(--mm-color-denim); + color: var(--mm-color-white); +} + +.icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.6rem; + height: 1.6rem; + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: 1rem; + border: 2px solid currentColor; + border-radius: 50%; + line-height: 1; +} + +.body { + padding: 0.85rem 1.1rem 0.95rem; +} + +.label { + font-family: var(--mm-font-heading); + font-size: 0.75rem; + font-weight: 900; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--mm-text-secondary); + margin-bottom: 0.35rem; +} + +.content > :first-child { margin-top: 0; } +.content > :last-child { margin-bottom: 0; } +.content p { margin: 0.4rem 0; line-height: 1.6; } + +/* Kind variants */ +.note .bar { background: var(--mm-color-denim); } +.note .label { color: var(--mm-denim-600); } + +.tip .bar { background: #2C7A4F; } /* operational green */ +.tip .label { color: #1F5A39; } +[data-theme='dark'] .tip .label { color: #6FBF8E; } + +/* Important = stronger emphasis than Note, softer than Warning. Marigold accent. */ +.important .bar { background: var(--mm-color-marigold); color: var(--mm-color-black); } +.important .icon { border-color: var(--mm-color-black); } +.important .label { color: var(--mm-marigold-700); } +[data-theme='dark'] .important .label { color: var(--mm-marigold-300); } + +/* Warning = stop sign. Bark/red treatment via custom token. */ +.warning .bar { background: var(--mm-color-bark); color: var(--mm-color-white); } +.warning .label { color: var(--mm-color-bark); } +[data-theme='dark'] .warning .label { color: var(--mm-color-sand); } + +.security .bar { background: #8B1F1F; } /* sec red */ +.security .label { color: #8B1F1F; } +[data-theme='dark'] .security .label { color: #E9A0A0; } diff --git a/docs/site/src/components/CardGrid/index.tsx b/docs/site/src/components/CardGrid/index.tsx new file mode 100644 index 000000000000..70c28d6972b9 --- /dev/null +++ b/docs/site/src/components/CardGrid/index.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +type Card = { + title: string; + description: string; + to: string; + icon?: string; // CompassIcon name + meta?: string; // small annotation (e.g., "549 endpoints") +}; + +/** + * Grid of navigation cards for landing pages. Replaces bulleted lists + * of links — each card is a discrete navigation surface with title, + * description, and optional Compass icon + meta. + * + * Usage: + * + */ +export default function CardGrid({cards, columns = 3}: {cards: Card[]; columns?: 2 | 3 | 4}) { + return ( +
    + {cards.map((c, i) => ( + + {c.icon && } +
    +
    {c.title}
    +

    {c.description}

    + {c.meta && {c.meta}} +
    + + + ))} +
    + ); +} diff --git a/docs/site/src/components/CardGrid/styles.module.css b/docs/site/src/components/CardGrid/styles.module.css new file mode 100644 index 000000000000..624cecd9f474 --- /dev/null +++ b/docs/site/src/components/CardGrid/styles.module.css @@ -0,0 +1,96 @@ +.grid { + display: grid; + gap: 1rem; + margin: 1.5rem 0 2.5rem; +} + +.cols2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); } +.cols3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); } +.cols4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } + +.card { + position: relative; + display: flex; + align-items: flex-start; + gap: 0.85rem; + padding: 1.1rem 1.25rem 1.1rem 1.1rem; + background: var(--mm-bg-surface); + border: 1px solid var(--mm-border-subtle); + border-left: 3px solid var(--mm-color-marigold); + border-radius: 4px; + text-decoration: none; + color: inherit; + transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease; +} +.card:hover { + transform: translateY(-1px); + box-shadow: 0 12px 24px -16px rgba(30, 50, 92, 0.25); + border-color: var(--mm-color-marigold); + text-decoration: none; + color: inherit; +} + +[data-theme='dark'] .card { + background: var(--mm-denim-800); + border-color: var(--mm-denim-700); + border-left-color: var(--mm-color-marigold); +} + +.icon { + flex: 0 0 auto; + width: 1.6rem; + height: 1.6rem; + background: var(--mm-color-denim); + border-radius: 3px; + margin-top: 0.15rem; +} + +.body { + flex: 1 1 auto; + min-width: 0; +} + +.title { + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: 1rem; + letter-spacing: 0.01em; + margin-bottom: 0.3rem; + color: var(--mm-text-primary); +} + +.description { + font-size: 0.88rem; + line-height: 1.45; + margin: 0 0 0.4rem; + color: var(--mm-text-secondary); +} + +.meta { + display: inline-block; + font-family: var(--mm-font-mono); + font-size: 0.72rem; + letter-spacing: 0.02em; + color: var(--mm-marigold-700); + background: var(--mm-marigold-100); + padding: 0.1rem 0.45rem; + border-radius: 2px; +} + +[data-theme='dark'] .meta { + color: var(--mm-color-marigold); + background: rgba(255, 188, 31, 0.12); +} + +.arrow { + position: absolute; + top: 1.1rem; + right: 1rem; + color: var(--mm-text-secondary); + font-size: 1.1rem; + transition: transform 0.12s ease, color 0.12s ease; +} +.card:hover .arrow { + color: var(--mm-color-marigold); + transform: translateX(2px); +} diff --git a/docs/site/src/components/CompassIcon/index.tsx b/docs/site/src/components/CompassIcon/index.tsx new file mode 100644 index 000000000000..bc0534679379 --- /dev/null +++ b/docs/site/src/components/CompassIcon/index.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import styles from './styles.module.css'; + +/** + * Brand-aligned icon. Ports the Hugo `compass-icon` shortcode used in + * mattermost-developer-documentation. Backed by SVGs in + * docs-site/static/img/icons/. During phase 4 the full Compass icon + * library is bulk-imported (see PLAN.md §11.2 Week 1). + * + * Usage: + * + */ +export default function CompassIcon({ + name, + size = 'sm', + tone = 'denim', + alt = '', +}: { + name: string; + size?: 'xs' | 'sm' | 'md' | 'lg'; + tone?: 'denim' | 'marigold' | 'inherit'; + alt?: string; +}) { + const src = useBaseUrl(`/img/icons/${name}.svg`); + return ( + + ); +} diff --git a/docs/site/src/components/CompassIcon/styles.module.css b/docs/site/src/components/CompassIcon/styles.module.css new file mode 100644 index 000000000000..b870cd081f14 --- /dev/null +++ b/docs/site/src/components/CompassIcon/styles.module.css @@ -0,0 +1,20 @@ +.icon { + display: inline-block; + vertical-align: -0.15em; + background-color: currentColor; + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-size: contain; + mask-position: center; + -webkit-mask-position: center; +} + +.xs { width: 0.85em; height: 0.85em; } +.sm { width: 1em; height: 1em; } +.md { width: 1.4em; height: 1.4em; } +.lg { width: 2em; height: 2em; } + +.denim { color: var(--mm-color-denim); } +.marigold { color: var(--mm-color-marigold); } +.inherit { color: inherit; } diff --git a/docs/site/src/components/DeploymentArchitectureBuilder/data.ts b/docs/site/src/components/DeploymentArchitectureBuilder/data.ts new file mode 100644 index 000000000000..1a15df5bb020 --- /dev/null +++ b/docs/site/src/components/DeploymentArchitectureBuilder/data.ts @@ -0,0 +1,369 @@ +// Data tables for the Deployment Architecture builder. +// +// Tier sizing follows the Mattermost scaling guide. Provider SKUs are +// illustrative starting points — verify with current pricing and any +// regional / compliance constraints before committing to a procurement +// decision. + +export type Tier = { + id: string; + label: string; + seats: string; + description: string; + appNodes: number; + appCpu: number; + appRam: number; + dbReplicas: number; + redis: boolean; + search: 'none' | 'optional' | 'recommended' | 'required'; + searchNodes: number; + loadBalancer: 'none' | 'single' | 'cluster'; + storage: 'local' | 'object'; + ha: boolean; +}; + +export const TIERS: Tier[] = [ + { + id: 'trial', + label: 'Trial / Pilot', + seats: '≤ 200 users', + description: 'Single host for evaluation. Mattermost and PostgreSQL co-located; no separate proxy or cache.', + appNodes: 1, + appCpu: 2, + appRam: 4, + dbReplicas: 0, + redis: false, + search: 'none', + searchNodes: 0, + loadBalancer: 'none', + storage: 'local', + ha: false, + }, + { + id: 'small', + label: 'Small', + seats: '≤ 2,000 users', + description: 'Separate app and database hosts. NGINX reverse proxy. Single Mattermost node — restart causes a brief outage.', + appNodes: 1, + appCpu: 4, + appRam: 16, + dbReplicas: 0, + redis: false, + search: 'optional', + searchNodes: 1, + loadBalancer: 'single', + storage: 'object', + ha: false, + }, + { + id: 'medium', + label: 'Medium', + seats: '≤ 10,000 users', + description: 'High availability: 2-node Mattermost cluster behind a load balancer. PostgreSQL with read replica.', + appNodes: 2, + appCpu: 8, + appRam: 32, + dbReplicas: 1, + redis: false, + search: 'recommended', + searchNodes: 1, + loadBalancer: 'single', + storage: 'object', + ha: true, + }, + { + id: 'large', + label: 'Large', + seats: '≤ 25,000 users', + description: '4-node Mattermost cluster. PostgreSQL primary + 2 read replicas. Dedicated Elasticsearch / OpenSearch cluster for message search.', + appNodes: 4, + appCpu: 16, + appRam: 64, + dbReplicas: 2, + redis: false, + search: 'required', + searchNodes: 3, + loadBalancer: 'cluster', + storage: 'object', + ha: true, + }, + { + id: 'xlarge', + label: 'Extra Large', + seats: '≤ 50,000 users', + description: '8-node Mattermost cluster. PostgreSQL primary + 2 replicas with connection pooler. OpenSearch cluster (5 nodes).', + appNodes: 8, + appCpu: 16, + appRam: 64, + dbReplicas: 2, + redis: false, + search: 'required', + searchNodes: 5, + loadBalancer: 'cluster', + storage: 'object', + ha: true, + }, + { + id: 'mega', + label: 'Mega', + seats: '≤ 100,000 users', + description: '16-node Mattermost cluster. PostgreSQL with connection pooler + multiple read replicas. OpenSearch cluster (5+ data nodes). CDN in front of static assets.', + appNodes: 16, + appCpu: 32, + appRam: 128, + dbReplicas: 3, + redis: false, + search: 'required', + searchNodes: 5, + loadBalancer: 'cluster', + storage: 'object', + ha: true, + }, + { + id: 'hyperscale', + label: 'Hyperscale', + seats: '≤ 200,000 users', + description: '32-node Mattermost cluster. Sharded PostgreSQL via connection pooler. Redis cluster (5+ nodes). OpenSearch cluster (10+ data nodes). Multi-region CDN.', + appNodes: 32, + appCpu: 32, + appRam: 128, + dbReplicas: 4, + redis: true, + search: 'required', + searchNodes: 10, + loadBalancer: 'cluster', + storage: 'object', + ha: true, + }, +]; + +export type DeploymentType = 'vm' | 'kubernetes'; +export type Provider = 'aws' | 'azure' | 'gcp' | 'oci' | 'on-prem'; + +export const PROVIDERS: {id: Provider; label: string}[] = [ + {id: 'aws', label: 'AWS'}, + {id: 'azure', label: 'Azure'}, + {id: 'gcp', label: 'Google Cloud'}, + {id: 'oci', label: 'Oracle Cloud (OCI)'}, + {id: 'on-prem', label: 'On-prem / Other'}, +]; + +/* ============================ Brand short names ============================ + * Used in the diagram boxes — proper service product name per provider. + * Longer descriptive labels live in the BOM under "Recommended size / SKU". */ + +export const DB_BRAND: Record = { + aws: 'Amazon RDS (PostgreSQL)', + azure: 'Azure Database (PostgreSQL)', + gcp: 'Cloud SQL (PostgreSQL)', + oci: 'OCI Database (PostgreSQL)', + 'on-prem': 'PostgreSQL (self-managed)', +}; + +export const REDIS_BRAND: Record = { + aws: 'Amazon ElastiCache (Redis)', + azure: 'Azure Cache for Redis', + gcp: 'Memorystore (Redis)', + oci: 'OCI Cache (Redis)', + 'on-prem': 'Redis (self-managed)', +}; + +export const SEARCH_BRAND: Record = { + aws: 'Amazon OpenSearch', + azure: 'Self-hosted OpenSearch', + gcp: 'Self-hosted OpenSearch', + oci: 'OCI Search (OpenSearch)', + 'on-prem': 'OpenSearch (self-managed)', +}; + +export const STORAGE_BRAND: Record = { + aws: 'Amazon S3', + azure: 'Azure Blob Storage', + gcp: 'Cloud Storage', + oci: 'OCI Object Storage', + 'on-prem': 'MinIO (S3-compatible)', +}; + +export const LB_BRAND_VM: Record = { + aws: 'AWS Application Load Balancer', + azure: 'Azure Application Gateway', + gcp: 'Google Cloud HTTPS LB', + oci: 'OCI Flexible Load Balancer', + 'on-prem': 'NGINX / HAProxy', +}; + +export const LB_BRAND_K8S: Record = { + aws: 'NGINX Ingress + AWS NLB', + azure: 'NGINX Ingress + Azure LB', + gcp: 'NGINX Ingress + GCP LB', + oci: 'NGINX Ingress + OCI LB', + 'on-prem': 'NGINX Ingress Controller', +}; + +/* ============================ DB instance sizing ============================ */ + +const DB_INSTANCE = { + aws: {trial: 'co-located', small: 'db.m5.large', medium: 'db.m5.xlarge', large: 'db.m5.2xlarge', xlarge: 'db.m5.4xlarge', mega: 'db.r5.4xlarge', hyperscale: 'db.r5.8xlarge'}, + azure: {trial: 'co-located', small: 'D4ds_v4', medium: 'D8ds_v4', large: 'D16ds_v4', xlarge: 'D32ds_v4', mega: 'E32ds_v4', hyperscale: 'E48ds_v4'}, + gcp: {trial: 'co-located', small: 'db-n1-standard-4', medium: 'db-n1-standard-8', large: 'db-n1-standard-16', xlarge: 'db-n1-standard-32', mega: 'db-n1-highmem-32', hyperscale: 'db-n1-highmem-64'}, + oci: {trial: 'co-located', small: 'PostgreSQL.E4.4', medium: 'PostgreSQL.E4.8', large: 'PostgreSQL.E4.16', xlarge: 'PostgreSQL.E4.32', mega: 'PostgreSQL.E4.64', hyperscale: 'PostgreSQL.E4.96'}, + 'on-prem': {trial: 'co-located', small: '4 vCPU / 16 GB', medium: '8 vCPU / 32 GB', large: '16 vCPU / 64 GB', xlarge: '32 vCPU / 128 GB', mega: '32 vCPU / 256 GB', hyperscale: '64 vCPU / 384 GB'}, +} as const; + +const APP_SKU = { + aws: {'2-4': 't3.medium', '4-16': 'm5.xlarge', '8-32': 'm5.2xlarge', '16-64': 'm5.4xlarge', '32-128': 'm6i.8xlarge'}, + azure: {'2-4': 'B2ms', '4-16': 'D4s_v3', '8-32': 'D8s_v3', '16-64': 'D16s_v3', '32-128': 'D32s_v3'}, + gcp: {'2-4': 'e2-medium', '4-16': 'e2-standard-4', '8-32': 'e2-standard-8', '16-64': 'n2-standard-16', '32-128': 'n2-standard-32'}, + oci: {'2-4': 'VM.Standard.E4.Flex (2 OCPU)', '4-16': 'VM.Standard.E4.Flex (4 OCPU)', '8-32': 'VM.Standard.E4.Flex (8 OCPU)', '16-64': 'VM.Standard.E4.Flex (16 OCPU)', '32-128': 'VM.Standard.E4.Flex (32 OCPU)'}, + 'on-prem': {'2-4': '2 vCPU / 4 GB VM', '4-16': '4 vCPU / 16 GB VM', '8-32': '8 vCPU / 32 GB VM', '16-64': '16 vCPU / 64 GB VM', '32-128': '32 vCPU / 128 GB VM'}, +} as const; + +function bucketFor(cpu: number): keyof typeof APP_SKU['aws'] { + if (cpu <= 2) return '2-4'; + if (cpu <= 4) return '4-16'; + if (cpu <= 8) return '8-32'; + if (cpu <= 16) return '16-64'; + return '32-128'; +} + +/* ============================ Bill of materials ============================ */ + +export type BomRow = { + component: string; + quantity: string; + spec: string; + notes?: string; +}; + +export type BomOptions = { + calls: boolean; + push: boolean; +}; + +export function bomFor( + tier: Tier, + deploymentType: DeploymentType, + provider: Provider, + opts: BomOptions, +): BomRow[] { + const rows: BomRow[] = []; + const onPrem = provider === 'on-prem'; + const k8s = deploymentType === 'kubernetes'; + const bucket = bucketFor(tier.appCpu); + const tierId = tier.id as keyof typeof DB_INSTANCE['aws']; + + // Load balancer / ingress + if (tier.loadBalancer !== 'none') { + rows.push({ + component: k8s ? 'Ingress controller' : 'Load balancer', + quantity: tier.loadBalancer === 'cluster' ? 'HA pair' : '1', + spec: k8s ? LB_BRAND_K8S[provider] : LB_BRAND_VM[provider], + notes: 'TLS terminated at the proxy. Mattermost behind, listening on HTTP/8065.', + }); + } + + // App / Mattermost + rows.push({ + component: k8s ? 'Mattermost (Operator)' : 'Mattermost app server', + quantity: `${tier.appNodes} node${tier.appNodes > 1 ? 's' : ''}`, + spec: k8s + ? `${tier.appCpu} vCPU / ${tier.appRam} GB RAM per pod — worker nodes: ${APP_SKU[provider][bucket]}` + : `${APP_SKU[provider][bucket]} (${tier.appCpu} vCPU / ${tier.appRam} GB RAM)`, + notes: tier.ha + ? 'High availability — restarts and upgrades are non-disruptive.' + : 'Single node — restarts cause a brief outage.', + }); + + // Database + rows.push({ + component: 'PostgreSQL (primary)', + quantity: '1', + spec: `${DB_BRAND[provider]} — ${DB_INSTANCE[provider][tierId]}`, + notes: tier.id === 'trial' ? 'Co-located with the app for evaluation only.' : 'Separate host. PostgreSQL 14 minimum. App connects on TCP/5432.', + }); + if (tier.dbReplicas > 0) { + rows.push({ + component: 'PostgreSQL read replicas', + quantity: `${tier.dbReplicas}`, + spec: onPrem + ? 'Streaming replication, same size as primary' + : `${DB_BRAND[provider]} read replica`, + notes: 'Read queries (search, dashboards) offloaded from the primary.', + }); + } + + // Redis + if (tier.redis) { + rows.push({ + component: 'Redis cache', + quantity: tier.appNodes >= 16 ? 'Cluster (5+ nodes)' : tier.appNodes >= 8 ? 'Cluster (3 nodes)' : '1 node', + spec: REDIS_BRAND[provider], + notes: 'Required for HA — coordinates sessions and cluster state across app nodes. App connects on TCP/6379.', + }); + } + + // Search + if (tier.search !== 'none') { + rows.push({ + component: 'Search index', + quantity: `${tier.searchNodes} node${tier.searchNodes > 1 ? 's' : ''}`, + spec: SEARCH_BRAND[provider], + notes: + tier.search === 'optional' + ? 'Optional at this size — message search will work via PostgreSQL but is slower above ~5,000 users. App connects on HTTPS/9200.' + : tier.search === 'recommended' + ? 'Recommended — message search performance degrades on the DB alone at this scale. App connects on HTTPS/9200.' + : 'Required — message search at this scale cannot run on PostgreSQL alone. App connects on HTTPS/9200.', + }); + } + + // File storage + rows.push({ + component: 'File storage', + quantity: '—', + spec: tier.storage === 'local' ? 'Local disk on app host (trial only)' : STORAGE_BRAND[provider], + notes: tier.storage === 'local' + ? 'Acceptable for trial only. Move to object storage before any HA or multi-node config.' + : 'S3-compatible bucket. App connects on HTTPS/443. Backup + versioning recommended.', + }); + + // Calls (RTCD) — optional + if (opts.calls) { + rows.push({ + component: 'Calls / RTCD service', + quantity: tier.appNodes >= 8 ? '2-3 nodes (HA)' : '1 node', + spec: 'Mattermost RTCD (real-time communications daemon) — small container or VM (2 vCPU / 4 GB)', + notes: + 'Standalone service for audio + screen-share. Clients connect on UDP/8443 (and TCP/8443 fallback). Mattermost talks to RTCD on TCP/8045 for the API.', + }); + rows.push({ + component: 'Calls plugin', + quantity: '—', + spec: 'Bundled Calls plugin enabled in System Console', + notes: 'Required to drive the RTCD service. Configure provider URL pointing at RTCD endpoint.', + }); + } + + // Push notification proxy — optional + if (opts.push) { + rows.push({ + component: 'Push notification proxy', + quantity: '1', + spec: 'Mattermost Push Proxy (open source) — small single host (1 vCPU / 2 GB) or container', + notes: + 'Mediates APNs (api.push.apple.com) and FCM (fcm.googleapis.com) on HTTPS/443. Use HPNS instead if you can reach Mattermost-managed; self-host for air-gapped / sovereign deployments.', + }); + } + + // Kubernetes-specific: cluster sizing note + if (k8s) { + rows.push({ + component: 'Kubernetes cluster', + quantity: tier.appNodes <= 2 ? '3 worker nodes (min)' : `${tier.appNodes + 2}+ worker nodes`, + spec: provider === 'aws' ? 'Amazon EKS' : provider === 'azure' ? 'Azure AKS' : provider === 'gcp' ? 'Google GKE' : provider === 'oci' ? 'Oracle OKE' : 'self-managed K8s', + notes: 'Sized for app pods + system overhead. Mattermost Operator manages the app lifecycle.', + }); + } + + return rows; +} diff --git a/docs/site/src/components/DeploymentArchitectureBuilder/index.tsx b/docs/site/src/components/DeploymentArchitectureBuilder/index.tsx new file mode 100644 index 000000000000..32002315450c --- /dev/null +++ b/docs/site/src/components/DeploymentArchitectureBuilder/index.tsx @@ -0,0 +1,600 @@ +import React, {useState, useMemo} from 'react'; +import styles from './styles.module.css'; +import { + TIERS, + PROVIDERS, + bomFor, + DB_BRAND, + REDIS_BRAND, + SEARCH_BRAND, + STORAGE_BRAND, + LB_BRAND_VM, + LB_BRAND_K8S, + type Tier, + type DeploymentType, + type Provider, +} from './data'; + +/** + * Interactive deployment-architecture builder. + * + * Pick a scale tier, deployment type, hosting provider, and optional + * services (Calls / Push). Renders an architecture diagram with explicit + * per-connection port labels, plus a bill of materials and a network + * flows table sized to those choices. + */ + +/* ============================ Diagram primitives ============================ */ + +function FlowDown({port}: {port: string}) { + return ( +
    + + {port} +
    + ); +} + +function MiniFlow({port}: {port: string}) { + return ( +
    + {port} +
    + ); +} + +function HFlow({direction, port}: {direction: 'left' | 'right'; port: string}) { + const arrow = direction === 'left' ? '←' : '→'; + return ( +
    + {arrow} + {port} +
    + ); +} + +function DataItem({ + port, + accent, + label, + subtitle, +}: { + port: string; + accent: string; + label: string; + subtitle: string; +}) { + return ( +
    + +
    +
    {label}
    +
    {subtitle}
    +
    +
    + ); +} + +/* ============================ Architecture diagram ============================ + * + * 3-column CSS grid: left side / center / right side. + * - Center column holds: clients, ALB, Mattermost, data tier (so they all + * align vertically — ALB is locked directly above Mattermost). + * - Left column holds RTCD when Calls is on. + * - Right column holds Push Proxy / HPNS. + * + * Connection labels are minimal (just ports). The Network Flows table + * below the BOM documents what each port is for. + */ + +function ArchDiagram({ + tier, + k8s, + provider, + showCalls, + pushMode, +}: { + tier: Tier; + k8s: boolean; + provider: Provider; + showCalls: boolean; + pushMode: 'self-hosted' | 'hpns'; +}) { + const showLb = tier.loadBalancer !== 'none'; + const showRedis = tier.redis; + const showSearch = tier.search !== 'none'; + const showReplica = tier.dbReplicas > 0; + + const lbName = k8s ? LB_BRAND_K8S[provider] : LB_BRAND_VM[provider]; + + return ( +
    + {/* Client tier — labeled container, two cards (Web/Desktop + Mobile) */} +
    +
    +
    Clients
    +
    +
    +
    Web & Desktop
    +
    Channels web app · Windows · macOS · Linux
    +
    +
    +
    Mobile
    +
    iOS · Android
    +
    +
    +
    +
    + + {/* Flow row: main HTTPS arrow from clients into LB / Mattermost */} +
    + +
    + + {/* Edge tier (ALB) — center column, locked above Mattermost */} + {showLb && ( + <> +
    +
    +
    {lbName}
    +
    + {tier.loadBalancer === 'cluster' ? 'HA pair · TLS termination' : 'TLS termination'} +
    +
    +
    +
    + +
    + + )} + + {/* App row: RTCD (left) — Mattermost (center) — Push (right), all in one row. + * The DIRECT pill floats absolutely above the RTCD box so it doesn't claim + * its own grid row (which would create an empty band across the diagram). */} + {showCalls && ( +
    +
    +
    +
    + direct + + UDP+TCP/8443 +
    +
    +
    RTCD (Calls)
    +
    + {tier.appNodes >= 8 ? 'HA (2–3 nodes)' : '1 node'} · audio + screen-share +
    +
    +
    + +
    +
    + )} + +
    +
    +
    + Mattermost{k8s ? ' (Operator)' : ''} + ×{tier.appNodes} +
    +
    + {tier.appCpu} vCPU · {tier.appRam} GB RAM{tier.ha ? ' · HA cluster' : ''} +
    +
    +
    + +
    +
    + + {pushMode === 'self-hosted' ? ( +
    +
    Push Proxy
    +
    self-hosted
    +
    + ) : ( +
    +
    Mattermost HPNS
    +
    + managed by Mattermost +
    + Hosted Push Notifications Service +
    +
    + )} +
    +
    + + {/* Data tier — spans full width below center */} +
    + 1 ? 's' : ''}` : ''}`} + /> + {showRedis && ( + = 8 ? 'Cluster' : 'Single'} · sessions + cluster state`} + /> + )} + {showSearch && ( + 1 ? 's' : ''} · message search`} + /> + )} + +
    +
    + ); +} + +/* ============================ Network Flows table ============================ + * + * Documents every connection in the architecture: source → destination, + * protocol, port, and purpose. Useful for firewall configuration. + * Rows are conditional on the user's choices. */ + +type NetworkFlow = { + from: string; + to: string; + protocol: string; + port: string; + direction: 'inbound' | 'internal' | 'egress'; + purpose: string; +}; + +function networkFlowsFor( + tier: Tier, + provider: Provider, + showCalls: boolean, + pushMode: 'self-hosted' | 'hpns', +): NetworkFlow[] { + const flows: NetworkFlow[] = []; + + flows.push({ + from: 'Web / Desktop / Mobile clients', + to: tier.loadBalancer !== 'none' ? 'Load balancer' : 'Mattermost', + protocol: 'HTTPS + WSS', + port: 'TCP/443', + direction: 'inbound', + purpose: 'Channels API, WebSocket events, file uploads', + }); + + if (showCalls) { + flows.push({ + from: 'Web / Desktop / Mobile clients', + to: 'RTCD', + protocol: 'UDP, TCP (fallback)', + port: '8443', + direction: 'inbound', + purpose: 'Calls media (audio, video, screen-share) — direct, bypasses LB', + }); + } + + if (tier.loadBalancer !== 'none') { + flows.push({ + from: 'Load balancer', + to: 'Mattermost', + protocol: 'HTTP', + port: 'TCP/8065', + direction: 'internal', + purpose: 'TLS-terminated app traffic', + }); + } + + flows.push({ + from: 'Mattermost', + to: `PostgreSQL (${DB_BRAND[provider]})`, + protocol: 'TCP', + port: '5432', + direction: 'internal', + purpose: 'Database queries', + }); + + if (tier.redis) { + flows.push({ + from: 'Mattermost', + to: `Redis (${REDIS_BRAND[provider]})`, + protocol: 'TCP', + port: '6379', + direction: 'internal', + purpose: 'Sessions, cluster coordination, cache', + }); + } + + if (tier.search !== 'none') { + flows.push({ + from: 'Mattermost', + to: `OpenSearch (${SEARCH_BRAND[provider]})`, + protocol: 'HTTPS', + port: '9200', + direction: 'internal', + purpose: 'Message search index reads + writes', + }); + } + + flows.push({ + from: 'Mattermost', + to: tier.storage === 'object' ? `Object storage (${STORAGE_BRAND[provider]})` : 'Local disk', + protocol: 'HTTPS', + port: 'TCP/443', + direction: tier.storage === 'object' ? 'internal' : 'internal', + purpose: 'File uploads, plugin assets, compliance exports', + }); + + if (showCalls) { + flows.push({ + from: 'Mattermost', + to: 'RTCD', + protocol: 'TCP', + port: '8045', + direction: 'internal', + purpose: 'Calls signaling and orchestration API', + }); + } + + flows.push({ + from: 'Mattermost', + to: pushMode === 'self-hosted' ? 'Mattermost Push Proxy (self-hosted)' : 'Mattermost HPNS (managed)', + protocol: 'HTTPS', + port: 'TCP/443', + direction: pushMode === 'self-hosted' ? 'internal' : 'egress', + purpose: 'Push notification submission', + }); + + flows.push({ + from: pushMode === 'self-hosted' ? 'Mattermost Push Proxy' : 'Mattermost HPNS', + to: 'Apple APNs (api.push.apple.com)', + protocol: 'HTTPS', + port: 'TCP/443', + direction: 'egress', + purpose: 'iOS push fan-out', + }); + + flows.push({ + from: pushMode === 'self-hosted' ? 'Mattermost Push Proxy' : 'Mattermost HPNS', + to: 'Google FCM (fcm.googleapis.com)', + protocol: 'HTTPS', + port: 'TCP/443', + direction: 'egress', + purpose: 'Android push fan-out', + }); + + return flows; +} + +function NetworkFlowsTable({flows}: {flows: NetworkFlow[]}) { + return ( + <> +

    Network flows

    +

    + Every connection in the architecture above — useful when configuring firewall + rules, security groups, or a CAP. Inbound = from clients;{' '} + internal = within the deployment boundary;{' '} + egress = out to external services. +

    +
    + + + + + + + + + + + + + {flows.map((f, i) => ( + + + + + + + + + ))} + +
    FromToDirectionProtocolPortPurpose
    {f.from}{f.to} + + {f.direction} + + {f.protocol}{f.port}{f.purpose}
    +
    + + ); +} + +/* ============================ Main component ============================ */ + +export default function DeploymentArchitectureBuilder() { + const [tierId, setTierId] = useState('medium'); + const [deploymentType, setDeploymentType] = useState('vm'); + const [provider, setProvider] = useState('aws'); + const [includeCalls, setIncludeCalls] = useState(false); + const [selfHostPush, setSelfHostPush] = useState(true); + + const tier = useMemo( + () => TIERS.find((t) => t.id === tierId) ?? TIERS[0], + [tierId], + ); + + const bom = useMemo( + () => bomFor(tier, deploymentType, provider, {calls: includeCalls, push: selfHostPush}), + [tier, deploymentType, provider, includeCalls, selfHostPush], + ); + + const flows = useMemo( + () => networkFlowsFor(tier, provider, includeCalls, selfHostPush ? 'self-hosted' : 'hpns'), + [tier, provider, includeCalls, selfHostPush], + ); + + return ( +
    +
    + + + + + + setDeploymentType(v as DeploymentType)} + options={[ + {value: 'vm', label: 'Virtual machines'}, + {value: 'kubernetes', label: 'Kubernetes'}, + ]} + /> + + + + + + + +
    + + +
    +
    +
    + + + + + +

    Bill of materials

    +
    + + + + + + + + + + + {bom.map((row, i) => ( + + + + + + + ))} + +
    ComponentQuantityRecommended size / SKUNotes
    {row.component}{row.quantity}{row.spec}{row.notes}
    +
    + + + +

    + Sizing follows the Mattermost scaling guide; provider SKUs are illustrative + starting points. Verify against current pricing, regional availability, and any + compliance constraints before procurement. +

    +
    + ); +} + +/* ============================ Small UI bits ============================ */ + +function ControlGroup({label, children}: {label: string; children: React.ReactNode}) { + return ( +
    +
    {label}
    + {children} +
    + ); +} + +function SegmentedControl({ + name, + value, + onChange, + options, +}: { + name: string; + value: T; + onChange: (v: T) => void; + options: {value: T; label: string}[]; +}) { + return ( +
    + {options.map((opt) => ( + + ))} +
    + ); +} diff --git a/docs/site/src/components/DeploymentArchitectureBuilder/styles.module.css b/docs/site/src/components/DeploymentArchitectureBuilder/styles.module.css new file mode 100644 index 000000000000..3be781cfdaad --- /dev/null +++ b/docs/site/src/components/DeploymentArchitectureBuilder/styles.module.css @@ -0,0 +1,860 @@ +/* Deployment Architecture builder. + * Brand alignment: denim headers, marigold accents on boxes, white cards. + * Layout: controls → summary → diagram (stacked rows) → bill of materials. */ + +.builder { + margin: 1.5rem 0 2rem; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.18)); + border-radius: 8px; + overflow: hidden; + background: var(--mm-color-white); + box-shadow: 0 4px 18px -14px rgba(30, 50, 92, 0.4); +} + +[data-theme='dark'] .builder { + background: var(--mm-denim-700, #121E37); + border-color: rgba(255, 255, 255, 0.1); +} + +/* ============================ Controls ============================ */ + +.controls { + display: grid; + grid-template-columns: minmax(200px, 0.9fr) minmax(220px, 1fr) minmax(280px, 1.3fr) minmax(180px, 0.9fr); + gap: 1rem; + padding: 1rem 1.25rem; + background: var(--mm-color-denim, #1E325C); + color: var(--mm-color-white); + align-items: end; +} + +@media (max-width: 1100px) { + .controls { grid-template-columns: 1fr 1fr; } +} + +@media (max-width: 720px) { + .controls { grid-template-columns: 1fr; } +} + +.controlGroup { + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.controlLabel { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.7rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: rgba(255, 255, 255, 0.78); +} + +.select { + appearance: none; + -webkit-appearance: none; + background-color: var(--mm-color-white); + color: var(--mm-text-primary); + border: 1px solid rgba(255, 255, 255, 0.25); + border-radius: 4px; + padding: 0.55rem 2.25rem 0.55rem 0.7rem; + font-size: 0.9rem; + font-family: var(--mm-font-sans); + cursor: pointer; + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231E325C' stroke-width='2'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 0.55rem center; + background-size: 1rem 1rem; +} + +.segmented { + display: inline-flex; + flex-wrap: wrap; + gap: 0.3rem; + background: rgba(255, 255, 255, 0.07); + padding: 0.2rem; + border-radius: 4px; +} + +.segment { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.4rem 0.7rem; + font-size: 0.82rem; + font-weight: 600; + font-family: var(--mm-font-sans); + color: rgba(255, 255, 255, 0.78); + cursor: pointer; + border-radius: 3px; + transition: background 120ms ease, color 120ms ease; + white-space: nowrap; +} + +.segment:hover { + color: var(--mm-color-white); +} + +.segmentActive { + background: var(--mm-color-marigold, #FFBC1F); + color: var(--mm-color-black, #1B1D22) !important; +} + +.segmentInput { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +/* Optional services checkboxes */ +.checkboxes { + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.checkbox { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.92); + cursor: pointer; + user-select: none; +} + +.checkbox input[type="checkbox"] { + appearance: none; + -webkit-appearance: none; + width: 1rem; + height: 1rem; + border: 1.5px solid rgba(255, 255, 255, 0.55); + border-radius: 3px; + background: transparent; + cursor: pointer; + position: relative; + transition: border-color 120ms ease, background 120ms ease; +} + +.checkbox input[type="checkbox"]:hover { + border-color: var(--mm-color-marigold, #FFBC1F); +} + +.checkbox input[type="checkbox"]:checked { + background: var(--mm-color-marigold, #FFBC1F); + border-color: var(--mm-color-marigold, #FFBC1F); +} + +.checkbox input[type="checkbox"]:checked::after { + content: ''; + position: absolute; + left: 3px; + top: 0; + width: 4px; + height: 8px; + border: solid var(--mm-color-black, #1B1D22); + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +/* ============================ Summary ============================ */ + +.summary { + padding: 0.85rem 1.25rem; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-bottom: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.12)); + font-size: 0.88rem; + line-height: 1.55; + color: var(--mm-text-primary); +} + +[data-theme='dark'] .summary { + background: rgba(255, 255, 255, 0.03); + color: var(--mm-color-white); +} + +.summary strong { + color: var(--mm-color-denim, #1E325C); +} + +[data-theme='dark'] .summary strong { + color: var(--mm-color-marigold, #FFBC1F); +} + +/* ============================ Diagram ============================ */ + +/* Diagram laid out as a 3-column grid: + * col 1 (1fr, justify-end): left-side components — RTCD when Calls is on + * col 2 (auto): center spine — clients, ALB, Mattermost, data tier + * col 3 (1fr, justify-start): right-side components — Push Proxy / HPNS + * + * The center column auto-sizes to Mattermost's box width, so the ALB sits + * directly above Mattermost regardless of whether RTCD/Push are present. + * Side columns fill remaining space and align toward the spine. */ +.diagram { + display: grid; + /* 1fr | auto | 1fr — equal side columns guarantee Mattermost is dead-centred + * regardless of what's in the side columns (RTCD on/off, Push narrow/wide). */ + grid-template-columns: 1fr auto 1fr; + align-items: center; + row-gap: 0.85rem; /* generous vertical rhythm */ + column-gap: 1rem; /* visible breathing room around Mattermost-adjacent arrows */ + padding: 1.5rem 1.25rem 1rem; +} + +/* Center column — every spine element (clients, ALB, flows, Mattermost) lives here */ +.gridCenter { + grid-column: 2; + justify-self: center; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + flex-wrap: wrap; +} + +/* Left column — RTCD lives here when Calls is enabled */ +.gridLeft { + grid-column: 1; + justify-self: end; + display: flex; + align-items: center; + gap: 0.5rem; +} + +/* Right column — Push Proxy / HPNS lives here */ +.gridRight { + grid-column: 3; + justify-self: start; + display: flex; + align-items: center; + gap: 0.5rem; +} + +/* Full-width rows — data tier spans the whole diagram */ +.gridFull { + grid-column: 1 / -1; + justify-self: center; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + justify-content: center; + width: 100%; +} + +/* Side group: box + horizontal connector together (used in left/right columns). + * Generous gap so the arrow has equal breathing room from its anchor box + * and from Mattermost (matched to .diagram column-gap). */ +.sideGroup { + display: inline-flex; + align-items: center; + gap: 1rem; +} + +/* Direct-flow pill sits in col 1, aligned to the right edge */ +.directFlowCell { + align-self: center; +} + +/* Legacy class kept for the few places using it (none active) */ +.row { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + justify-content: center; + width: 100%; + position: relative; +} + +.rowData { + margin-top: 0.2rem; + align-items: flex-start; +} + +/* App cluster — 3 columns aligned horizontally with arrow connectors: + * [Push column] ← [Mattermost] → [RTCD column] + * Stretches center-aligned; columns stack vertically inside (e.g., Push has + * APNs/FCM below it). Collapses to vertical at narrow viewports. */ +.appCluster { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.6rem; + margin: 0.3rem 0 0.6rem; + width: 100%; +} + +.appCol { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.3rem; +} + +/* Horizontal flow connector between columns — bordered pill with arrow + port */ +.hFlow { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.18rem 0.55rem; + font-family: var(--mm-font-mono, monospace); + font-size: 0.68rem; + font-weight: 600; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-bottom: 2px solid var(--mm-color-marigold, #FFBC1F); + border-radius: 2px; + white-space: nowrap; + align-self: center; +} + +[data-theme='dark'] .hFlow { + background: rgba(255, 255, 255, 0.04); +} + +.hArrow { + color: var(--mm-color-marigold, #FFBC1F); + font-weight: 700; + font-size: 0.9rem; + line-height: 1; +} + +.hFlowText { + color: var(--mm-color-denim, #1E325C); + font-weight: 600; +} + +[data-theme='dark'] .hFlowText { + color: var(--mm-color-white); +} + +.hFlowPorts { + margin-left: 0.45rem; + font-weight: 500; + color: var(--mm-text-secondary); + opacity: 0.85; +} + +[data-theme='dark'] .hFlowPorts { + color: rgba(255, 255, 255, 0.65); +} + +/* Each data tier component gets its own arrow + port indicator above it */ +.dataItem { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25rem; +} + +.miniFlow { + font-family: var(--mm-font-mono, monospace); + font-size: 0.68rem; + font-weight: 600; + color: var(--mm-color-denim, #1E325C); + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-left: 2px solid var(--mm-color-marigold, #FFBC1F); + padding: 0.15rem 0.45rem; + border-radius: 2px; + white-space: nowrap; +} + +[data-theme='dark'] .miniFlow { + color: var(--mm-color-white); + background: rgba(255, 255, 255, 0.05); +} + +.miniArrow { + color: var(--mm-color-marigold, #FFBC1F); + font-weight: 700; + margin-right: 0.15rem; +} + +/* Flow label between rows — shows protocol + port */ +.flow { + display: inline-flex; + align-items: center; + gap: 0.4rem; + margin: 0.15rem 0; + font-size: 0.7rem; + font-family: var(--mm-font-mono, monospace); + color: var(--mm-text-secondary, var(--mm-text-primary)); + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + padding: 0.18rem 0.55rem; + border-radius: 2px; + border-left: 2px solid var(--mm-color-marigold, #FFBC1F); +} + +[data-theme='dark'] .flow { + background: rgba(255, 255, 255, 0.04); + color: rgba(255, 255, 255, 0.78); +} + +.flowArrow { + color: var(--mm-color-marigold, #FFBC1F); + font-weight: 700; + font-size: 0.85rem; + line-height: 1; +} + +.flowText { + font-weight: 600; + color: var(--mm-color-denim, #1E325C); +} + +[data-theme='dark'] .flowText { + color: var(--mm-color-white); +} + +.flowPorts { + margin-left: 0.5rem; + font-weight: 500; + color: var(--mm-text-secondary); + opacity: 0.85; +} + +[data-theme='dark'] .flowPorts { + color: rgba(255, 255, 255, 0.65); +} + +/* Client tier — wrapped in a labeled container "Clients" */ +.clientsBox { + position: relative; + display: inline-block; + padding: 1.1rem 1rem 0.7rem; + border: 1.5px dashed var(--mm-border-subtle, rgba(30, 50, 92, 0.35)); + border-radius: 6px; + background: transparent; +} + +[data-theme='dark'] .clientsBox { + border-color: rgba(255, 255, 255, 0.25); +} + +.clientsLabel { + position: absolute; + top: -0.55rem; + left: 0.85rem; + padding: 0.05rem 0.45rem; + font-family: var(--mm-font-sans); + font-weight: 800; + font-size: 0.62rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--mm-color-denim, #1E325C); + background: var(--mm-color-white); +} + +[data-theme='dark'] .clientsLabel { + color: var(--mm-color-white); + background: var(--mm-denim-700, #121E37); +} + +.clientsRow { + display: flex; + gap: 0.6rem; + justify-content: center; + flex-wrap: nowrap; +} + +.client { + flex: 0 0 auto; + min-width: 12rem; + max-width: 16rem; + padding: 0.55rem 0.8rem; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.2)); + border-radius: 4px; + background: var(--mm-color-white); + color: var(--mm-text-primary); + text-align: center; +} + +[data-theme='dark'] .client { + color: var(--mm-color-white); + background: var(--mm-denim-800, #0C1424); + border-color: rgba(255, 255, 255, 0.1); +} + +.clientLabel { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.82rem; + color: var(--mm-color-denim, #1E325C); +} + +[data-theme='dark'] .clientLabel { + color: var(--mm-color-white); +} + +.clientSub { + font-size: 0.7rem; + margin-top: 0.15rem; + color: var(--mm-text-secondary, var(--mm-text-primary)); + opacity: 0.85; +} + +/* Legacy class kept for backward compat — used by old .rowClients references */ +.rowClients { + gap: 0.6rem; +} + +.box { + flex: 0 0 auto; + min-width: 9rem; + max-width: 14rem; + padding: 0.55rem 0.85rem; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.18)); + border-radius: 4px; + background: var(--mm-color-white); + color: var(--mm-text-primary); + text-align: center; + position: relative; +} + +[data-theme='dark'] .box { + background: var(--mm-denim-800, #0C1424); + color: var(--mm-color-white); + border-color: rgba(255, 255, 255, 0.12); +} + +.boxLabel { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.85rem; + line-height: 1.2; + color: var(--mm-color-denim, #1E325C); +} + +[data-theme='dark'] .boxLabel { + color: var(--mm-color-white); +} + +.qty { + display: inline-block; + margin-left: 0.3rem; + padding: 0.05rem 0.35rem; + font-size: 0.7rem; + font-weight: 700; + color: var(--mm-color-black); + background: var(--mm-color-marigold, #FFBC1F); + border-radius: 2px; +} + +.boxSub { + margin-top: 0.2rem; + font-size: 0.72rem; + line-height: 1.35; + color: var(--mm-text-secondary, var(--mm-text-primary)); + opacity: 0.85; +} + +/* Per-role left-edge accents. + * App-row boxes (App / Calls / Push) all share min-height so they align + * horizontally in the grid row even when their subtitles wrap differently. */ +.boxLb { border-left: 3px solid var(--mm-color-marigold, #FFBC1F); min-width: 16rem; } +.boxApp { border-left: 3px solid var(--mm-color-denim, #1E325C); min-width: 16rem; min-height: 4rem; } +.boxDb { border-left: 3px solid #1d6f42; min-width: 11rem; } /* postgres green */ +.boxRedis { border-left: 3px solid #d4322c; min-width: 11rem; } /* redis red */ +.boxSearch { border-left: 3px solid #5a3aa6; min-width: 11rem; } /* opensearch purple */ +.boxStorage { border-left: 3px solid #4a5568; min-width: 11rem; } /* neutral */ +.boxCalls { border-left: 3px solid #007a5a; min-width: 12rem; min-height: 4rem; } /* calls teal-green */ +.boxPush { border-left: 3px solid #3a6ea5; min-width: 12rem; min-height: 4rem; } /* push blue (self-hosted) */ + +/* HPNS managed-by-Mattermost variant — dotted border + secondary background */ +.boxPushManaged { + border: 1.5px dashed var(--mm-color-marigold, #FFBC1F); + background: rgba(255, 188, 31, 0.06); + min-width: 18rem; + min-height: 4rem; +} + +[data-theme='dark'] .boxPushManaged { + background: rgba(255, 188, 31, 0.1); +} + +.managedBadge { + display: inline-block; + margin-top: 0.2rem; + padding: 0.08rem 0.45rem; + font-size: 0.62rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + background: var(--mm-color-marigold, #FFBC1F); + color: var(--mm-color-black, #1B1D22); + border-radius: 2px; +} + +/* Flows-row container — sits between the client tier and the LB tier. + * When Calls is enabled, the direct client→RTCD flow renders on the LEFT + * (matching RTCD's column position below), and the main HTTPS+WSS path + * renders to its right. */ +.flowsRow { + display: flex; + align-items: center; + justify-content: center; + gap: 0.6rem; + flex-wrap: wrap; + margin: 0.15rem 0; +} + +.flowDirect { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.18rem 0.55rem; + background: rgba(0, 122, 90, 0.08); + border-left: 2px solid #007a5a; + border-radius: 2px; + font-family: var(--mm-font-mono, monospace); + font-size: 0.68rem; + font-weight: 600; + color: var(--mm-color-denim, #1E325C); + white-space: nowrap; +} + +[data-theme='dark'] .flowDirect { + background: rgba(0, 122, 90, 0.18); + color: var(--mm-color-white); +} + +/* RTCD column wrapper — relative anchor for the absolutely-positioned DIRECT pill */ +.rtcdWrap { + position: relative; +} + +/* Floating DIRECT pill: sits above the RTCD box without claiming a grid row */ +.flowDirectAbove { + position: absolute; + bottom: calc(100% + 0.35rem); + left: 50%; + transform: translateX(-50%); + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.18rem 0.55rem; + background: rgba(0, 122, 90, 0.08); + border-left: 2px solid #007a5a; + border-radius: 2px; + font-family: var(--mm-font-mono, monospace); + font-size: 0.68rem; + font-weight: 600; + color: var(--mm-color-denim, #1E325C); + white-space: nowrap; + pointer-events: none; +} + +[data-theme='dark'] .flowDirectAbove { + background: rgba(0, 122, 90, 0.22); + color: var(--mm-color-white); +} + +.directBadge { + display: inline-block; + padding: 0.05rem 0.35rem; + font-size: 0.6rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + background: #007a5a; + color: var(--mm-color-white); + border-radius: 2px; +} + +.flowArrowDiag { + color: #007a5a; + font-weight: 700; + font-size: 0.95rem; + line-height: 1; +} + +.directText { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +/* Legacy inline-in-RTCD callout (no longer used after layout swap) */ +.calloutDirect { + margin-top: 0.5rem; + padding: 0.4rem 0.55rem; + background: rgba(0, 122, 90, 0.08); + border-left: 2px solid #007a5a; + border-radius: 2px; + font-size: 0.7rem; + line-height: 1.45; + text-align: left; + color: var(--mm-text-primary); +} + +[data-theme='dark'] .calloutDirect { + background: rgba(0, 122, 90, 0.18); + color: var(--mm-color-white); +} + +.calloutDirect code { + font-family: var(--mm-font-mono, monospace); + font-size: 0.66rem; + background: rgba(255, 255, 255, 0.6); + padding: 0.05rem 0.3rem; + border-radius: 2px; +} + +[data-theme='dark'] .calloutDirect code { + background: rgba(255, 255, 255, 0.1); + color: var(--mm-color-white); +} + +.calloutBadge { + display: inline-block; + margin-right: 0.35rem; + padding: 0.05rem 0.35rem; + font-size: 0.6rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + background: #007a5a; + color: var(--mm-color-white); + border-radius: 2px; +} + +/* External services (APNs / FCM) — small, secondary visual treatment */ +.external { + display: inline-flex; + flex-direction: column; + align-items: center; + padding: 0.45rem 0.95rem; + border: 1px dotted var(--mm-border-subtle, rgba(30, 50, 92, 0.3)); + border-radius: 4px; + background: transparent; + text-align: center; + min-width: 12rem; +} + +[data-theme='dark'] .external { + border-color: rgba(255, 255, 255, 0.25); +} + +.externalLabel { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.78rem; + color: var(--mm-text-secondary, var(--mm-text-primary)); + letter-spacing: 0.04em; +} + +.externalSub { + font-size: 0.66rem; + margin-top: 0.1rem; + color: var(--mm-text-secondary, var(--mm-text-primary)); + opacity: 0.75; +} + +/* ============================ Bill of materials ============================ */ + +.bomHeading { + margin: 1.25rem 1.25rem 0.6rem; + font-family: var(--mm-font-sans); + font-size: 1rem; + font-weight: 700; + color: var(--mm-color-denim, #1E325C); + display: flex; + align-items: center; + gap: 0.45rem; +} + +.bomHeading::before { + content: ''; + display: inline-block; + width: 0.85rem; + height: 0.85rem; + background: var(--mm-color-marigold, #FFBC1F); +} + +[data-theme='dark'] .bomHeading { + color: var(--mm-color-white); +} + +.bomTableWrap { + overflow-x: auto; + padding: 0 1.25rem; +} + +.bomTable { + width: 100%; + border-collapse: collapse; + font-size: 0.85rem; + min-width: 720px; +} + +.bomTable th, +.bomTable td { + text-align: left; + padding: 0.55rem 0.75rem; + border-bottom: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.1)); + vertical-align: top; +} + +.bomTable th { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--mm-text-secondary, var(--mm-text-primary)); + border-bottom: 2px solid var(--mm-color-denim, #1E325C); + background: var(--mm-denim-50, rgba(30, 50, 92, 0.04)); +} + +[data-theme='dark'] .bomTable th { + background: rgba(255, 255, 255, 0.03); + color: var(--mm-color-white); +} + +.cellComponent { font-weight: 600; width: 18%; min-width: 9rem; } +.cellQty { width: 12%; min-width: 5rem; color: var(--mm-text-secondary); } +.cellSpec { width: 30%; font-family: var(--mm-font-mono, monospace); font-size: 0.8rem; } +.cellNotes { width: 40%; color: var(--mm-text-secondary, var(--mm-text-primary)); opacity: 0.95; } + +.caveat { + margin: 0.9rem 1.25rem 1.25rem; + font-size: 0.78rem; + line-height: 1.5; + color: var(--mm-text-secondary, var(--mm-text-primary)); + opacity: 0.85; +} + +/* Network flows table — intro paragraph + direction pills */ +.flowsIntro { + margin: 0.4rem 1.25rem 0.75rem; + font-size: 0.82rem; + line-height: 1.5; + color: var(--mm-text-secondary, var(--mm-text-primary)); +} + +.directionPill { + display: inline-block; + padding: 0.1rem 0.45rem; + font-size: 0.65rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + border-radius: 2px; + color: var(--mm-color-white); + white-space: nowrap; +} + +.dir_inbound { background: #3a6ea5; } +.dir_internal { background: #4a5568; } +.dir_egress { background: #b45309; } + +@media (max-width: 720px) { + .bomTable { min-width: 0; } + .cellSpec, .cellNotes { font-size: 0.78rem; } +} diff --git a/docs/site/src/components/DeploymentAvailability/index.tsx b/docs/site/src/components/DeploymentAvailability/index.tsx new file mode 100644 index 000000000000..ff2de202bfac --- /dev/null +++ b/docs/site/src/components/DeploymentAvailability/index.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +// Per-page deployment-mode badge. Paired with . +// +// Canonical mode slugs: +// cloud-shared — Mattermost Cloud (multi-tenant) +// cloud-dedicated — Mattermost Cloud Dedicated (single-tenant managed) +// cloud-government — Mattermost Cloud Government (FedRAMP Moderate) +// self-hosted — customer-managed, internet-connected +// air-gapped — customer-managed, network-isolated +// tactical-edge — DDIL forward-deployed +// +// Usage: +// + +type Mode = + | 'cloud-shared' + | 'cloud-dedicated' + | 'cloud-government' + | 'self-hosted' + | 'air-gapped' + | 'tactical-edge'; + +const MODE_LABEL: Record = { + 'cloud-shared': 'Cloud', + 'cloud-dedicated': 'Cloud Dedicated', + 'cloud-government': 'Cloud Government', + 'self-hosted': 'Self-Hosted', + 'air-gapped': 'Air-Gapped', + 'tactical-edge': 'Tactical Edge', +}; + +const KNOWN_MODES = Object.keys(MODE_LABEL) as Mode[]; + +function parseModes(value: string): {valid: Mode[]; invalid: string[]} { + const valid: Mode[] = []; + const invalid: string[] = []; + for (const raw of value.split(',').map((s) => s.trim()).filter(Boolean)) { + if ((KNOWN_MODES as string[]).includes(raw)) valid.push(raw as Mode); + else invalid.push(raw); + } + return {valid, invalid}; +} + +export default function DeploymentAvailability({modes}: {modes: string}) { + const {valid, invalid} = parseModes(modes || ''); + + if (invalid.length > 0) { + return ( + + ); + } + if (valid.length === 0) { + return ( + + ); + } + + const labels = valid.map((m) => MODE_LABEL[m]).join(', '); + return ( + + ); +} diff --git a/docs/site/src/components/DeploymentAvailability/styles.module.css b/docs/site/src/components/DeploymentAvailability/styles.module.css new file mode 100644 index 000000000000..240433758c36 --- /dev/null +++ b/docs/site/src/components/DeploymentAvailability/styles.module.css @@ -0,0 +1,52 @@ +/* Shares the visual contract with EditionAvailability. */ + +.badge { + display: inline-flex; + align-items: center; + gap: 0.45rem; + margin: 0.35rem 0.6rem 0.35rem 0; + padding: 0.35rem 0.7rem; + border-radius: 4px; + font-size: 0.85rem; + line-height: 1.2; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-left: 3px solid var(--mm-color-denim, #1E325C); + color: var(--mm-text-primary); +} + +[data-theme='dark'] .badge { + background: rgba(255, 255, 255, 0.04); +} + +.deployment { + border-left-color: var(--mm-color-denim, #1E325C); +} + +.key { + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.72rem; + opacity: 0.75; +} + +.value { + font-weight: 600; +} + +.value a { + color: inherit; + text-decoration: none; + border-bottom: 1px dotted currentColor; +} + +.value a:hover { + text-decoration: none; + border-bottom-style: solid; +} + +.unknown { + background: #fff3cd; + color: #664d03; + border-left-color: #ffc107; +} diff --git a/docs/site/src/components/DeploymentOnly/index.tsx b/docs/site/src/components/DeploymentOnly/index.tsx new file mode 100644 index 000000000000..908fc3016a74 --- /dev/null +++ b/docs/site/src/components/DeploymentOnly/index.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import BrowserOnly from '@docusaurus/BrowserOnly'; + +// Inline conditional rendering keyed off the `?scope=` URL parameter. +// Pattern adopted from Teleport (`?scope=enterprise`). Same canonical page, +// multiple rendered variants by deployment mode. +// +// Usage: +// +// This paragraph only renders when ?scope=self-hosted or ?scope=air-gapped. +// +// +// +// Cloud-specific content. Hidden when ?scope= is set to a non-Cloud mode. +// +// +// Behaviour: +// - No `?scope=` in URL: render the content (default = show everything). +// - `?scope=` present and `` is in `modes`: render content. +// - `?scope=` present and NOT in `modes`: hide content. +// - SSR: render content (matches "no scope" default — safe for SEO). + +type Mode = + | 'cloud-shared' + | 'cloud-dedicated' + | 'cloud-government' + | 'self-hosted' + | 'air-gapped' + | 'tactical-edge'; + +const KNOWN_MODES: Mode[] = [ + 'cloud-shared', + 'cloud-dedicated', + 'cloud-government', + 'self-hosted', + 'air-gapped', + 'tactical-edge', +]; + +function getScope(): string | null { + if (typeof window === 'undefined') return null; + try { + return new URLSearchParams(window.location.search).get('scope'); + } catch { + return null; + } +} + +function Inner({ + modes, + children, +}: { + modes: string; + children: React.ReactNode; +}) { + const allowed = (modes || '') + .split(',') + .map((s) => s.trim()) + .filter((s) => (KNOWN_MODES as string[]).includes(s)); + + const scope = getScope(); + if (!scope) return <>{children}; // No filter set — show everything. + if (allowed.includes(scope)) return <>{children}; + return null; +} + +export default function DeploymentOnly(props: { + modes: string; + children: React.ReactNode; +}) { + return ( + {props.children}}> + {() => } + + ); +} diff --git a/docs/site/src/components/EditionAvailability/index.tsx b/docs/site/src/components/EditionAvailability/index.tsx new file mode 100644 index 000000000000..51a5dc6fe4c1 --- /dev/null +++ b/docs/site/src/components/EditionAvailability/index.tsx @@ -0,0 +1,71 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +// Per-page edition badge. Authors mark which Mattermost editions a feature +// or configuration applies to. Renders a single-row inline badge at the +// top of the page (paired with ). +// +// Canonical tier slugs: +// free — Mattermost Team Edition (free, OSS) +// professional — Mattermost Professional +// enterprise — Mattermost Enterprise +// enterprise-advanced — Mattermost Enterprise Advanced +// +// Usage: +// +// + +type Tier = 'free' | 'professional' | 'enterprise' | 'enterprise-advanced'; + +const TIER_LABEL: Record = { + 'free': 'Team Edition', + 'professional': 'Professional', + 'enterprise': 'Enterprise', + 'enterprise-advanced': 'Enterprise Advanced', +}; + +const KNOWN_TIERS = Object.keys(TIER_LABEL) as Tier[]; + +function parseTiers(value: string): {valid: Tier[]; invalid: string[]} { + const valid: Tier[] = []; + const invalid: string[] = []; + for (const raw of value.split(',').map((s) => s.trim()).filter(Boolean)) { + if ((KNOWN_TIERS as string[]).includes(raw)) { + valid.push(raw as Tier); + } else { + invalid.push(raw); + } + } + return {valid, invalid}; +} + +export default function EditionAvailability({tiers}: {tiers: string}) { + const {valid, invalid} = parseTiers(tiers || ''); + + if (invalid.length > 0) { + return ( + + ); + } + if (valid.length === 0) { + return ( + + ); + } + + const labels = valid.map((t) => TIER_LABEL[t]).join(', '); + return ( + + ); +} diff --git a/docs/site/src/components/EditionAvailability/styles.module.css b/docs/site/src/components/EditionAvailability/styles.module.css new file mode 100644 index 000000000000..80a6b52a3afd --- /dev/null +++ b/docs/site/src/components/EditionAvailability/styles.module.css @@ -0,0 +1,54 @@ +/* Per-page Edition / Deployment / Attestation badges. + * Shared visual contract; the three badge components compose into a + * single inline row at the top of the page. */ + +.badge { + display: inline-flex; + align-items: center; + gap: 0.45rem; + margin: 0.35rem 0.6rem 0.35rem 0; + padding: 0.35rem 0.7rem; + border-radius: 4px; + font-size: 0.85rem; + line-height: 1.2; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-left: 3px solid var(--mm-color-denim, #1E325C); + color: var(--mm-text-primary); +} + +[data-theme='dark'] .badge { + background: rgba(255, 255, 255, 0.04); +} + +.edition { + border-left-color: var(--mm-color-marigold, #FFBC1F); +} + +.key { + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.72rem; + opacity: 0.75; +} + +.value { + font-weight: 600; +} + +.value a { + color: inherit; + text-decoration: none; + border-bottom: 1px dotted currentColor; +} + +.value a:hover { + text-decoration: none; + border-bottom-style: solid; +} + +.unknown { + background: #fff3cd; + color: #664d03; + border-left-color: #ffc107; +} diff --git a/docs/site/src/components/Eyebrow/index.tsx b/docs/site/src/components/Eyebrow/index.tsx new file mode 100644 index 000000000000..b17723d95213 --- /dev/null +++ b/docs/site/src/components/Eyebrow/index.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import styles from './styles.module.css'; + +/** + * Small section-name marker that sits above the H1 on inner-page + * landings. Replaces the Hero block on /api, /api/examples, and + * /developers — content-first, no marketing flair, brand presence + * via the marigold uppercase eyebrow only. + * + * Usage: + * API Reference + * # REST API v4 + * Subtitle paragraph... + */ +export default function Eyebrow({children}: {children: React.ReactNode}) { + return
    {children}
    ; +} diff --git a/docs/site/src/components/Eyebrow/styles.module.css b/docs/site/src/components/Eyebrow/styles.module.css new file mode 100644 index 000000000000..61012de33d47 --- /dev/null +++ b/docs/site/src/components/Eyebrow/styles.module.css @@ -0,0 +1,16 @@ +.eyebrow { + display: inline-block; + font-family: var(--mm-font-heading); + font-size: 0.74rem; + font-weight: 900; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--mm-marigold-700); + border-bottom: 2px solid var(--mm-color-marigold); + padding-bottom: 0.25rem; + margin-bottom: 1rem; +} + +[data-theme='dark'] .eyebrow { + color: var(--mm-color-marigold); +} diff --git a/docs/site/src/components/Hero/index.tsx b/docs/site/src/components/Hero/index.tsx new file mode 100644 index 000000000000..a6c9b01cdb9d --- /dev/null +++ b/docs/site/src/components/Hero/index.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import styles from './styles.module.css'; + +type Cta = { + label: string; + to: string; + variant?: 'primary' | 'ghost'; +}; + +type Props = { + eyebrow?: string; + title?: string; + subtitle?: string; + ctas?: Cta[]; + /** Pillars under the hero — defaults to brand pillars on the home hero. */ + pillars?: {label: string; description?: string}[]; + /** Restraint level: 'full' for /, 'compact' for /developers /api. */ + intensity?: 'full' | 'compact'; +}; + +export default function Hero({ + eyebrow, + title, + subtitle, + ctas = [], + pillars, + intensity = 'compact', +}: Props): React.ReactElement { + const camoUrl = useBaseUrl('/img/patterns/hex-camo-denim.svg'); + return ( +
    +
    + {eyebrow &&
    {eyebrow}
    } + {title &&

    {title}

    } + {subtitle &&

    {subtitle}

    } + {ctas.length > 0 && ( +
    + {ctas.map((cta, i) => ( + + {cta.label} + + + ))} +
    + )} + {pillars && ( +
      + {pillars.map((p) => ( +
    • + {p.label} + {p.description && {p.description}} +
    • + ))} +
    + )} +
    +
    +
    + ); +} diff --git a/docs/site/src/components/Hero/styles.module.css b/docs/site/src/components/Hero/styles.module.css new file mode 100644 index 000000000000..07fcbaa9f25a --- /dev/null +++ b/docs/site/src/components/Hero/styles.module.css @@ -0,0 +1,175 @@ +/* Branded landing-page hero. Mid-intensity per design call: + * full-bleed denim with hex camo, but capped height so it doesn't + * dominate every visit. The curved bottom edge (`.curve`) matches + * the brand book's photo/color transition treatment. + */ + +/* The hero fills the article column it lives in (no full-viewport escape). + * Why: 100vw includes scrollbar width on Windows/Chrome and produces a + * horizontal-scroll bleed. Also when a sidebar is present, escaping to + * 100vw misaligns the hero's centered inner content vs. the body content + * below (which sits in the article column). Containing the hero keeps + * its left/right edges consistent with the rest of the page. */ +/* The hero is a flat banded section, no rounded corners (the card-like + * frame felt clunky and disconnected from the rest of the page). The + * pattern sits under a heavier dimming overlay so it reads as + * atmospheric texture, not foreground motif. */ +.hero { + position: relative; + width: 100%; + margin-top: -1.25rem; + margin-bottom: 2.5rem; + background-color: var(--mm-color-denim); + background-image: + linear-gradient(180deg, rgba(12, 20, 36, 0.55) 0%, rgba(12, 20, 36, 0.25) 100%), + radial-gradient(ellipse 50% 100% at 100% 50%, rgba(91, 119, 177, 0.15) 0%, rgba(30, 50, 92, 0) 60%), + var(--mm-hero-camo); + background-size: cover, cover, 108px 125px; + background-repeat: no-repeat, no-repeat, repeat; + color: var(--mm-color-white); + overflow: hidden; + isolation: isolate; + border-bottom: 3px solid var(--mm-color-marigold); +} + +.full { + padding: clamp(2rem, 3.5vw, 3rem) 0 clamp(2rem, 3.5vw, 3rem); +} + +.compact { + padding: clamp(1.5rem, 2.5vw, 2.25rem) 0 clamp(1.75rem, 3vw, 2.5rem); +} + +.inner { + /* Fill the hero band; the band itself is sized by its parent + * (the article column). Padding keeps content off the band edges. */ + margin: 0 auto; + padding: 0 clamp(1.25rem, 3vw, 2rem); + position: relative; + z-index: 2; +} + +.eyebrow { + display: inline-block; + font-family: var(--mm-font-heading); + font-size: 0.72rem; + font-weight: 900; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--mm-color-marigold); + border: 1px solid rgba(255, 188, 31, 0.55); + padding: 0.32rem 0.75rem; + border-radius: 2px; + margin-bottom: 1rem; +} + +.title { + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: clamp(1.6rem, 3.2vw, 2.4rem); + line-height: 1.1; + letter-spacing: -0.01em; + color: var(--mm-color-white); + margin: 0 0 0.75rem; + max-width: 28ch; +} + +.full .title { + font-size: clamp(1.85rem, 3.8vw, 3rem); + max-width: 24ch; +} + +.subtitle { + font-size: clamp(0.95rem, 1.2vw, 1.1rem); + line-height: 1.55; + color: rgba(255, 255, 255, 0.82); + max-width: 64ch; + margin: 0 0 1.5rem; +} + +.ctas { + display: flex; + flex-wrap: wrap; + gap: 0.75rem 1rem; + margin-top: 0.5rem; +} + +.ctaPrimary, +.ctaGhost { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.65rem 1.1rem; + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: 0.78rem; + letter-spacing: 0.05em; + text-transform: uppercase; + text-decoration: none; + border-radius: 3px; + transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; +} + +.ctaPrimary { + background: var(--mm-color-marigold); + color: var(--mm-color-black); + border: 2px solid var(--mm-color-marigold); +} +.ctaPrimary:hover { + transform: translateY(-1px); + box-shadow: 0 10px 18px -10px rgba(0, 0, 0, 0.5); + color: var(--mm-color-black); + text-decoration: none; +} + +.ctaGhost { + background: transparent; + color: var(--mm-color-white); + border: 2px solid rgba(255, 255, 255, 0.5); +} +.ctaGhost:hover { + background: rgba(255, 255, 255, 0.08); + border-color: var(--mm-color-white); + color: var(--mm-color-white); + text-decoration: none; +} + +.pillars { + list-style: none; + padding: 1.75rem 0 0; + margin: 1.75rem 0 0; + border-top: 1px solid rgba(255, 255, 255, 0.15); + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 1rem 1.5rem; +} + +@media (max-width: 720px) { + .pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} + +.pillars li { + position: relative; + padding-top: 0.65rem; + border-top: 2px solid var(--mm-color-marigold); +} + +.pillars strong { + display: block; + font-family: var(--mm-font-heading); + font-size: 0.9rem; + font-weight: 900; + letter-spacing: 0.04em; + text-transform: uppercase; + margin-bottom: 0.25rem; + color: var(--mm-color-white); +} + +.pillars span { + display: block; + font-size: 0.82rem; + line-height: 1.45; + color: rgba(255, 255, 255, 0.75); +} + +.curve { display: none; } /* dropping the curve — too theatrical at this scale */ diff --git a/docs/site/src/components/IMEDiagram/index.tsx b/docs/site/src/components/IMEDiagram/index.tsx new file mode 100644 index 000000000000..51941c5291e0 --- /dev/null +++ b/docs/site/src/components/IMEDiagram/index.tsx @@ -0,0 +1,254 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +/** + * Interactive Intelligent Mission Environment (IME) diagram. + * + * Recreates the four-layer IME infographic (Use Cases → Application → + * Integration → Deployment) with every region linked to its canonical + * documentation page. Replaces the static infographic image on the + * landing page so visitors can drill into the docs from the diagram + * itself. + */ + +type CellProps = { + to: string; + title: string; + children: React.ReactNode; + icon?: React.ReactNode; +}; + +function Cell({to, title, children, icon}: CellProps) { + return ( + + {icon && {icon}} +
    + {title} +
    {children}
    +
    + + ); +} + +/* === Inline brand-aligned SVG icons (marigold tone via currentColor) === */ +const IconChat = () => ( + + + +); +const IconChecklist = () => ( + + + +); +const IconCall = () => ( + + + +); +const IconTarget = () => ( + + + + + +); +const IconSparkles = () => ( + + + +); +const IconShield = () => ( + + + +); +const IconCode = () => ( + + + +); +const IconServer = () => ( + + + + + + +); +const IconCompass = () => ( + + + + +); +const IconLayers = () => ( + + + + + +); +const IconPlug = () => ( + + + +); +const IconGlobe = () => ( + + + + + +); +const IconDevices = () => ( + + + + + +); +const IconVideo = () => ( + + + + +); + +export default function IMEDiagram() { + return ( +
    + {/* USE CASES */} +
    +
    Use Cases
    +
    +
    + }> + SOC/CERT ops, out-of-band incident response, Red Team + + }> + Dev productivity, CI/CD, platform engineering, emergency comms + + }> + Critical workflow, Zero Trust, C2 to tactical edge, joint ops + +
    +
    +
    + + {/* APPLICATION */} +
    +
    Application
    +
    +
    +
    +

    Secure Collaborative Workflow

    +

    + Messaging collaboration across web, desktop, and mobile with file sharing, + audio/screenshare, workflow automation, issue tracking, bots, agents, and open + API access — integrating into modern toolchains and legacy systems with + advanced customization and security controls. +

    +
    +
    + }> + Mattermost Channels for ChatOps and automation + + }> + Mattermost Playbooks for automating SOPs + + }> + Mattermost Calls for real‑time calling and screenshare + + }> + Mattermost Boards for Kanban and work management + + }> + Mattermost Agents — AI assistance and integration + +
    +
    +
    + + + Desktop, web, mobile & Microsoft Teams clients + + + + Extensible open-source architecture + +
    +
    +
    + + {/* INTEGRATION */} +
    +
    Integration
    +
    +
    +
    +

    Integration & AI Platform

    +

    + Operational extensibility with pre-packaged, source-available connectors, + automations, and templates for rapid and effective systems integration. +

    +
    + }> +
      +
    • Pre-packaged and custom integrations
    • +
    • Webhooks and slash commands
    • +
    • Plugin architecture
    • +
    +
    + }> +
      +
    • Sovereign AI model support via OpenAI APIs
    • +
    • Custom instructions, RAG, semantic search
    • +
    • Responsible AI control plane
    • +
    • MCP and agent-to-agent architecture
    • +
    +
    +
    +
    + + + Video meetings: Pexip · Webex · Cisco + + + + Pre-built: GitHub · GitLab · Jira · ServiceNow · M365 + +
    +
    +
    + + {/* DEPLOYMENT */} +
    +
    Deployment
    +
    +
    +
    +

    Sovereign, Cyber‑Resilient Deployment

    +

    + Kubernetes-based orchestration on private, government, and air-gapped clouds. + Scales from tactical edge to strategic core with geo-distributed ultra-high + availability. +

    +
    + }> + Runs at the edge, in your data center, in sovereign clouds, and on global hyperscalers: Azure, AWS, Google Cloud, Oracle Cloud. + + }> +
      +
    • Classified, air-gapped, and DDIL operations
    • +
    • Defense-grade controls, monitoring, and mobile security
    • +
    • Scales to 200K+ users
    • +
    +
    +
    +
    +
    +
    + ); +} diff --git a/docs/site/src/components/IMEDiagram/styles.module.css b/docs/site/src/components/IMEDiagram/styles.module.css new file mode 100644 index 000000000000..6f592c142308 --- /dev/null +++ b/docs/site/src/components/IMEDiagram/styles.module.css @@ -0,0 +1,348 @@ +/* Intelligent Mission Environment diagram — v2. + * + * Tighter visual match to the brand infographic: + * - Application zone visibly contained in a denim wash + border + * - Intro panels are NOT clickable cards; they're text columns with a + * marigold left-edge accent (brand-aligned, signals "category label") + * - Use Case cells use a soft denim-tinted background, not white-on-white + * - All clickable cells share the same white-with-marigold-on-hover treatment + * - Section titles get a thin marigold underline for visual rhythm + */ + +.diagram { + margin: 2rem 0 2.5rem; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.18)); + border-radius: 8px; + overflow: hidden; + background: var(--mm-color-white); + box-shadow: 0 4px 18px -14px rgba(30, 50, 92, 0.4); +} + +[data-theme='dark'] .diagram { + background: var(--mm-denim-700, #121E37); + border-color: rgba(255, 255, 255, 0.1); +} + +/* === Layer scaffold (vertical denim label on left + content area on right) === */ + +.layer { + display: grid; + grid-template-columns: 2rem 1fr; + border-top: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.15)); +} +.layer:first-child { + border-top: none; +} + +.layerLabel { + display: flex; + align-items: center; + justify-content: center; + background: var(--mm-color-denim, #1E325C); + color: var(--mm-color-white, #fff); + font-family: var(--mm-font-sans); + font-weight: 800; + font-size: 0.62rem; + letter-spacing: 0.22em; + text-transform: uppercase; + writing-mode: vertical-rl; + transform: rotate(180deg); + padding: 0.85rem 0; +} + +.layerBody { + padding: 0.9rem 1rem; + background: var(--mm-bg-page, #fff); +} + +[data-theme='dark'] .layerBody { + background: var(--mm-denim-800, #0C1424); +} + +/* Application zone gets a stronger denim wash to visibly contain it, + matching the original infographic where the whole Application block + reads as one tinted panel. */ +.layerApplication .layerBody { + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); +} +[data-theme='dark'] .layerApplication .layerBody { + background: rgba(255, 255, 255, 0.03); +} + +/* === Use Cases row — 3 horizontal cells, soft grey-tinted === */ + +.useCaseRow { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0.6rem; +} + +.useCaseRow .cell { + background: var(--mm-denim-50, rgba(30, 50, 92, 0.045)); + border-color: transparent; +} +.useCaseRow .cell:hover { + background: var(--mm-color-white, #fff); + border-color: var(--mm-color-marigold, #FFBC1F); +} +[data-theme='dark'] .useCaseRow .cell { + background: rgba(255, 255, 255, 0.04); + border-color: transparent; +} + +/* === Intro panels (Application / Integration / Deployment left column) === + Not clickable. Marigold left-edge accent for visual rhythm. */ + +.appIntro, +.intIntro, +.depIntro { + padding: 0.25rem 0.6rem 0.25rem 0.7rem; + border-left: 3px solid var(--mm-color-marigold, #FFBC1F); +} + +.appIntro h3, +.intIntro h3, +.depIntro h3 { + display: flex; + align-items: center; + gap: 0.45rem; + font-family: var(--mm-font-sans); + font-size: 0.95rem; + font-weight: 700; + color: var(--mm-color-denim, #1E325C); + margin: 0 0 0.4rem; + letter-spacing: -0.005em; + line-height: 1.25; +} + +.introIcon { + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + width: 1.2rem; + height: 1.2rem; + color: var(--mm-color-marigold, #FFBC1F); +} + +.introIcon svg { + width: 100%; + height: 100%; +} + +[data-theme='dark'] .appIntro h3, +[data-theme='dark'] .intIntro h3, +[data-theme='dark'] .depIntro h3 { + color: var(--mm-color-white); +} + +.appIntro p, +.intIntro p, +.depIntro p { + font-size: 0.78rem; + line-height: 1.5; + color: var(--mm-text-secondary, var(--mm-text-primary)); + margin: 0; +} + +/* === Application grid: intro + 5 product cards === */ + +.appGrid { + display: grid; + grid-template-columns: minmax(190px, 1.1fr) 3.4fr; + gap: 1rem; + align-items: stretch; +} + +.productGrid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 0.5rem; +} + +.appFooter { + display: grid; + /* Footer strips read as standalone bands — balanced columns so neither + * label wraps mid-phrase. (The grid above intentionally mirrors the + * intro/products asymmetry; the footer doesn't need to.) */ + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-top: 0.65rem; +} + +.footerCell { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.55rem 0.85rem; + font-size: 0.78rem; + font-weight: 600; + text-align: center; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.15)); + border-radius: 4px; + background: var(--mm-bg-page, #fff); + color: var(--mm-text-primary); + text-decoration: none; + transition: border-color 120ms ease, background 120ms ease; +} + +.footerIcon { + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + width: 1.1rem; + height: 1.1rem; + color: var(--mm-color-marigold, #FFBC1F); +} + +.footerIcon svg { + width: 100%; + height: 100%; +} +.footerCell:hover { + border-color: var(--mm-color-marigold, #FFBC1F); + background: var(--mm-marigold-100, rgba(255, 188, 31, 0.08)); + color: var(--mm-text-primary); + text-decoration: none; +} + +[data-theme='dark'] .footerCell { + background: var(--mm-denim-700, #121E37); + color: var(--mm-color-white); +} + +/* === Integration & Deployment grids === */ + +.intGrid, +.depGrid { + display: grid; + grid-template-columns: minmax(190px, 1.1fr) 1.7fr 1.7fr; + gap: 1rem; + align-items: stretch; +} + +/* === Cell — the reusable clickable unit === */ + +.cell { + display: flex; + flex-direction: column; + gap: 0.35rem; + padding: 0.6rem 0.7rem; + border: 1px solid var(--mm-border-subtle, rgba(30, 50, 92, 0.18)); + border-radius: 4px; + background: var(--mm-bg-page, #fff); + color: var(--mm-text-primary); + text-decoration: none; + transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease; +} +.cell:hover { + border-color: var(--mm-color-marigold, #FFBC1F); + box-shadow: 0 4px 14px -10px rgba(30, 50, 92, 0.35); + text-decoration: none; + color: var(--mm-text-primary); + transform: translateY(-1px); +} + +[data-theme='dark'] .cell { + background: var(--mm-denim-700, #121E37); + color: var(--mm-color-white); + border-color: rgba(255, 255, 255, 0.1); +} +[data-theme='dark'] .cell:hover { + color: var(--mm-color-white); +} + +.icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.45rem; + height: 1.45rem; + color: var(--mm-color-marigold, #FFBC1F); + margin-bottom: 0.15rem; +} + +.icon svg { + width: 100%; + height: 100%; +} + +.cellBody { + display: flex; + flex-direction: column; + gap: 0.15rem; +} + +.cellTitle { + font-family: var(--mm-font-sans); + font-weight: 700; + font-size: 0.82rem; + line-height: 1.25; + color: var(--mm-color-denim, #1E325C); +} + +[data-theme='dark'] .cellTitle { + color: var(--mm-color-white); +} + +.cellText { + font-size: 0.74rem; + line-height: 1.4; + color: var(--mm-text-secondary, var(--mm-text-primary)); +} + +.cellText ul { + margin: 0.2rem 0 0; + padding-left: 0.95rem; + list-style: disc; +} + +.cellText li { + margin: 0.08rem 0; +} + +/* === Use Case cells get larger title + tighter sub-text — readable at row scale === */ + +.useCaseRow .cellTitle { + font-size: 0.95rem; +} +.useCaseRow .cellText { + font-size: 0.78rem; +} + +/* === Responsive collapse === */ + +@media (max-width: 980px) { + .appGrid, + .intGrid, + .depGrid { + grid-template-columns: 1fr; + } + .productGrid { + grid-template-columns: repeat(2, 1fr); + } + .appFooter { + grid-template-columns: 1fr; + } +} + +@media (max-width: 600px) { + .useCaseRow { + grid-template-columns: 1fr; + } + .productGrid { + grid-template-columns: 1fr; + } + .layer { + grid-template-columns: 1fr; + } + .layerLabel { + writing-mode: horizontal-tb; + transform: none; + padding: 0.4rem 0.85rem; + justify-content: flex-start; + font-size: 0.65rem; + } +} diff --git a/docs/site/src/components/MethodLegend/index.tsx b/docs/site/src/components/MethodLegend/index.tsx new file mode 100644 index 000000000000..712e104d446b --- /dev/null +++ b/docs/site/src/components/MethodLegend/index.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import styles from './styles.module.css'; + +const METHODS: Array<{verb: string; tone: string; meaning: string}> = [ + {verb: 'GET', tone: 'get', meaning: 'Read'}, + {verb: 'POST', tone: 'post', meaning: 'Create / action'}, + {verb: 'PUT', tone: 'put', meaning: 'Replace'}, + {verb: 'PATCH', tone: 'patch', meaning: 'Update fields'}, + {verb: 'DELETE', tone: 'delete', meaning: 'Remove'}, +]; + +/** + * Inline legend that decodes the HTTP method colors used throughout + * the API sidebar and endpoint pages. Most readers internalize these + * fast — but the first 30 seconds on the API landing matter, and the + * legend collapses that ramp. + */ +export default function MethodLegend() { + return ( +
      + {METHODS.map((m) => ( +
    • + {m.verb} + {m.meaning} +
    • + ))} +
    + ); +} diff --git a/docs/site/src/components/MethodLegend/styles.module.css b/docs/site/src/components/MethodLegend/styles.module.css new file mode 100644 index 000000000000..b16e5bf500b7 --- /dev/null +++ b/docs/site/src/components/MethodLegend/styles.module.css @@ -0,0 +1,41 @@ +.legend { + list-style: none; + margin: 1rem 0 2rem; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: 0.5rem 1rem; + font-size: 0.85rem; +} + +.item { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0; + margin: 0; +} + +.badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 3.6rem; + padding: 0.2rem 0.55rem; + font-family: var(--mm-font-mono); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.04em; + border-radius: 3px; + color: var(--mm-color-white); +} + +.get { background: #2D7BD2; } /* operational blue */ +.post { background: #2C7A4F; } /* operational green */ +.put { background: #A86A1F; } /* operational amber */ +.patch { background: #6B4FA0; } /* operational violet */ +.delete { background: #8B1F1F; } /* operational red */ + +.meaning { + color: var(--mm-text-secondary); +} diff --git a/docs/site/src/components/PlanAvailability/index.tsx b/docs/site/src/components/PlanAvailability/index.tsx new file mode 100644 index 000000000000..b4cd4fcc51a0 --- /dev/null +++ b/docs/site/src/components/PlanAvailability/index.tsx @@ -0,0 +1,124 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import styles from './styles.module.css'; + +// Plan-availability and Academy badges. Replaces Sphinx's +// .. include:: /_static/badges/.rst +// pattern. Slug values mirror the original badge filenames so the +// mechanical RST→MDX conversion is a 1:1 rewrite. + +type PlanData = { + kind: 'plan'; + text: string; + linkText: string; + href: string; +}; + +type AcademyData = { + kind: 'academy'; + title: string; + href: string; +}; + +const BADGES: Record = { + // Plan-availability banners + 'all-commercial': { + kind: 'plan', + text: 'Available on', + linkText: 'Entry, Professional, Enterprise, and Enterprise Advanced plans', + href: 'https://mattermost.com/pricing/', + }, + 'ent-plus': { + kind: 'plan', + text: 'Available on', + linkText: 'Enterprise and Enterprise Advanced plans', + href: 'https://mattermost.com/pricing/', + }, + 'ent-adv': { + kind: 'plan', + text: 'Available on', + linkText: 'Enterprise Advanced plans', + href: 'https://mattermost.com/pricing/', + }, + 'ent-cloud-dedicated': { + kind: 'plan', + text: 'Available only on', + linkText: 'Enterprise and Enterprise Advanced plans', + href: 'https://mattermost.com/contact-sales/', + }, + 'entry-adv': { + kind: 'plan', + text: 'Available on', + linkText: 'Entry and Enterprise Advanced plans', + href: 'https://mattermost.com/pricing/', + }, + 'entry-ent': { + kind: 'plan', + text: 'Available on', + linkText: 'Entry, Enterprise, and Enterprise Advanced plans (not available on Professional)', + href: 'https://mattermost.com/pricing/', + }, + 'pro-plus': { + kind: 'plan', + text: 'Available on', + linkText: 'Professional, Enterprise, and Enterprise Advanced plans', + href: 'https://mattermost.com/pricing/', + }, + + // Academy callout cards + 'academy': {kind: 'academy', title: 'Free online training available', href: 'https://academy.mattermost.com'}, + 'academy-calls': {kind: 'academy', title: 'Learn about Mattermost Calls', href: 'https://academy.mattermost.com/p/new-mattermost-copilot-multi-llm-setup-usage'}, + 'academy-channels': {kind: 'academy', title: 'Learn about Mattermost channels', href: 'https://mattermost.com/pl/mattermost-academy-channels-training'}, + 'academy-copilot-calls': {kind: 'academy', title: 'Learn about Mattermost Copilot and Calls', href: 'https://academy.mattermost.com/p/streamline-communication-with-mattermost-copilot-calls'}, + 'academy-copilot-setup': {kind: 'academy', title: 'Learn about setting up and configuring Mattermost Copilot with multiple LLMs', href: 'https://academy.mattermost.com/p/new-mattermost-copilot-multi-llm-setup-usage'}, + 'academy-customize-ui': {kind: 'academy', title: 'Learn what you can customize', href: 'https://mattermost.com/pl/mattermost-academy-customization-training'}, + 'academy-file-storage': {kind: 'academy', title: 'Learn about file storage', href: 'https://mattermost.com/pl/mattermost-academy-configure-file-storage-training'}, + 'academy-mattermost-database': {kind: 'academy', title: 'Learn about setting up the Mattermost database', href: 'https://mattermost.com/pl/mattermost-academy-database-configuration-training'}, + 'academy-message-formatting': {kind: 'academy', title: 'Learn about message formatting', href: 'https://mattermost.com/pl/mattermost-academy-format-messages-training'}, + 'academy-msteams': {kind: 'academy', title: 'Learn about integrating with Microsoft Teams', href: 'https://academy.mattermost.com/p/new-mattermost-for-microsoft-teams-integration'}, + 'academy-notifications': {kind: 'academy', title: 'Learn about notifications', href: 'https://mattermost.com/pl/mattermost-academy-notifications-training'}, + 'academy-platform-overview':{kind: 'academy', title: 'Learn about Mattermost', href: 'https://mattermost.com/pl/mattermost-academy-intro-training'}, + 'academy-playbooks': {kind: 'academy', title: 'Learn about Mattermost Playbooks', href: 'https://academy.mattermost.com/p/mattermost-playbooks-onboarding-training'}, + 'academy-search': {kind: 'academy', title: 'Learn about search', href: 'https://mattermost.com/pl/mattermost-academy-search-training'}, + 'academy-tarball-deployment':{kind: 'academy', title: 'Learn about deploying Mattermost using a tarball', href: 'https://mattermost.com/pl/mattermost-academy-deploy-tarball-training'}, + 'academy-tarball-upgrade': {kind: 'academy', title: 'Learn about upgrading Mattermost using a tarball', href: 'https://mattermost.com/pl/mattermost-academy-upgrade-tarball-training'}, + 'academy-teams': {kind: 'academy', title: 'Learn about teams', href: 'https://academy.mattermost.com/p/new-mattermost-for-microsoft-teams-integration'}, +}; + +export default function PlanAvailability({slug}: {slug: string}) { + const flagSrc = useBaseUrl('/img/badges/flag-yellow.svg'); + const academySrc = useBaseUrl('/img/badges/academy-callout.jpg'); + const data = BADGES[slug]; + + if (!data) { + return ( +
    + Unknown plan-availability slug: {slug} +
    + ); + } + + if (data.kind === 'plan') { + return ( + + ); + } + + return ( + + +
    + Mattermost Academy + {data.title} +
    + + ); +} diff --git a/docs/site/src/components/PlanAvailability/styles.module.css b/docs/site/src/components/PlanAvailability/styles.module.css new file mode 100644 index 000000000000..957f9cd96cc1 --- /dev/null +++ b/docs/site/src/components/PlanAvailability/styles.module.css @@ -0,0 +1,90 @@ +/* Plan-availability banner + Academy callout card. + * Ports the visual contract of the Sphinx _static/badges/*.rst includes. */ + +.badge { + display: flex; + align-items: center; + gap: 0.65rem; + margin: 1rem 0; + border-radius: 6px; + font-size: 0.95rem; +} + +/* Plan-availability — flat denim-tinted strip, marigold flag on the left. */ +.plan { + padding: 0.55rem 0.85rem; + background: var(--mm-denim-50, rgba(30, 50, 92, 0.05)); + border-left: 3px solid var(--mm-color-marigold); + color: var(--mm-text-primary); +} + +[data-theme='dark'] .plan { + background: rgba(255, 188, 31, 0.07); + color: var(--mm-text-primary); +} + +.plan a { + font-weight: 600; +} + +.flag { + flex: 0 0 1.05rem; + width: 1.05rem; + height: auto; +} + +/* Academy callout — full-bleed card with image on the left, two stacked + * lines of copy on the right. Whole card is the clickable link. */ +.academy { + display: flex; + align-items: stretch; + text-decoration: none; + color: inherit; + overflow: hidden; + border: 1px solid var(--mm-border-subtle); + background: var(--mm-bg-surface); + transition: box-shadow 120ms ease, transform 120ms ease; +} + +.academy:hover { + text-decoration: none; + box-shadow: 0 4px 12px rgba(30, 50, 92, 0.12); + transform: translateY(-1px); +} + +.academyImg { + flex: 0 0 auto; + width: 6rem; + height: 100%; + object-fit: cover; + display: block; +} + +.academyCopy { + display: flex; + flex-direction: column; + justify-content: center; + padding: 0.7rem 1rem; + gap: 0.15rem; +} + +.academyAccent { + font-family: var(--mm-font-heading); + font-size: 0.7rem; + font-weight: 900; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--mm-color-marigold); +} + +.academyTitle { + font-weight: 600; + color: var(--mm-text-primary); +} + +.unknown { + padding: 0.55rem 0.85rem; + background: #fff3cd; + color: #664d03; + border-left: 3px solid #ffc107; +} diff --git a/docs/site/src/components/PlanBadge/index.tsx b/docs/site/src/components/PlanBadge/index.tsx new file mode 100644 index 000000000000..30846d828c3e --- /dev/null +++ b/docs/site/src/components/PlanBadge/index.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import styles from './styles.module.css'; + +type Plan = 'free' | 'professional' | 'enterprise' | 'cloud' | 'self-hosted'; + +const META: Record = { + 'free': {label: 'Free', tone: 'neutral'}, + 'professional': {label: 'Professional', tone: 'accent'}, + 'enterprise': {label: 'Enterprise', tone: 'inverse'}, + 'cloud': {label: 'Cloud', tone: 'neutral'}, + 'self-hosted': {label: 'Self-hosted', tone: 'neutral'}, +}; + +export default function PlanBadge({plan}: {plan: Plan}) { + const m = META[plan]; + return {m.label}; +} diff --git a/docs/site/src/components/PlanBadge/styles.module.css b/docs/site/src/components/PlanBadge/styles.module.css new file mode 100644 index 000000000000..c17c4d5dca37 --- /dev/null +++ b/docs/site/src/components/PlanBadge/styles.module.css @@ -0,0 +1,33 @@ +.badge { + display: inline-block; + padding: 0.18rem 0.55rem; + font-family: var(--mm-font-heading); + font-size: 0.68rem; + font-weight: 900; + letter-spacing: 0.08em; + text-transform: uppercase; + border-radius: 2px; + vertical-align: middle; + margin: 0 0.25rem; +} + +.neutral { + background: var(--mm-denim-50); + color: var(--mm-denim-700); + border: 1px solid var(--mm-denim-100); +} +[data-theme='dark'] .neutral { + background: var(--mm-denim-800); + color: var(--mm-denim-100); + border-color: var(--mm-denim-700); +} + +.accent { + background: var(--mm-color-marigold); + color: var(--mm-color-black); +} + +.inverse { + background: var(--mm-color-denim); + color: var(--mm-color-white); +} diff --git a/docs/site/src/components/StatStrip/index.tsx b/docs/site/src/components/StatStrip/index.tsx new file mode 100644 index 000000000000..1c7cae646fee --- /dev/null +++ b/docs/site/src/components/StatStrip/index.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import styles from './styles.module.css'; + +type Stat = { + value: string | number; + label: string; + hint?: string; +}; + +/** + * Horizontal strip of headline numbers — used at the top of landing + * pages to surface the size/scope of the section in a single glance. + * + * Usage: + * + */ +export default function StatStrip({stats}: {stats: Stat[]}) { + return ( +
      + {stats.map((s) => ( +
    • + {s.value} + {s.label} + {s.hint && {s.hint}} +
    • + ))} +
    + ); +} diff --git a/docs/site/src/components/StatStrip/styles.module.css b/docs/site/src/components/StatStrip/styles.module.css new file mode 100644 index 000000000000..4d7f5404cfee --- /dev/null +++ b/docs/site/src/components/StatStrip/styles.module.css @@ -0,0 +1,48 @@ +.strip { + list-style: none; + margin: 1.5rem 0 2.5rem; + padding: 1.25rem 0; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1rem 2rem; + border-top: 2px solid var(--mm-color-marigold); + border-bottom: 1px solid var(--mm-border-subtle); +} + +.stat { + display: flex; + flex-direction: column; + gap: 0.15rem; + padding: 0; + margin: 0; +} + +.value { + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: clamp(1.75rem, 2.5vw, 2.4rem); + line-height: 1; + letter-spacing: -0.02em; + color: var(--mm-color-denim); +} + +[data-theme='dark'] .value { + color: var(--mm-color-white); +} + +.label { + font-family: var(--mm-font-heading); + font-weight: 900; + font-size: 0.7rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--mm-text-secondary); + margin-top: 0.4rem; +} + +.hint { + font-size: 0.78rem; + line-height: 1.4; + color: var(--mm-text-secondary); + margin-top: 0.25rem; +} diff --git a/docs/site/src/css/custom.css b/docs/site/src/css/custom.css new file mode 100644 index 000000000000..5812efe229f8 --- /dev/null +++ b/docs/site/src/css/custom.css @@ -0,0 +1,555 @@ +/* + * Mattermost docs theme overrides on top of Infima. + * Tokens live in tokens.css. This file maps tokens to Infima vars and + * adds the brand surface treatments (navbar density, code blocks, + * sidebar, footer) so the site reads as part of the Mattermost product + * family, not a default Docusaurus install. + */ + +/* === Map brand tokens onto Infima === */ + +:root { + --ifm-color-primary: var(--mm-denim-500); + --ifm-color-primary-dark: var(--mm-denim-600); + --ifm-color-primary-darker: var(--mm-denim-700); + --ifm-color-primary-darkest: var(--mm-denim-800); + --ifm-color-primary-light: var(--mm-denim-400); + --ifm-color-primary-lighter: var(--mm-denim-300); + --ifm-color-primary-lightest: var(--mm-denim-200); + + --ifm-font-family-base: var(--mm-font-sans); + --ifm-font-family-monospace: var(--mm-font-mono); + --ifm-heading-font-family: var(--mm-font-heading); + --ifm-heading-font-weight: 900; + --ifm-h1-font-size: 2.6rem; + --ifm-h2-font-size: 1.85rem; + --ifm-h3-font-size: 1.35rem; + --ifm-line-height-base: 1.65; + --ifm-spacing-vertical: 1.2rem; + + --ifm-code-font-size: 90%; + --docusaurus-highlighted-code-line-bg: rgba(30, 50, 92, 0.1); + + --ifm-background-color: var(--mm-bg-page); + --ifm-background-surface-color: var(--mm-bg-surface); + --ifm-navbar-background-color: var(--mm-color-denim); + --ifm-navbar-link-color: rgba(255, 255, 255, 0.85); + --ifm-navbar-link-hover-color: var(--mm-color-white); + --ifm-navbar-height: 4rem; + --ifm-footer-background-color: var(--mm-color-denim); + --ifm-footer-color: var(--mm-color-white); + --ifm-footer-link-color: rgba(255,255,255,0.78); + --ifm-footer-link-hover-color: var(--mm-color-marigold); + --ifm-footer-title-color: var(--mm-color-white); + + --ifm-link-color: var(--mm-link); + --ifm-link-hover-color: var(--mm-link-hover); + --ifm-link-hover-decoration: underline; + + --ifm-toc-border-color: var(--mm-border-subtle); + --ifm-hr-border-color: var(--mm-border-subtle); + + /* Sidebar */ + --ifm-menu-color: var(--mm-denim-700); + --ifm-menu-color-active: var(--mm-color-denim); + --ifm-menu-color-background-active: var(--mm-denim-50); + --ifm-menu-color-background-hover: var(--mm-denim-50); + --ifm-menu-link-padding-vertical: 0.45rem; + --ifm-menu-link-padding-horizontal: 0.85rem; +} + +[data-theme='dark'] { + --ifm-color-primary: var(--mm-color-sky); + --ifm-color-primary-dark: var(--mm-denim-300); + --ifm-color-primary-darker: var(--mm-denim-400); + --ifm-color-primary-darkest: var(--mm-denim-500); + --ifm-color-primary-light: var(--mm-denim-100); + --ifm-color-primary-lighter: var(--mm-denim-50); + --ifm-color-primary-lightest: var(--mm-color-white); + + --ifm-background-color: var(--mm-bg-page); + --ifm-background-surface-color: var(--mm-bg-surface); + --docusaurus-highlighted-code-line-bg: rgba(255, 188, 31, 0.18); + + --ifm-navbar-background-color: var(--mm-denim-800); + --ifm-navbar-link-color: rgba(255,255,255,0.85); + --ifm-navbar-link-hover-color: var(--mm-color-white); + + --ifm-menu-color: rgba(255,255,255,0.78); + --ifm-menu-color-active: var(--mm-color-white); + --ifm-menu-color-background-active: var(--mm-denim-700); + --ifm-menu-color-background-hover: var(--mm-denim-700); +} + +/* === Type rhythm === */ + +html { + font-feature-settings: "ss01", "cv11"; /* Inter alt forms */ +} + +body { + font-family: var(--mm-font-sans); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Headlines target Trade Gothic Next Heavy proportions: tighter set + * than Archivo Black's default. We tune letter-spacing per size and + * apply a mild horizontal squeeze via font-stretch where the platform + * supports it (no-op on Archivo Black, which is fixed-width). */ +h1, h2, h3, h4 { + font-family: var(--mm-font-heading); + letter-spacing: -0.015em; + line-height: 1.12; + font-stretch: 92%; /* ignored by static fonts; helps with variable Saira if loaded */ +} + +h1 { letter-spacing: -0.025em; } +h2 { letter-spacing: -0.018em; } +h3 { letter-spacing: -0.012em; } + +/* Section heading rhythm — a small marigold rule sits above each h2. + * Scoped via the `mm-section` class (auto-applied below) so it doesn't + * collide with OpenAPI plugin internal h2s (endpoint URL header, + * Request/Response panels, tab headings, etc.) which use their own + * layout and get squashed by our padding-top. + * + * The auto-apply trick: any h2 inside a doc page that ISN'T a + * descendant of an `.openapi-*` container gets the rule. */ +.markdown h2:not([class*="openapi"]):not([class*="openapi"] *) { + position: relative; + margin-top: 3rem; + padding-top: 1.4rem; +} +.markdown h2:not([class*="openapi"]):not([class*="openapi"] *)::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 3rem; + height: 2px; + background: var(--mm-color-marigold); +} + +/* Belt-and-braces: explicitly null the rule on every OpenAPI plugin + * heading we know the plugin emits. */ +.markdown .openapi__method-endpoint-path, +.markdown .openapi-tabs__heading, +.markdown .openapi-tabs__response-header, +.markdown [class*="openapi"] h2 { + position: static !important; + margin-top: 0 !important; + padding-top: 0 !important; +} +.markdown .openapi__method-endpoint-path::before, +.markdown .openapi-tabs__heading::before, +.markdown .openapi-tabs__response-header::before, +.markdown [class*="openapi"] h2::before { + display: none !important; +} + +/* === Navbar — solid denim with white text === */ + +.navbar { + background-color: var(--mm-color-denim); + border-bottom: 2px solid var(--mm-color-marigold); + box-shadow: 0 2px 12px -8px rgba(0, 0, 0, 0.35); +} + +.navbar__inner { + max-width: 1280px; + margin: 0 auto; + padding: 0 clamp(1rem, 2.5vw, 1.75rem); +} + +.navbar__brand { + margin-right: 1.5rem; +} +.navbar__logo { + height: 1.85rem; + margin-right: 0; +} + +.navbar__item { + font-size: 0.9rem; +} + +.navbar__link { + /* Body font (Inter) for legibility at small sizes — Archivo Black 900 is + * designed for display headlines, not 12-14px nav. Brand identity is + * preserved via uppercase + letter-spacing. */ + font-family: var(--mm-font-sans); + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + font-size: 0.875rem; + padding: 0 0.85rem; + position: relative; +} + +.navbar__link { + color: rgba(255, 255, 255, 0.92); +} +.navbar__link:hover { + color: var(--mm-color-white); + text-decoration: none; +} +.navbar__link--active, +.navbar__link[aria-current="page"] { + color: var(--mm-color-white); +} +.navbar__link--active::after, +.navbar__link[aria-current="page"]::after { + content: ''; + position: absolute; + left: 0.85rem; + right: 0.85rem; + bottom: -1.2rem; + height: 3px; + background: var(--mm-color-marigold); +} + +/* GitHub link → render as outlined ghost on a denim navbar. */ +.navbar__items--right .navbar__link[href*="github.com"] { + border: 1px solid rgba(255, 255, 255, 0.3); + color: var(--mm-color-white); + border-radius: 3px; + padding: 0.4rem 0.9rem; + letter-spacing: 0.06em; +} +.navbar__items--right .navbar__link[href*="github.com"]:hover { + background: rgba(255, 255, 255, 0.1); + border-color: var(--mm-color-white); +} + +/* Color-mode toggle on a denim navbar — white icon, subtle hover. */ +.navbar .clean-btn { + color: rgba(255, 255, 255, 0.78); +} +.navbar .clean-btn:hover { + color: var(--mm-color-white); + background: rgba(255, 255, 255, 0.08); +} + +/* === Sidebar === */ + +.theme-doc-sidebar-container { + border-right: 1px solid var(--mm-border-subtle) !important; +} +[data-theme='dark'] .theme-doc-sidebar-container { + border-right-color: var(--mm-denim-700) !important; +} + +.menu { + padding: 1.25rem 0.75rem !important; + font-size: 0.9rem; +} + +.menu__list-item-collapsible, +.menu__link { + border-radius: 3px; +} + +.menu__link--sublist-caret::after { + opacity: 0.6; +} + +.menu__caret { + background: transparent !important; +} + +.menu__list-item--collapsed .menu__list-item-collapsible { + border-radius: 3px; +} + +/* Categories at any depth — including OpenAPI tag groups in the API + * sidebar (users → Users, audit logs → Audit Logs) — render in Trade + * Gothic Heavy with title case. (`::first-letter` doesn't apply to + * the menu link's flex layout, so we use text-transform: capitalize + * which capitalizes the first letter of every word.) */ +.menu .menu__list-item-collapsible > .menu__link, +.menu > .menu__list > .menu__list-item > .menu__link { + font-family: var(--mm-font-heading); + font-weight: 900; + letter-spacing: 0.02em; + text-transform: capitalize; + font-size: 0.82rem; + color: var(--mm-text-secondary); + padding-top: 0.55rem; + padding-bottom: 0.4rem; +} + +/* Endpoint leaves keep their natural case (e.g. "Login to Mattermost server"). */ +.menu .menu__link.api-method { + font-family: var(--mm-font-sans); + font-weight: 500; + letter-spacing: 0; + text-transform: none; + font-size: 0.85rem; + color: var(--mm-text-primary); +} + +/* === Code === */ + +code { + background-color: var(--mm-denim-50); + border: 1px solid var(--mm-border-subtle); + border-radius: 3px; + padding: 0.1em 0.35em; + font-size: 0.88em; +} +[data-theme='dark'] code { + background-color: var(--mm-denim-800); + border-color: var(--mm-denim-700); +} + +.theme-code-block { + border: 1px solid var(--mm-border-subtle); + border-radius: 4px; + box-shadow: none !important; +} + +[data-theme='dark'] .theme-code-block { + border-color: var(--mm-denim-700); +} + +.theme-code-block .prism-code { + font-size: 0.85rem; + background: var(--mm-denim-50) !important; +} +[data-theme='dark'] .theme-code-block .prism-code { + background: var(--mm-denim-800) !important; +} + +/* Copy button — denim border, marigold on hover */ +.clean-btn[class*="copyButton"] { + border: 1px solid var(--mm-border-subtle) !important; + border-radius: 3px !important; +} +.clean-btn[class*="copyButton"]:hover { + background: var(--mm-color-marigold) !important; + color: var(--mm-color-black) !important; + border-color: var(--mm-color-marigold) !important; +} + +/* === Tables === */ + +table { + display: table; + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; +} +table thead { + background: var(--mm-color-denim); +} +table thead th { + color: var(--mm-color-white); + font-family: var(--mm-font-heading); + font-weight: 900; + letter-spacing: 0.04em; + text-transform: uppercase; + font-size: 0.78rem; + padding: 0.85rem 1rem; + text-align: left; + border: none; +} +table tbody td { + border-color: var(--mm-border-subtle); + padding: 0.7rem 1rem; +} +table tbody tr:nth-child(even) { + background: var(--mm-denim-50); +} +[data-theme='dark'] table tbody tr:nth-child(even) { + background: var(--mm-denim-800); +} + +/* === Blockquote === */ + +blockquote { + border-left: 4px solid var(--mm-color-marigold); + background: var(--mm-bg-subtle); + padding: 1rem 1.25rem; + margin: 1.5rem 0; + border-radius: 0 4px 4px 0; + color: var(--mm-text-primary); +} + +/* === Footer === */ + +.footer { + background-color: var(--ifm-footer-background-color); + background-image: + linear-gradient(0deg, rgba(12, 20, 36, 0.55), rgba(12, 20, 36, 0.55)), + url('/img/patterns/hex-camo-denim.svg'); + background-size: cover, 108px 125px; + background-repeat: no-repeat, repeat; + color: var(--ifm-footer-color); + padding: 3.5rem 1rem 2.5rem; +} +.footer__title { + color: var(--ifm-footer-title-color); + font-family: var(--mm-font-heading); + letter-spacing: 0.08em; + text-transform: uppercase; + font-size: 0.78rem; + margin-bottom: 1rem; +} +.footer__copyright { + margin-top: 2rem; + padding-top: 1.25rem; + border-top: 1px solid rgba(255,255,255,0.18); + font-size: 0.82rem; + color: rgba(255,255,255,0.7); +} + +/* === Doc page chrome === */ + +/* Docusaurus's default `.theme-doc-markdown` is fluid; we don't constrain + * it. The OpenAPI plugin's 2-column layout (request panel on the right) + * needs the full width of the article column. Long-form prose pages get + * comfortable measure via the article container's natural max-width. */ +.theme-doc-markdown { + font-size: 1rem; +} + +.theme-doc-markdown h1:first-child { + margin-top: 0.5rem; + font-size: 2.4rem; + letter-spacing: -0.025em; +} + +/* Widen the docs main container so the sidebar isn't pushed to the edge + * with a huge gap before the content. Default Infima container is too + * conservative for API pages with right panels. */ +.docMainContainer_TBSr, +[class*='docMainContainer'] { + max-width: none !important; +} +.docMainContainer_TBSr > .container, +[class*='docMainContainer'] > .container { + max-width: 1600px; + padding-left: clamp(1rem, 2vw, 2rem); + padding-right: clamp(1rem, 2vw, 2rem); +} + +/* TOC right column (per-page) */ +.table-of-contents { + border-left: 1px solid var(--mm-border-subtle); + padding: 0.4rem 0 0.4rem 1rem; + font-size: 0.82rem; +} +.table-of-contents__link--active, +.table-of-contents__link:hover { + color: var(--mm-color-denim); + font-weight: 600; +} + +/* === Marigold CTA pill (used in MDX content) === */ + +.mm-cta { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.25rem; + background: var(--mm-color-marigold); + color: var(--mm-color-black); + font-family: var(--mm-font-heading); + font-weight: 900; + letter-spacing: 0.04em; + text-transform: uppercase; + border-radius: 3px; + text-decoration: none; + transition: transform 0.12s ease, box-shadow 0.12s ease; +} +.mm-cta:hover { + transform: translateY(-1px); + box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.25); + color: var(--mm-color-black); + text-decoration: none; +} + +/* === Mobile / responsive === */ + +@media (max-width: 996px) { + /* Tables: scroll horizontally instead of overflowing the viewport. */ + .markdown table { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + /* Tighter heading scale on small screens. */ + .markdown h1 { font-size: 1.85rem; line-height: 1.15; } + .markdown h2 { font-size: 1.4rem; } + .markdown h3 { font-size: 1.15rem; } +} + +@media (max-width: 768px) { + /* Navbar: tighter logo + items. */ + .navbar__inner { padding: 0 0.75rem; } + .navbar__logo { height: 1.5rem; } + .navbar__link { padding: 0 0.5rem; font-size: 0.72rem; } + + /* OpenAPI right-panel (Authorization, Request, Response) — stacks + * below the content on phones instead of squeezing in a 2nd column. */ + .openapi-right-panel__container { + width: 100% !important; + margin-top: 1.5rem; + } + .openapi-left-panel__container { + width: 100% !important; + } + + /* Footer: looser stacking, less padding. */ + .footer { padding: 2.5rem 1rem 1.75rem; } + + /* Code blocks: smaller font for phones so lines don't break too eagerly. */ + .theme-code-block .prism-code { font-size: 0.78rem; } +} + +@media (max-width: 480px) { + /* Hide the marigold accent on the navbar at very narrow widths + * where the gradient distracts from the compact nav. */ + .navbar::after { display: none; } + + /* Hero: even tighter on small phones. */ + .markdown h1 { font-size: 1.6rem; } +} + +/* === Section divider used between Hero and content === */ + +.mm-section-rule { + height: 0; + border: none; + border-top: 2px solid var(--mm-color-marigold); + width: 3rem; + margin: 2.5rem 0 1.5rem; +} + +/* (Marigold strip is now the navbar's own border-bottom.) */ + +/* === Pages with a Hero hide breadcrumbs + prev/next pagination === + * Hero is already a strong page-opener; the breadcrumbs ("Home > + * Product Overview > Overview") read as redundant clutter. */ + +.theme-doc-markdown:has(.mm-hero) ~ nav.pagination-nav, +nav.pagination-nav:has(+ .theme-doc-markdown .mm-hero) { + display: none; +} + +article:has(.mm-hero) > .theme-doc-breadcrumbs, +article:has(.mm-hero) > nav[aria-label*="readcrumb"], +.theme-doc-markdown:has(.mm-hero) > div:first-child:has(nav[aria-label*="readcrumb"]), +nav[aria-label*="readcrumb"]:has(~ .theme-doc-markdown .mm-hero) { + display: none; +} + +/* Pages with a Hero: drop the article's top-padding so the hero band + * sits flush under the navbar. Hero and body content both fill the + * article column naturally (no width override needed). */ +.theme-doc-markdown:has(.mm-hero) { + padding-top: 0; +} diff --git a/docs/site/src/css/tokens.css b/docs/site/src/css/tokens.css new file mode 100644 index 000000000000..1d010e79c81d --- /dev/null +++ b/docs/site/src/css/tokens.css @@ -0,0 +1,85 @@ +/* + * Mattermost brand design tokens. + * Source: Mattermost-Brand-Guidelines-2025. + * See PLAN.md §3.2 for the full token spec and rationale. + * + * Accessibility constraint (per brand guidelines): use only black or white + * text on the four primary colors — these combinations are pre-approved + * for contrast. + */ + +:root { + /* === Primary palette === */ + --mm-color-denim: #1E325C; /* primary brand, dominant */ + --mm-color-marigold: #FFBC1F; /* accent — CTAs only, used sparingly */ + --mm-color-white: #FFFFFF; + --mm-color-black: #1B1D22; + + /* === Secondary palette (sparingly, never overpower) === */ + --mm-color-sand: #CCC4AE; + --mm-color-bark: #604F3D; + --mm-color-sky: #C5D2EC; + + /* === Denim shade ramp (derived for surfaces, borders, focus rings) === */ + --mm-denim-50: #EEF1F8; + --mm-denim-100: #D6DDEC; + --mm-denim-200: #ADBBD8; + --mm-denim-300: #8499C5; + --mm-denim-400: #5B77B1; + --mm-denim-500: #1E325C; /* = denim, brand primary */ + --mm-denim-600: #182849; + --mm-denim-700: #121E37; + --mm-denim-800: #0C1424; + --mm-denim-900: #060A12; + + /* === Marigold shade ramp === */ + --mm-marigold-100: #FFEFC8; + --mm-marigold-300: #FFD672; + --mm-marigold-500: #FFBC1F; /* = marigold, brand accent */ + --mm-marigold-700: #B27F00; + + /* === Typography === + * Trade Gothic Next is licensed via Adobe Fonts and not embedded yet + * (open item — see PLAN.md §12). Until licensing is confirmed, body uses + * Inter and headlines use Archivo Black, which is the closest free match + * for Trade Gothic Heavy's geometric, ultra-bold display feel. */ + --mm-font-sans: "Inter", "Trade Gothic Next", -apple-system, BlinkMacSystemFont, + "Segoe UI", "Helvetica Neue", system-ui, sans-serif; + --mm-font-heading: "Archivo Black", "Trade Gothic Next Heavy", + "Helvetica Neue", "Impact", system-ui, sans-serif; + --mm-font-mono: "JetBrains Mono", "SF Mono", "Menlo", "Consolas", + "Liberation Mono", monospace; + + /* === Semantic surfaces (light) === */ + --mm-bg-page: var(--mm-color-white); + --mm-bg-surface: var(--mm-color-white); + --mm-bg-inverse: var(--mm-color-denim); + --mm-bg-subtle: var(--mm-denim-50); + --mm-text-primary: var(--mm-color-black); + --mm-text-secondary: var(--mm-denim-600); + --mm-text-inverse: var(--mm-color-white); + --mm-text-on-accent: var(--mm-color-black); /* black text on marigold */ + --mm-border-subtle: var(--mm-denim-100); + --mm-border-strong: var(--mm-denim-300); + --mm-link: var(--mm-color-denim); + --mm-link-hover: var(--mm-denim-700); + --mm-accent: var(--mm-color-marigold); + --mm-focus-ring: var(--mm-marigold-500); +} + +/* === Dark mode (data-theme=dark applied by Docusaurus) === */ +[data-theme='dark'] { + --mm-bg-page: #0E1525; + --mm-bg-surface: #14213D; + --mm-bg-inverse: var(--mm-color-denim); + --mm-bg-subtle: var(--mm-denim-800); + --mm-text-primary: var(--mm-color-white); + --mm-text-secondary: var(--mm-denim-200); + --mm-text-inverse: var(--mm-color-black); + --mm-text-on-accent: var(--mm-color-black); + --mm-border-subtle: var(--mm-denim-700); + --mm-border-strong: var(--mm-denim-500); + --mm-link: var(--mm-color-sky); + --mm-link-hover: var(--mm-color-white); + --mm-accent: var(--mm-color-marigold); +} diff --git a/docs/site/src/theme/MDXComponents.tsx b/docs/site/src/theme/MDXComponents.tsx new file mode 100644 index 000000000000..aba9ade45034 --- /dev/null +++ b/docs/site/src/theme/MDXComponents.tsx @@ -0,0 +1,48 @@ +// Globally-available MDX components. Authors can write ... +// in any .mdx file without an import. + +import MDXComponents from '@theme-original/MDXComponents'; +import {Note, Tip, Important, Warning, Security} from '@site/src/components/Callout'; +import PlanBadge from '@site/src/components/PlanBadge'; +import PlanAvailability from '@site/src/components/PlanAvailability'; +import EditionAvailability from '@site/src/components/EditionAvailability'; +import DeploymentAvailability from '@site/src/components/DeploymentAvailability'; +import AttestationStatus from '@site/src/components/AttestationStatus'; +import DeploymentOnly from '@site/src/components/DeploymentOnly'; +import IMEDiagram from '@site/src/components/IMEDiagram'; +import DeploymentArchitectureBuilder from '@site/src/components/DeploymentArchitectureBuilder'; +import CompassIcon from '@site/src/components/CompassIcon'; +import Hero from '@site/src/components/Hero'; +import Eyebrow from '@site/src/components/Eyebrow'; +import StatStrip from '@site/src/components/StatStrip'; +import MethodLegend from '@site/src/components/MethodLegend'; +import CardGrid from '@site/src/components/CardGrid'; +// Globally available so migrated developer docs (Hugo `tabs` shortcode) +// can use them without imports. +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +export default { + ...MDXComponents, + Note, + Tip, + Important, + Warning, + Security, + PlanBadge, + PlanAvailability, + EditionAvailability, + DeploymentAvailability, + AttestationStatus, + DeploymentOnly, + IMEDiagram, + DeploymentArchitectureBuilder, + CompassIcon, + Hero, + Eyebrow, + StatStrip, + MethodLegend, + CardGrid, + Tabs, + TabItem, +}; diff --git a/docs/site/static/.nojekyll b/docs/site/static/.nojekyll new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/site/static/images/AzureApp_App_Directory_Grant_Admin_Consent.png b/docs/site/static/images/AzureApp_App_Directory_Grant_Admin_Consent.png new file mode 100644 index 000000000000..2b5a45778945 Binary files /dev/null and b/docs/site/static/images/AzureApp_App_Directory_Grant_Admin_Consent.png differ diff --git a/docs/site/static/images/AzureApp_App_Directory_IDsv2.png b/docs/site/static/images/AzureApp_App_Directory_IDsv2.png new file mode 100644 index 000000000000..7ca46e93f091 Binary files /dev/null and b/docs/site/static/images/AzureApp_App_Directory_IDsv2.png differ diff --git a/docs/site/static/images/AzureApp_Client_Secret_Expiry.png b/docs/site/static/images/AzureApp_Client_Secret_Expiry.png new file mode 100644 index 000000000000..878a2b3c855f Binary files /dev/null and b/docs/site/static/images/AzureApp_Client_Secret_Expiry.png differ diff --git a/docs/site/static/images/AzureApp_Client_Secret_Setup.png b/docs/site/static/images/AzureApp_Client_Secret_Setup.png new file mode 100644 index 000000000000..d44f37c780b9 Binary files /dev/null and b/docs/site/static/images/AzureApp_Client_Secret_Setup.png differ diff --git a/docs/site/static/images/AzureApp_New_Registration.png b/docs/site/static/images/AzureApp_New_Registration.png new file mode 100644 index 000000000000..86c1cbf45cc4 Binary files /dev/null and b/docs/site/static/images/AzureApp_New_Registration.png differ diff --git a/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_ExposeAPI.png b/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_ExposeAPI.png new file mode 100644 index 000000000000..ab8dfbe57523 Binary files /dev/null and b/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_ExposeAPI.png differ diff --git a/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_TeamsAppAdd.png b/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_TeamsAppAdd.png new file mode 100644 index 000000000000..8401632fe103 Binary files /dev/null and b/docs/site/static/images/AzureApp_New_Registration_MSEmbedded_TeamsAppAdd.png differ diff --git a/docs/site/static/images/AzureApp_New_Registration_MS_Embedded.png b/docs/site/static/images/AzureApp_New_Registration_MS_Embedded.png new file mode 100644 index 000000000000..0828179ec698 Binary files /dev/null and b/docs/site/static/images/AzureApp_New_Registration_MS_Embedded.png differ diff --git a/docs/site/static/images/AzureApp_New_Registration_MS_Embedded_Application.png b/docs/site/static/images/AzureApp_New_Registration_MS_Embedded_Application.png new file mode 100644 index 000000000000..3bc5d8a9c5ee Binary files /dev/null and b/docs/site/static/images/AzureApp_New_Registration_MS_Embedded_Application.png differ diff --git a/docs/site/static/images/AzureApp_SetupMenuv2.png b/docs/site/static/images/AzureApp_SetupMenuv2.png new file mode 100644 index 000000000000..2176be567a2d Binary files /dev/null and b/docs/site/static/images/AzureApp_SetupMenuv2.png differ diff --git a/docs/site/static/images/Channels_Hero.png b/docs/site/static/images/Channels_Hero.png new file mode 100644 index 000000000000..678f6a238383 Binary files /dev/null and b/docs/site/static/images/Channels_Hero.png differ diff --git a/docs/site/static/images/DDIL-disconnected-secure-communication-collaboration.png b/docs/site/static/images/DDIL-disconnected-secure-communication-collaboration.png new file mode 100644 index 000000000000..42046f52f801 Binary files /dev/null and b/docs/site/static/images/DDIL-disconnected-secure-communication-collaboration.png differ diff --git a/docs/site/static/images/DiscordDarkTheme.png b/docs/site/static/images/DiscordDarkTheme.png new file mode 100644 index 000000000000..2946c11d565e Binary files /dev/null and b/docs/site/static/images/DiscordDarkTheme.png differ diff --git a/docs/site/static/images/DiscordNewDarkTheme.png b/docs/site/static/images/DiscordNewDarkTheme.png new file mode 100644 index 000000000000..9caf378cd303 Binary files /dev/null and b/docs/site/static/images/DiscordNewDarkTheme.png differ diff --git a/docs/site/static/images/Enterprise-to-Tactical-Edge.png b/docs/site/static/images/Enterprise-to-Tactical-Edge.png new file mode 100644 index 000000000000..e0ef346dff94 Binary files /dev/null and b/docs/site/static/images/Enterprise-to-Tactical-Edge.png differ diff --git a/docs/site/static/images/External-Collaboration-with-Enterprise-Control.png b/docs/site/static/images/External-Collaboration-with-Enterprise-Control.png new file mode 100644 index 000000000000..5132a5290f26 Binary files /dev/null and b/docs/site/static/images/External-Collaboration-with-Enterprise-Control.png differ diff --git a/docs/site/static/images/Fully-Sovereign-Communication-Inside-MSTeams.png b/docs/site/static/images/Fully-Sovereign-Communication-Inside-MSTeams.png new file mode 100644 index 000000000000..7f4fc03703b2 Binary files /dev/null and b/docs/site/static/images/Fully-Sovereign-Communication-Inside-MSTeams.png differ diff --git a/docs/site/static/images/GitHub.png b/docs/site/static/images/GitHub.png new file mode 100644 index 000000000000..7548c465ad27 Binary files /dev/null and b/docs/site/static/images/GitHub.png differ diff --git a/docs/site/static/images/Group_Configuration.png b/docs/site/static/images/Group_Configuration.png new file mode 100644 index 000000000000..41e32b333832 Binary files /dev/null and b/docs/site/static/images/Group_Configuration.png differ diff --git a/docs/site/static/images/Group_Group_Member_Sync.png b/docs/site/static/images/Group_Group_Member_Sync.png new file mode 100644 index 000000000000..571cad85e9ec Binary files /dev/null and b/docs/site/static/images/Group_Group_Member_Sync.png differ diff --git a/docs/site/static/images/Group_Members.png b/docs/site/static/images/Group_Members.png new file mode 100644 index 000000000000..0b303ac8dec1 Binary files /dev/null and b/docs/site/static/images/Group_Members.png differ diff --git a/docs/site/static/images/Group_filter.png b/docs/site/static/images/Group_filter.png new file mode 100644 index 000000000000..c168a9bd8450 Binary files /dev/null and b/docs/site/static/images/Group_filter.png differ diff --git a/docs/site/static/images/Groups_listing.png b/docs/site/static/images/Groups_listing.png new file mode 100644 index 000000000000..7d2ff4813910 Binary files /dev/null and b/docs/site/static/images/Groups_listing.png differ diff --git a/docs/site/static/images/GruvboxDark.png b/docs/site/static/images/GruvboxDark.png new file mode 100644 index 000000000000..a3fd13b53f7f Binary files /dev/null and b/docs/site/static/images/GruvboxDark.png differ diff --git a/docs/site/static/images/Headings1.png b/docs/site/static/images/Headings1.png new file mode 100644 index 000000000000..d6d42c0073fa Binary files /dev/null and b/docs/site/static/images/Headings1.png differ diff --git a/docs/site/static/images/Headings2.png b/docs/site/static/images/Headings2.png new file mode 100644 index 000000000000..bc09bbc9684c Binary files /dev/null and b/docs/site/static/images/Headings2.png differ diff --git a/docs/site/static/images/Intelligent-RT-Incident-Response.png b/docs/site/static/images/Intelligent-RT-Incident-Response.png new file mode 100644 index 000000000000..76cf8f39d6b2 Binary files /dev/null and b/docs/site/static/images/Intelligent-RT-Incident-Response.png differ diff --git a/docs/site/static/images/LinkFailed.png b/docs/site/static/images/LinkFailed.png new file mode 100644 index 000000000000..9d62c9bc9fad Binary files /dev/null and b/docs/site/static/images/LinkFailed.png differ diff --git a/docs/site/static/images/Mattermost.png b/docs/site/static/images/Mattermost.png new file mode 100644 index 000000000000..710175b3436c Binary files /dev/null and b/docs/site/static/images/Mattermost.png differ diff --git a/docs/site/static/images/MattermostDark.png b/docs/site/static/images/MattermostDark.png new file mode 100644 index 000000000000..20bc4a41f9a1 Binary files /dev/null and b/docs/site/static/images/MattermostDark.png differ diff --git a/docs/site/static/images/Microsoft-Calendar-viewcal.png b/docs/site/static/images/Microsoft-Calendar-viewcal.png new file mode 100644 index 000000000000..945a13b2c26c Binary files /dev/null and b/docs/site/static/images/Microsoft-Calendar-viewcal.png differ diff --git a/docs/site/static/images/Monokai.png b/docs/site/static/images/Monokai.png new file mode 100644 index 000000000000..68083bb3a1f4 Binary files /dev/null and b/docs/site/static/images/Monokai.png differ diff --git a/docs/site/static/images/NightOwlDark.png b/docs/site/static/images/NightOwlDark.png new file mode 100644 index 000000000000..c3c3369b2d75 Binary files /dev/null and b/docs/site/static/images/NightOwlDark.png differ diff --git a/docs/site/static/images/On-Prem-Skype-for-Business-replace.png b/docs/site/static/images/On-Prem-Skype-for-Business-replace.png new file mode 100644 index 000000000000..a4cfab7946e1 Binary files /dev/null and b/docs/site/static/images/On-Prem-Skype-for-Business-replace.png differ diff --git a/docs/site/static/images/OneDark.png b/docs/site/static/images/OneDark.png new file mode 100644 index 000000000000..dcb053e1a5d8 Binary files /dev/null and b/docs/site/static/images/OneDark.png differ diff --git a/docs/site/static/images/Organization.png b/docs/site/static/images/Organization.png new file mode 100644 index 000000000000..9976d8acadc7 Binary files /dev/null and b/docs/site/static/images/Organization.png differ diff --git a/docs/site/static/images/Playbooks_Hero.png b/docs/site/static/images/Playbooks_Hero.png new file mode 100644 index 000000000000..e6aa9d5032f9 Binary files /dev/null and b/docs/site/static/images/Playbooks_Hero.png differ diff --git a/docs/site/static/images/Retro.gif b/docs/site/static/images/Retro.gif new file mode 100644 index 000000000000..d9ead2405aa6 Binary files /dev/null and b/docs/site/static/images/Retro.gif differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_000.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_000.png new file mode 100644 index 000000000000..51acf2b1ce5c Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_000.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_001.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_001.png new file mode 100644 index 000000000000..43018b596e46 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_001.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_002.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_002.png new file mode 100644 index 000000000000..9a70ec98386d Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_002.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_003.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_003.png new file mode 100644 index 000000000000..f776a7356ce3 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_003.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_004.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_004.png new file mode 100644 index 000000000000..a62d605eb095 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_004.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_005.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_005.png new file mode 100644 index 000000000000..2f8f82193d8b Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_005.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_006.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_006.png new file mode 100644 index 000000000000..d384b262b141 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_006.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_007.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_007.png new file mode 100644 index 000000000000..90e07646e7fe Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_007.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_008.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_008.png new file mode 100644 index 000000000000..7327ea7fa1f9 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_008.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_009.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_009.png new file mode 100644 index 000000000000..f6c721a1a64a Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_009.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_010.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_010.png new file mode 100644 index 000000000000..60c59d342ac6 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_010.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_011.png b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_011.png new file mode 100644 index 000000000000..6aacd0066a10 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_add-new-relying-party-trust_011.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_configure-saml_001.png b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_001.png new file mode 100644 index 000000000000..83b8da37893f Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_001.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_configure-saml_002.png b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_002.png new file mode 100644 index 000000000000..9d2c9891e4a1 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_002.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_configure-saml_003.png b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_003.png new file mode 100644 index 000000000000..0108492dc313 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_003.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_configure-saml_004.png b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_004.png new file mode 100644 index 000000000000..284a92d5d25c Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_configure-saml_004.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_001.png b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_001.png new file mode 100644 index 000000000000..3a0180046c7b Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_001.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_002.png b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_002.png new file mode 100644 index 000000000000..4fcea0b7448a Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_002.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_003.png b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_003.png new file mode 100644 index 000000000000..920ce4f3aa23 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_003.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_004.png b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_004.png new file mode 100644 index 000000000000..a73b19a811a3 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_004.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_005.png b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_005.png new file mode 100644 index 000000000000..66c65584e8f9 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_create-claim-rules_005.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_001.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_001.png new file mode 100644 index 000000000000..9542fd881571 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_001.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_003.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_003.png new file mode 100644 index 000000000000..c59a9e96efca Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_003.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_004.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_004.png new file mode 100644 index 000000000000..3d36f0575eb9 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_004.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_005.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_005.png new file mode 100644 index 000000000000..fbf94d6992bd Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_005.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_006.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_006.png new file mode 100644 index 000000000000..7faa41a329f8 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_006.png differ diff --git a/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_007.png b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_007.png new file mode 100644 index 000000000000..1bc5e4bb4cd1 Binary files /dev/null and b/docs/site/static/images/SSO-SAML-ADFS_export-id-provider-cert_007.png differ diff --git a/docs/site/static/images/SolarizedDark.png b/docs/site/static/images/SolarizedDark.png new file mode 100644 index 000000000000..e4f0eac1ed02 Binary files /dev/null and b/docs/site/static/images/SolarizedDark.png differ diff --git a/docs/site/static/images/Team_Channel_Membership_Sync.png b/docs/site/static/images/Team_Channel_Membership_Sync.png new file mode 100644 index 000000000000..9775d0551793 Binary files /dev/null and b/docs/site/static/images/Team_Channel_Membership_Sync.png differ diff --git a/docs/site/static/images/WindowsDark.png b/docs/site/static/images/WindowsDark.png new file mode 100644 index 000000000000..0aafa36ac029 Binary files /dev/null and b/docs/site/static/images/WindowsDark.png differ diff --git a/docs/site/static/images/access-user-groups.png b/docs/site/static/images/access-user-groups.png new file mode 100644 index 000000000000..f0ef7325345b Binary files /dev/null and b/docs/site/static/images/access-user-groups.png differ diff --git a/docs/site/static/images/active-past-surveys.png b/docs/site/static/images/active-past-surveys.png new file mode 100644 index 000000000000..84b53cbf6c54 Binary files /dev/null and b/docs/site/static/images/active-past-surveys.png differ diff --git a/docs/site/static/images/add-custom-emoji1.png b/docs/site/static/images/add-custom-emoji1.png new file mode 100644 index 000000000000..a338a7fb0772 Binary files /dev/null and b/docs/site/static/images/add-custom-emoji1.png differ diff --git a/docs/site/static/images/add-ip-filter-range.png b/docs/site/static/images/add-ip-filter-range.png new file mode 100644 index 000000000000..7d5e6d50bf02 Binary files /dev/null and b/docs/site/static/images/add-ip-filter-range.png differ diff --git a/docs/site/static/images/add-member-pop.jpg b/docs/site/static/images/add-member-pop.jpg new file mode 100644 index 000000000000..f11efaa23c25 Binary files /dev/null and b/docs/site/static/images/add-member-pop.jpg differ diff --git a/docs/site/static/images/add-member-to-channel.png b/docs/site/static/images/add-member-to-channel.png new file mode 100644 index 000000000000..0fce9852ab9d Binary files /dev/null and b/docs/site/static/images/add-member-to-channel.png differ diff --git a/docs/site/static/images/add-members-to-a-channel.png b/docs/site/static/images/add-members-to-a-channel.png new file mode 100644 index 000000000000..cdb64b6549bf Binary files /dev/null and b/docs/site/static/images/add-members-to-a-channel.png differ diff --git a/docs/site/static/images/add-members-to-a-team.png b/docs/site/static/images/add-members-to-a-team.png new file mode 100644 index 000000000000..b6eeef839956 Binary files /dev/null and b/docs/site/static/images/add-members-to-a-team.png differ diff --git a/docs/site/static/images/add-user-to-team.png b/docs/site/static/images/add-user-to-team.png new file mode 100644 index 000000000000..ec36f1e2d73e Binary files /dev/null and b/docs/site/static/images/add-user-to-team.png differ diff --git a/docs/site/static/images/add_custom_emoji.png b/docs/site/static/images/add_custom_emoji.png new file mode 100644 index 000000000000..60555c1ffd6e Binary files /dev/null and b/docs/site/static/images/add_custom_emoji.png differ diff --git a/docs/site/static/images/adfs_10_configure_mfa.png b/docs/site/static/images/adfs_10_configure_mfa.png new file mode 100644 index 000000000000..9b312ba5fd5f Binary files /dev/null and b/docs/site/static/images/adfs_10_configure_mfa.png differ diff --git a/docs/site/static/images/adfs_11_authorization.png b/docs/site/static/images/adfs_11_authorization.png new file mode 100644 index 000000000000..c70a03bbe473 Binary files /dev/null and b/docs/site/static/images/adfs_11_authorization.png differ diff --git a/docs/site/static/images/adfs_12_ready_to_add_trust.png b/docs/site/static/images/adfs_12_ready_to_add_trust.png new file mode 100644 index 000000000000..038fdc23b987 Binary files /dev/null and b/docs/site/static/images/adfs_12_ready_to_add_trust.png differ diff --git a/docs/site/static/images/adfs_13_finish_trust.png b/docs/site/static/images/adfs_13_finish_trust.png new file mode 100644 index 000000000000..f4801ad8a43f Binary files /dev/null and b/docs/site/static/images/adfs_13_finish_trust.png differ diff --git a/docs/site/static/images/adfs_14_claim_rules_editor.png b/docs/site/static/images/adfs_14_claim_rules_editor.png new file mode 100644 index 000000000000..f110e26c0726 Binary files /dev/null and b/docs/site/static/images/adfs_14_claim_rules_editor.png differ diff --git a/docs/site/static/images/adfs_15_choose_rule_type.png b/docs/site/static/images/adfs_15_choose_rule_type.png new file mode 100644 index 000000000000..ca7c508054c8 Binary files /dev/null and b/docs/site/static/images/adfs_15_choose_rule_type.png differ diff --git a/docs/site/static/images/adfs_16_configure_claim_rule.png b/docs/site/static/images/adfs_16_configure_claim_rule.png new file mode 100644 index 000000000000..0f73efe6daa5 Binary files /dev/null and b/docs/site/static/images/adfs_16_configure_claim_rule.png differ diff --git a/docs/site/static/images/adfs_17_transformation_of_incoming_claim.png b/docs/site/static/images/adfs_17_transformation_of_incoming_claim.png new file mode 100644 index 000000000000..be61b05d1a27 Binary files /dev/null and b/docs/site/static/images/adfs_17_transformation_of_incoming_claim.png differ diff --git a/docs/site/static/images/adfs_18_configure_incoming_claim.png b/docs/site/static/images/adfs_18_configure_incoming_claim.png new file mode 100644 index 000000000000..ec0191c08536 Binary files /dev/null and b/docs/site/static/images/adfs_18_configure_incoming_claim.png differ diff --git a/docs/site/static/images/adfs_19_export_idp_cert_start.png b/docs/site/static/images/adfs_19_export_idp_cert_start.png new file mode 100644 index 000000000000..0966fc02a26f Binary files /dev/null and b/docs/site/static/images/adfs_19_export_idp_cert_start.png differ diff --git a/docs/site/static/images/adfs_1_add_new_relying_party_trust.png b/docs/site/static/images/adfs_1_add_new_relying_party_trust.png new file mode 100644 index 000000000000..d7ec87289992 Binary files /dev/null and b/docs/site/static/images/adfs_1_add_new_relying_party_trust.png differ diff --git a/docs/site/static/images/adfs_20_export_idp_cert_copy.png b/docs/site/static/images/adfs_20_export_idp_cert_copy.png new file mode 100644 index 000000000000..d1ec519075a4 Binary files /dev/null and b/docs/site/static/images/adfs_20_export_idp_cert_copy.png differ diff --git a/docs/site/static/images/adfs_21-2_export_idp_cert_wizard.png b/docs/site/static/images/adfs_21-2_export_idp_cert_wizard.png new file mode 100644 index 000000000000..2c609f244e0a Binary files /dev/null and b/docs/site/static/images/adfs_21-2_export_idp_cert_wizard.png differ diff --git a/docs/site/static/images/adfs_21-3_export_idp_cert_wizard.png b/docs/site/static/images/adfs_21-3_export_idp_cert_wizard.png new file mode 100644 index 000000000000..a16020b31d9e Binary files /dev/null and b/docs/site/static/images/adfs_21-3_export_idp_cert_wizard.png differ diff --git a/docs/site/static/images/adfs_21_export_idp_cert_wizard.png b/docs/site/static/images/adfs_21_export_idp_cert_wizard.png new file mode 100644 index 000000000000..cea3d45b7d5d Binary files /dev/null and b/docs/site/static/images/adfs_21_export_idp_cert_wizard.png differ diff --git a/docs/site/static/images/adfs_22_mattermost_basics.png b/docs/site/static/images/adfs_22_mattermost_basics.png new file mode 100644 index 000000000000..eec60fc8b167 Binary files /dev/null and b/docs/site/static/images/adfs_22_mattermost_basics.png differ diff --git a/docs/site/static/images/adfs_23_mattermost_verification.png b/docs/site/static/images/adfs_23_mattermost_verification.png new file mode 100644 index 000000000000..16c03c54ba33 Binary files /dev/null and b/docs/site/static/images/adfs_23_mattermost_verification.png differ diff --git a/docs/site/static/images/adfs_24_mattermost_encryption.png b/docs/site/static/images/adfs_24_mattermost_encryption.png new file mode 100644 index 000000000000..ff2f9b4cdf92 Binary files /dev/null and b/docs/site/static/images/adfs_24_mattermost_encryption.png differ diff --git a/docs/site/static/images/adfs_25_mattermost_attributes.png b/docs/site/static/images/adfs_25_mattermost_attributes.png new file mode 100644 index 000000000000..0ba98f18f337 Binary files /dev/null and b/docs/site/static/images/adfs_25_mattermost_attributes.png differ diff --git a/docs/site/static/images/adfs_26_mattermost_login_button.png b/docs/site/static/images/adfs_26_mattermost_login_button.png new file mode 100644 index 000000000000..1063e180cfed Binary files /dev/null and b/docs/site/static/images/adfs_26_mattermost_login_button.png differ diff --git a/docs/site/static/images/adfs_2_start_wizard.png b/docs/site/static/images/adfs_2_start_wizard.png new file mode 100644 index 000000000000..3dbbf8f6a0cb Binary files /dev/null and b/docs/site/static/images/adfs_2_start_wizard.png differ diff --git a/docs/site/static/images/adfs_3_select_data_source.png b/docs/site/static/images/adfs_3_select_data_source.png new file mode 100644 index 000000000000..fdc4d225071d Binary files /dev/null and b/docs/site/static/images/adfs_3_select_data_source.png differ diff --git a/docs/site/static/images/adfs_4_specify_display_name.png b/docs/site/static/images/adfs_4_specify_display_name.png new file mode 100644 index 000000000000..ffcf114b1849 Binary files /dev/null and b/docs/site/static/images/adfs_4_specify_display_name.png differ diff --git a/docs/site/static/images/adfs_5_choose_profile.png b/docs/site/static/images/adfs_5_choose_profile.png new file mode 100644 index 000000000000..09f9fe0991af Binary files /dev/null and b/docs/site/static/images/adfs_5_choose_profile.png differ diff --git a/docs/site/static/images/adfs_6_configure_certificate_default.png b/docs/site/static/images/adfs_6_configure_certificate_default.png new file mode 100644 index 000000000000..f0e136238af5 Binary files /dev/null and b/docs/site/static/images/adfs_6_configure_certificate_default.png differ diff --git a/docs/site/static/images/adfs_7_configure_certificate_encryption.png b/docs/site/static/images/adfs_7_configure_certificate_encryption.png new file mode 100644 index 000000000000..b568b863161c Binary files /dev/null and b/docs/site/static/images/adfs_7_configure_certificate_encryption.png differ diff --git a/docs/site/static/images/adfs_8_configure_url.png b/docs/site/static/images/adfs_8_configure_url.png new file mode 100644 index 000000000000..d1137e039fb8 Binary files /dev/null and b/docs/site/static/images/adfs_8_configure_url.png differ diff --git a/docs/site/static/images/adfs_9_configure_identifiers.png b/docs/site/static/images/adfs_9_configure_identifiers.png new file mode 100644 index 000000000000..d6b97d69324d Binary files /dev/null and b/docs/site/static/images/adfs_9_configure_identifiers.png differ diff --git a/docs/site/static/images/agents-meeting-summary.png b/docs/site/static/images/agents-meeting-summary.png new file mode 100644 index 000000000000..5973e707919b Binary files /dev/null and b/docs/site/static/images/agents-meeting-summary.png differ diff --git a/docs/site/static/images/allow-create-posts-for-a-channel.png b/docs/site/static/images/allow-create-posts-for-a-channel.png new file mode 100644 index 000000000000..a3632c5d6624 Binary files /dev/null and b/docs/site/static/images/allow-create-posts-for-a-channel.png differ diff --git a/docs/site/static/images/allow-manage-bookmarks-for-a-channel.png b/docs/site/static/images/allow-manage-bookmarks-for-a-channel.png new file mode 100644 index 000000000000..724c45c527e3 Binary files /dev/null and b/docs/site/static/images/allow-manage-bookmarks-for-a-channel.png differ diff --git a/docs/site/static/images/allow-manage-members-for-a-channel.png b/docs/site/static/images/allow-manage-members-for-a-channel.png new file mode 100644 index 000000000000..82c71cdbc3de Binary files /dev/null and b/docs/site/static/images/allow-manage-members-for-a-channel.png differ diff --git a/docs/site/static/images/allow-mentions-for-a-channel.png b/docs/site/static/images/allow-mentions-for-a-channel.png new file mode 100644 index 000000000000..fc53bf467db1 Binary files /dev/null and b/docs/site/static/images/allow-mentions-for-a-channel.png differ diff --git a/docs/site/static/images/allow-post-reactions-for-a-channel.png b/docs/site/static/images/allow-post-reactions-for-a-channel.png new file mode 100644 index 000000000000..2e9f22db0252 Binary files /dev/null and b/docs/site/static/images/allow-post-reactions-for-a-channel.png differ diff --git a/docs/site/static/images/announcement-banner.png b/docs/site/static/images/announcement-banner.png new file mode 100644 index 000000000000..d6dcfb87d2e8 Binary files /dev/null and b/docs/site/static/images/announcement-banner.png differ diff --git a/docs/site/static/images/anyone-can-join-a-team.png b/docs/site/static/images/anyone-can-join-a-team.png new file mode 100644 index 000000000000..d1ab30707dd1 Binary files /dev/null and b/docs/site/static/images/anyone-can-join-a-team.png differ diff --git a/docs/site/static/images/architecture-mpe.png b/docs/site/static/images/architecture-mpe.png new file mode 100644 index 000000000000..d01e970c57eb Binary files /dev/null and b/docs/site/static/images/architecture-mpe.png differ diff --git a/docs/site/static/images/architecture-ms-teams-collab.png b/docs/site/static/images/architecture-ms-teams-collab.png new file mode 100644 index 000000000000..9b3c049b3bcd Binary files /dev/null and b/docs/site/static/images/architecture-ms-teams-collab.png differ diff --git a/docs/site/static/images/architecture-ms-teams-ddil.png b/docs/site/static/images/architecture-ms-teams-ddil.png new file mode 100644 index 000000000000..cd0523660e0a Binary files /dev/null and b/docs/site/static/images/architecture-ms-teams-ddil.png differ diff --git a/docs/site/static/images/architecture_high_availability.png b/docs/site/static/images/architecture_high_availability.png new file mode 100644 index 000000000000..eb03957a516b Binary files /dev/null and b/docs/site/static/images/architecture_high_availability.png differ diff --git a/docs/site/static/images/architecture_with_proxy.png b/docs/site/static/images/architecture_with_proxy.png new file mode 100644 index 000000000000..9e8a038dadd5 Binary files /dev/null and b/docs/site/static/images/architecture_with_proxy.png differ diff --git a/docs/site/static/images/archive-a-channel.png b/docs/site/static/images/archive-a-channel.png new file mode 100644 index 000000000000..e2a3dda0f602 Binary files /dev/null and b/docs/site/static/images/archive-a-channel.png differ diff --git a/docs/site/static/images/archive-a-playbook.gif b/docs/site/static/images/archive-a-playbook.gif new file mode 100644 index 000000000000..963651cc39e1 Binary files /dev/null and b/docs/site/static/images/archive-a-playbook.gif differ diff --git a/docs/site/static/images/archive-a-team.png b/docs/site/static/images/archive-a-team.png new file mode 100644 index 000000000000..29936553118c Binary files /dev/null and b/docs/site/static/images/archive-a-team.png differ diff --git a/docs/site/static/images/assign-people-to-system-role.png b/docs/site/static/images/assign-people-to-system-role.png new file mode 100644 index 000000000000..a8e1b8f9e586 Binary files /dev/null and b/docs/site/static/images/assign-people-to-system-role.png differ diff --git a/docs/site/static/images/azure-certs-secrets.png b/docs/site/static/images/azure-certs-secrets.png new file mode 100644 index 000000000000..f272a4da2ced Binary files /dev/null and b/docs/site/static/images/azure-certs-secrets.png differ diff --git a/docs/site/static/images/azure-configured-permissions.png b/docs/site/static/images/azure-configured-permissions.png new file mode 100644 index 000000000000..f7f1a8c51cb7 Binary files /dev/null and b/docs/site/static/images/azure-configured-permissions.png differ diff --git a/docs/site/static/images/blockQuotes.png b/docs/site/static/images/blockQuotes.png new file mode 100644 index 000000000000..eb1ad7e079f5 Binary files /dev/null and b/docs/site/static/images/blockQuotes.png differ diff --git a/docs/site/static/images/boards-kanban.png b/docs/site/static/images/boards-kanban.png new file mode 100644 index 000000000000..2065929b6f0d Binary files /dev/null and b/docs/site/static/images/boards-kanban.png differ diff --git a/docs/site/static/images/browse-channels.png b/docs/site/static/images/browse-channels.png new file mode 100644 index 000000000000..d9a84c91cae5 Binary files /dev/null and b/docs/site/static/images/browse-channels.png differ diff --git a/docs/site/static/images/calendar2.png b/docs/site/static/images/calendar2.png new file mode 100644 index 000000000000..c472fa38e926 Binary files /dev/null and b/docs/site/static/images/calendar2.png differ diff --git a/docs/site/static/images/call-window.png b/docs/site/static/images/call-window.png new file mode 100644 index 000000000000..31cc2b3ad938 Binary files /dev/null and b/docs/site/static/images/call-window.png differ diff --git a/docs/site/static/images/calls-deployment-kubernetes.png b/docs/site/static/images/calls-deployment-kubernetes.png new file mode 100644 index 000000000000..fe21bc91a0cf Binary files /dev/null and b/docs/site/static/images/calls-deployment-kubernetes.png differ diff --git a/docs/site/static/images/card-prop-example.png b/docs/site/static/images/card-prop-example.png new file mode 100644 index 000000000000..60b9f5128f3f Binary files /dev/null and b/docs/site/static/images/card-prop-example.png differ diff --git a/docs/site/static/images/channel-configuration-details.png b/docs/site/static/images/channel-configuration-details.png new file mode 100644 index 000000000000..91ec2482341e Binary files /dev/null and b/docs/site/static/images/channel-configuration-details.png differ diff --git a/docs/site/static/images/channel-files-icon.png b/docs/site/static/images/channel-files-icon.png new file mode 100644 index 000000000000..e2bfed5816a3 Binary files /dev/null and b/docs/site/static/images/channel-files-icon.png differ diff --git a/docs/site/static/images/channel-header.png b/docs/site/static/images/channel-header.png new file mode 100644 index 000000000000..638c3cd50ad9 Binary files /dev/null and b/docs/site/static/images/channel-header.png differ diff --git a/docs/site/static/images/channel-heading-categories.png b/docs/site/static/images/channel-heading-categories.png new file mode 100644 index 000000000000..f9eb0b67852c Binary files /dev/null and b/docs/site/static/images/channel-heading-categories.png differ diff --git a/docs/site/static/images/channel-more.png b/docs/site/static/images/channel-more.png new file mode 100644 index 000000000000..3e69867c237d Binary files /dev/null and b/docs/site/static/images/channel-more.png differ diff --git a/docs/site/static/images/channel-notification-settings.gif b/docs/site/static/images/channel-notification-settings.gif new file mode 100644 index 000000000000..c2a5793d9087 Binary files /dev/null and b/docs/site/static/images/channel-notification-settings.gif differ diff --git a/docs/site/static/images/channel-purpose-info.png b/docs/site/static/images/channel-purpose-info.png new file mode 100644 index 000000000000..02a6835427c8 Binary files /dev/null and b/docs/site/static/images/channel-purpose-info.png differ diff --git a/docs/site/static/images/channel-search-filters.png b/docs/site/static/images/channel-search-filters.png new file mode 100644 index 000000000000..25ec226adb6c Binary files /dev/null and b/docs/site/static/images/channel-search-filters.png differ diff --git a/docs/site/static/images/channel-sidebar-navigation.gif b/docs/site/static/images/channel-sidebar-navigation.gif new file mode 100644 index 000000000000..1e0b050cbf51 Binary files /dev/null and b/docs/site/static/images/channel-sidebar-navigation.gif differ diff --git a/docs/site/static/images/channel_sidebar_updates.gif b/docs/site/static/images/channel_sidebar_updates.gif new file mode 100644 index 000000000000..c618cd918ea9 Binary files /dev/null and b/docs/site/static/images/channel_sidebar_updates.gif differ diff --git a/docs/site/static/images/checklist.png b/docs/site/static/images/checklist.png new file mode 100644 index 000000000000..956012242742 Binary files /dev/null and b/docs/site/static/images/checklist.png differ diff --git a/docs/site/static/images/chrome-activity-badge.png b/docs/site/static/images/chrome-activity-badge.png new file mode 100644 index 000000000000..8d788b338237 Binary files /dev/null and b/docs/site/static/images/chrome-activity-badge.png differ diff --git a/docs/site/static/images/chrome-mention-badge.png b/docs/site/static/images/chrome-mention-badge.png new file mode 100644 index 000000000000..faf7b1f9de42 Binary files /dev/null and b/docs/site/static/images/chrome-mention-badge.png differ diff --git a/docs/site/static/images/clear-custom-status.png b/docs/site/static/images/clear-custom-status.png new file mode 100644 index 000000000000..7b572359338b Binary files /dev/null and b/docs/site/static/images/clear-custom-status.png differ diff --git a/docs/site/static/images/collapse-sidebar.png b/docs/site/static/images/collapse-sidebar.png new file mode 100644 index 000000000000..138f8d08498d Binary files /dev/null and b/docs/site/static/images/collapse-sidebar.png differ diff --git a/docs/site/static/images/collapsed-reply-threads.gif b/docs/site/static/images/collapsed-reply-threads.gif new file mode 100644 index 000000000000..19138d005d1e Binary files /dev/null and b/docs/site/static/images/collapsed-reply-threads.gif differ diff --git a/docs/site/static/images/connect-via-mscalendar-connect.png b/docs/site/static/images/connect-via-mscalendar-connect.png new file mode 100644 index 000000000000..9bc6c7a41d0f Binary files /dev/null and b/docs/site/static/images/connect-via-mscalendar-connect.png differ diff --git a/docs/site/static/images/convert-public-channel-to-private.png b/docs/site/static/images/convert-public-channel-to-private.png new file mode 100644 index 000000000000..e3856abc1548 Binary files /dev/null and b/docs/site/static/images/convert-public-channel-to-private.png differ diff --git a/docs/site/static/images/copy-link.png b/docs/site/static/images/copy-link.png new file mode 100644 index 000000000000..4decba1f6095 Binary files /dev/null and b/docs/site/static/images/copy-link.png differ diff --git a/docs/site/static/images/cpa-properties.png b/docs/site/static/images/cpa-properties.png new file mode 100644 index 000000000000..05f77400664a Binary files /dev/null and b/docs/site/static/images/cpa-properties.png differ diff --git a/docs/site/static/images/create-channel-or-open-direct-message-on-mobile.jpg b/docs/site/static/images/create-channel-or-open-direct-message-on-mobile.jpg new file mode 100644 index 000000000000..05f964759149 Binary files /dev/null and b/docs/site/static/images/create-channel-or-open-direct-message-on-mobile.jpg differ diff --git a/docs/site/static/images/create-google-sso-credentials.png b/docs/site/static/images/create-google-sso-credentials.png new file mode 100644 index 000000000000..ba0ea99e5520 Binary files /dev/null and b/docs/site/static/images/create-google-sso-credentials.png differ diff --git a/docs/site/static/images/create-incoming-webhook-details.png b/docs/site/static/images/create-incoming-webhook-details.png new file mode 100644 index 000000000000..9c8fc9151c5a Binary files /dev/null and b/docs/site/static/images/create-incoming-webhook-details.png differ diff --git a/docs/site/static/images/create-jira-issue.png b/docs/site/static/images/create-jira-issue.png new file mode 100644 index 000000000000..bb585bed5f02 Binary files /dev/null and b/docs/site/static/images/create-jira-issue.png differ diff --git a/docs/site/static/images/create-outgoing-webhook-details-more.png b/docs/site/static/images/create-outgoing-webhook-details-more.png new file mode 100644 index 000000000000..913304589cd1 Binary files /dev/null and b/docs/site/static/images/create-outgoing-webhook-details-more.png differ diff --git a/docs/site/static/images/create-outgoing-webhook-details.png b/docs/site/static/images/create-outgoing-webhook-details.png new file mode 100644 index 000000000000..ea47af270637 Binary files /dev/null and b/docs/site/static/images/create-outgoing-webhook-details.png differ diff --git a/docs/site/static/images/create-team.gif b/docs/site/static/images/create-team.gif new file mode 100644 index 000000000000..486ecee5ff53 Binary files /dev/null and b/docs/site/static/images/create-team.gif differ diff --git a/docs/site/static/images/crt-following-thread.jpg b/docs/site/static/images/crt-following-thread.jpg new file mode 100644 index 000000000000..8961caf94f04 Binary files /dev/null and b/docs/site/static/images/crt-following-thread.jpg differ diff --git a/docs/site/static/images/crt-following-thread.png b/docs/site/static/images/crt-following-thread.png new file mode 100644 index 000000000000..52cb7bf29def Binary files /dev/null and b/docs/site/static/images/crt-following-thread.png differ diff --git a/docs/site/static/images/crt-thread-view.jpg b/docs/site/static/images/crt-thread-view.jpg new file mode 100644 index 000000000000..ab0f7e17c651 Binary files /dev/null and b/docs/site/static/images/crt-thread-view.jpg differ diff --git a/docs/site/static/images/dark-theme-via-os.gif b/docs/site/static/images/dark-theme-via-os.gif new file mode 100644 index 000000000000..6ea0cee5b74a Binary files /dev/null and b/docs/site/static/images/dark-theme-via-os.gif differ diff --git a/docs/site/static/images/database-configuration-settings-replica-lag-grafana-1.jpg b/docs/site/static/images/database-configuration-settings-replica-lag-grafana-1.jpg new file mode 100644 index 000000000000..7d67d125f0bd Binary files /dev/null and b/docs/site/static/images/database-configuration-settings-replica-lag-grafana-1.jpg differ diff --git a/docs/site/static/images/database-configuration-settings-replica-lag-grafana-2.jpg b/docs/site/static/images/database-configuration-settings-replica-lag-grafana-2.jpg new file mode 100644 index 000000000000..129c85002b18 Binary files /dev/null and b/docs/site/static/images/database-configuration-settings-replica-lag-grafana-2.jpg differ diff --git a/docs/site/static/images/deactivate-user.png b/docs/site/static/images/deactivate-user.png new file mode 100644 index 000000000000..de7c0991f3b1 Binary files /dev/null and b/docs/site/static/images/deactivate-user.png differ diff --git a/docs/site/static/images/delete_custom_emoji.png b/docs/site/static/images/delete_custom_emoji.png new file mode 100644 index 000000000000..24a46ffc35a0 Binary files /dev/null and b/docs/site/static/images/delete_custom_emoji.png differ diff --git a/docs/site/static/images/desktop-app-settings.jpg b/docs/site/static/images/desktop-app-settings.jpg new file mode 100644 index 000000000000..9a559c2a4a80 Binary files /dev/null and b/docs/site/static/images/desktop-app-settings.jpg differ diff --git a/docs/site/static/images/desktop-edit-server.png b/docs/site/static/images/desktop-edit-server.png new file mode 100644 index 000000000000..b37bfa019704 Binary files /dev/null and b/docs/site/static/images/desktop-edit-server.png differ diff --git a/docs/site/static/images/desktop-multi.png b/docs/site/static/images/desktop-multi.png new file mode 100644 index 000000000000..023aaa698851 Binary files /dev/null and b/docs/site/static/images/desktop-multi.png differ diff --git a/docs/site/static/images/desktop-notification-check.gif b/docs/site/static/images/desktop-notification-check.gif new file mode 100644 index 000000000000..0275e8664206 Binary files /dev/null and b/docs/site/static/images/desktop-notification-check.gif differ diff --git a/docs/site/static/images/desktop-notification-prompt.png b/docs/site/static/images/desktop-notification-prompt.png new file mode 100644 index 000000000000..72d2a3cc3707 Binary files /dev/null and b/docs/site/static/images/desktop-notification-prompt.png differ diff --git a/docs/site/static/images/desktop-remove-server.png b/docs/site/static/images/desktop-remove-server.png new file mode 100644 index 000000000000..79c1dfe1d3c7 Binary files /dev/null and b/docs/site/static/images/desktop-remove-server.png differ diff --git a/docs/site/static/images/desktop-server-add.png b/docs/site/static/images/desktop-server-add.png new file mode 100644 index 000000000000..a92eb5f5d79a Binary files /dev/null and b/docs/site/static/images/desktop-server-add.png differ diff --git a/docs/site/static/images/desktop-server-notification-check.gif b/docs/site/static/images/desktop-server-notification-check.gif new file mode 100644 index 000000000000..82648bc438ef Binary files /dev/null and b/docs/site/static/images/desktop-server-notification-check.gif differ diff --git a/docs/site/static/images/desktop-system-permissions.png b/docs/site/static/images/desktop-system-permissions.png new file mode 100644 index 000000000000..4ce8f1fabeec Binary files /dev/null and b/docs/site/static/images/desktop-system-permissions.png differ diff --git a/docs/site/static/images/desktop-unfollow-message-thread.jpg b/docs/site/static/images/desktop-unfollow-message-thread.jpg new file mode 100644 index 000000000000..ab5300597de4 Binary files /dev/null and b/docs/site/static/images/desktop-unfollow-message-thread.jpg differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00001.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00001.png new file mode 100644 index 000000000000..92824d771b69 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00001.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00002.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00002.png new file mode 100644 index 000000000000..ccdea704f596 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00002.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00003.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00003.png new file mode 100644 index 000000000000..8f9d17c0dff8 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00003.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00004.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00004.png new file mode 100644 index 000000000000..c079b9472267 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00004.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00005.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00005.png new file mode 100644 index 000000000000..c48d94b373cb Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00005.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00006.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00006.png new file mode 100644 index 000000000000..a8c6b515e049 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00006.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00007.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00007.png new file mode 100644 index 000000000000..0ff6d5cb6854 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00007.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00008.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00008.png new file mode 100644 index 000000000000..1becdf76f397 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00008.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00009.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00009.png new file mode 100644 index 000000000000..1cedffc03043 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00009.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00010.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00010.png new file mode 100644 index 000000000000..f1559511647c Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00010.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00011.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00011.png new file mode 100644 index 000000000000..79adf18174ce Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00011.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00012.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00012.png new file mode 100644 index 000000000000..85714737f76c Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00012.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00013.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00013.png new file mode 100644 index 000000000000..4549750a4fb2 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00013.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00014.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00014.png new file mode 100644 index 000000000000..fa648b94ccfc Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00014.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00015.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00015.png new file mode 100644 index 000000000000..6ae567060a63 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00015.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00016.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00016.png new file mode 100644 index 000000000000..de01cd828485 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00016.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00017.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00017.png new file mode 100644 index 000000000000..16f41ccccb20 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00017.png differ diff --git a/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00018.png b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00018.png new file mode 100644 index 000000000000..c387bcf30a60 Binary files /dev/null and b/docs/site/static/images/desktop/msi_gpo/msi_gpo_installation_test_00018.png differ diff --git a/docs/site/static/images/developer-tools-call-widget.png b/docs/site/static/images/developer-tools-call-widget.png new file mode 100644 index 000000000000..54cc679cc5d2 Binary files /dev/null and b/docs/site/static/images/developer-tools-call-widget.png differ diff --git a/docs/site/static/images/dm-display.gif b/docs/site/static/images/dm-display.gif new file mode 100644 index 000000000000..33f1128471fd Binary files /dev/null and b/docs/site/static/images/dm-display.gif differ diff --git a/docs/site/static/images/dr1.png b/docs/site/static/images/dr1.png new file mode 100644 index 000000000000..689855ab746f Binary files /dev/null and b/docs/site/static/images/dr1.png differ diff --git a/docs/site/static/images/dr2.png b/docs/site/static/images/dr2.png new file mode 100644 index 000000000000..3f16e90f04d6 Binary files /dev/null and b/docs/site/static/images/dr2.png differ diff --git a/docs/site/static/images/dr3.png b/docs/site/static/images/dr3.png new file mode 100644 index 000000000000..85f1a6ae0f44 Binary files /dev/null and b/docs/site/static/images/dr3.png differ diff --git a/docs/site/static/images/edit-custom-group.png b/docs/site/static/images/edit-custom-group.png new file mode 100644 index 000000000000..a93114e71030 Binary files /dev/null and b/docs/site/static/images/edit-custom-group.png differ diff --git a/docs/site/static/images/edit-team-icon.png b/docs/site/static/images/edit-team-icon.png new file mode 100644 index 000000000000..d72886f6b351 Binary files /dev/null and b/docs/site/static/images/edit-team-icon.png differ diff --git a/docs/site/static/images/edit-viewer-system-admin-role.png b/docs/site/static/images/edit-viewer-system-admin-role.png new file mode 100644 index 000000000000..b5db85cf2212 Binary files /dev/null and b/docs/site/static/images/edit-viewer-system-admin-role.png differ diff --git a/docs/site/static/images/emoji-skin-tone.png b/docs/site/static/images/emoji-skin-tone.png new file mode 100644 index 000000000000..9bdbfe8eafb5 Binary files /dev/null and b/docs/site/static/images/emoji-skin-tone.png differ diff --git a/docs/site/static/images/emojiautocomplete.png b/docs/site/static/images/emojiautocomplete.png new file mode 100644 index 000000000000..143e9d81bfc6 Binary files /dev/null and b/docs/site/static/images/emojiautocomplete.png differ diff --git a/docs/site/static/images/enable-debug-logging.png b/docs/site/static/images/enable-debug-logging.png new file mode 100644 index 000000000000..9c49c005abe4 Binary files /dev/null and b/docs/site/static/images/enable-debug-logging.png differ diff --git a/docs/site/static/images/enable-disable-ip-filtering.gif b/docs/site/static/images/enable-disable-ip-filtering.gif new file mode 100644 index 000000000000..18aba17c3638 Binary files /dev/null and b/docs/site/static/images/enable-disable-ip-filtering.gif differ diff --git a/docs/site/static/images/enable-notifications.png b/docs/site/static/images/enable-notifications.png new file mode 100644 index 000000000000..2450ff07bbaf Binary files /dev/null and b/docs/site/static/images/enable-notifications.png differ diff --git a/docs/site/static/images/expand-sidebar.png b/docs/site/static/images/expand-sidebar.png new file mode 100644 index 000000000000..661510d32e51 Binary files /dev/null and b/docs/site/static/images/expand-sidebar.png differ diff --git a/docs/site/static/images/favorite-channel-desktop.png b/docs/site/static/images/favorite-channel-desktop.png new file mode 100644 index 000000000000..77982ea7bcd0 Binary files /dev/null and b/docs/site/static/images/favorite-channel-desktop.png differ diff --git a/docs/site/static/images/favorites-list-sidebar.png b/docs/site/static/images/favorites-list-sidebar.png new file mode 100644 index 000000000000..58fcaf1f6bfa Binary files /dev/null and b/docs/site/static/images/favorites-list-sidebar.png differ diff --git a/docs/site/static/images/file-search-filter.png b/docs/site/static/images/file-search-filter.png new file mode 100644 index 000000000000..a7ef7df026c3 Binary files /dev/null and b/docs/site/static/images/file-search-filter.png differ diff --git a/docs/site/static/images/find-channels.png b/docs/site/static/images/find-channels.png new file mode 100644 index 000000000000..e5d2451dbae5 Binary files /dev/null and b/docs/site/static/images/find-channels.png differ diff --git a/docs/site/static/images/find-teams.png b/docs/site/static/images/find-teams.png new file mode 100644 index 000000000000..73b6e1b3ed45 Binary files /dev/null and b/docs/site/static/images/find-teams.png differ diff --git a/docs/site/static/images/find-users.png b/docs/site/static/images/find-users.png new file mode 100644 index 000000000000..ad98f4c786e6 Binary files /dev/null and b/docs/site/static/images/find-users.png differ diff --git a/docs/site/static/images/forward-message.png b/docs/site/static/images/forward-message.png new file mode 100644 index 000000000000..8ab98a79b0cd Binary files /dev/null and b/docs/site/static/images/forward-message.png differ diff --git a/docs/site/static/images/github-integration.png b/docs/site/static/images/github-integration.png new file mode 100644 index 000000000000..2294accd3873 Binary files /dev/null and b/docs/site/static/images/github-integration.png differ diff --git a/docs/site/static/images/github_mattermost.png b/docs/site/static/images/github_mattermost.png new file mode 100644 index 000000000000..d5a5281b6fd3 Binary files /dev/null and b/docs/site/static/images/github_mattermost.png differ diff --git a/docs/site/static/images/gitlab_mattermost.png b/docs/site/static/images/gitlab_mattermost.png new file mode 100644 index 000000000000..60cc28f099e6 Binary files /dev/null and b/docs/site/static/images/gitlab_mattermost.png differ diff --git a/docs/site/static/images/google-sso-credentials.png b/docs/site/static/images/google-sso-credentials.png new file mode 100644 index 000000000000..0da15a4797af Binary files /dev/null and b/docs/site/static/images/google-sso-credentials.png differ diff --git a/docs/site/static/images/google-sso-redirect-uri.png b/docs/site/static/images/google-sso-redirect-uri.png new file mode 100644 index 000000000000..0c4b27a36075 Binary files /dev/null and b/docs/site/static/images/google-sso-redirect-uri.png differ diff --git a/docs/site/static/images/google-sso-web-app-name.png b/docs/site/static/images/google-sso-web-app-name.png new file mode 100644 index 000000000000..910392e19cdb Binary files /dev/null and b/docs/site/static/images/google-sso-web-app-name.png differ diff --git a/docs/site/static/images/grafana-dashboard-msteams.png b/docs/site/static/images/grafana-dashboard-msteams.png new file mode 100644 index 000000000000..69d956660924 Binary files /dev/null and b/docs/site/static/images/grafana-dashboard-msteams.png differ diff --git a/docs/site/static/images/guest-user-attribute.png b/docs/site/static/images/guest-user-attribute.png new file mode 100644 index 000000000000..920e3ff0fe65 Binary files /dev/null and b/docs/site/static/images/guest-user-attribute.png differ diff --git a/docs/site/static/images/icon-76x76.png b/docs/site/static/images/icon-76x76.png new file mode 100644 index 000000000000..b73457efd555 Binary files /dev/null and b/docs/site/static/images/icon-76x76.png differ diff --git a/docs/site/static/images/image-proxy.png b/docs/site/static/images/image-proxy.png new file mode 100644 index 000000000000..659f0b24536c Binary files /dev/null and b/docs/site/static/images/image-proxy.png differ diff --git a/docs/site/static/images/ime.png b/docs/site/static/images/ime.png new file mode 100644 index 000000000000..bf060c18fcc3 Binary files /dev/null and b/docs/site/static/images/ime.png differ diff --git a/docs/site/static/images/incoming-webhook-created.png b/docs/site/static/images/incoming-webhook-created.png new file mode 100644 index 000000000000..056c86bcd373 Binary files /dev/null and b/docs/site/static/images/incoming-webhook-created.png differ diff --git a/docs/site/static/images/install_nginx_welcome.png b/docs/site/static/images/install_nginx_welcome.png new file mode 100644 index 000000000000..bd834219fd43 Binary files /dev/null and b/docs/site/static/images/install_nginx_welcome.png differ diff --git a/docs/site/static/images/invite-people.png b/docs/site/static/images/invite-people.png new file mode 100644 index 000000000000..3cd960167d44 Binary files /dev/null and b/docs/site/static/images/invite-people.png differ diff --git a/docs/site/static/images/ip-address-not-in-filters.png b/docs/site/static/images/ip-address-not-in-filters.png new file mode 100644 index 000000000000..3016b6e7e27a Binary files /dev/null and b/docs/site/static/images/ip-address-not-in-filters.png differ diff --git a/docs/site/static/images/join-channels.png b/docs/site/static/images/join-channels.png new file mode 100644 index 000000000000..306c6f4661a2 Binary files /dev/null and b/docs/site/static/images/join-channels.png differ diff --git a/docs/site/static/images/join-team.png b/docs/site/static/images/join-team.png new file mode 100644 index 000000000000..c7f0acb9c938 Binary files /dev/null and b/docs/site/static/images/join-team.png differ diff --git a/docs/site/static/images/jump-to-message.png b/docs/site/static/images/jump-to-message.png new file mode 100644 index 000000000000..f3b04c60f116 Binary files /dev/null and b/docs/site/static/images/jump-to-message.png differ diff --git a/docs/site/static/images/keyboard-shortcuts.png b/docs/site/static/images/keyboard-shortcuts.png new file mode 100644 index 000000000000..cb99e123af72 Binary files /dev/null and b/docs/site/static/images/keyboard-shortcuts.png differ diff --git a/docs/site/static/images/keycloak-mapper-details.png b/docs/site/static/images/keycloak-mapper-details.png new file mode 100644 index 000000000000..08eca3d0e5b3 Binary files /dev/null and b/docs/site/static/images/keycloak-mapper-details.png differ diff --git a/docs/site/static/images/keycloak_1_client_settings.png b/docs/site/static/images/keycloak_1_client_settings.png new file mode 100644 index 000000000000..43aad3be666a Binary files /dev/null and b/docs/site/static/images/keycloak_1_client_settings.png differ diff --git a/docs/site/static/images/keycloak_1_client_settings_2.png b/docs/site/static/images/keycloak_1_client_settings_2.png new file mode 100644 index 000000000000..862a0f9fad23 Binary files /dev/null and b/docs/site/static/images/keycloak_1_client_settings_2.png differ diff --git a/docs/site/static/images/keycloak_1_client_signature_encryption.png b/docs/site/static/images/keycloak_1_client_signature_encryption.png new file mode 100644 index 000000000000..2e80815a5442 Binary files /dev/null and b/docs/site/static/images/keycloak_1_client_signature_encryption.png differ diff --git a/docs/site/static/images/keycloak_2_saml_keys.png b/docs/site/static/images/keycloak_2_saml_keys.png new file mode 100644 index 000000000000..46abb4add125 Binary files /dev/null and b/docs/site/static/images/keycloak_2_saml_keys.png differ diff --git a/docs/site/static/images/keycloak_2_saml_keys_2.png b/docs/site/static/images/keycloak_2_saml_keys_2.png new file mode 100644 index 000000000000..5fed32d165bb Binary files /dev/null and b/docs/site/static/images/keycloak_2_saml_keys_2.png differ diff --git a/docs/site/static/images/keycloak_4_create_id_attribute.png b/docs/site/static/images/keycloak_4_create_id_attribute.png new file mode 100644 index 000000000000..8a64222b48bb Binary files /dev/null and b/docs/site/static/images/keycloak_4_create_id_attribute.png differ diff --git a/docs/site/static/images/keycloak_4_create_username_attribute.png b/docs/site/static/images/keycloak_4_create_username_attribute.png new file mode 100644 index 000000000000..ebc4de6f669d Binary files /dev/null and b/docs/site/static/images/keycloak_4_create_username_attribute.png differ diff --git a/docs/site/static/images/keycloak_4_create_username_attribute_finished.png b/docs/site/static/images/keycloak_4_create_username_attribute_finished.png new file mode 100644 index 000000000000..aeba8f150cc9 Binary files /dev/null and b/docs/site/static/images/keycloak_4_create_username_attribute_finished.png differ diff --git a/docs/site/static/images/keycloak_5_export_metadata.png b/docs/site/static/images/keycloak_5_export_metadata.png new file mode 100644 index 000000000000..2639ba306712 Binary files /dev/null and b/docs/site/static/images/keycloak_5_export_metadata.png differ diff --git a/docs/site/static/images/keycloak_6_get_metadata.png b/docs/site/static/images/keycloak_6_get_metadata.png new file mode 100644 index 000000000000..8b18e5209066 Binary files /dev/null and b/docs/site/static/images/keycloak_6_get_metadata.png differ diff --git a/docs/site/static/images/keycloak_7_mattermost_config.png b/docs/site/static/images/keycloak_7_mattermost_config.png new file mode 100644 index 000000000000..3f55d25ed328 Binary files /dev/null and b/docs/site/static/images/keycloak_7_mattermost_config.png differ diff --git a/docs/site/static/images/keycloak_8_mattermost_encryption.png b/docs/site/static/images/keycloak_8_mattermost_encryption.png new file mode 100644 index 000000000000..1393ef66a991 Binary files /dev/null and b/docs/site/static/images/keycloak_8_mattermost_encryption.png differ diff --git a/docs/site/static/images/keycloak_9_mattermost_attributes.png b/docs/site/static/images/keycloak_9_mattermost_attributes.png new file mode 100644 index 000000000000..da1a854b87db Binary files /dev/null and b/docs/site/static/images/keycloak_9_mattermost_attributes.png differ diff --git a/docs/site/static/images/keywords-highlighted.gif b/docs/site/static/images/keywords-highlighted.gif new file mode 100644 index 000000000000..5bbc17d7ba55 Binary files /dev/null and b/docs/site/static/images/keywords-highlighted.gif differ diff --git a/docs/site/static/images/keywords-trigger-mentions.gif b/docs/site/static/images/keywords-trigger-mentions.gif new file mode 100644 index 000000000000..65b06faeaf62 Binary files /dev/null and b/docs/site/static/images/keywords-trigger-mentions.gif differ diff --git a/docs/site/static/images/latex-codeblock.png b/docs/site/static/images/latex-codeblock.png new file mode 100644 index 000000000000..ef7c723edbd3 Binary files /dev/null and b/docs/site/static/images/latex-codeblock.png differ diff --git a/docs/site/static/images/latex-inline.png b/docs/site/static/images/latex-inline.png new file mode 100644 index 000000000000..1da4c70d312d Binary files /dev/null and b/docs/site/static/images/latex-inline.png differ diff --git a/docs/site/static/images/leave-channels.png b/docs/site/static/images/leave-channels.png new file mode 100644 index 000000000000..13b7834d9b8d Binary files /dev/null and b/docs/site/static/images/leave-channels.png differ diff --git a/docs/site/static/images/legal-hold-secret.png b/docs/site/static/images/legal-hold-secret.png new file mode 100644 index 000000000000..0ddd11ee54cb Binary files /dev/null and b/docs/site/static/images/legal-hold-secret.png differ diff --git a/docs/site/static/images/legal-holds.png b/docs/site/static/images/legal-holds.png new file mode 100644 index 000000000000..6b76c2459acd Binary files /dev/null and b/docs/site/static/images/legal-holds.png differ diff --git a/docs/site/static/images/login-ad.png b/docs/site/static/images/login-ad.png new file mode 100644 index 000000000000..62df18c4d1a0 Binary files /dev/null and b/docs/site/static/images/login-ad.png differ diff --git a/docs/site/static/images/login-email-username.png b/docs/site/static/images/login-email-username.png new file mode 100644 index 000000000000..12fc51e16f96 Binary files /dev/null and b/docs/site/static/images/login-email-username.png differ diff --git a/docs/site/static/images/login-gitlab.png b/docs/site/static/images/login-gitlab.png new file mode 100644 index 000000000000..13cd29840630 Binary files /dev/null and b/docs/site/static/images/login-gitlab.png differ diff --git a/docs/site/static/images/login-google.png b/docs/site/static/images/login-google.png new file mode 100644 index 000000000000..e72f5554b69d Binary files /dev/null and b/docs/site/static/images/login-google.png differ diff --git a/docs/site/static/images/login-onelogin.png b/docs/site/static/images/login-onelogin.png new file mode 100644 index 000000000000..87930090936c Binary files /dev/null and b/docs/site/static/images/login-onelogin.png differ diff --git a/docs/site/static/images/mac-desktop-app-settings.png b/docs/site/static/images/mac-desktop-app-settings.png new file mode 100644 index 000000000000..c336cba6f27a Binary files /dev/null and b/docs/site/static/images/mac-desktop-app-settings.png differ diff --git a/docs/site/static/images/manage-roles.png b/docs/site/static/images/manage-roles.png new file mode 100644 index 000000000000..b161a1be6f98 Binary files /dev/null and b/docs/site/static/images/manage-roles.png differ diff --git a/docs/site/static/images/manage-user-groups.png b/docs/site/static/images/manage-user-groups.png new file mode 100644 index 000000000000..8b487af2c625 Binary files /dev/null and b/docs/site/static/images/manage-user-groups.png differ diff --git a/docs/site/static/images/manage-webhooks.png b/docs/site/static/images/manage-webhooks.png new file mode 100644 index 000000000000..bdb5fb5cbd1a Binary files /dev/null and b/docs/site/static/images/manage-webhooks.png differ diff --git a/docs/site/static/images/mark-message-as-unread.png b/docs/site/static/images/mark-message-as-unread.png new file mode 100644 index 000000000000..9c6e14fb2025 Binary files /dev/null and b/docs/site/static/images/mark-message-as-unread.png differ diff --git a/docs/site/static/images/markdownTable1.png b/docs/site/static/images/markdownTable1.png new file mode 100644 index 000000000000..da2b79d05a89 Binary files /dev/null and b/docs/site/static/images/markdownTable1.png differ diff --git a/docs/site/static/images/mattermost-cloud-dedicated-reference-architecture.png b/docs/site/static/images/mattermost-cloud-dedicated-reference-architecture.png new file mode 100644 index 000000000000..37264ae26482 Binary files /dev/null and b/docs/site/static/images/mattermost-cloud-dedicated-reference-architecture.png differ diff --git a/docs/site/static/images/mattermost-cloud-native-export-architecture-diagram.png b/docs/site/static/images/mattermost-cloud-native-export-architecture-diagram.png new file mode 100644 index 000000000000..125e1096505c Binary files /dev/null and b/docs/site/static/images/mattermost-cloud-native-export-architecture-diagram.png differ diff --git a/docs/site/static/images/mattermost-for-microsoft_365.png b/docs/site/static/images/mattermost-for-microsoft_365.png new file mode 100644 index 000000000000..e942e54f32eb Binary files /dev/null and b/docs/site/static/images/mattermost-for-microsoft_365.png differ diff --git a/docs/site/static/images/mattermost-in-msteams-2.png b/docs/site/static/images/mattermost-in-msteams-2.png new file mode 100644 index 000000000000..e39b789f3da5 Binary files /dev/null and b/docs/site/static/images/mattermost-in-msteams-2.png differ diff --git a/docs/site/static/images/mattermost-in-msteams.png b/docs/site/static/images/mattermost-in-msteams.png new file mode 100644 index 000000000000..4972d347b61a Binary files /dev/null and b/docs/site/static/images/mattermost-in-msteams.png differ diff --git a/docs/site/static/images/mattermost_active_jobs_chart.png b/docs/site/static/images/mattermost_active_jobs_chart.png new file mode 100644 index 000000000000..3f8512048766 Binary files /dev/null and b/docs/site/static/images/mattermost_active_jobs_chart.png differ diff --git a/docs/site/static/images/mattermost_datasource.png b/docs/site/static/images/mattermost_datasource.png new file mode 100644 index 000000000000..fccab86a934f Binary files /dev/null and b/docs/site/static/images/mattermost_datasource.png differ diff --git a/docs/site/static/images/mattermost_dynamic_range_annotation.png b/docs/site/static/images/mattermost_dynamic_range_annotation.png new file mode 100644 index 000000000000..d4f0a29e23f1 Binary files /dev/null and b/docs/site/static/images/mattermost_dynamic_range_annotation.png differ diff --git a/docs/site/static/images/mattermost_enterprise_license.png b/docs/site/static/images/mattermost_enterprise_license.png new file mode 100644 index 000000000000..f70752102976 Binary files /dev/null and b/docs/site/static/images/mattermost_enterprise_license.png differ diff --git a/docs/site/static/images/mattermost_system_server_start_time.png b/docs/site/static/images/mattermost_system_server_start_time.png new file mode 100644 index 000000000000..f52a60ec5fcc Binary files /dev/null and b/docs/site/static/images/mattermost_system_server_start_time.png differ diff --git a/docs/site/static/images/message-formatting-toolbar.gif b/docs/site/static/images/message-formatting-toolbar.gif new file mode 100644 index 000000000000..f25a929abc48 Binary files /dev/null and b/docs/site/static/images/message-formatting-toolbar.gif differ diff --git a/docs/site/static/images/message-more.png b/docs/site/static/images/message-more.png new file mode 100644 index 000000000000..0aa64403f3fa Binary files /dev/null and b/docs/site/static/images/message-more.png differ diff --git a/docs/site/static/images/message-navigation.gif b/docs/site/static/images/message-navigation.gif new file mode 100644 index 000000000000..12cbdd5f0594 Binary files /dev/null and b/docs/site/static/images/message-navigation.gif differ diff --git a/docs/site/static/images/messagesTable1.png b/docs/site/static/images/messagesTable1.png new file mode 100644 index 000000000000..041a5f01f2f0 Binary files /dev/null and b/docs/site/static/images/messagesTable1.png differ diff --git a/docs/site/static/images/messaging-new-hero.png b/docs/site/static/images/messaging-new-hero.png new file mode 100644 index 000000000000..ceb1f2da8956 Binary files /dev/null and b/docs/site/static/images/messaging-new-hero.png differ diff --git a/docs/site/static/images/microsoft-calendar-settings.png b/docs/site/static/images/microsoft-calendar-settings.png new file mode 100644 index 000000000000..feac6589d13d Binary files /dev/null and b/docs/site/static/images/microsoft-calendar-settings.png differ diff --git a/docs/site/static/images/microsoft-calendar-slash-commands.png b/docs/site/static/images/microsoft-calendar-slash-commands.png new file mode 100644 index 000000000000..d6214af1f986 Binary files /dev/null and b/docs/site/static/images/microsoft-calendar-slash-commands.png differ diff --git a/docs/site/static/images/microsoft-teams-chat-notifications.gif b/docs/site/static/images/microsoft-teams-chat-notifications.gif new file mode 100644 index 000000000000..ff5e3c4e3af8 Binary files /dev/null and b/docs/site/static/images/microsoft-teams-chat-notifications.gif differ diff --git a/docs/site/static/images/microsoft-teams-chat-notifications.png b/docs/site/static/images/microsoft-teams-chat-notifications.png new file mode 100644 index 000000000000..1067f16198bb Binary files /dev/null and b/docs/site/static/images/microsoft-teams-chat-notifications.png differ diff --git a/docs/site/static/images/mission-ready-mobile.png b/docs/site/static/images/mission-ready-mobile.png new file mode 100644 index 000000000000..6a08b2864643 Binary files /dev/null and b/docs/site/static/images/mission-ready-mobile.png differ diff --git a/docs/site/static/images/mm-guset-config.png b/docs/site/static/images/mm-guset-config.png new file mode 100644 index 000000000000..6fd0e3ea792a Binary files /dev/null and b/docs/site/static/images/mm-guset-config.png differ diff --git a/docs/site/static/images/mobile-add-first-channel-bookmark.jpg b/docs/site/static/images/mobile-add-first-channel-bookmark.jpg new file mode 100644 index 000000000000..e48ad1d0bc98 Binary files /dev/null and b/docs/site/static/images/mobile-add-first-channel-bookmark.jpg differ diff --git a/docs/site/static/images/mobile-add-selected-member-to-a-channel.jpg b/docs/site/static/images/mobile-add-selected-member-to-a-channel.jpg new file mode 100644 index 000000000000..8069217f6e31 Binary files /dev/null and b/docs/site/static/images/mobile-add-selected-member-to-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-add-subsequent-channel-bookmarks.jpg b/docs/site/static/images/mobile-add-subsequent-channel-bookmarks.jpg new file mode 100644 index 000000000000..dd857a03a2f9 Binary files /dev/null and b/docs/site/static/images/mobile-add-subsequent-channel-bookmarks.jpg differ diff --git a/docs/site/static/images/mobile-add-user-from-profile.jpg b/docs/site/static/images/mobile-add-user-from-profile.jpg new file mode 100644 index 000000000000..5dff3f8adea2 Binary files /dev/null and b/docs/site/static/images/mobile-add-user-from-profile.jpg differ diff --git a/docs/site/static/images/mobile-add-user-to-a-channel-by-mentioning.jpg b/docs/site/static/images/mobile-add-user-to-a-channel-by-mentioning.jpg new file mode 100644 index 000000000000..e09c5e554f36 Binary files /dev/null and b/docs/site/static/images/mobile-add-user-to-a-channel-by-mentioning.jpg differ diff --git a/docs/site/static/images/mobile-attach-a-channel-bookmark-file.jpg b/docs/site/static/images/mobile-attach-a-channel-bookmark-file.jpg new file mode 100644 index 000000000000..155e33c3aa38 Binary files /dev/null and b/docs/site/static/images/mobile-attach-a-channel-bookmark-file.jpg differ diff --git a/docs/site/static/images/mobile-attach-a-channel-bookmark-link.jpg b/docs/site/static/images/mobile-attach-a-channel-bookmark-link.jpg new file mode 100644 index 000000000000..a25fd6012e2f Binary files /dev/null and b/docs/site/static/images/mobile-attach-a-channel-bookmark-link.jpg differ diff --git a/docs/site/static/images/mobile-attach-a-file-to-send-in-a-channel.gif b/docs/site/static/images/mobile-attach-a-file-to-send-in-a-channel.gif new file mode 100644 index 000000000000..af98966d3614 Binary files /dev/null and b/docs/site/static/images/mobile-attach-a-file-to-send-in-a-channel.gif differ diff --git a/docs/site/static/images/mobile-browse-public-channels-using-filters.jpg b/docs/site/static/images/mobile-browse-public-channels-using-filters.jpg new file mode 100644 index 000000000000..6183d795ce67 Binary files /dev/null and b/docs/site/static/images/mobile-browse-public-channels-using-filters.jpg differ diff --git a/docs/site/static/images/mobile-browse-public-channels-using-search.jpg b/docs/site/static/images/mobile-browse-public-channels-using-search.jpg new file mode 100644 index 000000000000..9272d48416ab Binary files /dev/null and b/docs/site/static/images/mobile-browse-public-channels-using-search.jpg differ diff --git a/docs/site/static/images/mobile-browse-public-channels.jpg b/docs/site/static/images/mobile-browse-public-channels.jpg new file mode 100644 index 000000000000..fd8537ecfdd1 Binary files /dev/null and b/docs/site/static/images/mobile-browse-public-channels.jpg differ diff --git a/docs/site/static/images/mobile-channel-name-click.jpg b/docs/site/static/images/mobile-channel-name-click.jpg new file mode 100644 index 000000000000..7ab167add8bf Binary files /dev/null and b/docs/site/static/images/mobile-channel-name-click.jpg differ diff --git a/docs/site/static/images/mobile-chat-in-a-call.gif b/docs/site/static/images/mobile-chat-in-a-call.gif new file mode 100644 index 000000000000..4cc305ed1327 Binary files /dev/null and b/docs/site/static/images/mobile-chat-in-a-call.gif differ diff --git a/docs/site/static/images/mobile-confirm-archive-a-channel.jpg b/docs/site/static/images/mobile-confirm-archive-a-channel.jpg new file mode 100644 index 000000000000..76388632a469 Binary files /dev/null and b/docs/site/static/images/mobile-confirm-archive-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-confirm-convert-to-private-channel.jpg b/docs/site/static/images/mobile-confirm-convert-to-private-channel.jpg new file mode 100644 index 000000000000..72ae2df7d820 Binary files /dev/null and b/docs/site/static/images/mobile-confirm-convert-to-private-channel.jpg differ diff --git a/docs/site/static/images/mobile-confirm-delete-a-message.jpg b/docs/site/static/images/mobile-confirm-delete-a-message.jpg new file mode 100644 index 000000000000..7518bf07b00d Binary files /dev/null and b/docs/site/static/images/mobile-confirm-delete-a-message.jpg differ diff --git a/docs/site/static/images/mobile-confirm-leave-a-channel.jpg b/docs/site/static/images/mobile-confirm-leave-a-channel.jpg new file mode 100644 index 000000000000..e590971d50e4 Binary files /dev/null and b/docs/site/static/images/mobile-confirm-leave-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-confirm-remove-user-from-channel.jpg b/docs/site/static/images/mobile-confirm-remove-user-from-channel.jpg new file mode 100644 index 000000000000..14aa4c0d18dd Binary files /dev/null and b/docs/site/static/images/mobile-confirm-remove-user-from-channel.jpg differ diff --git a/docs/site/static/images/mobile-confirm-unarchive-a-channel.jpg b/docs/site/static/images/mobile-confirm-unarchive-a-channel.jpg new file mode 100644 index 000000000000..1b12717c2c0e Binary files /dev/null and b/docs/site/static/images/mobile-confirm-unarchive-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-convert-group-to-private-channel.jpg b/docs/site/static/images/mobile-convert-group-to-private-channel.jpg new file mode 100644 index 000000000000..e7a78dfcbcf3 Binary files /dev/null and b/docs/site/static/images/mobile-convert-group-to-private-channel.jpg differ diff --git a/docs/site/static/images/mobile-convert-to-private-channel.jpg b/docs/site/static/images/mobile-convert-to-private-channel.jpg new file mode 100644 index 000000000000..c1d3243784d7 Binary files /dev/null and b/docs/site/static/images/mobile-convert-to-private-channel.jpg differ diff --git a/docs/site/static/images/mobile-copy-a-channel-bookmark-link.gif b/docs/site/static/images/mobile-copy-a-channel-bookmark-link.gif new file mode 100644 index 000000000000..f8b4a5c224e5 Binary files /dev/null and b/docs/site/static/images/mobile-copy-a-channel-bookmark-link.gif differ diff --git a/docs/site/static/images/mobile-copy-a-link-to-the-message.gif b/docs/site/static/images/mobile-copy-a-link-to-the-message.gif new file mode 100644 index 000000000000..5368c8a63b8e Binary files /dev/null and b/docs/site/static/images/mobile-copy-a-link-to-the-message.gif differ diff --git a/docs/site/static/images/mobile-delete-a-channel-bookmark.gif b/docs/site/static/images/mobile-delete-a-channel-bookmark.gif new file mode 100644 index 000000000000..f7326df1fecb Binary files /dev/null and b/docs/site/static/images/mobile-delete-a-channel-bookmark.gif differ diff --git a/docs/site/static/images/mobile-delete-a-message.gif b/docs/site/static/images/mobile-delete-a-message.gif new file mode 100644 index 000000000000..59607745d5b3 Binary files /dev/null and b/docs/site/static/images/mobile-delete-a-message.gif differ diff --git a/docs/site/static/images/mobile-draft-a-message.gif b/docs/site/static/images/mobile-draft-a-message.gif new file mode 100644 index 000000000000..313745c776d6 Binary files /dev/null and b/docs/site/static/images/mobile-draft-a-message.gif differ diff --git a/docs/site/static/images/mobile-edit-a-channel-bookmark.gif b/docs/site/static/images/mobile-edit-a-channel-bookmark.gif new file mode 100644 index 000000000000..6e793173aaba Binary files /dev/null and b/docs/site/static/images/mobile-edit-a-channel-bookmark.gif differ diff --git a/docs/site/static/images/mobile-edit-a-message.gif b/docs/site/static/images/mobile-edit-a-message.gif new file mode 100644 index 000000000000..92526537d987 Binary files /dev/null and b/docs/site/static/images/mobile-edit-a-message.gif differ diff --git a/docs/site/static/images/mobile-edit-channel.jpg b/docs/site/static/images/mobile-edit-channel.jpg new file mode 100644 index 000000000000..6d3d17cade1f Binary files /dev/null and b/docs/site/static/images/mobile-edit-channel.jpg differ diff --git a/docs/site/static/images/mobile-editing-a-message.jpg b/docs/site/static/images/mobile-editing-a-message.jpg new file mode 100644 index 000000000000..56c0469ee5a9 Binary files /dev/null and b/docs/site/static/images/mobile-editing-a-message.jpg differ diff --git a/docs/site/static/images/mobile-exit-after-removing-user-from-a-channel.jpg b/docs/site/static/images/mobile-exit-after-removing-user-from-a-channel.jpg new file mode 100644 index 000000000000..834fdd3c76a5 Binary files /dev/null and b/docs/site/static/images/mobile-exit-after-removing-user-from-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-favorite-a-channel-within-channel.jpg b/docs/site/static/images/mobile-favorite-a-channel-within-channel.jpg new file mode 100644 index 000000000000..3f8677caff83 Binary files /dev/null and b/docs/site/static/images/mobile-favorite-a-channel-within-channel.jpg differ diff --git a/docs/site/static/images/mobile-follow-a-message-thread-by-tapping-follow.gif b/docs/site/static/images/mobile-follow-a-message-thread-by-tapping-follow.gif new file mode 100644 index 000000000000..91a61495e4fe Binary files /dev/null and b/docs/site/static/images/mobile-follow-a-message-thread-by-tapping-follow.gif differ diff --git a/docs/site/static/images/mobile-follow-a-message-thread-with-follow-option.gif b/docs/site/static/images/mobile-follow-a-message-thread-with-follow-option.gif new file mode 100644 index 000000000000..694defee5279 Binary files /dev/null and b/docs/site/static/images/mobile-follow-a-message-thread-with-follow-option.gif differ diff --git a/docs/site/static/images/mobile-follow-a-message-with-no-replies.gif b/docs/site/static/images/mobile-follow-a-message-with-no-replies.gif new file mode 100644 index 000000000000..9b83294e6603 Binary files /dev/null and b/docs/site/static/images/mobile-follow-a-message-with-no-replies.gif differ diff --git a/docs/site/static/images/mobile-include-emojis-for-a-message-reaction.gif b/docs/site/static/images/mobile-include-emojis-for-a-message-reaction.gif new file mode 100644 index 000000000000..5358ccbcc10d Binary files /dev/null and b/docs/site/static/images/mobile-include-emojis-for-a-message-reaction.gif differ diff --git a/docs/site/static/images/mobile-invite-people-to-the-team.png b/docs/site/static/images/mobile-invite-people-to-the-team.png new file mode 100644 index 000000000000..03040a5c2414 Binary files /dev/null and b/docs/site/static/images/mobile-invite-people-to-the-team.png differ diff --git a/docs/site/static/images/mobile-manage-channel-members-list.jpg b/docs/site/static/images/mobile-manage-channel-members-list.jpg new file mode 100644 index 000000000000..e68e57cc7ced Binary files /dev/null and b/docs/site/static/images/mobile-manage-channel-members-list.jpg differ diff --git a/docs/site/static/images/mobile-mark-a-message-as-unread.gif b/docs/site/static/images/mobile-mark-a-message-as-unread.gif new file mode 100644 index 000000000000..337d79140353 Binary files /dev/null and b/docs/site/static/images/mobile-mark-a-message-as-unread.gif differ diff --git a/docs/site/static/images/mobile-more-options-to-download-or-view-a-file.jpg b/docs/site/static/images/mobile-more-options-to-download-or-view-a-file.jpg new file mode 100644 index 000000000000..0024f7662090 Binary files /dev/null and b/docs/site/static/images/mobile-more-options-to-download-or-view-a-file.jpg differ diff --git a/docs/site/static/images/mobile-pin-a-message-to-the-channel.gif b/docs/site/static/images/mobile-pin-a-message-to-the-channel.gif new file mode 100644 index 000000000000..4b3aad8c4d02 Binary files /dev/null and b/docs/site/static/images/mobile-pin-a-message-to-the-channel.gif differ diff --git a/docs/site/static/images/mobile-post-proxy-relay.png b/docs/site/static/images/mobile-post-proxy-relay.png new file mode 100644 index 000000000000..a094a91015d5 Binary files /dev/null and b/docs/site/static/images/mobile-post-proxy-relay.png differ diff --git a/docs/site/static/images/mobile-pre-proxy-relay.png b/docs/site/static/images/mobile-pre-proxy-relay.png new file mode 100644 index 000000000000..67675bbe2fc8 Binary files /dev/null and b/docs/site/static/images/mobile-pre-proxy-relay.png differ diff --git a/docs/site/static/images/mobile-provide-private-channel-name-for-the-group.jpg b/docs/site/static/images/mobile-provide-private-channel-name-for-the-group.jpg new file mode 100644 index 000000000000..b7a74c8abfb2 Binary files /dev/null and b/docs/site/static/images/mobile-provide-private-channel-name-for-the-group.jpg differ diff --git a/docs/site/static/images/mobile-react-using-emojis-in-a-call.gif b/docs/site/static/images/mobile-react-using-emojis-in-a-call.gif new file mode 100644 index 000000000000..1ae7ad53225f Binary files /dev/null and b/docs/site/static/images/mobile-react-using-emojis-in-a-call.gif differ diff --git a/docs/site/static/images/mobile-remove-user-from-a-channel.jpg b/docs/site/static/images/mobile-remove-user-from-a-channel.jpg new file mode 100644 index 000000000000..31bcf47439d5 Binary files /dev/null and b/docs/site/static/images/mobile-remove-user-from-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-rename-channel-name-and-save.jpg b/docs/site/static/images/mobile-rename-channel-name-and-save.jpg new file mode 100644 index 000000000000..d171bcdb3f17 Binary files /dev/null and b/docs/site/static/images/mobile-rename-channel-name-and-save.jpg differ diff --git a/docs/site/static/images/mobile-reply-to-a-message-by-tapping-on-it.gif b/docs/site/static/images/mobile-reply-to-a-message-by-tapping-on-it.gif new file mode 100644 index 000000000000..46d508628fa4 Binary files /dev/null and b/docs/site/static/images/mobile-reply-to-a-message-by-tapping-on-it.gif differ diff --git a/docs/site/static/images/mobile-reply-to-a-message-using-reply.gif b/docs/site/static/images/mobile-reply-to-a-message-using-reply.gif new file mode 100644 index 000000000000..dbab5d65b336 Binary files /dev/null and b/docs/site/static/images/mobile-reply-to-a-message-using-reply.gif differ diff --git a/docs/site/static/images/mobile-save-a-message.gif b/docs/site/static/images/mobile-save-a-message.gif new file mode 100644 index 000000000000..1c91c47157d9 Binary files /dev/null and b/docs/site/static/images/mobile-save-a-message.gif differ diff --git a/docs/site/static/images/mobile-search-for-messages.jpg b/docs/site/static/images/mobile-search-for-messages.jpg new file mode 100644 index 000000000000..3901a98a13c7 Binary files /dev/null and b/docs/site/static/images/mobile-search-for-messages.jpg differ diff --git a/docs/site/static/images/mobile-search-message-criteria-with-hashtags.jpg b/docs/site/static/images/mobile-search-message-criteria-with-hashtags.jpg new file mode 100644 index 000000000000..b5e3bf2feb49 Binary files /dev/null and b/docs/site/static/images/mobile-search-message-criteria-with-hashtags.jpg differ diff --git a/docs/site/static/images/mobile-search-message-results.jpg b/docs/site/static/images/mobile-search-message-results.jpg new file mode 100644 index 000000000000..4cbc7e174a5f Binary files /dev/null and b/docs/site/static/images/mobile-search-message-results.jpg differ diff --git a/docs/site/static/images/mobile-search-message-team-selection.jpg b/docs/site/static/images/mobile-search-message-team-selection.jpg new file mode 100644 index 000000000000..254f814d5529 Binary files /dev/null and b/docs/site/static/images/mobile-search-message-team-selection.jpg differ diff --git a/docs/site/static/images/mobile-search-message-with-modifiers.jpg b/docs/site/static/images/mobile-search-message-with-modifiers.jpg new file mode 100644 index 000000000000..c093b2b78be7 Binary files /dev/null and b/docs/site/static/images/mobile-search-message-with-modifiers.jpg differ diff --git a/docs/site/static/images/mobile-select-a-channel.jpg b/docs/site/static/images/mobile-select-a-channel.jpg new file mode 100644 index 000000000000..0a56773522e9 Binary files /dev/null and b/docs/site/static/images/mobile-select-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-select-a-group-message.jpg b/docs/site/static/images/mobile-select-a-group-message.jpg new file mode 100644 index 000000000000..f8074d3ce39c Binary files /dev/null and b/docs/site/static/images/mobile-select-a-group-message.jpg differ diff --git a/docs/site/static/images/mobile-select-members-to-add-to-a-channel.jpg b/docs/site/static/images/mobile-select-members-to-add-to-a-channel.jpg new file mode 100644 index 000000000000..2601355ecd9f Binary files /dev/null and b/docs/site/static/images/mobile-select-members-to-add-to-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-select-more-options-for-a-channel.jpg b/docs/site/static/images/mobile-select-more-options-for-a-channel.jpg new file mode 100644 index 000000000000..ba0939fa9c43 Binary files /dev/null and b/docs/site/static/images/mobile-select-more-options-for-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-select-more-options-for-a-group.jpg b/docs/site/static/images/mobile-select-more-options-for-a-group.jpg new file mode 100644 index 000000000000..c4650278e5a1 Binary files /dev/null and b/docs/site/static/images/mobile-select-more-options-for-a-group.jpg differ diff --git a/docs/site/static/images/mobile-select-view-info-for-a-channel.jpg b/docs/site/static/images/mobile-select-view-info-for-a-channel.jpg new file mode 100644 index 000000000000..db42077247e1 Binary files /dev/null and b/docs/site/static/images/mobile-select-view-info-for-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-select-view-info-for-a-group.jpg b/docs/site/static/images/mobile-select-view-info-for-a-group.jpg new file mode 100644 index 000000000000..6739fd4c5bae Binary files /dev/null and b/docs/site/static/images/mobile-select-view-info-for-a-group.jpg differ diff --git a/docs/site/static/images/mobile-send-invite-to.png b/docs/site/static/images/mobile-send-invite-to.png new file mode 100644 index 000000000000..71377879883a Binary files /dev/null and b/docs/site/static/images/mobile-send-invite-to.png differ diff --git a/docs/site/static/images/mobile-sending-a-message.gif b/docs/site/static/images/mobile-sending-a-message.gif new file mode 100644 index 000000000000..38d78da35734 Binary files /dev/null and b/docs/site/static/images/mobile-sending-a-message.gif differ diff --git a/docs/site/static/images/mobile-start-a-call-in-a-channel.gif b/docs/site/static/images/mobile-start-a-call-in-a-channel.gif new file mode 100644 index 000000000000..b17d589db0da Binary files /dev/null and b/docs/site/static/images/mobile-start-a-call-in-a-channel.gif differ diff --git a/docs/site/static/images/mobile-start-a-call-recording-using-call-banner.gif b/docs/site/static/images/mobile-start-a-call-recording-using-call-banner.gif new file mode 100644 index 000000000000..dc3c976d03a9 Binary files /dev/null and b/docs/site/static/images/mobile-start-a-call-recording-using-call-banner.gif differ diff --git a/docs/site/static/images/mobile-start-a-call-recording-using-slash-commands.gif b/docs/site/static/images/mobile-start-a-call-recording-using-slash-commands.gif new file mode 100644 index 000000000000..da67084f53aa Binary files /dev/null and b/docs/site/static/images/mobile-start-a-call-recording-using-slash-commands.gif differ diff --git a/docs/site/static/images/mobile-stop-a-call-recording-using-call-banner.gif b/docs/site/static/images/mobile-stop-a-call-recording-using-call-banner.gif new file mode 100644 index 000000000000..85d5812ddcbe Binary files /dev/null and b/docs/site/static/images/mobile-stop-a-call-recording-using-call-banner.gif differ diff --git a/docs/site/static/images/mobile-stop-a-call-recording-using-slash-commands.gif b/docs/site/static/images/mobile-stop-a-call-recording-using-slash-commands.gif new file mode 100644 index 000000000000..e3af7aed832e Binary files /dev/null and b/docs/site/static/images/mobile-stop-a-call-recording-using-slash-commands.gif differ diff --git a/docs/site/static/images/mobile-tap-a-file-name-to-download.jpg b/docs/site/static/images/mobile-tap-a-file-name-to-download.jpg new file mode 100644 index 000000000000..0e1d5f10b0c5 Binary files /dev/null and b/docs/site/static/images/mobile-tap-a-file-name-to-download.jpg differ diff --git a/docs/site/static/images/mobile-type-a-message-in-a-channel.jpg b/docs/site/static/images/mobile-type-a-message-in-a-channel.jpg new file mode 100644 index 000000000000..2970a564978f Binary files /dev/null and b/docs/site/static/images/mobile-type-a-message-in-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-unarchive-a-channel.jpg b/docs/site/static/images/mobile-unarchive-a-channel.jpg new file mode 100644 index 000000000000..a13a823e84e5 Binary files /dev/null and b/docs/site/static/images/mobile-unarchive-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-unfavorite-a-channel-from-within-the-channel.jpg b/docs/site/static/images/mobile-unfavorite-a-channel-from-within-the-channel.jpg new file mode 100644 index 000000000000..15abea83576b Binary files /dev/null and b/docs/site/static/images/mobile-unfavorite-a-channel-from-within-the-channel.jpg differ diff --git a/docs/site/static/images/mobile-unfavorite-a-channel.jpg b/docs/site/static/images/mobile-unfavorite-a-channel.jpg new file mode 100644 index 000000000000..9fc07520b4d6 Binary files /dev/null and b/docs/site/static/images/mobile-unfavorite-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-unfollow-a-message-thread-by-tapping-following.gif b/docs/site/static/images/mobile-unfollow-a-message-thread-by-tapping-following.gif new file mode 100644 index 000000000000..c4901f22e32b Binary files /dev/null and b/docs/site/static/images/mobile-unfollow-a-message-thread-by-tapping-following.gif differ diff --git a/docs/site/static/images/mobile-unfollow-a-message-thread-with-unfollow-option.gif b/docs/site/static/images/mobile-unfollow-a-message-thread-with-unfollow-option.gif new file mode 100644 index 000000000000..d7ecba7da3b7 Binary files /dev/null and b/docs/site/static/images/mobile-unfollow-a-message-thread-with-unfollow-option.gif differ diff --git a/docs/site/static/images/mobile-unpin-a-message-from-pinned-messages.gif b/docs/site/static/images/mobile-unpin-a-message-from-pinned-messages.gif new file mode 100644 index 000000000000..be8e959a6741 Binary files /dev/null and b/docs/site/static/images/mobile-unpin-a-message-from-pinned-messages.gif differ diff --git a/docs/site/static/images/mobile-unpin-a-message-from-the-channel.gif b/docs/site/static/images/mobile-unpin-a-message-from-the-channel.gif new file mode 100644 index 000000000000..e8590674d5ca Binary files /dev/null and b/docs/site/static/images/mobile-unpin-a-message-from-the-channel.gif differ diff --git a/docs/site/static/images/mobile-unsave-a-message-from-saved-messages.gif b/docs/site/static/images/mobile-unsave-a-message-from-saved-messages.gif new file mode 100644 index 000000000000..3dac23660fa9 Binary files /dev/null and b/docs/site/static/images/mobile-unsave-a-message-from-saved-messages.gif differ diff --git a/docs/site/static/images/mobile-unsave-a-message-from-the-channel.gif b/docs/site/static/images/mobile-unsave-a-message-from-the-channel.gif new file mode 100644 index 000000000000..62368591f636 Binary files /dev/null and b/docs/site/static/images/mobile-unsave-a-message-from-the-channel.gif differ diff --git a/docs/site/static/images/mobile-update-channel-header.jpg b/docs/site/static/images/mobile-update-channel-header.jpg new file mode 100644 index 000000000000..2b663c89a069 Binary files /dev/null and b/docs/site/static/images/mobile-update-channel-header.jpg differ diff --git a/docs/site/static/images/mobile-update-channel-purpose.jpg b/docs/site/static/images/mobile-update-channel-purpose.jpg new file mode 100644 index 000000000000..4d3516555e34 Binary files /dev/null and b/docs/site/static/images/mobile-update-channel-purpose.jpg differ diff --git a/docs/site/static/images/mobile-view-members-of-a-channel.jpg b/docs/site/static/images/mobile-view-members-of-a-channel.jpg new file mode 100644 index 000000000000..e964c19ca1bd Binary files /dev/null and b/docs/site/static/images/mobile-view-members-of-a-channel.jpg differ diff --git a/docs/site/static/images/mobile-view-saved-messages.gif b/docs/site/static/images/mobile-view-saved-messages.gif new file mode 100644 index 000000000000..4cda7be33506 Binary files /dev/null and b/docs/site/static/images/mobile-view-saved-messages.gif differ diff --git a/docs/site/static/images/mobile-view-the-pinned-message-in-the-pinned-messages-list.jpg b/docs/site/static/images/mobile-view-the-pinned-message-in-the-pinned-messages-list.jpg new file mode 100644 index 000000000000..35eeb6bd7a45 Binary files /dev/null and b/docs/site/static/images/mobile-view-the-pinned-message-in-the-pinned-messages-list.jpg differ diff --git a/docs/site/static/images/more-actions.png b/docs/site/static/images/more-actions.png new file mode 100644 index 000000000000..4123e67bfc99 Binary files /dev/null and b/docs/site/static/images/more-actions.png differ diff --git a/docs/site/static/images/ms-calendar-add-permission.png b/docs/site/static/images/ms-calendar-add-permission.png new file mode 100644 index 000000000000..f7f1a8c51cb7 Binary files /dev/null and b/docs/site/static/images/ms-calendar-add-permission.png differ diff --git a/docs/site/static/images/ms-calendar-api-permissions.png b/docs/site/static/images/ms-calendar-api-permissions.png new file mode 100644 index 000000000000..15ba78e1fbd2 Binary files /dev/null and b/docs/site/static/images/ms-calendar-api-permissions.png differ diff --git a/docs/site/static/images/ms-calendar-certs-secrets.png b/docs/site/static/images/ms-calendar-certs-secrets.png new file mode 100644 index 000000000000..29fd041e040b Binary files /dev/null and b/docs/site/static/images/ms-calendar-certs-secrets.png differ diff --git a/docs/site/static/images/ms-calendar-copy-ids.png b/docs/site/static/images/ms-calendar-copy-ids.png new file mode 100644 index 000000000000..c501e7308254 Binary files /dev/null and b/docs/site/static/images/ms-calendar-copy-ids.png differ diff --git a/docs/site/static/images/ms-calendar-delegated-permissions.png b/docs/site/static/images/ms-calendar-delegated-permissions.png new file mode 100644 index 000000000000..91ae8f5faf94 Binary files /dev/null and b/docs/site/static/images/ms-calendar-delegated-permissions.png differ diff --git a/docs/site/static/images/ms-calendar-intro.png b/docs/site/static/images/ms-calendar-intro.png new file mode 100644 index 000000000000..b9176fb6be23 Binary files /dev/null and b/docs/site/static/images/ms-calendar-intro.png differ diff --git a/docs/site/static/images/ms-calendar-new-azure-registration.png b/docs/site/static/images/ms-calendar-new-azure-registration.png new file mode 100644 index 000000000000..c8fd67b3a8e4 Binary files /dev/null and b/docs/site/static/images/ms-calendar-new-azure-registration.png differ diff --git a/docs/site/static/images/ms-calendar-new-client-secret.png b/docs/site/static/images/ms-calendar-new-client-secret.png new file mode 100644 index 000000000000..a15cc6a07ce6 Binary files /dev/null and b/docs/site/static/images/ms-calendar-new-client-secret.png differ diff --git a/docs/site/static/images/ms-calendar-single-tenant.png b/docs/site/static/images/ms-calendar-single-tenant.png new file mode 100644 index 000000000000..0e8480cd55d7 Binary files /dev/null and b/docs/site/static/images/ms-calendar-single-tenant.png differ diff --git a/docs/site/static/images/ms-teams-meeting-permissions-final-state.png b/docs/site/static/images/ms-teams-meeting-permissions-final-state.png new file mode 100644 index 000000000000..c8db47b3f6ec Binary files /dev/null and b/docs/site/static/images/ms-teams-meeting-permissions-final-state.png differ diff --git a/docs/site/static/images/ms-teams-meetings-add-permission.png b/docs/site/static/images/ms-teams-meetings-add-permission.png new file mode 100644 index 000000000000..7a83b6a7ac19 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-add-permission.png differ diff --git a/docs/site/static/images/ms-teams-meetings-api-permissions.png b/docs/site/static/images/ms-teams-meetings-api-permissions.png new file mode 100644 index 000000000000..15ba78e1fbd2 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-api-permissions.png differ diff --git a/docs/site/static/images/ms-teams-meetings-certs-secrets.png b/docs/site/static/images/ms-teams-meetings-certs-secrets.png new file mode 100644 index 000000000000..29fd041e040b Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-certs-secrets.png differ diff --git a/docs/site/static/images/ms-teams-meetings-copy-ids.png b/docs/site/static/images/ms-teams-meetings-copy-ids.png new file mode 100644 index 000000000000..c501e7308254 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-copy-ids.png differ diff --git a/docs/site/static/images/ms-teams-meetings-delegated-permissions.png b/docs/site/static/images/ms-teams-meetings-delegated-permissions.png new file mode 100644 index 000000000000..05b438a613ef Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-delegated-permissions.png differ diff --git a/docs/site/static/images/ms-teams-meetings-grant-admin-consent.png b/docs/site/static/images/ms-teams-meetings-grant-admin-consent.png new file mode 100644 index 000000000000..ed3783cd48d1 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-grant-admin-consent.png differ diff --git a/docs/site/static/images/ms-teams-meetings-new-azure-registration.png b/docs/site/static/images/ms-teams-meetings-new-azure-registration.png new file mode 100644 index 000000000000..c8fd67b3a8e4 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-new-azure-registration.png differ diff --git a/docs/site/static/images/ms-teams-meetings-new-client-secret.png b/docs/site/static/images/ms-teams-meetings-new-client-secret.png new file mode 100644 index 000000000000..a15cc6a07ce6 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-new-client-secret.png differ diff --git a/docs/site/static/images/ms-teams-meetings-reg-info.png b/docs/site/static/images/ms-teams-meetings-reg-info.png new file mode 100644 index 000000000000..77bec396cc86 Binary files /dev/null and b/docs/site/static/images/ms-teams-meetings-reg-info.png differ diff --git a/docs/site/static/images/multi-select-drag.gif b/docs/site/static/images/multi-select-drag.gif new file mode 100644 index 000000000000..92483521d964 Binary files /dev/null and b/docs/site/static/images/multi-select-drag.gif differ diff --git a/docs/site/static/images/multi-select-move.gif b/docs/site/static/images/multi-select-move.gif new file mode 100644 index 000000000000..92579f9a85b8 Binary files /dev/null and b/docs/site/static/images/multi-select-move.gif differ diff --git a/docs/site/static/images/mute-categories.gif b/docs/site/static/images/mute-categories.gif new file mode 100644 index 000000000000..f252b2d177ea Binary files /dev/null and b/docs/site/static/images/mute-categories.gif differ diff --git a/docs/site/static/images/navigation.gif b/docs/site/static/images/navigation.gif new file mode 100644 index 000000000000..1e0b050cbf51 Binary files /dev/null and b/docs/site/static/images/navigation.gif differ diff --git a/docs/site/static/images/new-azure-registration.png b/docs/site/static/images/new-azure-registration.png new file mode 100644 index 000000000000..c8fd67b3a8e4 Binary files /dev/null and b/docs/site/static/images/new-azure-registration.png differ diff --git a/docs/site/static/images/note-client-and-tenant-id.png b/docs/site/static/images/note-client-and-tenant-id.png new file mode 100644 index 000000000000..3e87f593c21c Binary files /dev/null and b/docs/site/static/images/note-client-and-tenant-id.png differ diff --git a/docs/site/static/images/notices.png b/docs/site/static/images/notices.png new file mode 100644 index 000000000000..c0ec75f60ac6 Binary files /dev/null and b/docs/site/static/images/notices.png differ diff --git a/docs/site/static/images/notices_admin.png b/docs/site/static/images/notices_admin.png new file mode 100644 index 000000000000..fb6dcbe8b33f Binary files /dev/null and b/docs/site/static/images/notices_admin.png differ diff --git a/docs/site/static/images/nps-admin.png b/docs/site/static/images/nps-admin.png new file mode 100644 index 000000000000..703cec137cf8 Binary files /dev/null and b/docs/site/static/images/nps-admin.png differ diff --git a/docs/site/static/images/nps-survey.png b/docs/site/static/images/nps-survey.png new file mode 100644 index 000000000000..d0ddd5407906 Binary files /dev/null and b/docs/site/static/images/nps-survey.png differ diff --git a/docs/site/static/images/okta_10_mattermost_basics.png b/docs/site/static/images/okta_10_mattermost_basics.png new file mode 100644 index 000000000000..eec60fc8b167 Binary files /dev/null and b/docs/site/static/images/okta_10_mattermost_basics.png differ diff --git a/docs/site/static/images/okta_11_mattermost_verification.png b/docs/site/static/images/okta_11_mattermost_verification.png new file mode 100644 index 000000000000..16c03c54ba33 Binary files /dev/null and b/docs/site/static/images/okta_11_mattermost_verification.png differ diff --git a/docs/site/static/images/okta_12_mattermost_encryption.png b/docs/site/static/images/okta_12_mattermost_encryption.png new file mode 100644 index 000000000000..ff2f9b4cdf92 Binary files /dev/null and b/docs/site/static/images/okta_12_mattermost_encryption.png differ diff --git a/docs/site/static/images/okta_13_mattermost_attributes.png b/docs/site/static/images/okta_13_mattermost_attributes.png new file mode 100644 index 000000000000..08798d55e422 Binary files /dev/null and b/docs/site/static/images/okta_13_mattermost_attributes.png differ diff --git a/docs/site/static/images/okta_14_mattermost_login_button.png b/docs/site/static/images/okta_14_mattermost_login_button.png new file mode 100644 index 000000000000..d76a9d4ff06e Binary files /dev/null and b/docs/site/static/images/okta_14_mattermost_login_button.png differ diff --git a/docs/site/static/images/okta_1_new_app.png b/docs/site/static/images/okta_1_new_app.png new file mode 100644 index 000000000000..bcfb8df56af8 Binary files /dev/null and b/docs/site/static/images/okta_1_new_app.png differ diff --git a/docs/site/static/images/okta_2_general_settings.png b/docs/site/static/images/okta_2_general_settings.png new file mode 100644 index 000000000000..f8bfd29f4485 Binary files /dev/null and b/docs/site/static/images/okta_2_general_settings.png differ diff --git a/docs/site/static/images/okta_3_initial_saml_settings.png b/docs/site/static/images/okta_3_initial_saml_settings.png new file mode 100644 index 000000000000..bf3517f53ad1 Binary files /dev/null and b/docs/site/static/images/okta_3_initial_saml_settings.png differ diff --git a/docs/site/static/images/okta_4_initial_saml_settings.png b/docs/site/static/images/okta_4_initial_saml_settings.png new file mode 100644 index 000000000000..823773d30ab0 Binary files /dev/null and b/docs/site/static/images/okta_4_initial_saml_settings.png differ diff --git a/docs/site/static/images/okta_5_advanced_saml_settings.png b/docs/site/static/images/okta_5_advanced_saml_settings.png new file mode 100644 index 000000000000..7ef1e50be796 Binary files /dev/null and b/docs/site/static/images/okta_5_advanced_saml_settings.png differ diff --git a/docs/site/static/images/okta_6_attribute_statements.png b/docs/site/static/images/okta_6_attribute_statements.png new file mode 100644 index 000000000000..719784d5ed8e Binary files /dev/null and b/docs/site/static/images/okta_6_attribute_statements.png differ diff --git a/docs/site/static/images/okta_7_support_configuration.png b/docs/site/static/images/okta_7_support_configuration.png new file mode 100644 index 000000000000..099a39e2a5ec Binary files /dev/null and b/docs/site/static/images/okta_7_support_configuration.png differ diff --git a/docs/site/static/images/okta_8_view_instructions.png b/docs/site/static/images/okta_8_view_instructions.png new file mode 100644 index 000000000000..31f2a23a20d7 Binary files /dev/null and b/docs/site/static/images/okta_8_view_instructions.png differ diff --git a/docs/site/static/images/okta_9_view_instructions.png b/docs/site/static/images/okta_9_view_instructions.png new file mode 100644 index 000000000000..40506799c849 Binary files /dev/null and b/docs/site/static/images/okta_9_view_instructions.png differ diff --git a/docs/site/static/images/onelogin_10_sso_certificate.png b/docs/site/static/images/onelogin_10_sso_certificate.png new file mode 100644 index 000000000000..94f3a6afca58 Binary files /dev/null and b/docs/site/static/images/onelogin_10_sso_certificate.png differ diff --git a/docs/site/static/images/onelogin_1_new_app.png b/docs/site/static/images/onelogin_1_new_app.png new file mode 100644 index 000000000000..e7ed77299abc Binary files /dev/null and b/docs/site/static/images/onelogin_1_new_app.png differ diff --git a/docs/site/static/images/onelogin_2_basic_configuration.png b/docs/site/static/images/onelogin_2_basic_configuration.png new file mode 100644 index 000000000000..a934f3de0741 Binary files /dev/null and b/docs/site/static/images/onelogin_2_basic_configuration.png differ diff --git a/docs/site/static/images/onelogin_3_configuration_1.png b/docs/site/static/images/onelogin_3_configuration_1.png new file mode 100644 index 000000000000..f3e3e6be3d7c Binary files /dev/null and b/docs/site/static/images/onelogin_3_configuration_1.png differ diff --git a/docs/site/static/images/onelogin_4_configuration_2.png b/docs/site/static/images/onelogin_4_configuration_2.png new file mode 100644 index 000000000000..d1339a91434e Binary files /dev/null and b/docs/site/static/images/onelogin_4_configuration_2.png differ diff --git a/docs/site/static/images/onelogin_5_parameters_add.png b/docs/site/static/images/onelogin_5_parameters_add.png new file mode 100644 index 000000000000..03474387b00c Binary files /dev/null and b/docs/site/static/images/onelogin_5_parameters_add.png differ diff --git a/docs/site/static/images/onelogin_6_parameters_add_2.png b/docs/site/static/images/onelogin_6_parameters_add_2.png new file mode 100644 index 000000000000..e7646133e8c0 Binary files /dev/null and b/docs/site/static/images/onelogin_6_parameters_add_2.png differ diff --git a/docs/site/static/images/onelogin_7_parameters_add_3.png b/docs/site/static/images/onelogin_7_parameters_add_3.png new file mode 100644 index 000000000000..81d779ff7aea Binary files /dev/null and b/docs/site/static/images/onelogin_7_parameters_add_3.png differ diff --git a/docs/site/static/images/onelogin_8_parameters_add_4.png b/docs/site/static/images/onelogin_8_parameters_add_4.png new file mode 100644 index 000000000000..b01f388d4fa9 Binary files /dev/null and b/docs/site/static/images/onelogin_8_parameters_add_4.png differ diff --git a/docs/site/static/images/onelogin_9_sso.png b/docs/site/static/images/onelogin_9_sso.png new file mode 100644 index 000000000000..3580a156178f Binary files /dev/null and b/docs/site/static/images/onelogin_9_sso.png differ diff --git a/docs/site/static/images/oracle/job-monitor.png b/docs/site/static/images/oracle/job-monitor.png new file mode 100644 index 000000000000..584b002e37cb Binary files /dev/null and b/docs/site/static/images/oracle/job-monitor.png differ diff --git a/docs/site/static/images/oracle/marketplace-listing.png b/docs/site/static/images/oracle/marketplace-listing.png new file mode 100644 index 000000000000..873adf728c2b Binary files /dev/null and b/docs/site/static/images/oracle/marketplace-listing.png differ diff --git a/docs/site/static/images/oracle/stack-info.png b/docs/site/static/images/oracle/stack-info.png new file mode 100644 index 000000000000..a6eb1409dc65 Binary files /dev/null and b/docs/site/static/images/oracle/stack-info.png differ diff --git a/docs/site/static/images/outgoing-webhook-created.png b/docs/site/static/images/outgoing-webhook-created.png new file mode 100644 index 000000000000..3bbf26f648d2 Binary files /dev/null and b/docs/site/static/images/outgoing-webhook-created.png differ diff --git a/docs/site/static/images/perf-1.png b/docs/site/static/images/perf-1.png new file mode 100644 index 000000000000..625f805bf8ab Binary files /dev/null and b/docs/site/static/images/perf-1.png differ diff --git a/docs/site/static/images/perf-2.png b/docs/site/static/images/perf-2.png new file mode 100644 index 000000000000..b34446f28c79 Binary files /dev/null and b/docs/site/static/images/perf-2.png differ diff --git a/docs/site/static/images/perf-3.png b/docs/site/static/images/perf-3.png new file mode 100644 index 000000000000..7817fd9ee12d Binary files /dev/null and b/docs/site/static/images/perf-3.png differ diff --git a/docs/site/static/images/perf-4.png b/docs/site/static/images/perf-4.png new file mode 100644 index 000000000000..69acc3865e9f Binary files /dev/null and b/docs/site/static/images/perf-4.png differ diff --git a/docs/site/static/images/perf-5.png b/docs/site/static/images/perf-5.png new file mode 100644 index 000000000000..f4133909adf2 Binary files /dev/null and b/docs/site/static/images/perf-5.png differ diff --git a/docs/site/static/images/perf-6.png b/docs/site/static/images/perf-6.png new file mode 100644 index 000000000000..ca96dec22e57 Binary files /dev/null and b/docs/site/static/images/perf-6.png differ diff --git a/docs/site/static/images/perf-7.png b/docs/site/static/images/perf-7.png new file mode 100644 index 000000000000..8ff3f1ae1165 Binary files /dev/null and b/docs/site/static/images/perf-7.png differ diff --git a/docs/site/static/images/perf-8.png b/docs/site/static/images/perf-8.png new file mode 100644 index 000000000000..25a1badd4504 Binary files /dev/null and b/docs/site/static/images/perf-8.png differ diff --git a/docs/site/static/images/perf-9-b.png b/docs/site/static/images/perf-9-b.png new file mode 100644 index 000000000000..69c45a627642 Binary files /dev/null and b/docs/site/static/images/perf-9-b.png differ diff --git a/docs/site/static/images/perf_monitoring_caching_metrics.png b/docs/site/static/images/perf_monitoring_caching_metrics.png new file mode 100644 index 000000000000..d634c8faf015 Binary files /dev/null and b/docs/site/static/images/perf_monitoring_caching_metrics.png differ diff --git a/docs/site/static/images/perf_monitoring_go_metrics.png b/docs/site/static/images/perf_monitoring_go_metrics.png new file mode 100644 index 000000000000..aff643d4fe39 Binary files /dev/null and b/docs/site/static/images/perf_monitoring_go_metrics.png differ diff --git a/docs/site/static/images/perf_monitoring_http_metrics.png b/docs/site/static/images/perf_monitoring_http_metrics.png new file mode 100644 index 000000000000..eed68b6db27e Binary files /dev/null and b/docs/site/static/images/perf_monitoring_http_metrics.png differ diff --git a/docs/site/static/images/perf_monitoring_messaging_metrics.png b/docs/site/static/images/perf_monitoring_messaging_metrics.png new file mode 100644 index 000000000000..ecbd889616c3 Binary files /dev/null and b/docs/site/static/images/perf_monitoring_messaging_metrics.png differ diff --git a/docs/site/static/images/perf_monitoring_system_console.png b/docs/site/static/images/perf_monitoring_system_console.png new file mode 100644 index 000000000000..b003c19d6cb7 Binary files /dev/null and b/docs/site/static/images/perf_monitoring_system_console.png differ diff --git a/docs/site/static/images/permalink-previews.png b/docs/site/static/images/permalink-previews.png new file mode 100644 index 000000000000..54cd3ab38f3b Binary files /dev/null and b/docs/site/static/images/permalink-previews.png differ diff --git a/docs/site/static/images/pin-message-to-channel.png b/docs/site/static/images/pin-message-to-channel.png new file mode 100644 index 000000000000..5475b5bd9683 Binary files /dev/null and b/docs/site/static/images/pin-message-to-channel.png differ diff --git a/docs/site/static/images/pinned-example-channel.png b/docs/site/static/images/pinned-example-channel.png new file mode 100644 index 000000000000..0c27a9f52045 Binary files /dev/null and b/docs/site/static/images/pinned-example-channel.png differ diff --git a/docs/site/static/images/pinned-example-rhs.png b/docs/site/static/images/pinned-example-rhs.png new file mode 100644 index 000000000000..84ec0f0f0a25 Binary files /dev/null and b/docs/site/static/images/pinned-example-rhs.png differ diff --git a/docs/site/static/images/pinned-posts.png b/docs/site/static/images/pinned-posts.png new file mode 100644 index 000000000000..2aa437b36246 Binary files /dev/null and b/docs/site/static/images/pinned-posts.png differ diff --git a/docs/site/static/images/playbook-attribute-actions.png b/docs/site/static/images/playbook-attribute-actions.png new file mode 100644 index 000000000000..8af61c771687 Binary files /dev/null and b/docs/site/static/images/playbook-attribute-actions.png differ diff --git a/docs/site/static/images/playbook-attributes-create-first.png b/docs/site/static/images/playbook-attributes-create-first.png new file mode 100644 index 000000000000..03bf72bec9ad Binary files /dev/null and b/docs/site/static/images/playbook-attributes-create-first.png differ diff --git a/docs/site/static/images/playbook-attributes-create-second.png b/docs/site/static/images/playbook-attributes-create-second.png new file mode 100644 index 000000000000..3e220a6335cd Binary files /dev/null and b/docs/site/static/images/playbook-attributes-create-second.png differ diff --git a/docs/site/static/images/playbook-conditions-add.png b/docs/site/static/images/playbook-conditions-add.png new file mode 100644 index 000000000000..a9a401b749a9 Binary files /dev/null and b/docs/site/static/images/playbook-conditions-add.png differ diff --git a/docs/site/static/images/playbook-conditions-values.png b/docs/site/static/images/playbook-conditions-values.png new file mode 100644 index 000000000000..a142e5c84883 Binary files /dev/null and b/docs/site/static/images/playbook-conditions-values.png differ diff --git a/docs/site/static/images/playbook-metrics.png b/docs/site/static/images/playbook-metrics.png new file mode 100644 index 000000000000..46efb62c547b Binary files /dev/null and b/docs/site/static/images/playbook-metrics.png differ diff --git a/docs/site/static/images/playbooks.png b/docs/site/static/images/playbooks.png new file mode 100644 index 000000000000..13263e4fc851 Binary files /dev/null and b/docs/site/static/images/playbooks.png differ diff --git a/docs/site/static/images/private-channel-create.jpg b/docs/site/static/images/private-channel-create.jpg new file mode 100644 index 000000000000..011fecb6ecf7 Binary files /dev/null and b/docs/site/static/images/private-channel-create.jpg differ diff --git a/docs/site/static/images/private-link-architecture.png b/docs/site/static/images/private-link-architecture.png new file mode 100644 index 000000000000..fc334c632b59 Binary files /dev/null and b/docs/site/static/images/private-link-architecture.png differ diff --git a/docs/site/static/images/product-menu-integrations.png b/docs/site/static/images/product-menu-integrations.png new file mode 100644 index 000000000000..89ced9e5fdff Binary files /dev/null and b/docs/site/static/images/product-menu-integrations.png differ diff --git a/docs/site/static/images/profile-log-out.png b/docs/site/static/images/profile-log-out.png new file mode 100644 index 000000000000..94be4c43cb77 Binary files /dev/null and b/docs/site/static/images/profile-log-out.png differ diff --git a/docs/site/static/images/push-notification-stats.png b/docs/site/static/images/push-notification-stats.png new file mode 100644 index 000000000000..07c74eceb3f2 Binary files /dev/null and b/docs/site/static/images/push-notification-stats.png differ diff --git a/docs/site/static/images/push-notifications-not-sent-distribution.png b/docs/site/static/images/push-notifications-not-sent-distribution.png new file mode 100644 index 000000000000..b5aaabe82426 Binary files /dev/null and b/docs/site/static/images/push-notifications-not-sent-distribution.png differ diff --git a/docs/site/static/images/push-proxy-delivery-rate.png b/docs/site/static/images/push-proxy-delivery-rate.png new file mode 100644 index 000000000000..7e4c1ef10535 Binary files /dev/null and b/docs/site/static/images/push-proxy-delivery-rate.png differ diff --git a/docs/site/static/images/read-write-storage-performance.png b/docs/site/static/images/read-write-storage-performance.png new file mode 100644 index 000000000000..d3f752658bbf Binary files /dev/null and b/docs/site/static/images/read-write-storage-performance.png differ diff --git a/docs/site/static/images/recent-emojis.png b/docs/site/static/images/recent-emojis.png new file mode 100644 index 000000000000..66706fcc1141 Binary files /dev/null and b/docs/site/static/images/recent-emojis.png differ diff --git a/docs/site/static/images/recent-mentions.png b/docs/site/static/images/recent-mentions.png new file mode 100644 index 000000000000..4ee16180db14 Binary files /dev/null and b/docs/site/static/images/recent-mentions.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident1.png b/docs/site/static/images/recipe/prod-vuln-incident1.png new file mode 100644 index 000000000000..4199993cf0c6 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident1.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident10.png b/docs/site/static/images/recipe/prod-vuln-incident10.png new file mode 100644 index 000000000000..e1d6b6cb2002 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident10.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident2.png b/docs/site/static/images/recipe/prod-vuln-incident2.png new file mode 100644 index 000000000000..ee17338f54bb Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident2.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident3.png b/docs/site/static/images/recipe/prod-vuln-incident3.png new file mode 100644 index 000000000000..be688ba27a7b Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident3.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident4.png b/docs/site/static/images/recipe/prod-vuln-incident4.png new file mode 100644 index 000000000000..2aba0f94f8a2 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident4.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident5.png b/docs/site/static/images/recipe/prod-vuln-incident5.png new file mode 100644 index 000000000000..2e97c4842ab2 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident5.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident6.png b/docs/site/static/images/recipe/prod-vuln-incident6.png new file mode 100644 index 000000000000..15931a273965 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident6.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident7.png b/docs/site/static/images/recipe/prod-vuln-incident7.png new file mode 100644 index 000000000000..9a9e692076b9 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident7.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident8.png b/docs/site/static/images/recipe/prod-vuln-incident8.png new file mode 100644 index 000000000000..a6c7b6aa9e69 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident8.png differ diff --git a/docs/site/static/images/recipe/prod-vuln-incident9.png b/docs/site/static/images/recipe/prod-vuln-incident9.png new file mode 100644 index 000000000000..fdd01834b1c7 Binary files /dev/null and b/docs/site/static/images/recipe/prod-vuln-incident9.png differ diff --git a/docs/site/static/images/register-azure-app.png b/docs/site/static/images/register-azure-app.png new file mode 100644 index 000000000000..73945b59fda8 Binary files /dev/null and b/docs/site/static/images/register-azure-app.png differ diff --git a/docs/site/static/images/remember-client-secret.png b/docs/site/static/images/remember-client-secret.png new file mode 100644 index 000000000000..2a77cb3d0f4b Binary files /dev/null and b/docs/site/static/images/remember-client-secret.png differ diff --git a/docs/site/static/images/remember-tenant-client.png b/docs/site/static/images/remember-tenant-client.png new file mode 100644 index 000000000000..161084f3d57a Binary files /dev/null and b/docs/site/static/images/remember-tenant-client.png differ diff --git a/docs/site/static/images/remove-from-saved-posts.png b/docs/site/static/images/remove-from-saved-posts.png new file mode 100644 index 000000000000..91d27d31b5d6 Binary files /dev/null and b/docs/site/static/images/remove-from-saved-posts.png differ diff --git a/docs/site/static/images/remove-member-from-channel.png b/docs/site/static/images/remove-member-from-channel.png new file mode 100644 index 000000000000..4fa61d3395cd Binary files /dev/null and b/docs/site/static/images/remove-member-from-channel.png differ diff --git a/docs/site/static/images/remove-members-from-a-channel.png b/docs/site/static/images/remove-members-from-a-channel.png new file mode 100644 index 000000000000..d3aa6cd2f5b6 Binary files /dev/null and b/docs/site/static/images/remove-members-from-a-channel.png differ diff --git a/docs/site/static/images/remove-members-from-a-team.png b/docs/site/static/images/remove-members-from-a-team.png new file mode 100644 index 000000000000..65658904c7f3 Binary files /dev/null and b/docs/site/static/images/remove-members-from-a-team.png differ diff --git a/docs/site/static/images/remove-user-from-team.png b/docs/site/static/images/remove-user-from-team.png new file mode 100644 index 000000000000..81a473f33df2 Binary files /dev/null and b/docs/site/static/images/remove-user-from-team.png differ diff --git a/docs/site/static/images/reply-to-message.png b/docs/site/static/images/reply-to-message.png new file mode 100644 index 000000000000..1ced74fd9247 Binary files /dev/null and b/docs/site/static/images/reply-to-message.png differ diff --git a/docs/site/static/images/restore-an-archived-playbook.gif b/docs/site/static/images/restore-an-archived-playbook.gif new file mode 100644 index 000000000000..714e4851a2fc Binary files /dev/null and b/docs/site/static/images/restore-an-archived-playbook.gif differ diff --git a/docs/site/static/images/restore-previous-edited-message.gif b/docs/site/static/images/restore-previous-edited-message.gif new file mode 100644 index 000000000000..d461aaee1d74 Binary files /dev/null and b/docs/site/static/images/restore-previous-edited-message.gif differ diff --git a/docs/site/static/images/restrict-role-access.png b/docs/site/static/images/restrict-role-access.png new file mode 100644 index 000000000000..9d7244553770 Binary files /dev/null and b/docs/site/static/images/restrict-role-access.png differ diff --git a/docs/site/static/images/revoke-user-session.png b/docs/site/static/images/revoke-user-session.png new file mode 100644 index 000000000000..4e0abedef41d Binary files /dev/null and b/docs/site/static/images/revoke-user-session.png differ diff --git a/docs/site/static/images/save-message.png b/docs/site/static/images/save-message.png new file mode 100644 index 000000000000..610635b877b0 Binary files /dev/null and b/docs/site/static/images/save-message.png differ diff --git a/docs/site/static/images/schedule-a-message.png b/docs/site/static/images/schedule-a-message.png new file mode 100644 index 000000000000..1116354d29c7 Binary files /dev/null and b/docs/site/static/images/schedule-a-message.png differ diff --git a/docs/site/static/images/search-all-teams.png b/docs/site/static/images/search-all-teams.png new file mode 100644 index 000000000000..d2bb04523816 Binary files /dev/null and b/docs/site/static/images/search-all-teams.png differ diff --git a/docs/site/static/images/search-files.png b/docs/site/static/images/search-files.png new file mode 100644 index 000000000000..a7820210a946 Binary files /dev/null and b/docs/site/static/images/search-files.png differ diff --git a/docs/site/static/images/search-messages-expanded.png b/docs/site/static/images/search-messages-expanded.png new file mode 100644 index 000000000000..611d777a3573 Binary files /dev/null and b/docs/site/static/images/search-messages-expanded.png differ diff --git a/docs/site/static/images/search-messages.png b/docs/site/static/images/search-messages.png new file mode 100644 index 000000000000..c37fd10115c8 Binary files /dev/null and b/docs/site/static/images/search-messages.png differ diff --git a/docs/site/static/images/secure-out-of-band.png b/docs/site/static/images/secure-out-of-band.png new file mode 100644 index 000000000000..f0b2dba9f630 Binary files /dev/null and b/docs/site/static/images/secure-out-of-band.png differ diff --git a/docs/site/static/images/select-add-incoming-webhook.png b/docs/site/static/images/select-add-incoming-webhook.png new file mode 100644 index 000000000000..c811fe1f706e Binary files /dev/null and b/docs/site/static/images/select-add-incoming-webhook.png differ diff --git a/docs/site/static/images/select-add-outgoing-webhook.png b/docs/site/static/images/select-add-outgoing-webhook.png new file mode 100644 index 000000000000..c24309d0797d Binary files /dev/null and b/docs/site/static/images/select-add-outgoing-webhook.png differ diff --git a/docs/site/static/images/select-google-sso-web-app.png b/docs/site/static/images/select-google-sso-web-app.png new file mode 100644 index 000000000000..9b59702dad61 Binary files /dev/null and b/docs/site/static/images/select-google-sso-web-app.png differ diff --git a/docs/site/static/images/select-manage-apps.png b/docs/site/static/images/select-manage-apps.png new file mode 100644 index 000000000000..02233284f684 Binary files /dev/null and b/docs/site/static/images/select-manage-apps.png differ diff --git a/docs/site/static/images/server-logout-indicator.png b/docs/site/static/images/server-logout-indicator.png new file mode 100644 index 000000000000..331dc6c8c181 Binary files /dev/null and b/docs/site/static/images/server-logout-indicator.png differ diff --git a/docs/site/static/images/set-a-channel-to-public-or-private.png b/docs/site/static/images/set-a-channel-to-public-or-private.png new file mode 100644 index 000000000000..477311d2acc1 Binary files /dev/null and b/docs/site/static/images/set-a-channel-to-public-or-private.png differ diff --git a/docs/site/static/images/set-your-availability-dnd.png b/docs/site/static/images/set-your-availability-dnd.png new file mode 100644 index 000000000000..ad6419d93fb9 Binary files /dev/null and b/docs/site/static/images/set-your-availability-dnd.png differ diff --git a/docs/site/static/images/sign-in-entraid.png b/docs/site/static/images/sign-in-entraid.png new file mode 100644 index 000000000000..266f0825cf9e Binary files /dev/null and b/docs/site/static/images/sign-in-entraid.png differ diff --git a/docs/site/static/images/sort-categories.gif b/docs/site/static/images/sort-categories.gif new file mode 100644 index 000000000000..72a384b5cb68 Binary files /dev/null and b/docs/site/static/images/sort-categories.gif differ diff --git a/docs/site/static/images/source-available-license.png b/docs/site/static/images/source-available-license.png new file mode 100644 index 000000000000..4c0c10bb933d Binary files /dev/null and b/docs/site/static/images/source-available-license.png differ diff --git a/docs/site/static/images/specific-email-domains-can-join-a-team.png b/docs/site/static/images/specific-email-domains-can-join-a-team.png new file mode 100644 index 000000000000..ae4755982d0e Binary files /dev/null and b/docs/site/static/images/specific-email-domains-can-join-a-team.png differ diff --git a/docs/site/static/images/start-group-conversation.jpg b/docs/site/static/images/start-group-conversation.jpg new file mode 100644 index 000000000000..39da1cef02e2 Binary files /dev/null and b/docs/site/static/images/start-group-conversation.jpg differ diff --git a/docs/site/static/images/survey-contents.png b/docs/site/static/images/survey-contents.png new file mode 100644 index 000000000000..83d765b43abe Binary files /dev/null and b/docs/site/static/images/survey-contents.png differ diff --git a/docs/site/static/images/survey-schedule.png b/docs/site/static/images/survey-schedule.png new file mode 100644 index 000000000000..7a8ba8a44567 Binary files /dev/null and b/docs/site/static/images/survey-schedule.png differ diff --git a/docs/site/static/images/switch-channels.png b/docs/site/static/images/switch-channels.png new file mode 100644 index 000000000000..07628c9ebb67 Binary files /dev/null and b/docs/site/static/images/switch-channels.png differ diff --git a/docs/site/static/images/sync-group-members-in-a-channel.png b/docs/site/static/images/sync-group-members-in-a-channel.png new file mode 100644 index 000000000000..72c00ea852cc Binary files /dev/null and b/docs/site/static/images/sync-group-members-in-a-channel.png differ diff --git a/docs/site/static/images/sync-group-members-in-a-team.png b/docs/site/static/images/sync-group-members-in-a-team.png new file mode 100644 index 000000000000..341220f21dd5 Binary files /dev/null and b/docs/site/static/images/sync-group-members-in-a-team.png differ diff --git a/docs/site/static/images/syntax-highlighting-github.png b/docs/site/static/images/syntax-highlighting-github.png new file mode 100644 index 000000000000..d87ce9594919 Binary files /dev/null and b/docs/site/static/images/syntax-highlighting-github.png differ diff --git a/docs/site/static/images/syntax-highlighting-monokai.png b/docs/site/static/images/syntax-highlighting-monokai.png new file mode 100644 index 000000000000..8ccfe656a813 Binary files /dev/null and b/docs/site/static/images/syntax-highlighting-monokai.png differ diff --git a/docs/site/static/images/syntax-highlighting-sol-dark.png b/docs/site/static/images/syntax-highlighting-sol-dark.png new file mode 100644 index 000000000000..6bedfd11b748 Binary files /dev/null and b/docs/site/static/images/syntax-highlighting-sol-dark.png differ diff --git a/docs/site/static/images/syntax-highlighting-sol-light.png b/docs/site/static/images/syntax-highlighting-sol-light.png new file mode 100644 index 000000000000..30b69d559a7f Binary files /dev/null and b/docs/site/static/images/syntax-highlighting-sol-light.png differ diff --git a/docs/site/static/images/system-console-commercial-support.png b/docs/site/static/images/system-console-commercial-support.png new file mode 100644 index 000000000000..0f66b0df2d87 Binary files /dev/null and b/docs/site/static/images/system-console-commercial-support.png differ diff --git a/docs/site/static/images/system-console-ip-filtering.png b/docs/site/static/images/system-console-ip-filtering.png new file mode 100644 index 000000000000..9f5870f0b2c5 Binary files /dev/null and b/docs/site/static/images/system-console-ip-filtering.png differ diff --git a/docs/site/static/images/system-scheme.png b/docs/site/static/images/system-scheme.png new file mode 100644 index 000000000000..06081f37d2f6 Binary files /dev/null and b/docs/site/static/images/system-scheme.png differ diff --git a/docs/site/static/images/task-actions.png b/docs/site/static/images/task-actions.png new file mode 100644 index 000000000000..066cb5f10467 Binary files /dev/null and b/docs/site/static/images/task-actions.png differ diff --git a/docs/site/static/images/team-configuration-details.png b/docs/site/static/images/team-configuration-details.png new file mode 100644 index 000000000000..6ebe33144e7a Binary files /dev/null and b/docs/site/static/images/team-configuration-details.png differ diff --git a/docs/site/static/images/team-scheme.png b/docs/site/static/images/team-scheme.png new file mode 100644 index 000000000000..acbb069145f0 Binary files /dev/null and b/docs/site/static/images/team-scheme.png differ diff --git a/docs/site/static/images/team-search-filters.png b/docs/site/static/images/team-search-filters.png new file mode 100644 index 000000000000..3cc53054f800 Binary files /dev/null and b/docs/site/static/images/team-search-filters.png differ diff --git a/docs/site/static/images/team-settings.png b/docs/site/static/images/team-settings.png new file mode 100644 index 000000000000..b9c8789674e3 Binary files /dev/null and b/docs/site/static/images/team-settings.png differ diff --git a/docs/site/static/images/teams.gif b/docs/site/static/images/teams.gif new file mode 100644 index 000000000000..1accf44b059d Binary files /dev/null and b/docs/site/static/images/teams.gif differ diff --git a/docs/site/static/images/teams_plugin_notification_settings.png b/docs/site/static/images/teams_plugin_notification_settings.png new file mode 100644 index 000000000000..3de5d3e7d0ed Binary files /dev/null and b/docs/site/static/images/teams_plugin_notification_settings.png differ diff --git a/docs/site/static/images/tenant-client-secret-sysconsole.png b/docs/site/static/images/tenant-client-secret-sysconsole.png new file mode 100644 index 000000000000..94020242bc83 Binary files /dev/null and b/docs/site/static/images/tenant-client-secret-sysconsole.png differ diff --git a/docs/site/static/images/total-acked-push-notifications.png b/docs/site/static/images/total-acked-push-notifications.png new file mode 100644 index 000000000000..7107005e9472 Binary files /dev/null and b/docs/site/static/images/total-acked-push-notifications.png differ diff --git a/docs/site/static/images/transport-encryption.png b/docs/site/static/images/transport-encryption.png new file mode 100644 index 000000000000..74c352eaa258 Binary files /dev/null and b/docs/site/static/images/transport-encryption.png differ diff --git a/docs/site/static/images/true-up-schedule.png b/docs/site/static/images/true-up-schedule.png new file mode 100644 index 000000000000..dbe8e54c7a2c Binary files /dev/null and b/docs/site/static/images/true-up-schedule.png differ diff --git a/docs/site/static/images/unarchive-channel.png b/docs/site/static/images/unarchive-channel.png new file mode 100644 index 000000000000..7d6b661aa2af Binary files /dev/null and b/docs/site/static/images/unarchive-channel.png differ diff --git a/docs/site/static/images/unpin-message-from-channel.png b/docs/site/static/images/unpin-message-from-channel.png new file mode 100644 index 000000000000..c179211e6123 Binary files /dev/null and b/docs/site/static/images/unpin-message-from-channel.png differ diff --git a/docs/site/static/images/unreads.gif b/docs/site/static/images/unreads.gif new file mode 100644 index 000000000000..20d7fda3ee55 Binary files /dev/null and b/docs/site/static/images/unreads.gif differ diff --git a/docs/site/static/images/urgent-message.png b/docs/site/static/images/urgent-message.png new file mode 100644 index 000000000000..39095c2c7e37 Binary files /dev/null and b/docs/site/static/images/urgent-message.png differ diff --git a/docs/site/static/images/user-email-update.png b/docs/site/static/images/user-email-update.png new file mode 100644 index 000000000000..ac2b710c6be5 Binary files /dev/null and b/docs/site/static/images/user-email-update.png differ diff --git a/docs/site/static/images/user-feedback.png b/docs/site/static/images/user-feedback.png new file mode 100644 index 000000000000..ef9e81023117 Binary files /dev/null and b/docs/site/static/images/user-feedback.png differ diff --git a/docs/site/static/images/user-id.png b/docs/site/static/images/user-id.png new file mode 100644 index 000000000000..4c273f9847a6 Binary files /dev/null and b/docs/site/static/images/user-id.png differ diff --git a/docs/site/static/images/user-password-reset.png b/docs/site/static/images/user-password-reset.png new file mode 100644 index 000000000000..b0040932eb8b Binary files /dev/null and b/docs/site/static/images/user-password-reset.png differ diff --git a/docs/site/static/images/user-profile-details.png b/docs/site/static/images/user-profile-details.png new file mode 100644 index 000000000000..4c273f9847a6 Binary files /dev/null and b/docs/site/static/images/user-profile-details.png differ diff --git a/docs/site/static/images/user-search-filters.png b/docs/site/static/images/user-search-filters.png new file mode 100644 index 000000000000..de4a748928f9 Binary files /dev/null and b/docs/site/static/images/user-search-filters.png differ diff --git a/docs/site/static/images/web-desktop-invite-people-to-the-team.png b/docs/site/static/images/web-desktop-invite-people-to-the-team.png new file mode 100644 index 000000000000..8a7ecca8d180 Binary files /dev/null and b/docs/site/static/images/web-desktop-invite-people-to-the-team.png differ diff --git a/docs/site/static/images/webhooksTable.png b/docs/site/static/images/webhooksTable.png new file mode 100644 index 000000000000..a0709cfb84c4 Binary files /dev/null and b/docs/site/static/images/webhooksTable.png differ diff --git a/docs/site/static/images/workspace-optimization.png b/docs/site/static/images/workspace-optimization.png new file mode 100644 index 000000000000..d735ce93ce19 Binary files /dev/null and b/docs/site/static/images/workspace-optimization.png differ diff --git a/docs/site/static/images/write-dm.png b/docs/site/static/images/write-dm.png new file mode 100644 index 000000000000..54c50f070c60 Binary files /dev/null and b/docs/site/static/images/write-dm.png differ diff --git a/docs/site/static/img/badges/academy-callout.jpg b/docs/site/static/img/badges/academy-callout.jpg new file mode 100644 index 000000000000..8c6323df18dc Binary files /dev/null and b/docs/site/static/img/badges/academy-callout.jpg differ diff --git a/docs/site/static/img/badges/deployment-yellow.svg b/docs/site/static/img/badges/deployment-yellow.svg new file mode 100644 index 000000000000..511a5d9c88da --- /dev/null +++ b/docs/site/static/img/badges/deployment-yellow.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/site/static/img/badges/deployment.svg b/docs/site/static/img/badges/deployment.svg new file mode 100644 index 000000000000..1a37dff3d7a8 --- /dev/null +++ b/docs/site/static/img/badges/deployment.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/site/static/img/badges/flag-yellow.svg b/docs/site/static/img/badges/flag-yellow.svg new file mode 100644 index 000000000000..b08372047f18 --- /dev/null +++ b/docs/site/static/img/badges/flag-yellow.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/site/static/img/badges/flag.svg b/docs/site/static/img/badges/flag.svg new file mode 100644 index 000000000000..c9ac1117fa12 --- /dev/null +++ b/docs/site/static/img/badges/flag.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/site/static/img/brand/icon-denim.svg b/docs/site/static/img/brand/icon-denim.svg new file mode 100644 index 000000000000..d185ef27da72 --- /dev/null +++ b/docs/site/static/img/brand/icon-denim.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/brand/icon-white.svg b/docs/site/static/img/brand/icon-white.svg new file mode 100644 index 000000000000..9afe78433815 --- /dev/null +++ b/docs/site/static/img/brand/icon-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/brand/logo-horizontal-denim.svg b/docs/site/static/img/brand/logo-horizontal-denim.svg new file mode 100644 index 000000000000..3e6dc0f35434 --- /dev/null +++ b/docs/site/static/img/brand/logo-horizontal-denim.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/brand/logo-horizontal-white.svg b/docs/site/static/img/brand/logo-horizontal-white.svg new file mode 100644 index 000000000000..0297836d1c21 --- /dev/null +++ b/docs/site/static/img/brand/logo-horizontal-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/patterns/hex-camo-denim.svg b/docs/site/static/img/patterns/hex-camo-denim.svg new file mode 100644 index 000000000000..49958ae6a8b7 --- /dev/null +++ b/docs/site/static/img/patterns/hex-camo-denim.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/site/static/img/ui/Ack-Button-Default.svg b/docs/site/static/img/ui/Ack-Button-Default.svg new file mode 100644 index 000000000000..4aac532d6c6f --- /dev/null +++ b/docs/site/static/img/ui/Ack-Button-Default.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/site/static/img/ui/account-plus-outline_F0801.svg b/docs/site/static/img/ui/account-plus-outline_F0801.svg new file mode 100644 index 000000000000..0496bdfdb021 --- /dev/null +++ b/docs/site/static/img/ui/account-plus-outline_F0801.svg @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/alert-circle-outline_F05D6.svg b/docs/site/static/img/ui/alert-circle-outline_F05D6.svg new file mode 100644 index 000000000000..3d7c5027b9d5 --- /dev/null +++ b/docs/site/static/img/ui/alert-circle-outline_F05D6.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/archive-outline_F120E.svg b/docs/site/static/img/ui/archive-outline_F120E.svg new file mode 100644 index 000000000000..7458d7367fd1 --- /dev/null +++ b/docs/site/static/img/ui/archive-outline_F120E.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/arrow-down-bold-circle-outline_F0048.svg b/docs/site/static/img/ui/arrow-down-bold-circle-outline_F0048.svg new file mode 100644 index 000000000000..fd3167381be0 --- /dev/null +++ b/docs/site/static/img/ui/arrow-down-bold-circle-outline_F0048.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/away.png b/docs/site/static/img/ui/away.png new file mode 100644 index 000000000000..10ac04ae3240 Binary files /dev/null and b/docs/site/static/img/ui/away.png differ diff --git a/docs/site/static/img/ui/bookmark-outline_F00C3.svg b/docs/site/static/img/ui/bookmark-outline_F00C3.svg new file mode 100644 index 000000000000..916110e8375f --- /dev/null +++ b/docs/site/static/img/ui/bookmark-outline_F00C3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/bookmark_F00C0.svg b/docs/site/static/img/ui/bookmark_F00C0.svg new file mode 100644 index 000000000000..5d6a305f3ae0 --- /dev/null +++ b/docs/site/static/img/ui/bookmark_F00C0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/checkmark.svg b/docs/site/static/img/ui/checkmark.svg new file mode 100644 index 000000000000..d6de25ee9738 --- /dev/null +++ b/docs/site/static/img/ui/checkmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/site/static/img/ui/circle-multiple-outline_F0695.svg b/docs/site/static/img/ui/circle-multiple-outline_F0695.svg new file mode 100644 index 000000000000..a537e2348786 --- /dev/null +++ b/docs/site/static/img/ui/circle-multiple-outline_F0695.svg @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/code-tags_F0174.svg b/docs/site/static/img/ui/code-tags_F0174.svg new file mode 100644 index 000000000000..25fa0ffca569 --- /dev/null +++ b/docs/site/static/img/ui/code-tags_F0174.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/creation-outline_F1C2B.svg b/docs/site/static/img/ui/creation-outline_F1C2B.svg new file mode 100644 index 000000000000..6cf8773ef79a --- /dev/null +++ b/docs/site/static/img/ui/creation-outline_F1C2B.svg @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/docs/site/static/img/ui/dnd.png b/docs/site/static/img/ui/dnd.png new file mode 100644 index 000000000000..cef7ab7b40df Binary files /dev/null and b/docs/site/static/img/ui/dnd.png differ diff --git a/docs/site/static/img/ui/dock-window_F10AC.svg b/docs/site/static/img/ui/dock-window_F10AC.svg new file mode 100644 index 000000000000..15be877bea6d --- /dev/null +++ b/docs/site/static/img/ui/dock-window_F10AC.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/dots-horizontal_F01D8.svg b/docs/site/static/img/ui/dots-horizontal_F01D8.svg new file mode 100644 index 000000000000..35e5a0ab66ca --- /dev/null +++ b/docs/site/static/img/ui/dots-horizontal_F01D8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/dots-vertical_F01D9.svg b/docs/site/static/img/ui/dots-vertical_F01D9.svg new file mode 100644 index 000000000000..e065db6dc0eb --- /dev/null +++ b/docs/site/static/img/ui/dots-vertical_F01D9.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/download-outline_F0B8F.svg b/docs/site/static/img/ui/download-outline_F0B8F.svg new file mode 100644 index 000000000000..105503e2cb21 --- /dev/null +++ b/docs/site/static/img/ui/download-outline_F0B8F.svg @@ -0,0 +1 @@ + diff --git a/docs/site/static/img/ui/edit-on-github.png b/docs/site/static/img/ui/edit-on-github.png new file mode 100644 index 000000000000..15ccc31b8931 Binary files /dev/null and b/docs/site/static/img/ui/edit-on-github.png differ diff --git a/docs/site/static/img/ui/emoticon-outline_F01F2.svg b/docs/site/static/img/ui/emoticon-outline_F01F2.svg new file mode 100644 index 000000000000..7467bf255c18 --- /dev/null +++ b/docs/site/static/img/ui/emoticon-outline_F01F2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/emoticon-plus-outline_E80F.svg b/docs/site/static/img/ui/emoticon-plus-outline_E80F.svg new file mode 100644 index 000000000000..9ac989dec6f9 --- /dev/null +++ b/docs/site/static/img/ui/emoticon-plus-outline_E80F.svg @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/eye-outline_F06D0.svg b/docs/site/static/img/ui/eye-outline_F06D0.svg new file mode 100644 index 000000000000..63bcb4365bd8 --- /dev/null +++ b/docs/site/static/img/ui/eye-outline_F06D0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/file-text-outline_F09EE.svg b/docs/site/static/img/ui/file-text-outline_F09EE.svg new file mode 100644 index 000000000000..90831cba83cc --- /dev/null +++ b/docs/site/static/img/ui/file-text-outline_F09EE.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/fire_F0238.svg b/docs/site/static/img/ui/fire_F0238.svg new file mode 100644 index 000000000000..79c2ee704000 --- /dev/null +++ b/docs/site/static/img/ui/fire_F0238.svg @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-bold_F0264.svg b/docs/site/static/img/ui/format-bold_F0264.svg new file mode 100644 index 000000000000..e48e37cae64a --- /dev/null +++ b/docs/site/static/img/ui/format-bold_F0264.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-header_E81D.svg b/docs/site/static/img/ui/format-header_E81D.svg new file mode 100644 index 000000000000..86c24314ac64 --- /dev/null +++ b/docs/site/static/img/ui/format-header_E81D.svg @@ -0,0 +1 @@ + diff --git a/docs/site/static/img/ui/format-italic_F0277.svg b/docs/site/static/img/ui/format-italic_F0277.svg new file mode 100644 index 000000000000..1d91b84f91e7 --- /dev/null +++ b/docs/site/static/img/ui/format-italic_F0277.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-letter-case_F0B34.svg b/docs/site/static/img/ui/format-letter-case_F0B34.svg new file mode 100644 index 000000000000..f47e69fa48a1 --- /dev/null +++ b/docs/site/static/img/ui/format-letter-case_F0B34.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-list-bulleted_F0279.svg b/docs/site/static/img/ui/format-list-bulleted_F0279.svg new file mode 100644 index 000000000000..3eb8f96f9f6e --- /dev/null +++ b/docs/site/static/img/ui/format-list-bulleted_F0279.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-list-numbered_F027B.svg b/docs/site/static/img/ui/format-list-numbered_F027B.svg new file mode 100644 index 000000000000..1b11dd8b7b0d --- /dev/null +++ b/docs/site/static/img/ui/format-list-numbered_F027B.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-quote-open_F0757.svg b/docs/site/static/img/ui/format-quote-open_F0757.svg new file mode 100644 index 000000000000..13d990ec3619 --- /dev/null +++ b/docs/site/static/img/ui/format-quote-open_F0757.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/format-strikethrough-variant_F0281.svg b/docs/site/static/img/ui/format-strikethrough-variant_F0281.svg new file mode 100644 index 000000000000..4dceffe637fb --- /dev/null +++ b/docs/site/static/img/ui/format-strikethrough-variant_F0281.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/globe_E805.svg b/docs/site/static/img/ui/globe_E805.svg new file mode 100644 index 000000000000..b3d1b4bfd2a8 --- /dev/null +++ b/docs/site/static/img/ui/globe_E805.svg @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/information-outline_F02FD.svg b/docs/site/static/img/ui/information-outline_F02FD.svg new file mode 100644 index 000000000000..224f2b947c45 --- /dev/null +++ b/docs/site/static/img/ui/information-outline_F02FD.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/link-variant_F0339.svg b/docs/site/static/img/ui/link-variant_F0339.svg new file mode 100644 index 000000000000..51f81d5a2dcb --- /dev/null +++ b/docs/site/static/img/ui/link-variant_F0339.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/lock-outline_F0341.svg b/docs/site/static/img/ui/lock-outline_F0341.svg new file mode 100644 index 000000000000..5b7fa8a04f7e --- /dev/null +++ b/docs/site/static/img/ui/lock-outline_F0341.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/magnify_F0349.svg b/docs/site/static/img/ui/magnify_F0349.svg new file mode 100644 index 000000000000..ba8c0a069373 --- /dev/null +++ b/docs/site/static/img/ui/magnify_F0349.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/offline.png b/docs/site/static/img/ui/offline.png new file mode 100644 index 000000000000..07458cef0d5a Binary files /dev/null and b/docs/site/static/img/ui/offline.png differ diff --git a/docs/site/static/img/ui/online.png b/docs/site/static/img/ui/online.png new file mode 100644 index 000000000000..1f0d8fd5eeb7 Binary files /dev/null and b/docs/site/static/img/ui/online.png differ diff --git a/docs/site/static/img/ui/paperclip_F03E2.svg b/docs/site/static/img/ui/paperclip_F03E2.svg new file mode 100644 index 000000000000..a29426c96eab --- /dev/null +++ b/docs/site/static/img/ui/paperclip_F03E2.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/pencil-outline_F0CB6.svg b/docs/site/static/img/ui/pencil-outline_F0CB6.svg new file mode 100644 index 000000000000..772c9d580dff --- /dev/null +++ b/docs/site/static/img/ui/pencil-outline_F0CB6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/pin-outline_F0931.svg b/docs/site/static/img/ui/pin-outline_F0931.svg new file mode 100644 index 000000000000..7db5b089cfb3 --- /dev/null +++ b/docs/site/static/img/ui/pin-outline_F0931.svg @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/plus_F0415.svg b/docs/site/static/img/ui/plus_F0415.svg new file mode 100644 index 000000000000..2c2183906192 --- /dev/null +++ b/docs/site/static/img/ui/plus_F0415.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/products_E82F.svg b/docs/site/static/img/ui/products_E82F.svg new file mode 100644 index 000000000000..9c3e93b215a3 --- /dev/null +++ b/docs/site/static/img/ui/products_E82F.svg @@ -0,0 +1 @@ + diff --git a/docs/site/static/img/ui/reply-outline_F0F20.svg b/docs/site/static/img/ui/reply-outline_F0F20.svg new file mode 100644 index 000000000000..1deaf42a05c4 --- /dev/null +++ b/docs/site/static/img/ui/reply-outline_F0F20.svg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/restore_F099B.svg b/docs/site/static/img/ui/restore_F099B.svg new file mode 100644 index 000000000000..c039fd4dd9de --- /dev/null +++ b/docs/site/static/img/ui/restore_F099B.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/schedule-count-red-badge.png b/docs/site/static/img/ui/schedule-count-red-badge.png new file mode 100644 index 000000000000..4cffded4a66f Binary files /dev/null and b/docs/site/static/img/ui/schedule-count-red-badge.png differ diff --git a/docs/site/static/img/ui/send_F048A.svg b/docs/site/static/img/ui/send_F048A.svg new file mode 100644 index 000000000000..eefce2fb64bb --- /dev/null +++ b/docs/site/static/img/ui/send_F048A.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/server-variant_E81F.svg b/docs/site/static/img/ui/server-variant_E81F.svg new file mode 100644 index 000000000000..6f0bba60c99e --- /dev/null +++ b/docs/site/static/img/ui/server-variant_E81F.svg @@ -0,0 +1,5 @@ + + + diff --git a/docs/site/static/img/ui/settings-outline_F08BB.svg b/docs/site/static/img/ui/settings-outline_F08BB.svg new file mode 100644 index 000000000000..d36ea03c0216 --- /dev/null +++ b/docs/site/static/img/ui/settings-outline_F08BB.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/static/img/ui/star-outline_F04D2.svg b/docs/site/static/img/ui/star-outline_F04D2.svg new file mode 100644 index 000000000000..7b44618df9e6 --- /dev/null +++ b/docs/site/static/img/ui/star-outline_F04D2.svg @@ -0,0 +1,6 @@ + diff --git a/docs/site/tsconfig.json b/docs/site/tsconfig.json new file mode 100644 index 000000000000..405d777064cb --- /dev/null +++ b/docs/site/tsconfig.json @@ -0,0 +1,12 @@ +// This file is not used by "docusaurus start/build" commands. +// It is here to improve your IDE experience (type-checking, autocompletion...), +// and can also run the package.json "typecheck" script manually. +{ + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": ".", + "ignoreDeprecations": "6.0", + "strict": true + }, + "exclude": [".docusaurus", "build"] +} diff --git a/docs/styles/Mattermost/BrandVoice.yml b/docs/styles/Mattermost/BrandVoice.yml new file mode 100644 index 000000000000..e596796e17a0 --- /dev/null +++ b/docs/styles/Mattermost/BrandVoice.yml @@ -0,0 +1,19 @@ +extends: existence +message: "Brand voice: avoid '%s' in normative content. Mattermost is mission-critical, not casual." +level: warning +ignorecase: true +# Brand pillars: Focused, Adaptable, Secure, Resilient. +# Tone: 'Built for the War Room. Not the Break Room.' +# Banned casual phrasing in normative documentation. Acceptable in blog/marketing. +tokens: + - "easy peasy" + - "super easy" + - "no worries" + - "just kidding" + - "fun" + - "awesome" + - "cool" + - "yay" + - "let's go!" + - "magic" + - "magical" diff --git a/docs/styles/Mattermost/Headings.yml b/docs/styles/Mattermost/Headings.yml new file mode 100644 index 000000000000..cb1d33679098 --- /dev/null +++ b/docs/styles/Mattermost/Headings.yml @@ -0,0 +1,43 @@ +extends: capitalization +message: "Use sentence case for '%s' (capitalize only the first word and proper nouns)." +level: warning +match: $sentence +scope: heading +indicators: + - ":" +exceptions: + - Mattermost + - Channels + - Playbooks + - Boards + - Copilot + - Calls + - GitHub + - GitLab + - Kubernetes + - PostgreSQL + - MySQL + - LDAP + - SAML + - OAuth + - API + - APIs + - REST + - JSON + - YAML + - SSH + - TLS + - HTTP + - HTTPS + - URL + - URLs + - WebSocket + - WebSockets + - Markdown + - Cloud + - Server + - Enterprise + - Free + - Professional + - Zero Trust + - Mission in Motion diff --git a/docs/styles/Mattermost/SentenceLength.yml b/docs/styles/Mattermost/SentenceLength.yml new file mode 100644 index 000000000000..6820cc0068b5 --- /dev/null +++ b/docs/styles/Mattermost/SentenceLength.yml @@ -0,0 +1,6 @@ +extends: occurrence +message: "Sentence is %s words; consider breaking it up. Mission-critical content reads short." +level: suggestion +scope: sentence +max: 35 +token: \b(\w+)\b diff --git a/docs/styles/Mattermost/Terminology.yml b/docs/styles/Mattermost/Terminology.yml new file mode 100644 index 000000000000..46597594040d --- /dev/null +++ b/docs/styles/Mattermost/Terminology.yml @@ -0,0 +1,50 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +level: warning +ignorecase: true +# Mattermost product terminology. Codifies handbook style guide. +# See: https://handbook.mattermost.com/operations/research-and-development/product/technical-writing-team-handbook/documentation-style-guide +swap: + # Product names + matter most: Mattermost + matter-most: Mattermost + mattermost cloud: Mattermost Cloud + mattermost server: Mattermost Server + mattermost team edition: Mattermost Team Edition + mattermost enterprise edition: Mattermost Enterprise Edition + + # Feature names — proper-cased per brand + channels: Channels + playbooks: Playbooks + boards: Boards + copilot: Copilot + calls: Calls + + # Audience naming + e-mail: email + e mail: email + log-in: log in + login (verb): log in + log-out: log out + logout (verb): log out + sign-in: sign in + sign-out: sign out + + # Common technical terminology + github: GitHub + gitlab: GitLab + kubernetes: Kubernetes + postgres: PostgreSQL + mysql: MySQL + ldap: LDAP + saml: SAML + oauth: OAuth + api: API + apis: APIs + url: URL + urls: URLs + json: JSON + yaml: YAML + ssh: SSH + tls: TLS + ssl: TLS # Mattermost docs prefer TLS over SSL diff --git a/e2e-tests/.ci/server.generate.sh b/e2e-tests/.ci/server.generate.sh index 84e854dcf41a..c5b8a2787401 100755 --- a/e2e-tests/.ci/server.generate.sh +++ b/e2e-tests/.ci/server.generate.sh @@ -69,6 +69,7 @@ services: MM_FEATUREFLAGS_PERMISSIONPOLICIES: "true" MM_FEATUREFLAGS_TEAMMEMBERSHIPACCESSCONTROL: "true" MM_FEATUREFLAGS_CLASSIFICATIONMARKINGS: "true" + MM_FEATUREFLAGS_INTEGRATEDBOARDS: "true" MM_FEATUREFLAGS_PROPERTYFIELDRANK: "true" MM_FEATUREFLAGS_ATTRIBUTEVALUEMASKING: "true" MM_LOGSETTINGS_ENABLEDIAGNOSTICS: "false" diff --git a/e2e-tests/playwright/lib/src/server/default_config.ts b/e2e-tests/playwright/lib/src/server/default_config.ts index 1ae8fab70c9b..f32e53334755 100644 --- a/e2e-tests/playwright/lib/src/server/default_config.ts +++ b/e2e-tests/playwright/lib/src/server/default_config.ts @@ -819,7 +819,7 @@ const defaultServerConfig: AdminConfig = { BurnOnRead: true, EnableAIPluginBridge: false, EnableAIRecaps: false, - IntegratedBoards: false, + IntegratedBoards: true, CJKSearch: true, AggregatePluginMetrics: false, ManagedChannelCategories: false, diff --git a/e2e-tests/playwright/lib/src/ui/components/system_console/sections/system_attributes/board_attributes.ts b/e2e-tests/playwright/lib/src/ui/components/system_console/sections/system_attributes/board_attributes.ts new file mode 100644 index 000000000000..7b122c66ffe7 --- /dev/null +++ b/e2e-tests/playwright/lib/src/ui/components/system_console/sections/system_attributes/board_attributes.ts @@ -0,0 +1,288 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import type {Locator} from '@playwright/test'; +import {expect} from '@playwright/test'; + +const BOARD_ATTRIBUTES_URL = '/admin_console/system_attributes/board_attributes'; + +export type BoardAttributeType = 'Text' | 'Select' | 'Multi-select' | 'Date' | 'User'; + +export type ColorTokenName = 'Default' | 'Brown' | 'Orange' | 'Yellow' | 'Green' | 'Blue' | 'Purple' | 'Pink' | 'Red'; + +/** + * System Console -> System Attributes -> Board Attributes. + * + * Row-identity gotcha: controlled inputs in this table render their `value` + * via React state, which sets the DOM `.value` PROPERTY but does NOT update + * the `value` HTML ATTRIBUTE after the initial mount. Selectors of the form + * `input[value="X"]` only match for rows whose initial-render value is X + * (seeded fields, or fields persisted across reload). For unsaved / + * just-added rows, use `lastAddedRow()` or the locator returned by + * `addAttribute()`. + */ +export default class BoardAttributes { + readonly container: Locator; + private readonly page; + + readonly addAttributeButton: Locator; + readonly saveButton: Locator; + + constructor(container: Locator) { + this.container = container.getByTestId('boardAttributes'); + this.page = container.page(); + + this.addAttributeButton = this.container.getByRole('button', {name: 'Add attribute'}); + this.saveButton = this.page.getByTestId('saveSetting'); + } + + // ── Visibility / navigation ───────────────────────────────────────── + + async toBeVisible() { + await expect(this.container).toBeVisible(); + // Wait for the seeded rows to render so name-based lookups work + // reliably immediately after navigation — the property-fields fetch + // can complete just after waitForLoadState('networkidle') returns. + await expect(this.nameInputByValue('status')).toBeVisible(); + await expect(this.nameInputByValue('assignee')).toBeVisible(); + } + + async goto() { + await this.page.goto(BOARD_ATTRIBUTES_URL); + await this.page.waitForLoadState('domcontentloaded'); + } + + // ── Row / cell accessors ─────────────────────────────────────────── + + nameInput(nth: number): Locator { + return this.container.getByTestId('board-attribute-field-input').nth(nth); + } + + /** + * Find a name input by its initial-render value. Scoped to the table's + * own name-input testid so it cannot accidentally match unrelated inputs + * (option-rename inputs, type-filter input) that may share a value, and + * escapes the value for safe interpolation into the CSS attribute + * selector. See class-level comment about value-attribute caveats. + */ + nameInputByValue(value: string): Locator { + return this.container + .getByTestId('board-attribute-field-input') + .and(this.container.locator(`input[value="${escapeCssAttributeValue(value)}"]`)); + } + + lastNameInput(): Locator { + return this.container.getByTestId('board-attribute-field-input').last(); + } + + /** + * Find a row by the value attribute of its name input. Works for rows + * whose initial-render value matches — i.e. seeded fields and any field + * loaded after save+reload. Does NOT work for unsaved rows just added + * in this session; use lastAddedRow() for those. + */ + rowByName(name: string): Locator { + // The `has` locator is re-rooted at each candidate , so it must + // be a page-level locator (not a chain anchored at the table's own + // container). Anchor on the name-input testid so the row probe + // can't match through option chips or filter inputs. + return this.container.locator('tr', { + has: this.page.locator( + `input[data-testid="board-attribute-field-input"][value="${escapeCssAttributeValue(name)}"]`, + ), + }); + } + + /** + * Locator for the row containing the most recently added name input — + * the right way to address an unsaved row. Uses the last `` in the + * tbody since new rows append at the end. + */ + lastAddedRow(): Locator { + return this.container.locator('tbody tr').last(); + } + + typeSelectorInRow(row: Locator): Locator { + return row.getByTestId('fieldTypeSelectorMenuButton'); + } + + typeSelectorByName(name: string): Locator { + return this.typeSelectorInRow(this.rowByName(name)); + } + + dotMenuInRow(row: Locator): Locator { + return row.locator('[data-testid^="board-attribute-field_dotmenu-"]'); + } + + dotMenuByName(name: string): Locator { + return this.dotMenuInRow(this.rowByName(name)); + } + + optionChip(name: string): Locator { + return this.container.getByText(name, {exact: true}); + } + + optionDeleteButtonByName(optionName: string): Locator { + // The X-button's testid uses option.id (server id or pending id) — + // unstable from a test perspective. Walk from the visible chip label + // up to its ChipDropZone (carries `data-flip-key`) and locate the + // delete button inside. + return this.optionChip(optionName) + .locator('xpath=ancestor::span[@data-flip-key][1]') + .locator('button[data-testid^="property-option-delete-"]'); + } + + // ── Header / table-level actions ─────────────────────────────────── + + /** + * Click "Add attribute". When `name` is provided, fills and blurs the + * just-added name input. Returns the row locator for the new row, which + * the caller should use for subsequent interactions (changeTypeInRow, + * addOptionInRow, etc.) until after save. + */ + async addAttribute(name?: string): Promise { + await this.addAttributeButton.click(); + const row = this.lastAddedRow(); + if (name !== undefined) { + const input = row.locator('[data-testid="board-attribute-field-input"]'); + await input.fill(name); + await input.blur(); + } + return row; + } + + async saveAndWaitForSettled() { + await expect(this.saveButton).toBeEnabled(); + await this.saveButton.click(); + + // Save flushes pending changes; button returns to disabled state once + // all API calls complete and React re-renders with the new baseline. + await expect(this.saveButton).toBeDisabled({timeout: 15_000}); + } + + // ── Type menu interactions ───────────────────────────────────────── + + async openTypeMenuInRow(row: Locator) { + await this.typeSelectorInRow(row).click(); + } + + async chooseType(type: BoardAttributeType) { + // Scope to the type-selector menu (aria-label 'Select type') so a stray + // open color picker can't capture the click. scrollIntoViewIfNeeded + // covers Date/User at the bottom of the list when the menu's viewport + // is narrow (visible-but-not-in-clipping-region clicks otherwise no-op). + const item = this.page + .getByRole('menu', {name: 'Select type'}) + .getByRole('menuitemradio', {name: type, exact: true}); + await item.scrollIntoViewIfNeeded(); + await item.click(); + } + + async changeTypeInRow(row: Locator, type: BoardAttributeType) { + await this.openTypeMenuInRow(row); + await this.chooseType(type); + // Wait for the type selector to reflect the new choice — confirms the + // click dispatched and React rendered the new state. Without this the + // immediate next save() can race the dispatch and commit the old type. + await expect(this.typeSelectorInRow(row)).toContainText(type); + } + + async changeTypeByName(name: string, type: BoardAttributeType) { + await this.changeTypeInRow(this.rowByName(name), type); + } + + // ── Option / chip interactions ───────────────────────────────────── + + async addOptionInRow(row: Locator, optionName: string) { + await row.getByRole('button', {name: 'Add value'}).click(); + const newChip = row.locator('[data-testid^="property-option-chip-"]').last(); + await newChip.click(); + const renameInput = this.page.getByPlaceholder('Option name'); + await renameInput.fill(optionName); + await renameInput.blur(); + await this.closeChipMenu(); + } + + async addOption(rowName: string, optionName: string) { + await this.addOptionInRow(this.rowByName(rowName), optionName); + } + + async openOptionMenu(optionName: string) { + await this.optionChip(optionName).click(); + } + + async renameOption(currentName: string, newName: string) { + await this.openOptionMenu(currentName); + const renameInput = this.page.getByPlaceholder('Option name'); + await renameInput.fill(newName); + await renameInput.blur(); + await this.closeChipMenu(); + } + + async deleteOptionViaXButton(optionName: string) { + await this.optionDeleteButtonByName(optionName).click(); + } + + async chooseOptionColor(color: ColorTokenName) { + await this.page.getByRole('menuitemradio', {name: color, exact: true}).click(); + } + + async setOptionColor(optionName: string, color: ColorTokenName) { + await this.openOptionMenu(optionName); + await this.chooseOptionColor(color); + await this.closeChipMenu(); + } + + /** + * The chip menu (Menu.Container) renders as a MUI Popover whose invisible + * backdrop intercepts pointer events. Clicking the backdrop is what + * dismisses the popover — its onClick handler fires the Menu's close + * callback. We try backdrop click first (most reliable) and fall back to + * Escape if the backdrop has already detached. + */ + async closeChipMenu() { + const backdrop = this.page.locator('#backdropForMenuComponent'); + if ((await backdrop.count()) === 0) { + return; + } + // Backdrop click is the most reliable close path — it directly fires + // the Menu's onClose handler without relying on focus state. + await backdrop.click({force: true}); + try { + await backdrop.first().waitFor({state: 'detached', timeout: 3000}); + return; + } catch { + // Click didn't detach — try Escape as fallback. + } + await this.page.keyboard.press('Escape'); + await backdrop + .first() + .waitFor({state: 'detached', timeout: 2000}) + .catch(() => {}); + } + + // ── Dot menu interactions ────────────────────────────────────────── + + async openDotMenuInRow(row: Locator) { + await this.dotMenuInRow(row).click(); + } + + async openDotMenuByName(name: string) { + await this.openDotMenuInRow(this.rowByName(name)); + } + + async clickDuplicate() { + await this.page.getByText('Duplicate', {exact: true}).click(); + } + + async clickDeleteAttribute() { + await this.page.getByText('Delete attribute', {exact: true}).click(); + } +} + +// Escape characters that have special meaning inside a CSS attribute value +// when the value is interpolated between double quotes (`[attr="..."]`). +// Backslash must be escaped first so it doesn't double-escape the quote. +function escapeCssAttributeValue(value: string): string { + return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +} diff --git a/e2e-tests/playwright/lib/src/ui/components/system_console/sidebar.ts b/e2e-tests/playwright/lib/src/ui/components/system_console/sidebar.ts index 3df9829082fe..9edceecf0540 100644 --- a/e2e-tests/playwright/lib/src/ui/components/system_console/sidebar.ts +++ b/e2e-tests/playwright/lib/src/ui/components/system_console/sidebar.ts @@ -179,6 +179,7 @@ class UserManagementCategory extends SidebarCategory { class SystemAttributesCategory extends SidebarCategory { readonly userAttributes: SidebarSection; + readonly boardAttributes: SidebarSection; readonly attributeBasedAccess: SidebarSection; readonly membershipPolicies: SidebarSection; readonly permissionPolicies: SidebarSection; @@ -186,6 +187,7 @@ class SystemAttributesCategory extends SidebarCategory { constructor(container: Locator) { super(container); this.userAttributes = this.section('User Attributes'); + this.boardAttributes = this.section('Board Attributes'); this.attributeBasedAccess = this.section('Attribute-Based Access'); this.membershipPolicies = this.section('Membership Policies'); this.permissionPolicies = this.section('Permission Policies'); diff --git a/e2e-tests/playwright/lib/src/ui/pages/system_console.ts b/e2e-tests/playwright/lib/src/ui/pages/system_console.ts index 8b88aa976ecd..c2e845dc0a1a 100644 --- a/e2e-tests/playwright/lib/src/ui/pages/system_console.ts +++ b/e2e-tests/playwright/lib/src/ui/pages/system_console.ts @@ -15,6 +15,7 @@ import MobileSecurity from '@/ui/components/system_console/sections/environment/ import Localization from '@/ui/components/system_console/sections/site_configuration/localization'; import Notifications from '@/ui/components/system_console/sections/site_configuration/notifications'; import UsersAndTeams from '@/ui/components/system_console/sections/site_configuration/users_and_teams'; +import BoardAttributes from '@/ui/components/system_console/sections/system_attributes/board_attributes'; import SystemProperties from '@/ui/components/system_console/sections/system_attributes/system_properties'; import FeatureDiscovery from '@/ui/components/system_console/sections/system_users/feature_discovery'; @@ -47,6 +48,7 @@ export default class SystemConsolePage { // System Attributes readonly systemProperties: SystemProperties; + readonly boardAttributes: BoardAttributes; // Feature Discovery (license-gated features) readonly featureDiscovery: FeatureDiscovery; @@ -82,6 +84,7 @@ export default class SystemConsolePage { // System Attributes this.systemProperties = new SystemProperties(adminConsoleWrapper); + this.boardAttributes = new BoardAttributes(adminConsoleWrapper); // Feature Discovery this.featureDiscovery = new FeatureDiscovery(adminConsoleWrapper); diff --git a/e2e-tests/playwright/specs/functional/channels/channel_settings/channel_admin_self_inclusion.spec.ts b/e2e-tests/playwright/specs/functional/channels/channel_settings/channel_admin_self_inclusion.spec.ts index 728d96b5987a..ceb5cc193045 100644 --- a/e2e-tests/playwright/specs/functional/channels/channel_settings/channel_admin_self_inclusion.spec.ts +++ b/e2e-tests/playwright/specs/functional/channels/channel_settings/channel_admin_self_inclusion.spec.ts @@ -9,7 +9,7 @@ import type {Client4} from '@mattermost/client'; import type {Page} from '@playwright/test'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {UserProfile} from '@mattermost/types/users'; import {ChannelsPage, expect, newTestPassword, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/custom_attributes.spec.ts b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/custom_attributes.spec.ts index 4dd78242f417..b8828cfa9940 100644 --- a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/custom_attributes.spec.ts +++ b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/custom_attributes.spec.ts @@ -5,7 +5,7 @@ import type {Team} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; import type {Channel} from '@mattermost/types/channels'; import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/helpers.ts b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/helpers.ts index 40a9b98b52b7..2cfee463e6e3 100644 --- a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/helpers.ts +++ b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/helpers.ts @@ -3,7 +3,8 @@ import type {Page} from '@playwright/test'; import type {Client4} from '@mattermost/client'; -import type {UserPropertyField, UserPropertyFieldPatch, FieldType} from '@mattermost/types/properties'; +import type {FieldType} from '@mattermost/types/properties'; +import type {UserPropertyField, UserPropertyFieldPatch} from '@mattermost/types/properties_user'; import type {ChannelsPage} from '@mattermost/playwright-lib'; import {expect} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/user_settings.spec.ts b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/user_settings.spec.ts index 700b6852d469..dd96e6bef6f1 100644 --- a/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/user_settings.spec.ts +++ b/e2e-tests/playwright/specs/functional/channels/custom_profile_attributes/user_settings.spec.ts @@ -5,7 +5,7 @@ import type {Team} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; import type {Channel} from '@mattermost/types/channels'; import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/abac/policies/ranked_operators.spec.ts b/e2e-tests/playwright/specs/functional/system_console/abac/policies/ranked_operators.spec.ts index fc53adc1a3be..5c71cc1dea61 100644 --- a/e2e-tests/playwright/specs/functional/system_console/abac/policies/ranked_operators.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/abac/policies/ranked_operators.spec.ts @@ -11,7 +11,7 @@ import type {Client4} from '@mattermost/client'; import type {UserProfile} from '@mattermost/types/users'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, getRandomId, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/abac/support.ts b/e2e-tests/playwright/specs/functional/system_console/abac/support.ts index 4771c1bd31bb..67f44afaa74e 100644 --- a/e2e-tests/playwright/specs/functional/system_console/abac/support.ts +++ b/e2e-tests/playwright/specs/functional/system_console/abac/support.ts @@ -10,7 +10,7 @@ import {expect, type Page} from '@playwright/test'; import type {Client4} from '@mattermost/client'; import type {UserProfile} from '@mattermost/types/users'; import type {Channel} from '@mattermost/types/channels'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {newTestPassword} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/abac/user_attributes/display_name_in_selector.spec.ts b/e2e-tests/playwright/specs/functional/system_console/abac/user_attributes/display_name_in_selector.spec.ts index c8b094b36065..67efd098668a 100644 --- a/e2e-tests/playwright/specs/functional/system_console/abac/user_attributes/display_name_in_selector.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/abac/user_attributes/display_name_in_selector.spec.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, test, enableABAC, navigateToABACPage} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes.spec.ts new file mode 100644 index 000000000000..63051e781f30 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes.spec.ts @@ -0,0 +1,109 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import {setupBoardAttributesTest, cleanupCustomBoardFields} from './setup'; + +// Spec-scoped test data prefix. afterEach cleanup is filtered by this so +// concurrent specs sharing the same server can't delete each other's fields. +const BA_PREFIX = 'BA_'; + +test.describe('System Console - Board Attributes', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields((name) => name.startsWith(BA_PREFIX)); + }); + + test('renders page with seeded Status and Assignee rows and a disabled save button', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + // # Navigate via the sidebar entry + await systemConsolePage.sidebar.systemAttributes.boardAttributes.click(); + await ba.toBeVisible(); + + // * Status row is present with its three seeded values + await expect(ba.nameInputByValue('status')).toBeVisible(); + await expect(ba.optionChip('Todo')).toBeVisible(); + await expect(ba.optionChip('In Progress')).toBeVisible(); + await expect(ba.optionChip('Complete')).toBeVisible(); + + // * Assignee row is present + await expect(ba.nameInputByValue('assignee')).toBeVisible(); + + // * Save button is present but disabled — no pending changes + await expect(ba.saveButton).toBeVisible(); + await expect(ba.saveButton).toBeDisabled(); + }); + + test('seeded Status row is protected: read-only values, disabled name input', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // * The read-only values container exists exactly once — only the + // seeded protected select renders it + await expect(ba.container.getByTestId('property-values-readonly')).toHaveCount(1); + + // * Read-only chips render the seeded value names + await expect( + ba.container.getByTestId('property-values-readonly').getByText('Todo', {exact: true}), + ).toBeVisible(); + + // * Status name input is disabled — protected fields cannot be renamed + await expect(ba.nameInputByValue('status')).toBeDisabled(); + }); + + test('Assignee row uses the placeholder values column (user type renders an em-dash)', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // * Assignee row exists + await expect(ba.nameInputByValue('assignee')).toBeVisible(); + + // * Its values cell renders the em-dash placeholder (no options panel) + const assigneeRow = ba.rowByName('assignee'); + await expect(assigneeRow.getByText('—')).toBeVisible(); + await expect(assigneeRow.getByTestId('property-values-readonly')).toHaveCount(0); + await expect(assigneeRow.getByTestId('property-values-input')).toHaveCount(0); + }); + + test('adds, names, saves, and persists a custom text attribute across reload', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const name = `${BA_PREFIX}Priority_${Date.now()}`; + + // # Add a new attribute and name it + await ba.addAttribute(name); + + // # Save + await ba.saveAndWaitForSettled(); + + // * Field exists on the server + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const created = (fields ?? []).find((f) => f.name === name); + expect(created).toBeDefined(); + expect(created!.type).toBe('text'); + + // # Reload + await ba.goto(); + await ba.toBeVisible(); + + // * Field is still rendered + await expect(ba.nameInputByValue(name)).toBeVisible(); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_colors.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_colors.spec.ts new file mode 100644 index 000000000000..e0175b15a809 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_colors.spec.ts @@ -0,0 +1,99 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import {COLOR_TOKEN_NAMES, SERVER_COLOR_BY_UI_LABEL, setupBoardAttributesTest, cleanupCustomBoardFields} from './setup'; + +test.describe('Board Attributes - option color picker', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + test('assigns a color token to an option and the server persists the value', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Color_${Date.now()}`; + const optionName = 'Tagged'; + + // # Add a select attribute with one option, save baseline + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, optionName); + await ba.saveAndWaitForSettled(); + + // # Assign the Green color + await ba.setOptionColor(optionName, 'Green'); + await ba.saveAndWaitForSettled(); + + // * Server reflects the color token + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const updated = (fields ?? []).find((f) => f.name === attrName); + const option = ((updated!.attrs as {options?: Array<{name: string; color?: string}>})?.options ?? []).find( + (o) => o.name === optionName, + ); + expect(option?.color).toBe(SERVER_COLOR_BY_UI_LABEL.Green); + }); + + test('color assignment persists across reload and the picker shows the correct checked state', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Persist_${Date.now()}`; + + // # Add a select attribute with one option, save baseline + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'Colored'); + await ba.saveAndWaitForSettled(); + + // # Assign the Red color and save + await ba.setOptionColor('Colored', 'Red'); + await ba.saveAndWaitForSettled(); + + // # Reload + await ba.goto(); + await ba.toBeVisible(); + + // * Chip is still rendered + await expect(ba.optionChip('Colored')).toBeVisible(); + + // * The picker reflects the correct checked color + await ba.openOptionMenu('Colored'); + const checkedColor = ba.container.page().getByRole('menuitemradio', {name: 'Red', exact: true}); + await expect(checkedColor).toHaveAttribute('aria-checked', 'true'); + }); + + test('color picker exposes all nine color tokens', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Picker_${Date.now()}`; + + // # Add a select with one option, open its menu + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'Pick me'); + await ba.openOptionMenu('Pick me'); + + // * Every named color token is offered + for (const uiColor of COLOR_TOKEN_NAMES) { + await expect(ba.container.page().getByRole('menuitemradio', {name: uiColor, exact: true})).toBeVisible(); + } + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dnd.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dnd.spec.ts new file mode 100644 index 000000000000..541960eba3d2 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dnd.spec.ts @@ -0,0 +1,71 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import {cleanupCustomBoardFields, setupBoardAttributesTest} from './setup'; + +// Spec-scoped test data prefix. afterEach cleanup is filtered by this so +// concurrent specs sharing the same server (or running in alternation on a +// given worker) can't delete each other's fields. +const BA_DND_PREFIX = 'BA_DND_'; + +// Row reorder is driven through the drag handle's keyboard interface +// (ArrowUp / ArrowDown — see DraggableRow in webapp's list_table.tsx). That +// codepath dispatches the same `meta.onReorder` callback the native HTML5 +// drag flow uses, so a passing keyboard test proves the wiring end-to-end. +// +// Chip-level option reorder uses @atlaskit/pragmatic-drag-and-drop with no +// keyboard fallback in the product, and PDND requires real HTML5 drag +// events (Playwright's locator.dragTo() only emulates mouse events). A +// dedicated chip-reorder E2E is therefore deferred to a follow-up that +// either (a) adds keyboard a11y to chip reorder, or (b) introduces a +// shared playwright-lib helper for synthetic HTML5 drag dispatch. +test.describe('Board Attributes - reorder', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields((name) => name.startsWith(BA_DND_PREFIX)); + }); + + test('reorders custom rows via drag-handle keyboard and persists order across reload', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const a = `${BA_DND_PREFIX}Row_A_${Date.now()}`; + const b = `${BA_DND_PREFIX}Row_B_${Date.now()}`; + + // # Add two custom rows: A first (so it sits above B), then B + await ba.addAttribute(a); + await ba.addAttribute(b); + await ba.saveAndWaitForSettled(); + + // # Reload so both rows render with their persisted sort_order and + // can be addressed by name + await ba.goto(); + await ba.toBeVisible(); + + // # Focus A's drag handle and press ArrowDown to swap A past B. + // The handler in list_table.tsx clamps moves above the protected + // region, so moving custom A down by one cannot collide with the + // seeded protected rows. + const aHandle = ba.rowByName(a).locator('button.dragHandle'); + await aHandle.press('ArrowDown'); + + await ba.saveAndWaitForSettled(); + + // * Persisted sort_order reflects the swap: A is now below B + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const aField = (fields ?? []).find((f) => f.name === a); + const bField = (fields ?? []).find((f) => f.name === b); + const aOrder = (aField?.attrs as {sort_order?: number})?.sort_order ?? 0; + const bOrder = (bField?.attrs as {sort_order?: number})?.sort_order ?? 0; + expect(aOrder).toBeGreaterThan(bOrder); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dot_menu.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dot_menu.spec.ts new file mode 100644 index 000000000000..3fd67363da18 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_dot_menu.spec.ts @@ -0,0 +1,138 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import {setupBoardAttributesTest, cleanupCustomBoardFields} from './setup'; + +test.describe('Board Attributes - row dot menu', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + test('duplicates a custom attribute via the dot menu — copy gets a (2) suffix and persists', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const original = `Dup_${Date.now()}`; + + // # Add a saved custom attribute + await ba.addAttribute(original); + await ba.saveAndWaitForSettled(); + + // # Open the row's dot menu and click Duplicate + await ba.openDotMenuByName(original); + await ba.clickDuplicate(); + + // * A new row appears with the "(2)" suffix + const copy = `${original} (2)`; + await expect(ba.nameInputByValue(copy)).toBeVisible(); + + // # Save and reload + await ba.saveAndWaitForSettled(); + await ba.goto(); + await ba.toBeVisible(); + + // * Both the original and the (2)-suffixed copy persist + await expect(ba.nameInputByValue(original)).toBeVisible(); + await expect(ba.nameInputByValue(copy)).toBeVisible(); + + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const names = (fields ?? []).map((f) => f.name); + expect(names).toEqual(expect.arrayContaining([original, copy])); + }); + + test('deletes a saved custom attribute via the confirm modal — row disappears, server reflects', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const name = `Del_${Date.now()}`; + + // # Add a saved custom attribute + await ba.addAttribute(name); + await ba.saveAndWaitForSettled(); + + // # Open the dot menu, click Delete attribute + await ba.openDotMenuByName(name); + await ba.clickDeleteAttribute(); + + // * The confirmation modal appears + await expect(ba.container.page().getByRole('heading', {name: 'Delete board attribute'})).toBeVisible(); + + // # Confirm + await ba.container.page().getByRole('button', {name: 'Delete', exact: true}).click(); + + // # Save the delete + await ba.saveAndWaitForSettled(); + + // * The row is gone + await expect(ba.nameInputByValue(name)).toHaveCount(0); + + // * The server no longer lists the attribute + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const names = (fields ?? []).map((f) => f.name); + expect(names).not.toContain(name); + }); + + test('dismissing the delete-confirm modal keeps the row intact', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const name = `Keep_${Date.now()}`; + + // # Add and save a custom attribute + await ba.addAttribute(name); + await ba.saveAndWaitForSettled(); + + // # Open dot menu, click Delete, then Cancel the modal + await ba.openDotMenuByName(name); + await ba.clickDeleteAttribute(); + await ba.container.page().getByRole('button', {name: 'Cancel'}).click(); + + // * Modal is closed + await expect(ba.container.page().getByRole('heading', {name: 'Delete board attribute'})).toHaveCount(0); + + // * Row is still present + await expect(ba.nameInputByValue(name)).toBeVisible(); + + // * Save remains disabled — no pending changes were committed + await expect(ba.saveButton).toBeDisabled(); + }); + + test('Duplicate and Delete items are disabled on protected (seeded) rows', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // # Open the dot menu on the seeded Status row + await ba.openDotMenuByName('status'); + + // * Both menu items render but are aria-disabled + const duplicate = ba.container + .page() + .getByText('Duplicate', {exact: true}) + .locator('xpath=ancestor::*[@role="menuitem"][1]'); + const del = ba.container + .page() + .getByText('Delete attribute', {exact: true}) + .locator('xpath=ancestor::*[@role="menuitem"][1]'); + await expect(duplicate).toHaveAttribute('aria-disabled', 'true'); + await expect(del).toHaveAttribute('aria-disabled', 'true'); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_edge.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_edge.spec.ts new file mode 100644 index 000000000000..ff962fc7d3f6 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_edge.spec.ts @@ -0,0 +1,109 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import { + BOARDS_GROUP, + OBJECT_TYPE_POST, + SYSTEM_TARGET_TYPE, + setupBoardAttributesTest, + cleanupCustomBoardFields, +} from './setup'; + +const MAX_BOARD_ATTRIBUTES = 20; + +test.describe('Board Attributes - edge cases', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + test('hides the Add attribute button when the table is at the 20-attribute cap', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + // # Seed 18 custom attributes (Status + Assignee + 18 = 20) + for (let i = 0; i < MAX_BOARD_ATTRIBUTES - 2; i++) { + await adminClient.createPropertyField(BOARDS_GROUP, OBJECT_TYPE_POST, { + name: `Cap_${i}_${Date.now()}`, + type: 'text', + attrs: {sort_order: i}, + target_type: SYSTEM_TARGET_TYPE, + target_id: '', + } as Parameters[2]); + } + + await ba.goto(); + await ba.toBeVisible(); + + // * Add attribute button is no longer rendered (canCreate=false) + await expect(ba.addAttributeButton).toHaveCount(0); + }); + + test('changing a saved select attribute to text wipes its options on save', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Conv_${Date.now()}`; + + // # Add a select attribute with two options, save baseline + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'A'); + await ba.addOptionInRow(row, 'B'); + await ba.saveAndWaitForSettled(); + + // # Reload so the input's `value` attribute reflects the saved name — + // rowByName / changeTypeByName rely on `input[value=...]` for filter + await ba.goto(); + await ba.toBeVisible(); + + // # Change the type to Text + await ba.changeTypeByName(attrName, 'Text'); + + // # Save + await ba.saveAndWaitForSettled(); + + // * Server-side: the saved field is now type=text. The commit path + // omits the `options` key from the PATCH body for non-select types + // (board_attributes_utils.ts:126), so the server keeps the + // underlying option data — the UI is what hides it. Asserting the + // server-side wipe would require sending `options: []` explicitly. + const fields = await adminClient.getPropertyFields(BOARDS_GROUP, OBJECT_TYPE_POST, SYSTEM_TARGET_TYPE); + const updated = (fields ?? []).find((f) => f.name === attrName); + expect(updated).toBeDefined(); + expect(updated!.type).toBe('text'); + + // * UI-side: no editable values container is rendered for the row + const row2 = ba.rowByName(attrName); + await expect(row2.getByTestId('property-values-input')).toHaveCount(0); + }); + + test('clicking another sidebar entry with unsaved changes shows the discard-changes modal', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // # Add a row to create a pending change + await ba.addAttribute(`Pending_${Date.now()}`); + + // * Save button is enabled (pending changes exist) + await expect(ba.saveButton).toBeEnabled(); + + // # Click another sidebar entry (User Attributes) + await systemConsolePage.sidebar.systemAttributes.userAttributes.link.click(); + + // * The unsaved-changes modal appears + await expect(systemConsolePage.page.getByText('Discard Changes?', {exact: true})).toBeVisible(); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_options.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_options.spec.ts new file mode 100644 index 000000000000..9f550bca71fb --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_options.spec.ts @@ -0,0 +1,150 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import {setupBoardAttributesTest, cleanupCustomBoardFields} from './setup'; + +test.describe('Board Attributes - select option values', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + test('adds options and renames one — persists across reload', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Opts_${Date.now()}`; + + // # Add a select attribute with three options + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'Low'); + await ba.addOptionInRow(row, 'Medium'); + await ba.addOptionInRow(row, 'High'); + await ba.saveAndWaitForSettled(); + + // # Rename "Medium" → "Mid" and save + await ba.renameOption('Medium', 'Mid'); + await expect(ba.optionChip('Mid')).toBeVisible(); + await expect(ba.optionChip('Medium')).toHaveCount(0); + await ba.saveAndWaitForSettled(); + + // * Server reflects the create and rename + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const created = (fields ?? []).find((f) => f.name === attrName); + expect(created).toBeDefined(); + const optionNames = ((created!.attrs as {options?: Array<{name: string}>})?.options ?? []).map((o) => o.name); + expect(optionNames).toEqual(expect.arrayContaining(['Low', 'Mid', 'High'])); + expect(optionNames).not.toContain('Medium'); + + // # Reload + await ba.goto(); + await ba.toBeVisible(); + + // * Persisted state renders correctly + await expect(ba.optionChip('Low')).toBeVisible(); + await expect(ba.optionChip('Mid')).toBeVisible(); + await expect(ba.optionChip('High')).toBeVisible(); + }); + + test('deletes an option via the inline X button and persists across reload', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Del_${Date.now()}`; + + // # Add a select attribute with two options, save baseline + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'KeepMe'); + await ba.addOptionInRow(row, 'DeleteMe'); + await ba.saveAndWaitForSettled(); + + // # Delete one option + await ba.deleteOptionViaXButton('DeleteMe'); + await expect(ba.optionChip('DeleteMe')).toHaveCount(0); + await expect(ba.optionChip('KeepMe')).toBeVisible(); + await ba.saveAndWaitForSettled(); + + // * Server reflects the deletion + const fields = await adminClient.getPropertyFields('boards', 'post', 'system'); + const updated = (fields ?? []).find((f) => f.name === attrName); + const optionNames = ((updated!.attrs as {options?: Array<{name: string}>})?.options ?? []).map((o) => o.name); + expect(optionNames).toContain('KeepMe'); + expect(optionNames).not.toContain('DeleteMe'); + + // # Reload + await ba.goto(); + await ba.toBeVisible(); + + // * Only the kept option renders + await expect(ba.optionChip('KeepMe')).toBeVisible(); + await expect(ba.optionChip('DeleteMe')).toHaveCount(0); + }); + + test('shows an in-menu duplicate-name warning while typing an existing option name', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Dup_${Date.now()}`; + + // # Add a select attribute with two distinct options, save baseline + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'Alpha'); + await ba.addOptionInRow(row, 'Beta'); + await ba.saveAndWaitForSettled(); + + // # Open Alpha's menu and type "Beta" + await ba.openOptionMenu('Alpha'); + const renameInput = ba.container.page().getByPlaceholder('Option name'); + await renameInput.fill('Beta'); + + // * In-menu duplicate warning appears + await expect( + ba.container.page().getByText('A value with this name already exists.', {exact: true}), + ).toBeVisible(); + + // * aria-invalid is set on the input + await expect(renameInput).toHaveAttribute('aria-invalid', 'true'); + }); + + test('appends a unique default name when adding multiple unnamed options in a row', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `Auto_${Date.now()}`; + + // # Add a select attribute + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + + // # Click Add value three times without naming the options + await row.getByRole('button', {name: 'Add value'}).click(); + await row.getByRole('button', {name: 'Add value'}).click(); + await row.getByRole('button', {name: 'Add value'}).click(); + + // * Three default-named option chips appear with auto-incrementing suffixes + await expect(ba.optionChip('Option 1')).toBeVisible(); + await expect(ba.optionChip('Option 2')).toBeVisible(); + await expect(ba.optionChip('Option 3')).toBeVisible(); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_types.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_types.spec.ts new file mode 100644 index 000000000000..a30c5e600fcf --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_types.spec.ts @@ -0,0 +1,110 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import { + BOARDS_GROUP, + OBJECT_TYPE_POST, + SYSTEM_TARGET_TYPE, + setupBoardAttributesTest, + cleanupCustomBoardFields, +} from './setup'; +import type {BoardAttributeType} from './setup'; + +const SERVER_TYPE_BY_UI_LABEL: Record = { + Text: 'text', + Select: 'select', + 'Multi-select': 'multiselect', + Date: 'date', + User: 'user', +}; + +const TYPES: BoardAttributeType[] = ['Text', 'Select', 'Multi-select', 'Date', 'User']; + +test.describe('Board Attributes - attribute types', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + for (const uiType of TYPES) { + test(`adds a new attribute and changes its type to ${uiType} — persists across reload`, async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const name = `Type_${uiType.replace(/[^A-Za-z]/g, '')}_${Date.now()}`; + + // # Add a new attribute, fill its name, change the type + const row = await ba.addAttribute(name); + await ba.changeTypeInRow(row, uiType); + + // # Select / Multi-select require at least one option, otherwise + // validation gates save (ValidationWarningOptionsRequired). + if (uiType === 'Select' || uiType === 'Multi-select') { + await ba.addOptionInRow(row, 'Initial'); + } + + // # Save + await ba.saveAndWaitForSettled(); + + // * Server reflects the chosen type + const fields = await adminClient.getPropertyFields(BOARDS_GROUP, OBJECT_TYPE_POST, SYSTEM_TARGET_TYPE); + const created = (fields ?? []).find((f) => f.name === name); + expect(created).toBeDefined(); + expect(created!.type).toBe(SERVER_TYPE_BY_UI_LABEL[uiType]); + + // # Reload + await ba.goto(); + await ba.toBeVisible(); + + // * Row is still rendered + await expect(ba.nameInputByValue(name)).toBeVisible(); + + // * Row's type selector reflects the chosen type + await expect(ba.typeSelectorByName(name)).toContainText(uiType); + }); + } + + test('type menu opens with all five types and the default (Text) is checked', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // # Add a row (defaults to Text) + const row = await ba.addAttribute(`Menu_${Date.now()}`); + + // # Open the type menu + await ba.openTypeMenuInRow(row); + + // * All five types are listed + for (const uiType of TYPES) { + await expect(ba.container.page().getByRole('menuitemradio', {name: uiType, exact: true})).toBeVisible(); + } + + // * Default type (Text) is marked as the current selection + const textItem = ba.container.page().getByRole('menuitemradio', {name: 'Text', exact: true}); + await expect(textItem).toHaveAttribute('aria-checked', 'true'); + }); + + test('type selector is disabled on protected (seeded) rows', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // * Status and Assignee type selectors are disabled + await expect(ba.typeSelectorByName('status')).toBeDisabled(); + await expect(ba.typeSelectorByName('assignee')).toBeDisabled(); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_validation.spec.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_validation.spec.ts new file mode 100644 index 000000000000..d48efc4ca185 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/board_attributes_validation.spec.ts @@ -0,0 +1,161 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// *************************************************************** +// - [#] indicates a test step (e.g. # Go to a page) +// - [*] indicates an assertion (e.g. * Check the title) +// *************************************************************** + +import {expect, test} from '@mattermost/playwright-lib'; + +import { + BOARDS_GROUP, + OBJECT_TYPE_POST, + SYSTEM_TARGET_TYPE, + setupBoardAttributesTest, + cleanupCustomBoardFields, +} from './setup'; + +test.describe('Board Attributes - validation', {tag: '@board_attributes'}, () => { + test.afterEach(async () => { + await cleanupCustomBoardFields(); + }); + + test('blocks save while a new row has an empty name (name_required)', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // # Add a row but leave the name empty + await ba.addAttribute(''); + + // * The "please enter a name" warning is visible + await expect(ba.container.getByText('Please enter an attribute name.', {exact: true})).toBeVisible(); + + // * Save is disabled + await expect(ba.saveButton).toBeDisabled(); + }); + + test('blocks save when two pending rows share the same name (name_unique)', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const shared = `Dup_${Date.now()}`; + + // # Add two new rows with the same name + await ba.addAttribute(shared); + await ba.addAttribute(shared); + + // * Uniqueness warning surfaces on at least one row + await expect(ba.container.getByText('Attribute names must be unique.', {exact: true}).first()).toBeVisible(); + + // * Save is disabled + await expect(ba.saveButton).toBeDisabled(); + }); + + test('blocks save when a new row reuses a protected/seeded name', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + // # Add a new row and name it after the seeded protected "status" field + await ba.addAttribute('status'); + + // * A uniqueness warning surfaces. The validator's pendingByName lookup + // sees both the seeded status (always in the pending collection) + // and the new row, so name_unique fires first — name_taken is + // reserved for rename-against-a-saved-name conflicts. + await expect(ba.container.getByText('Attribute names must be unique.', {exact: true}).first()).toBeVisible(); + + // * Save is disabled + await expect(ba.saveButton).toBeDisabled(); + }); + + test('blocks save when renaming a saved attribute to match another saved name (name_taken)', async ({pw}) => { + const {adminClient, systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + const a = `NameTakenA_${Date.now()}`; + const b = `NameTakenB_${Date.now()}`; + const tmp = `NameTakenTmp_${Date.now()}`; + + // # Seed two saved attributes via API for deterministic setup — + // two rapid UI addAttribute calls can race the React dispatch + // batching, leaving the second's name update unflushed. + await adminClient.createPropertyField(BOARDS_GROUP, OBJECT_TYPE_POST, { + name: a, + type: 'text', + attrs: {sort_order: 0}, + target_type: SYSTEM_TARGET_TYPE, + target_id: '', + } as Parameters[2]); + await adminClient.createPropertyField(BOARDS_GROUP, OBJECT_TYPE_POST, { + name: b, + type: 'text', + attrs: {sort_order: 1}, + target_type: SYSTEM_TARGET_TYPE, + target_id: '', + } as Parameters[2]); + + await ba.goto(); + await ba.toBeVisible(); + + // # Rename A out of the way first, then rename B to A's saved name. + // The validator runs name_unique BEFORE name_taken, so if both rows + // shared the name 'a' in pending state name_unique would fire and + // mask the name_taken path. Renaming A → tmp leaves pendingByName + // ['a'] with only one entry (the renamed B), so the + // currentByName['a'] lookup fires name_taken against the saved A. + // + // React updates the `value` HTML attribute on re-render for + // controlled inputs, so once fill() commits the attribute changes + // and `rowByName(...)` can no longer locate the row by its + // original value — capture the input first, then blur via keyboard + // so the locator isn't re-resolved against a stale name. + const aInput = ba.rowByName(a).locator('[data-testid="board-attribute-field-input"]'); + await aInput.fill(tmp); + await systemConsolePage.page.keyboard.press('Tab'); + + const bInput = ba.rowByName(b).locator('[data-testid="board-attribute-field-input"]'); + await bInput.fill(a); + await systemConsolePage.page.keyboard.press('Tab'); + + // * The "name already taken" warning surfaces + await expect(ba.container.getByText('Attribute name already taken.', {exact: true})).toBeVisible(); + + // * Save is disabled + await expect(ba.saveButton).toBeDisabled(); + }); + + test('blocks save when two options in the same select share a name (values_unique)', async ({pw}) => { + const {systemConsolePage} = await setupBoardAttributesTest(pw); + const ba = systemConsolePage.boardAttributes; + + await ba.goto(); + await ba.toBeVisible(); + + const attrName = `OptDup_${Date.now()}`; + + // # Add a select attribute with two options committed to the same name. + // addOptionInRow opens the new chip's menu, fills its name, and blurs + // to commit — calling it twice with the same name commits a duplicate + // into the options collection, which is what triggers values_unique. + const row = await ba.addAttribute(attrName); + await ba.changeTypeInRow(row, 'Select'); + await ba.addOptionInRow(row, 'Alpha'); + await ba.addOptionInRow(row, 'Alpha'); + + // * Collection-level uniqueness warning surfaces under the chip list + await expect(ba.container.getByText('Values must be unique.', {exact: true})).toBeVisible(); + + // * Save is disabled + await expect(ba.saveButton).toBeDisabled(); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/board_attributes/setup.ts b/e2e-tests/playwright/specs/functional/system_console/board_attributes/setup.ts new file mode 100644 index 000000000000..fb713d74909e --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/board_attributes/setup.ts @@ -0,0 +1,113 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import type {Client4} from '@mattermost/client'; + +import type {SystemConsolePage, PlaywrightExtended} from '@mattermost/playwright-lib'; + +export const BOARDS_GROUP = 'boards'; +export const OBJECT_TYPE_POST = 'post'; +export const SYSTEM_TARGET_TYPE = 'system'; + +export type BoardAttributeType = 'Text' | 'Select' | 'Multi-select' | 'Date' | 'User'; + +export type ColorTokenName = 'Default' | 'Brown' | 'Orange' | 'Yellow' | 'Green' | 'Blue' | 'Purple' | 'Pink' | 'Red'; + +export const COLOR_TOKEN_NAMES: ColorTokenName[] = [ + 'Default', + 'Brown', + 'Orange', + 'Yellow', + 'Green', + 'Blue', + 'Purple', + 'Pink', + 'Red', +]; + +// Server-side color tokens map to the UI labels above. The hex/wire token is +// the lowercase form except 'default' which doubles as the fallback. +export const SERVER_COLOR_BY_UI_LABEL: Record = { + Default: 'default', + Brown: 'brown', + Orange: 'orange', + Yellow: 'yellow', + Green: 'green', + Blue: 'blue', + Purple: 'purple', + Pink: 'pink', + Red: 'red', +}; + +export type BoardAttributesTestContext = { + adminClient: Client4; + systemConsolePage: SystemConsolePage; +}; + +let cachedAdminClient: Client4 | null = null; + +export async function setupBoardAttributesTest(pw: PlaywrightExtended): Promise { + await pw.ensureLicense(); + await pw.skipIfNoLicense(); + + // Feature flags are read at server start from MM_FEATUREFLAGS_* env, + // not from runtime config patches — CI sets it in server.generate.sh; + // locally, export it before running the server. + await pw.skipIfFeatureFlagNotSet('IntegratedBoards', true); + + const {adminUser, adminClient} = await pw.initSetup(); + cachedAdminClient = adminClient; + + await deleteNonProtectedFields(adminClient); + + const {systemConsolePage} = await pw.testBrowser.login(adminUser); + await systemConsolePage.goto(); + await systemConsolePage.toBeVisible(); + + return {adminClient, systemConsolePage}; +} + +/** + * Best-effort teardown for custom (non-protected) board fields. + * + * Pass `nameFilter` (recommended) to scope cleanup to fields this spec + * created — important when multiple board_attributes specs share the same + * server. Without a filter, all non-protected fields in the system group + * are removed. + */ +export async function cleanupCustomBoardFields(nameFilter?: (name: string) => boolean): Promise { + if (!cachedAdminClient) { + return; + } + try { + await deleteNonProtectedFields(cachedAdminClient, nameFilter); + } catch { + // best-effort + } +} + +async function deleteNonProtectedFields(adminClient: Client4, nameFilter?: (name: string) => boolean): Promise { + try { + const fields = await adminClient.getPropertyFields(BOARDS_GROUP, OBJECT_TYPE_POST, SYSTEM_TARGET_TYPE); + for (const field of fields ?? []) { + if (field.protected) { + continue; + } + if (nameFilter && !nameFilter(field.name)) { + continue; + } + await adminClient.deletePropertyField(BOARDS_GROUP, OBJECT_TYPE_POST, field.id); + } + } catch (error: unknown) { + const statusCode = + typeof error === 'object' && error !== null && 'status_code' in error + ? (error as {status_code?: number}).status_code + : undefined; + if (statusCode === 404) { + // Boards group not yet seeded — first board creation will trigger + // doSetupBoardsProperties. + return; + } + throw error; + } +} diff --git a/e2e-tests/playwright/specs/functional/system_console/integration_management/revoke_non_compliant_tokens.spec.ts b/e2e-tests/playwright/specs/functional/system_console/integration_management/revoke_non_compliant_tokens.spec.ts new file mode 100644 index 000000000000..0da88508ebce --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/integration_management/revoke_non_compliant_tokens.spec.ts @@ -0,0 +1,209 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Client4} from '@mattermost/client'; + +import {expect, test, testConfig} from '@mattermost/playwright-lib'; + +/** + * E2E coverage for the "Revoke non-compliant tokens" admin console control added in + * MM-69075 (System Console > Integrations > Integration Management). + * + * A token is non-compliant once ServiceSettings.MaximumPersonalAccessTokenLifetimeDays > 0 + * and the token never expires, or expires beyond that cap. The policy only applies at + * creation time, so every seeded token below is created before the cap is patched in. + * Bot account tokens are exempt regardless of the policy. + * + * The non-compliant count and revoke operation are global (every user's tokens, not just + * the test's own), and this server is shared across concurrently running tests/workers. + * So assertions here check per-token outcomes (does this specific token still authenticate) + * and UI state transitions (enabled/disabled, which banner mode) rather than exact global + * counts, which would be flaky. See commit 56716c3616 for the same lesson learned in the + * server-side store tests. + */ + +const DAY_MS = 24 * 60 * 60 * 1000; +const TOKEN_ROLES = 'system_user system_user_access_token'; + +// Returns whether the given personal access token can still authenticate. The token +// secret is only present on the UserAccessToken returned at creation time. +async function tokenIsUsable(token: string | undefined): Promise { + if (!token) { + throw new Error('Expected a token secret, but none was returned by createUserAccessToken'); + } + + const client = new Client4(); + client.setUrl(testConfig.baseURL); + client.setToken(token); + try { + await client.getMe(); + return true; + } catch { + return false; + } +} + +test.describe('System Console > Integrations > Revoke non-compliant tokens @system_console', () => { + test('disables the button and shows a compliant banner when no policy is configured', async ({pw}) => { + const {adminUser, adminClient, user} = await pw.initSetup(); + await adminClient.patchConfig({ + ServiceSettings: {EnableUserAccessTokens: true, MaximumPersonalAccessTokenLifetimeDays: 0}, + }); + await adminClient.updateUserRoles(user.id, TOKEN_ROLES); + await pw.waitUntil(async () => { + const cfg = await adminClient.getConfig(); + return cfg.ServiceSettings?.MaximumPersonalAccessTokenLifetimeDays === 0; + }); + + // # A never-expiring token is fine while there is no cap + const token = await adminClient.createUserAccessToken(user.id, 'never expires token'); + + const {systemConsolePage, page} = await pw.testBrowser.login(adminUser); + await systemConsolePage.goto(); + await systemConsolePage.toBeVisible(); + await systemConsolePage.sidebar.integrations.integrationManagement.click(); + await page.waitForURL(/\/admin_console\/integrations\/integration_management/); + + const section = page.getByTestId('sysconsole_section_CustomIntegrationSettings'); + await expect(section).toBeVisible(); + + // * With no policy configured the server-side count is always 0 (nothing is + // "non-compliant" without a cap to violate), so the button is deterministically disabled + await expect(section.getByText('No personal access tokens currently need to be revoked.')).toBeVisible(); + await expect(section.getByRole('button', {name: 'Revoke non-compliant tokens'})).toBeDisabled(); + expect(await tokenIsUsable(token.token)).toBe(true); + }); + + test('shows a violation and reveals a confirmation modal that can be dismissed without revoking', async ({pw}) => { + const {adminUser, adminClient, user} = await pw.initSetup(); + await adminClient.patchConfig({ServiceSettings: {EnableUserAccessTokens: true}}); + await adminClient.updateUserRoles(user.id, TOKEN_ROLES); + + // # Seed a never-expiring token while there is no cap, then enable the cap so it becomes non-compliant + const token = await adminClient.createUserAccessToken(user.id, 'never expires token'); + await adminClient.patchConfig({ServiceSettings: {MaximumPersonalAccessTokenLifetimeDays: 30}}); + await pw.waitUntil(async () => { + const cfg = await adminClient.getConfig(); + return cfg.ServiceSettings?.MaximumPersonalAccessTokenLifetimeDays === 30; + }); + + const {systemConsolePage, page} = await pw.testBrowser.login(adminUser); + await systemConsolePage.goto(); + await systemConsolePage.toBeVisible(); + await systemConsolePage.sidebar.integrations.integrationManagement.click(); + await page.waitForURL(/\/admin_console\/integrations\/integration_management/); + + const section = page.getByTestId('sysconsole_section_CustomIntegrationSettings'); + await expect(section).toBeVisible(); + + // * At least one violation is now shown (ours), and the button is enabled + await expect( + section.getByText(/\d+ personal access tokens? currently violates? the maximum lifetime policy\./), + ).toBeVisible(); + const revokeButton = section.getByRole('button', {name: 'Revoke non-compliant tokens'}); + await expect(revokeButton).toBeEnabled(); + + // # Open the confirmation and cancel it + await revokeButton.click(); + const confirmModal = page.locator('#confirmModal'); + await expect(confirmModal.getByText('Revoke non-compliant personal access tokens?')).toBeVisible(); + await expect(confirmModal.getByText(/This will permanently revoke \d+ personal access tokens?/)).toBeVisible(); + await confirmModal.getByRole('button', {name: 'Cancel'}).click(); + await expect(confirmModal).toBeHidden(); + + // * Cancelling did not revoke our token + expect(await tokenIsUsable(token.token)).toBe(true); + }); + + test('revokes non-compliant tokens on confirm, invalidating them while compliant and bot tokens survive', async ({ + pw, + }) => { + const {adminUser, adminClient, user} = await pw.initSetup(); + await adminClient.patchConfig({ + ServiceSettings: {EnableUserAccessTokens: true, EnableBotAccountCreation: true}, + }); + await adminClient.updateUserRoles(user.id, TOKEN_ROLES); + + // # Seed one non-compliant token, one compliant token, and one exempt bot token, all + // # before the cap is enabled so the server allows their creation. + const nonCompliantToken = await adminClient.createUserAccessToken(user.id, 'never expires token'); + const compliantToken = await adminClient.createUserAccessToken( + user.id, + 'compliant token', + Date.now() + 10 * DAY_MS, + ); + const bot = await adminClient.createBot({ + username: `revoke-bot-${user.id.slice(0, 8)}`, + display_name: 'Revoke test bot', + }); + const botToken = await adminClient.createUserAccessToken(bot.user_id, 'bot token'); + + await adminClient.patchConfig({ServiceSettings: {MaximumPersonalAccessTokenLifetimeDays: 30}}); + await pw.waitUntil(async () => { + const cfg = await adminClient.getConfig(); + return cfg.ServiceSettings?.MaximumPersonalAccessTokenLifetimeDays === 30; + }); + + const {systemConsolePage, page} = await pw.testBrowser.login(adminUser); + await systemConsolePage.goto(); + await systemConsolePage.toBeVisible(); + await systemConsolePage.sidebar.integrations.integrationManagement.click(); + await page.waitForURL(/\/admin_console\/integrations\/integration_management/); + + const section = page.getByTestId('sysconsole_section_CustomIntegrationSettings'); + await expect(section).toBeVisible(); + + // # Confirm the revoke + await section.getByRole('button', {name: 'Revoke non-compliant tokens'}).click(); + const confirmModal = page.locator('#confirmModal'); + await confirmModal.getByRole('button', {name: 'Revoke tokens'}).click(); + + // * The success banner reports how many were revoked, and the button disables again + // (nothing left to revoke, since a revoke sweeps every non-compliant token server-wide) + await expect(section.getByText(/Revoked \d+ non-compliant personal access tokens?\./)).toBeVisible(); + await expect(section.getByRole('button', {name: 'Revoke non-compliant tokens'})).toBeDisabled(); + + // * The non-compliant token can no longer authenticate + await expect(async () => { + expect(await tokenIsUsable(nonCompliantToken.token)).toBe(false); + }).toPass(); + + // * The compliant token and the exempt bot token still authenticate + expect(await tokenIsUsable(compliantToken.token)).toBe(true); + expect(await tokenIsUsable(botToken.token)).toBe(true); + }); + + test('refreshes the violation banner after saving a new maximum lifetime policy from the same page', async ({ + pw, + }) => { + const {adminUser, adminClient, user} = await pw.initSetup(); + await adminClient.patchConfig({ + ServiceSettings: {EnableUserAccessTokens: true, MaximumPersonalAccessTokenLifetimeDays: 0}, + }); + await adminClient.updateUserRoles(user.id, TOKEN_ROLES); + + // # Seed a never-expiring token while there is no cap + const token = await adminClient.createUserAccessToken(user.id, 'never expires token'); + + const {systemConsolePage, page} = await pw.testBrowser.login(adminUser); + await systemConsolePage.goto(); + await systemConsolePage.toBeVisible(); + await systemConsolePage.sidebar.integrations.integrationManagement.click(); + await page.waitForURL(/\/admin_console\/integrations\/integration_management/); + + const section = page.getByTestId('sysconsole_section_CustomIntegrationSettings'); + await expect(section).toBeVisible(); + + // # Set a maximum lifetime and save, without leaving the page + const maxLifetimeInput = section.getByTestId('ServiceSettings.MaximumPersonalAccessTokenLifetimeDaysnumber'); + await maxLifetimeInput.fill('30'); + await section.getByRole('button', {name: 'Save'}).click(); + + // * The banner refreshes to flag the newly non-compliant token, without a page reload + await expect( + section.getByText(/\d+ personal access tokens? currently violates? the maximum lifetime policy\./), + ).toBeVisible(); + await expect(section.getByRole('button', {name: 'Revoke non-compliant tokens'})).toBeEnabled(); + expect(await tokenIsUsable(token.token)).toBe(true); + }); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/system_users/user_attributes_admin_editing.spec.ts b/e2e-tests/playwright/specs/functional/system_console/system_users/user_attributes_admin_editing.spec.ts index b9e83f8a391a..e76cd3245dfa 100644 --- a/e2e-tests/playwright/specs/functional/system_console/system_users/user_attributes_admin_editing.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/system_users/user_attributes_admin_editing.spec.ts @@ -16,7 +16,7 @@ import type {Team} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {SystemConsolePage} from '@mattermost/playwright-lib'; import {expect, getRandomId, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/system_users/user_ranked_value_picker.spec.ts b/e2e-tests/playwright/specs/functional/system_console/system_users/user_ranked_value_picker.spec.ts index f4cf3d98f782..33586e1e1cb8 100644 --- a/e2e-tests/playwright/specs/functional/system_console/system_users/user_ranked_value_picker.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/system_users/user_ranked_value_picker.spec.ts @@ -11,7 +11,8 @@ import type {Client4} from '@mattermost/client'; import type {UserProfile} from '@mattermost/types/users'; -import type {UserPropertyField, PropertyFieldOption} from '@mattermost/types/properties'; +import type {PropertyFieldOption} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, getRandomId, test} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/team_configuration/team_profile_edit.spec.ts b/e2e-tests/playwright/specs/functional/system_console/team_configuration/team_profile_edit.spec.ts new file mode 100644 index 000000000000..120fa703ccf9 --- /dev/null +++ b/e2e-tests/playwright/specs/functional/system_console/team_configuration/team_profile_edit.spec.ts @@ -0,0 +1,117 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {expect, test} from '@mattermost/playwright-lib'; + +/** + * @objective Verify a system admin can edit a team's name and description from the + * System Console Team Configuration page and that the changes are persisted. + */ +test('edits team name and description from the System Console', {tag: '@system_console'}, async ({pw}) => { + const {adminUser, adminClient} = await pw.initSetup(); + + // # Create a team with a known name and description + const initialDescription = 'Initial team description'; + const team = await adminClient.createTeam({ + ...(await pw.random.team()), + description: initialDescription, + }); + + // # Log in as a system admin and open the Team Configuration page + const {systemConsolePage} = await pw.testBrowser.login(adminUser); + const {page} = systemConsolePage; + await page.goto(`/admin_console/user_management/teams/${team.id}`); + + const nameInput = page.getByTestId('teamNameInput'); + const descriptionInput = page.getByTestId('teamDescriptionInput'); + + // * Verify the fields are prefilled with the current team values + await expect(nameInput).toHaveValue(team.display_name); + await expect(descriptionInput).toHaveValue(initialDescription); + + // # Edit the team name and description + const newName = `Edited Name ${pw.random.id()}`; + const newDescription = 'Edited team description'; + await nameInput.fill(newName); + await descriptionInput.fill(newDescription); + + // # Save the changes + await page.getByTestId('saveSetting').click(); + + // * Verify the page returns to the teams list after a successful save + await page.waitForURL(/\/admin_console\/user_management\/teams$/); + + // * Verify the changes were persisted on the server + const updatedTeam = await adminClient.getTeam(team.id); + expect(updatedTeam.display_name).toBe(newName); + expect(updatedTeam.description).toBe(newDescription); +}); + +/** + * @objective Verify saving a too-short team name is blocked with an inline validation + * error and does not persist the change. + */ +test('blocks saving a team name shorter than the minimum length', {tag: '@system_console'}, async ({pw}) => { + const {adminUser, adminClient} = await pw.initSetup(); + + // # Create a team to edit + const team = await adminClient.createTeam(await pw.random.team()); + + // # Log in as a system admin and open the Team Configuration page + const {systemConsolePage} = await pw.testBrowser.login(adminUser); + const {page} = systemConsolePage; + await page.goto(`/admin_console/user_management/teams/${team.id}`); + + const nameInput = page.getByTestId('teamNameInput'); + await expect(nameInput).toHaveValue(team.display_name); + + // # Enter a name below the minimum length and try to save + await nameInput.fill('a'); + await page.getByTestId('saveSetting').click(); + + // * Verify an inline validation error is shown and the page stays on the team + await expect(page.getByText('Team name must be 2 or more characters')).toBeVisible(); + expect(new URL(page.url()).pathname).toBe(`/admin_console/user_management/teams/${team.id}`); + + // * Verify the team name was not changed on the server + const unchangedTeam = await adminClient.getTeam(team.id); + expect(unchangedTeam.display_name).toBe(team.display_name); +}); + +/** + * @objective Verify that toggling Archive Team with a too-short team name surfaces the + * inline validation error on Save instead of leaving the "Save and Archive Team" + * confirmation modal stuck open with no feedback. + */ +test('blocks archiving a team when the team name is invalid', {tag: '@system_console'}, async ({pw}) => { + const {adminUser, adminClient} = await pw.initSetup(); + + // # Create a team to edit + const team = await adminClient.createTeam(await pw.random.team()); + + // # Log in as a system admin and open the Team Configuration page + const {systemConsolePage} = await pw.testBrowser.login(adminUser); + const {page} = systemConsolePage; + await page.goto(`/admin_console/user_management/teams/${team.id}`); + + const nameInput = page.getByTestId('teamNameInput'); + await expect(nameInput).toHaveValue(team.display_name); + + // # Enter a name below the minimum length, then toggle the team to be archived + await nameInput.fill('a'); + await page.getByRole('button', {name: 'Archive Team'}).click(); + + // # Try to save the archive + await page.getByTestId('saveSetting').click(); + + // * Verify the inline validation error is shown + await expect(page.getByText('Team name must be 2 or more characters')).toBeVisible(); + + // * Verify the Save and Archive Team confirmation modal did not open + await expect(page.getByText('Save and Archive Team')).not.toBeVisible(); + + // * Verify the team was neither renamed nor archived on the server + const unchangedTeam = await adminClient.getTeam(team.id); + expect(unchangedTeam.display_name).toBe(team.display_name); + expect(unchangedTeam.delete_at).toBe(0); +}); diff --git a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes.spec.ts b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes.spec.ts index f78008671ce5..0398ab21365f 100644 --- a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes.spec.ts @@ -16,7 +16,7 @@ */ import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, getAdminClient, test} from '@mattermost/playwright-lib'; import type {PlaywrightExtended, SystemConsolePage} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_display_name.spec.ts b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_display_name.spec.ts index 0e4a2bbf482a..07f10701501b 100644 --- a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_display_name.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_display_name.spec.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {UserProfile} from '@mattermost/types/users'; import {expect, test, testConfig} from '@mattermost/playwright-lib'; diff --git a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_rank.spec.ts b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_rank.spec.ts index a1680fcea834..5049364a905c 100644 --- a/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_rank.spec.ts +++ b/e2e-tests/playwright/specs/functional/system_console/user_attributes/user_attributes_rank.spec.ts @@ -13,7 +13,7 @@ */ import type {Client4} from '@mattermost/client'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {expect, test} from '@mattermost/playwright-lib'; import type {PlaywrightExtended, SystemConsolePage} from '@mattermost/playwright-lib'; diff --git a/server/.go-version b/server/.go-version index f8f738140964..ea0928cedf0d 100644 --- a/server/.go-version +++ b/server/.go-version @@ -1 +1 @@ -1.26.3 +1.26.4 diff --git a/server/Makefile b/server/Makefile index ebbac487cd32..c91995b3cdd0 100644 --- a/server/Makefile +++ b/server/Makefile @@ -166,7 +166,7 @@ PLUGIN_PACKAGES += mattermost-plugin-playbooks-v2.10.0 PLUGIN_PACKAGES += mattermost-plugin-servicenow-v2.4.0 PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.13.0 PLUGIN_PACKAGES += mattermost-plugin-agents-v2.4.2 -PLUGIN_PACKAGES += mattermost-plugin-boards-v9.3.0-rc2 +PLUGIN_PACKAGES += mattermost-plugin-boards-v9.3.0 PLUGIN_PACKAGES += mattermost-plugin-user-survey-v1.1.1 PLUGIN_PACKAGES += mattermost-plugin-mscalendar-v1.6.1 PLUGIN_PACKAGES += mattermost-plugin-msteams-meetings-v2.4.1 @@ -180,7 +180,7 @@ PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.3.0 ifeq ($(FIPS_ENABLED),true) PLUGIN_PACKAGES = mattermost-plugin-playbooks-v2.10.0%2B090a26d-fips PLUGIN_PACKAGES += mattermost-plugin-agents-v2.4.2%2B1305067-fips - PLUGIN_PACKAGES += mattermost-plugin-boards-v9.3.0-rc2%2B5880c13-fips + PLUGIN_PACKAGES += mattermost-plugin-boards-v9.3.0%2Bd454327-fips endif EE_PACKAGES=$(shell $(GO) list $(BUILD_ENTERPRISE_DIR)/...) diff --git a/server/build/Dockerfile.buildenv b/server/build/Dockerfile.buildenv index 54583233d27f..d19c5ff3e769 100644 --- a/server/build/Dockerfile.buildenv +++ b/server/build/Dockerfile.buildenv @@ -1,4 +1,4 @@ -FROM mattermost/golang-bullseye:1.26.3@sha256:3ae112b7dc291665c5582b9d768fc2adb4cdc3afbbd3fc82e03a10cd711e1a60 +FROM mattermost/golang-bullseye:1.26.4@sha256:6c979d9bf17e17dcd52fa052867f2910a4b9bca3f10d4c439e0b8f233a53d426 ARG NODE_VERSION=20.11.1 RUN apt-get update && apt-get install -y make git apt-transport-https ca-certificates curl software-properties-common build-essential zip xmlsec1 jq pgloader gnupg diff --git a/server/build/Dockerfile.buildenv-fips b/server/build/Dockerfile.buildenv-fips index 9a986d751323..c61a4960e0d5 100644 --- a/server/build/Dockerfile.buildenv-fips +++ b/server/build/Dockerfile.buildenv-fips @@ -1,4 +1,4 @@ -FROM cgr.dev/mattermost.com/go-msft-fips:1.26.3-dev@sha256:48ab99fede7fb33e132a0636072971e1ec4a69520865bfa1e4b517ee9cfdef34 +FROM cgr.dev/mattermost.com/go-msft-fips:1.26.4.1-dev@sha256:e237532162e2a755fef5944d2fcaff02923752c754a5d7b60836b7a8aa682317 ARG NODE_VERSION=20.11.1 RUN apk add curl ca-certificates mailcap unrtf wv poppler-utils tzdata gpg xmlsec diff --git a/server/channels/api4/api.go b/server/channels/api4/api.go index ebbd780b6362..2b053a0a854e 100644 --- a/server/channels/api4/api.go +++ b/server/channels/api4/api.go @@ -516,6 +516,7 @@ func InitLocal(srv *app.Server) *API { api.InitSamlLocal() api.InitCustomProfileAttributesLocal() api.InitAccessControlPolicyLocal() + api.InitStatusLocal() srv.LocalRouter.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) diff --git a/server/channels/api4/status_local.go b/server/channels/api4/status_local.go new file mode 100644 index 000000000000..8e1e8ece0442 --- /dev/null +++ b/server/channels/api4/status_local.go @@ -0,0 +1,11 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package api4 + +import "net/http" + +func (api *API) InitStatusLocal() { + api.BaseRoutes.User.Handle("/status", api.APILocal(getUserStatus)).Methods(http.MethodGet) + api.BaseRoutes.User.Handle("/status", api.APILocal(updateUserStatus)).Methods(http.MethodPut) +} diff --git a/server/channels/api4/user.go b/server/channels/api4/user.go index 17ee820db0fa..e6d273a65147 100644 --- a/server/channels/api4/user.go +++ b/server/channels/api4/user.go @@ -90,6 +90,8 @@ func (api *API) InitUser() { api.BaseRoutes.User.Handle("/tokens", api.APISessionRequired(getUserAccessTokensForUser)).Methods(http.MethodGet) api.BaseRoutes.Users.Handle("/tokens", api.APISessionRequired(getUserAccessTokens)).Methods(http.MethodGet) api.BaseRoutes.Users.Handle("/tokens/search", api.APISessionRequired(searchUserAccessTokens)).Methods(http.MethodPost) + api.BaseRoutes.Users.Handle("/tokens/non_compliant/count", api.APISessionRequired(countNonCompliantUserAccessTokens)).Methods(http.MethodGet) + api.BaseRoutes.Users.Handle("/tokens/non_compliant/revoke", api.APISessionRequired(revokeNonCompliantUserAccessTokens)).Methods(http.MethodPost) api.BaseRoutes.Users.Handle("/tokens/{token_id:[A-Za-z0-9]+}", api.APISessionRequired(getUserAccessToken)).Methods(http.MethodGet) api.BaseRoutes.Users.Handle("/tokens/revoke", api.APISessionRequired(revokeUserAccessToken)).Methods(http.MethodPost) api.BaseRoutes.Users.Handle("/tokens/disable", api.APISessionRequired(disableUserAccessToken)).Methods(http.MethodPost) @@ -3062,6 +3064,58 @@ func getUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { } } +func countNonCompliantUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { + if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { + c.SetPermissionError(model.PermissionManageSystem) + return + } + + count, appErr := c.App.CountNonCompliantUserAccessTokens() + if appErr != nil { + c.Err = appErr + return + } + + js, err := json.Marshal(model.NonCompliantUserAccessTokenResult{Count: count}) + if err != nil { + c.Err = model.NewAppError("countNonCompliantUserAccessTokens", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + + if _, err := w.Write(js); err != nil { + c.Logger.Warn("Error while writing response", mlog.Err(err)) + } +} + +func revokeNonCompliantUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { + auditRec := c.MakeAuditRecord(model.AuditEventRevokeNonCompliantUserAccessTokens, model.AuditStatusFail) + defer c.LogAuditRec(auditRec) + + if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { + c.SetPermissionError(model.PermissionManageSystem) + return + } + + count, appErr := c.App.RevokeNonCompliantUserAccessTokens(c.AppContext) + if appErr != nil { + c.Err = appErr + return + } + + model.AddEventParameterToAuditRec(auditRec, "revoked_count", count) + auditRec.Success() + + js, err := json.Marshal(model.NonCompliantUserAccessTokenResult{Count: count}) + if err != nil { + c.Err = model.NewAppError("revokeNonCompliantUserAccessTokens", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + + if _, err := w.Write(js); err != nil { + c.Logger.Warn("Error while writing response", mlog.Err(err)) + } +} + func getUserAccessTokensForUser(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireUserId() if c.Err != nil { diff --git a/server/channels/api4/user_test.go b/server/channels/api4/user_test.go index 46d9a6ab6f44..b1bec4fa024e 100644 --- a/server/channels/api4/user_test.go +++ b/server/channels/api4/user_test.go @@ -6537,6 +6537,131 @@ func TestGetUserAccessTokens(t *testing.T) { }) } +// seedNonCompliantTokens creates a mix of tokens for a user while no lifetime +// policy is in effect (so never-expiring and far-future tokens can be saved), +// plus a bot token, and returns the IDs of the tokens that should be considered +// non-compliant once a 30-day policy is enabled. +func seedNonCompliantTokens(t *testing.T, th *TestHelper) (nonCompliantIDs []string, compliantID string, botTokenID string) { + t.Helper() + + day := int64(24 * 60 * 60 * 1000) + + // Never-expiring token — non-compliant once a policy requires expiry. + noExpiry, appErr := th.App.CreateUserAccessToken(th.Context, &model.UserAccessToken{UserId: th.BasicUser.Id, Description: "no expiry"}) + require.Nil(t, appErr) + + // Far-future token beyond the 30-day cap — non-compliant. + farFuture, appErr := th.App.CreateUserAccessToken(th.Context, &model.UserAccessToken{UserId: th.BasicUser.Id, Description: "far future", ExpiresAt: model.GetMillis() + 60*day}) + require.Nil(t, appErr) + + // Token expiring within the cap — compliant, must survive. + compliant, appErr := th.App.CreateUserAccessToken(th.Context, &model.UserAccessToken{UserId: th.BasicUser.Id, Description: "compliant", ExpiresAt: model.GetMillis() + 10*day}) + require.Nil(t, appErr) + + // Bot token with no expiry — bots are exempt from the policy, must survive. + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableBotAccountCreation = true }) + bot := th.CreateBotWithSystemAdminClient(t) + botToken, appErr := th.App.CreateUserAccessToken(th.Context, &model.UserAccessToken{UserId: bot.UserId, Description: "bot token"}) + require.Nil(t, appErr) + + return []string{noExpiry.Id, farFuture.Id}, compliant.Id, botToken.Id +} + +func TestGetNonCompliantUserAccessTokenCount(t *testing.T) { + mainHelper.Parallel(t) + + t.Run("forbidden for non-admin", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + _, resp, err := th.Client.GetNonCompliantUserAccessTokenCount(context.Background()) + require.Error(t, err) + CheckForbiddenStatus(t, resp) + }) + + t.Run("returns zero when no policy is configured", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true }) + seedNonCompliantTokens(t, th) + + result, _, err := th.SystemAdminClient.GetNonCompliantUserAccessTokenCount(context.Background()) + require.NoError(t, err) + assert.Equal(t, int64(0), result.Count) + }) + + t.Run("counts only non-compliant non-bot tokens", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true }) + seedNonCompliantTokens(t, th) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.MaximumPersonalAccessTokenLifetimeDays = 30 }) + + result, _, err := th.SystemAdminClient.GetNonCompliantUserAccessTokenCount(context.Background()) + require.NoError(t, err) + assert.Equal(t, int64(2), result.Count) + }) +} + +func TestRevokeNonCompliantUserAccessTokens(t *testing.T) { + mainHelper.Parallel(t) + + t.Run("forbidden for non-admin", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + _, resp, err := th.Client.RevokeNonCompliantUserAccessTokens(context.Background()) + require.Error(t, err) + CheckForbiddenStatus(t, resp) + }) + + t.Run("refused when no policy is configured", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true }) + seedNonCompliantTokens(t, th) + + _, resp, err := th.SystemAdminClient.RevokeNonCompliantUserAccessTokens(context.Background()) + require.Error(t, err) + CheckBadRequestStatus(t, resp) + }) + + t.Run("revokes only non-compliant non-bot tokens", func(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true }) + nonCompliantIDs, compliantID, botTokenID := seedNonCompliantTokens(t, th) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.MaximumPersonalAccessTokenLifetimeDays = 30 }) + + result, _, err := th.SystemAdminClient.RevokeNonCompliantUserAccessTokens(context.Background()) + require.NoError(t, err) + assert.Equal(t, int64(2), result.Count) + + // Non-compliant tokens are gone. + for _, id := range nonCompliantIDs { + _, appErr := th.App.GetUserAccessToken(id, false) + require.NotNil(t, appErr) + } + + // Compliant and bot tokens survive. + _, appErr := th.App.GetUserAccessToken(compliantID, false) + require.Nil(t, appErr) + _, appErr = th.App.GetUserAccessToken(botTokenID, false) + require.Nil(t, appErr) + + // A second run is now a no-op. + result, _, err = th.SystemAdminClient.RevokeNonCompliantUserAccessTokens(context.Background()) + require.NoError(t, err) + assert.Equal(t, int64(0), result.Count) + }) +} + func TestSearchUserAccessToken(t *testing.T) { mainHelper.Parallel(t) diff --git a/server/channels/app/migrations.go b/server/channels/app/migrations.go index 18d6777c3449..352e7e0f4ff7 100644 --- a/server/channels/app/migrations.go +++ b/server/channels/app/migrations.go @@ -5,8 +5,10 @@ package app import ( "context" + "encoding/json" "errors" "fmt" + "maps" "os" "reflect" @@ -33,6 +35,8 @@ const ( contentFlaggingMigrationVersion = "v5" managedCategorySetupDoneKey = "managed_category_setup_done" managedCategoryMigrationVersion = "v2" + boardsPropertySetupDoneKey = "boards_property_setup_done" + boardsPropertyMigrationVersion = "v2" cpaDisplayNameBackfillKey = "cpa_display_name_backfill_done" contentFlaggingPropertyNameFlaggedPostId = "flagged_post_id" @@ -48,9 +52,6 @@ const ( contentFlaggingPropertyManageByContentFlagging = "content_flagging_managed" contentFlaggingPropertySubTypeTimestamp = "timestamp" - - boardsPropertySetupDoneKey = "boards_property_setup_done" - boardsPropertyMigrationVersion = "v1" ) // This function migrates the default built in roles from code/config to the database. @@ -798,6 +799,16 @@ func (s *Server) doSetupBoardsProperties() error { existingPropertiesMap[property.Name] = property } + // Default colours seeded by name. Used both when creating the Status field + // from scratch and when upgrading an existing v1 install (where we layer + // these colours onto the already-persisted options without rewriting their + // IDs — see mergeBoardsStatusColors below). + statusColorByName := map[string]string{ + model.BoardsStatusOptionTodo: model.BoardsStatusColorTodo, + model.BoardsStatusOptionInProgress: model.BoardsStatusColorInProgress, + model.BoardsStatusOptionComplete: model.BoardsStatusColorComplete, + } + expectedPropertiesMap := map[string]*model.PropertyField{ model.BoardsPropertyFieldAssignee: { GroupID: group.ID, @@ -818,9 +829,9 @@ func (s *Server) doSetupBoardsProperties() error { PermissionField: model.NewPointer(model.PermissionLevelNone), Attrs: map[string]any{ "options": []map[string]string{ - {"name": model.BoardsStatusOptionTodo}, - {"name": model.BoardsStatusOptionInProgress}, - {"name": model.BoardsStatusOptionComplete}, + {"name": model.BoardsStatusOptionTodo, "color": model.BoardsStatusColorTodo}, + {"name": model.BoardsStatusOptionInProgress, "color": model.BoardsStatusColorInProgress}, + {"name": model.BoardsStatusOptionComplete, "color": model.BoardsStatusColorComplete}, }, }, }, @@ -833,9 +844,20 @@ func (s *Server) doSetupBoardsProperties() error { if _, exists := existingPropertiesMap[name]; exists { property := existingPropertiesMap[name] property.Type = expectedProperty.Type - property.Attrs = expectedProperty.Attrs property.Protected = expectedProperty.Protected property.PermissionField = expectedProperty.PermissionField + + if name == model.BoardsPropertyFieldStatus { + // Status options already exist (with server-generated IDs from the v1 + // seed). NewPropertyOptionsFromFieldAttrs regenerates IDs for any + // options missing one, so a wholesale attrs replacement would orphan + // every reference. Layer colours onto the existing options by name + // and preserve their IDs. + property.Attrs = mergeBoardsStatusColors(property.Attrs, statusColorByName) + } else { + property.Attrs = expectedProperty.Attrs + } + propertiesToUpdate = append(propertiesToUpdate, property) } else { propertiesToCreate = append(propertiesToCreate, expectedProperty) @@ -873,6 +895,49 @@ func (s *Server) doSetupBoardsProperties() error { return nil } +// mergeBoardsStatusColors layers a name→color map onto the existing options +// stored in `attrs`, preserving every existing option's ID. Used during the +// v1 → v2 boards migration so previously-seeded Status options gain colours +// without having their server-generated IDs regenerated (which would orphan +// any card references). Options whose name isn't in `colorByName` are left +// untouched; admins who renamed seeded options stay in control. +func mergeBoardsStatusColors(attrs model.StringInterface, colorByName map[string]string) model.StringInterface { + if attrs == nil { + return attrs + } + rawOptions, ok := attrs["options"] + if !ok { + return attrs + } + + // attrs is model.StringInterface (map[string]any), so after JSON + // deserialisation rawOptions is []any of map[string]any. Round-trip + // to []map[string]any so the loop below can index each option by + // key without an outer .(map[string]any) assertion per element. + encoded, err := json.Marshal(rawOptions) + if err != nil { + mlog.Warn("Skipping boards Status colour merge: failed to marshal existing options", mlog.Err(err)) + return attrs + } + var options []map[string]any + if err := json.Unmarshal(encoded, &options); err != nil { + mlog.Warn("Skipping boards Status colour merge: failed to unmarshal existing options", mlog.Err(err)) + return attrs + } + + for i, opt := range options { + name, _ := opt["name"].(string) + if color, found := colorByName[name]; found { + options[i]["color"] = color + } + } + + out := make(model.StringInterface, len(attrs)) + maps.Copy(out, attrs) + out["options"] = options + return out +} + // seedSessionAttributeFields idempotently seeds the built-in session attribute property fields. func (s *Server) seedSessionAttributeFields(groupID string) error { existing, err := s.propertyService.SearchPropertyFields(nil, groupID, model.PropertyFieldSearchOpts{PerPage: 100}) diff --git a/server/channels/app/migrations_test.go b/server/channels/app/migrations_test.go index 789d6bd38172..5a81201851e4 100644 --- a/server/channels/app/migrations_test.go +++ b/server/channels/app/migrations_test.go @@ -5,6 +5,8 @@ package app import ( "context" + "encoding/json" + "maps" "sync" "testing" @@ -488,6 +490,15 @@ func TestDoSetupBoardsProperties(t *testing.T) { require.True(t, status.Protected) require.NotNil(t, status.Attrs["options"]) + // v2 seeds a default colour per status option. Verify the three seeded + // options carry the expected colours so kanban columns render with + // their intended palette out of the box. + assertStatusColors(t, status.Attrs, map[string]string{ + model.BoardsStatusOptionTodo: model.BoardsStatusColorTodo, + model.BoardsStatusOptionInProgress: model.BoardsStatusColorInProgress, + model.BoardsStatusOptionComplete: model.BoardsStatusColorComplete, + }) + data, sysErr := th.Store.System().GetByName(boardsPropertySetupDoneKey) require.NoError(t, sysErr) require.Equal(t, boardsPropertyMigrationVersion, data.Value) @@ -514,4 +525,116 @@ func TestDoSetupBoardsProperties(t *testing.T) { require.NoError(t, sysErr) require.Equal(t, boardsPropertyMigrationVersion, data.Value) }) + + t.Run("upgrading v1 → v2 layers colours onto existing options without rewriting their IDs", func(t *testing.T) { + // Setup() already runs v2 cleanly. Simulate a workspace that was + // previously seeded with v1 (no colours) by stripping every colour + // from the Status options and rolling the system flag back to v1. + th := Setup(t) + + group, appErr := th.App.GetPropertyGroup(th.Context, model.BoardsPropertyGroupName) + require.Nil(t, appErr) + + fields, appErr := th.App.SearchPropertyFields(th.Context, group.ID, model.PropertyFieldSearchOpts{PerPage: 100}) + require.Nil(t, appErr) + + var statusBefore *model.PropertyField + for _, f := range fields { + if f.Name == model.BoardsPropertyFieldStatus { + statusBefore = f + break + } + } + require.NotNil(t, statusBefore) + + // Snapshot the option IDs assigned by the v1 seed run so we can verify + // they survive the v2 upgrade. + idsBefore := optionIDsByName(t, statusBefore.Attrs) + require.Len(t, idsBefore, 3) + for _, id := range idsBefore { + require.NotEmpty(t, id) + } + + // Strip colours to simulate the v1 shape, then rewind the version flag. + stripped := stripStatusColors(t, statusBefore.Attrs) + statusBefore.Attrs = stripped + _, _, _, updateErr := th.Server.propertyService.UpdatePropertyFields(th.Context, group.ID, []*model.PropertyField{statusBefore}) + require.NoError(t, updateErr) + + sysErr := th.Store.System().SaveOrUpdate(&model.System{Name: boardsPropertySetupDoneKey, Value: "v1"}) + require.NoError(t, sysErr) + + // Run the migration again — should layer colours back on without + // changing option IDs. + require.NoError(t, th.Server.doSetupBoardsProperties()) + + fields, appErr = th.App.SearchPropertyFields(th.Context, group.ID, model.PropertyFieldSearchOpts{PerPage: 100}) + require.Nil(t, appErr) + var statusAfter *model.PropertyField + for _, f := range fields { + if f.Name == model.BoardsPropertyFieldStatus { + statusAfter = f + break + } + } + require.NotNil(t, statusAfter) + + assertStatusColors(t, statusAfter.Attrs, map[string]string{ + model.BoardsStatusOptionTodo: model.BoardsStatusColorTodo, + model.BoardsStatusOptionInProgress: model.BoardsStatusColorInProgress, + model.BoardsStatusOptionComplete: model.BoardsStatusColorComplete, + }) + + idsAfter := optionIDsByName(t, statusAfter.Attrs) + require.Equal(t, idsBefore, idsAfter, "v2 upgrade must preserve every existing option ID") + }) +} + +func assertStatusColors(t *testing.T, attrs model.StringInterface, want map[string]string) { + t.Helper() + got := map[string]string{} + encoded, err := json.Marshal(attrs["options"]) + require.NoError(t, err) + var options []map[string]any + require.NoError(t, json.Unmarshal(encoded, &options)) + for _, opt := range options { + name, _ := opt["name"].(string) + color, _ := opt["color"].(string) + if name != "" { + got[name] = color + } + } + require.Equal(t, want, got) +} + +func optionIDsByName(t *testing.T, attrs model.StringInterface) map[string]string { + t.Helper() + out := map[string]string{} + encoded, err := json.Marshal(attrs["options"]) + require.NoError(t, err) + var options []map[string]any + require.NoError(t, json.Unmarshal(encoded, &options)) + for _, opt := range options { + name, _ := opt["name"].(string) + id, _ := opt["id"].(string) + if name != "" { + out[name] = id + } + } + return out +} + +func stripStatusColors(t *testing.T, attrs model.StringInterface) model.StringInterface { + t.Helper() + encoded, err := json.Marshal(attrs["options"]) + require.NoError(t, err) + var options []map[string]any + require.NoError(t, json.Unmarshal(encoded, &options)) + for _, opt := range options { + delete(opt, "color") + } + out := make(model.StringInterface, len(attrs)) + maps.Copy(out, attrs) + out["options"] = options + return out } diff --git a/server/channels/app/plugin_hooks_test.go b/server/channels/app/plugin_hooks_test.go index 037adf29e159..e1560aae6aed 100644 --- a/server/channels/app/plugin_hooks_test.go +++ b/server/channels/app/plugin_hooks_test.go @@ -13,7 +13,6 @@ import ( "net/http/httptest" "os" "path/filepath" - "slices" "sort" "strconv" "strings" @@ -2851,58 +2850,16 @@ func TestHookServeMetrics(t *testing.T) { }) } -func assertHookPostExists(t *testing.T, th *TestHelper, channelID, expectedMessage string) { - t.Helper() - - assert.EventuallyWithT(t, func(c *assert.CollectT) { - // Page size 31 bypasses postLastPostsCache (only 30/60 are cached). - posts, appErr := th.App.GetPosts(th.Context, channelID, 0, 31) - if !assert.Nil(c, appErr) { - return - } - - found := false - for _, postID := range posts.Order { - if posts.Posts[postID].Message == expectedMessage { - found = true - break - } - } - assert.True(c, found, "expected hook post %q not found", expectedMessage) - }, 30*time.Second, 100*time.Millisecond) -} - -func assertPluginReadyForHooks(t *testing.T, th *TestHelper, pluginID string, requiredHooks ...string) { - t.Helper() - - assert.Eventually(t, func() bool { - env := th.App.GetPluginsEnvironment() - if env == nil || !env.IsActive(pluginID) { - return false - } - hooks, err := env.HooksForPlugin(pluginID) - if err != nil { - return false - } - if len(requiredHooks) == 0 { - return true - } - implemented, err := hooks.Implemented() - if err != nil { - return false - } - for _, requiredHook := range requiredHooks { - if !slices.Contains(implemented, requiredHook) { - return false - } - } - return true - }, 10*time.Second, 50*time.Millisecond, "plugin %q failed to become ready for hooks", pluginID) -} - func TestUserHasJoinedChannel(t *testing.T) { mainHelper.Parallel(t) - getPluginCode := func(adminUserID string) string { + + // These tests use the KV store to track whether the plugin is activated and whether its hook has been called + const pluginActivatedKey = "activated" + joinedKey := func(channelID, userID string) string { + return fmt.Sprintf("joined_%s_%s", channelID, userID) + } + + getPluginCode := func() string { return ` package main @@ -2913,26 +2870,19 @@ func TestUserHasJoinedChannel(t *testing.T) { "github.com/mattermost/mattermost/server/public/model" ) - const ( - adminUserID = "` + adminUserID + `" - ) - type MyPlugin struct { plugin.MattermostPlugin } - func (p *MyPlugin) UserHasJoinedChannel(c *plugin.Context, channelMember *model.ChannelMember, actor *model.User) { - message := fmt.Sprintf("Test: User %s joined %s", channelMember.UserId, channelMember.ChannelId) - if actor != nil && actor.Id != channelMember.UserId { - message = fmt.Sprintf("Test: User %s added to %s by %s", channelMember.UserId, channelMember.ChannelId, actor.Id) + func (p *MyPlugin) OnActivate() error { + if appErr := p.API.KVSet("` + pluginActivatedKey + `", []byte("true")); appErr != nil { + return appErr } + return nil + } - _, appErr := p.API.CreatePost(&model.Post{ - UserId: adminUserID, - ChannelId: channelMember.ChannelId, - Message: message, - }) - if appErr != nil { + func (p *MyPlugin) UserHasJoinedChannel(c *plugin.Context, channelMember *model.ChannelMember, actor *model.User) { + if appErr := p.API.KVSet(fmt.Sprintf("joined_%s_%s", channelMember.ChannelId, channelMember.UserId), []byte("true")); appErr != nil { panic(appErr) } } @@ -2942,9 +2892,38 @@ func TestUserHasJoinedChannel(t *testing.T) { } ` } - newPluginFixture := func() (string, string) { - pluginID := "testplugin" + model.NewId() - return pluginID, fmt.Sprintf(`{"id": %q, "server": {"executable": "backend.exe"}}`, pluginID) + pluginID := "testplugin" + pluginManifest := `{"id": "testplugin", "server": {"executable": "backend.exe"}}` + + waitForPluginActivated := func(t *testing.T, th *TestHelper) { + t.Helper() + require.EventuallyWithT(t, func(c *assert.CollectT) { + value, appErr := th.App.GetPluginKey(pluginID, pluginActivatedKey) + assert.Nil(c, appErr) + assert.Equal(c, []byte("true"), value) + }, 5*time.Second, 100*time.Millisecond) + } + + assertHookCalled := func(t *testing.T, th *TestHelper, channelID, userID string) { + t.Helper() + assert.EventuallyWithT(t, func(c *assert.CollectT) { + value, appErr := th.App.GetPluginKey(pluginID, joinedKey(channelID, userID)) + assert.Nil(c, appErr) + assert.Equal(c, []byte("true"), value) + }, 5*time.Second, 100*time.Millisecond) + } + + assertHookNotCalled := func(t *testing.T, th *TestHelper, channelID string, userIDs ...string) { + t.Helper() + assert.Never(t, func() bool { + for _, userID := range userIDs { + value, appErr := th.App.GetPluginKey(pluginID, joinedKey(channelID, userID)) + if appErr == nil && value != nil { + return true + } + } + return false + }, 1*time.Second, 100*time.Millisecond) } t.Run("should call hook when a user joins an existing channel", func(t *testing.T) { @@ -2959,25 +2938,22 @@ func TestUserHasJoinedChannel(t *testing.T) { channel, appErr := th.App.CreateChannel(th.Context, &model.Channel{ CreatorId: user1.Id, TeamId: th.BasicTeam.Id, - Name: "test_channel_" + model.NewId(), + Name: "test_channel", Type: model.ChannelTypeOpen, }, false) require.Nil(t, appErr) require.NotNil(t, channel) - pluginID, pluginManifest := newPluginFixture() - // Setup plugin after creating the channel - setupPluginAPITest(t, getPluginCode(th.SystemAdminUser.Id), pluginManifest, pluginID, th.App, th.Context) - assertPluginReadyForHooks(t, th, pluginID, "UserHasJoinedChannel") + setupPluginAPITest(t, getPluginCode(), pluginManifest, pluginID, th.App, th.Context) + waitForPluginActivated(t, th) _, appErr = th.App.AddChannelMember(th.Context, user2.Id, channel, ChannelMemberOpts{ UserRequestorID: user2.Id, }) require.Nil(t, appErr) - expectedMessage := fmt.Sprintf("Test: User %s joined %s", user2.Id, channel.Id) - assertHookPostExists(t, th, channel.Id, expectedMessage) + assertHookCalled(t, th, channel.Id, user2.Id) }) t.Run("should call hook when a user is added to an existing channel", func(t *testing.T) { @@ -2992,129 +2968,81 @@ func TestUserHasJoinedChannel(t *testing.T) { channel, appErr := th.App.CreateChannel(th.Context, &model.Channel{ CreatorId: user1.Id, TeamId: th.BasicTeam.Id, - Name: "test_channel_" + model.NewId(), + Name: "test_channel", Type: model.ChannelTypeOpen, }, false) require.Nil(t, appErr) require.NotNil(t, channel) - pluginID, pluginManifest := newPluginFixture() - // Setup plugin after creating the channel - setupPluginAPITest(t, getPluginCode(th.SystemAdminUser.Id), pluginManifest, pluginID, th.App, th.Context) - assertPluginReadyForHooks(t, th, pluginID, "UserHasJoinedChannel") + setupPluginAPITest(t, getPluginCode(), pluginManifest, pluginID, th.App, th.Context) + waitForPluginActivated(t, th) _, appErr = th.App.AddChannelMember(th.Context, user2.Id, channel, ChannelMemberOpts{ UserRequestorID: user1.Id, }) require.Nil(t, appErr) - expectedMessage := fmt.Sprintf("Test: User %s added to %s by %s", user2.Id, channel.Id, user1.Id) - assertHookPostExists(t, th, channel.Id, expectedMessage) + assertHookCalled(t, th, channel.Id, user2.Id) }) t.Run("should not call hook when a regular channel is created", func(t *testing.T) { mainHelper.Parallel(t) th := Setup(t, StartMetrics).InitBasic(t) - pluginID, pluginManifest := newPluginFixture() - // Setup plugin - setupPluginAPITest(t, getPluginCode(th.SystemAdminUser.Id), pluginManifest, pluginID, th.App, th.Context) - assertPluginReadyForHooks(t, th, pluginID) + setupPluginAPITest(t, getPluginCode(), pluginManifest, pluginID, th.App, th.Context) + waitForPluginActivated(t, th) user1 := th.CreateUser(t) channel, appErr := th.App.CreateChannel(th.Context, &model.Channel{ CreatorId: user1.Id, TeamId: th.BasicTeam.Id, - Name: "test_channel_" + model.NewId(), + Name: "test_channel", Type: model.ChannelTypeOpen, }, false) require.Nil(t, appErr) require.NotNil(t, channel) - var posts *model.PostList - require.EventuallyWithT(t, func(c *assert.CollectT) { - posts, appErr = th.App.GetPosts(th.Context, channel.Id, 0, 10) - assert.Nil(t, appErr) - }, 2*time.Second, 100*time.Millisecond) - - for _, postID := range posts.Order { - post := posts.Posts[postID] - - if strings.HasPrefix(post.Message, "Test: ") { - t.Log("Plugin message found:", post.Message) - t.FailNow() - } - } + assertHookNotCalled(t, th, channel.Id, user1.Id) }) t.Run("should not call hook when a DM is created", func(t *testing.T) { mainHelper.Parallel(t) th := Setup(t, StartMetrics).InitBasic(t) + // Setup plugin + setupPluginAPITest(t, getPluginCode(), pluginManifest, pluginID, th.App, th.Context) + waitForPluginActivated(t, th) + user1 := th.CreateUser(t) user2 := th.CreateUser(t) - pluginID, pluginManifest := newPluginFixture() - - // Setup plugin - setupPluginAPITest(t, getPluginCode(th.SystemAdminUser.Id), pluginManifest, pluginID, th.App, th.Context) - assertPluginReadyForHooks(t, th, pluginID) - channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, user1.Id, user2.Id) require.Nil(t, appErr) require.NotNil(t, channel) - var posts *model.PostList - require.EventuallyWithT(t, func(c *assert.CollectT) { - posts, appErr = th.App.GetPosts(th.Context, channel.Id, 0, 10) - assert.Nil(t, appErr) - }, 2*time.Second, 100*time.Millisecond) - - for _, postID := range posts.Order { - post := posts.Posts[postID] - - if strings.HasPrefix(post.Message, "Test: ") { - t.Log("Plugin message found:", post.Message) - t.FailNow() - } - } + assertHookNotCalled(t, th, channel.Id, user1.Id, user2.Id) }) t.Run("should not call hook when a GM is created", func(t *testing.T) { mainHelper.Parallel(t) th := Setup(t, StartMetrics).InitBasic(t) + // Setup plugin + setupPluginAPITest(t, getPluginCode(), pluginManifest, pluginID, th.App, th.Context) + waitForPluginActivated(t, th) + user1 := th.CreateUser(t) user2 := th.CreateUser(t) user3 := th.CreateUser(t) - pluginID, pluginManifest := newPluginFixture() - - // Setup plugin - setupPluginAPITest(t, getPluginCode(th.SystemAdminUser.Id), pluginManifest, pluginID, th.App, th.Context) - assertPluginReadyForHooks(t, th, pluginID) - channel, appErr := th.App.CreateGroupChannel(th.Context, []string{user1.Id, user2.Id, user3.Id}, user1.Id) require.Nil(t, appErr) require.NotNil(t, channel) - var posts *model.PostList - require.EventuallyWithT(t, func(c *assert.CollectT) { - posts, appErr = th.App.GetPosts(th.Context, channel.Id, 0, 10) - assert.Nil(t, appErr) - }, 2*time.Second, 100*time.Millisecond) - - for _, postID := range posts.Order { - post := posts.Posts[postID] - - if strings.HasPrefix(post.Message, "Test: ") { - t.Log("Plugin message found:", post.Message) - t.FailNow() - } - } + assertHookNotCalled(t, th, channel.Id, user1.Id, user2.Id) }) } diff --git a/server/channels/app/server.go b/server/channels/app/server.go index 1b47c8ef07ae..400296d5d73d 100644 --- a/server/channels/app/server.go +++ b/server/channels/app/server.go @@ -275,6 +275,7 @@ func NewServer(options ...Option) (*Server, error) { {Name: model.AccessControlPropertyGroupName, Version: model.PropertyGroupVersionV2, SchemaVersion: model.AccessControlPropertyGroupSchemaVersion}, {Name: model.SessionAttributesPropertyGroupName, Version: model.PropertyGroupVersionV2}, {Name: model.ContentFlaggingGroupName, Version: model.PropertyGroupVersionV1}, + {Name: model.BoardsPropertyGroupName, Version: model.PropertyGroupVersionV2}, }); err != nil { return nil, errors.Wrap(err, "failed to register builtin property groups") } diff --git a/server/channels/app/session.go b/server/channels/app/session.go index dfa4d1115622..f9b67fbe0aef 100644 --- a/server/channels/app/session.go +++ b/server/channels/app/session.go @@ -699,6 +699,102 @@ func (a *App) RevokeUserAccessToken(rctx request.CTX, token *model.UserAccessTok return a.RevokeSession(rctx, session) } +// revokeNonCompliantBatchLimit bounds both the number of rows fetched by +// GetNonCompliantExpiry and the corresponding DeleteByIds call, keeping the +// transaction footprint bounded even when a large number of tokens are +// non-compliant. revokeNonCompliantMaxBatches caps the iterations of a single +// revoke call so a runaway loop can't develop. +const ( + revokeNonCompliantBatchLimit = 1000 + revokeNonCompliantMaxBatches = 1000 +) + +// maxPersonalAccessTokenExpiry returns the latest ExpiresAt a token may carry to +// comply with the current ServiceSettings.MaximumPersonalAccessTokenLifetimeDays +// policy, along with whether a policy is in effect. When no maximum is +// configured (0), no policy applies and every token is compliant. +func (a *App) maxPersonalAccessTokenExpiry() (maxExpiresAt int64, enabled bool) { + cfg := a.Config().ServiceSettings + + maxDays := int64(0) + if cfg.MaximumPersonalAccessTokenLifetimeDays != nil { + maxDays = int64(*cfg.MaximumPersonalAccessTokenLifetimeDays) + } + + if maxDays <= 0 { + return 0, false + } + + return model.GetMillis() + maxDays*24*60*60*1000, true +} + +// CountNonCompliantUserAccessTokens returns the number of active, non-bot +// personal access tokens that violate the current maximum lifetime policy. It +// lets an admin preview the blast radius before revoking. When no policy is in +// effect it returns 0 — nothing is non-compliant. +func (a *App) CountNonCompliantUserAccessTokens() (int64, *model.AppError) { + maxExpiresAt, enabled := a.maxPersonalAccessTokenExpiry() + if !enabled { + return 0, nil + } + + count, err := a.Srv().Store().UserAccessToken().CountNonCompliantExpiry(maxExpiresAt) + if err != nil { + return 0, model.NewAppError("CountNonCompliantUserAccessTokens", "app.user_access_token.count_non_compliant.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + + return count, nil +} + +// RevokeNonCompliantUserAccessTokens hard-deletes every active, non-bot personal +// access token that violates the current maximum lifetime policy, along with any +// sessions minted from them. It returns the number of tokens actually deleted. +// Work is done in bounded batches to keep transactions small, and the per-user +// session cache is cleared so stale sessions aren't served from memory. When no +// policy is in effect the call is refused — there is nothing to revoke and a +// caller reaching this path likely has a stale view of the config. Auditing is +// the caller's responsibility, matching RevokeUserAccessToken. +func (a *App) RevokeNonCompliantUserAccessTokens(rctx request.CTX) (int64, *model.AppError) { + maxExpiresAt, enabled := a.maxPersonalAccessTokenExpiry() + if !enabled { + return 0, model.NewAppError("RevokeNonCompliantUserAccessTokens", "app.user_access_token.revoke_non_compliant.no_policy.app_error", nil, "", http.StatusBadRequest) + } + + var totalRevoked int64 + allRevoked := false + for range revokeNonCompliantMaxBatches { + userIDs, err := a.Srv().Store().UserAccessToken().DeleteNonCompliantExpiry(maxExpiresAt, revokeNonCompliantBatchLimit) + if err != nil { + return totalRevoked, model.NewAppError("RevokeNonCompliantUserAccessTokens", "app.user_access_token.delete.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + if len(userIDs) == 0 { + allRevoked = true + break + } + + totalRevoked += int64(len(userIDs)) + + seen := make(map[string]struct{}, len(userIDs)) + for _, userID := range userIDs { + if _, ok := seen[userID]; !ok { + seen[userID] = struct{}{} + a.ClearSessionCacheForUser(userID) + } + } + + if len(userIDs) < revokeNonCompliantBatchLimit { + allRevoked = true + break + } + } + + if !allRevoked { + return totalRevoked, model.NewAppError("RevokeNonCompliantUserAccessTokens", "app.user_access_token.revoke_non_compliant.partial.app_error", nil, "", http.StatusInternalServerError) + } + + return totalRevoked, nil +} + func (a *App) DisableUserAccessToken(rctx request.CTX, token *model.UserAccessToken) *model.AppError { var session *model.Session session, _ = a.ch.srv.platform.GetSessionContext(rctx, token.Token) diff --git a/server/channels/store/retrylayer/retrylayer.go b/server/channels/store/retrylayer/retrylayer.go index 7114c1d2601f..f10d4be8059c 100644 --- a/server/channels/store/retrylayer/retrylayer.go +++ b/server/channels/store/retrylayer/retrylayer.go @@ -18021,6 +18021,27 @@ func (s *RetryLayerUserStore) VerifyEmail(userID string, email string) (string, } +func (s *RetryLayerUserAccessTokenStore) CountNonCompliantExpiry(maxExpiresAt int64) (int64, error) { + + tries := 0 + for { + result, err := s.UserAccessTokenStore.CountNonCompliantExpiry(maxExpiresAt) + if err == nil { + return result, nil + } + if !isRepeatableError(err) { + return result, err + } + tries++ + if tries >= 3 { + err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures") + return result, err + } + timepkg.Sleep(100 * timepkg.Millisecond) + } + +} + func (s *RetryLayerUserAccessTokenStore) Delete(tokenID string) error { tries := 0 @@ -18084,6 +18105,27 @@ func (s *RetryLayerUserAccessTokenStore) DeleteByIds(tokenIDs []string) (int64, } +func (s *RetryLayerUserAccessTokenStore) DeleteNonCompliantExpiry(maxExpiresAt int64, limit int) ([]string, error) { + + tries := 0 + for { + result, err := s.UserAccessTokenStore.DeleteNonCompliantExpiry(maxExpiresAt, limit) + if err == nil { + return result, nil + } + if !isRepeatableError(err) { + return result, err + } + tries++ + if tries >= 3 { + err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures") + return result, err + } + timepkg.Sleep(100 * timepkg.Millisecond) + } + +} + func (s *RetryLayerUserAccessTokenStore) Get(tokenID string) (*model.UserAccessToken, error) { tries := 0 diff --git a/server/channels/store/sqlstore/user_access_token_store.go b/server/channels/store/sqlstore/user_access_token_store.go index ba33898c35c7..e35a11ffa63b 100644 --- a/server/channels/store/sqlstore/user_access_token_store.go +++ b/server/channels/store/sqlstore/user_access_token_store.go @@ -270,6 +270,65 @@ func (s SqlUserAccessTokenStore) GetExpiredBefore(cutoff int64, limit int) ([]*m return tokens, nil } +// CountNonCompliantExpiry returns the number of active, non-bot tokens that +// violate the maximum lifetime policy implied by maxExpiresAt. It is used to +// preview the blast radius before revoking. +func (s SqlUserAccessTokenStore) CountNonCompliantExpiry(maxExpiresAt int64) (int64, error) { + query := s.getQueryBuilder(). + Select("COUNT(*)"). + From("UserAccessTokens"). + Where(sq.Or{ + sq.Eq{"UserAccessTokens.ExpiresAt": 0}, + sq.Gt{"UserAccessTokens.ExpiresAt": maxExpiresAt}, + }). + Where(sq.Eq{"UserAccessTokens.IsActive": true}). + Where(sq.Expr("UserAccessTokens.UserId NOT IN (SELECT UserId FROM Bots)")) + + var count int64 + if err := s.GetReplica().GetBuilder(&count, query); err != nil { + return 0, errors.Wrap(err, "failed to count non-compliant UserAccessTokens") + } + + return count, nil +} + +// DeleteNonCompliantExpiry hard-deletes up to limit non-compliant tokens and +// their associated sessions in a single transaction, returning one UserId per +// deleted token row so the caller can count deletions and clear per-user +// session caches. A non-positive limit returns nil without hitting the DB. +func (s SqlUserAccessTokenStore) DeleteNonCompliantExpiry(maxExpiresAt int64, limit int) ([]string, error) { + if limit <= 0 { + return nil, nil + } + + sql := ` +WITH to_delete AS ( + SELECT Id, Token, UserId + FROM UserAccessTokens + WHERE (ExpiresAt = 0 OR ExpiresAt > $1) + AND IsActive = true + AND UserId NOT IN (SELECT UserId FROM Bots) + LIMIT $2 +), +deleted_sessions AS ( + DELETE FROM Sessions + WHERE Token IN (SELECT Token FROM to_delete) +), +deleted_tokens AS ( + DELETE FROM UserAccessTokens + WHERE Id IN (SELECT Id FROM to_delete) + RETURNING UserId +) +SELECT UserId FROM deleted_tokens` + + var userIDs []string + if err := s.GetMaster().Select(&userIDs, sql, maxExpiresAt, limit); err != nil { + return nil, errors.Wrap(err, "failed to delete non-compliant UserAccessTokens") + } + + return userIDs, nil +} + // DeleteByIds deletes the tokens identified by tokenIDs along with any sessions // minted from those tokens, all within a single transaction. It returns the // number of UserAccessTokens rows actually deleted. diff --git a/server/channels/store/store.go b/server/channels/store/store.go index 0d0dbdd0c8fd..66d490db0670 100644 --- a/server/channels/store/store.go +++ b/server/channels/store/store.go @@ -852,6 +852,8 @@ type UserAccessTokenStore interface { GetByToken(tokenString string) (*model.UserAccessToken, error) GetByUser(userID string, page, perPage int) ([]*model.UserAccessToken, error) GetExpiredBefore(cutoff int64, limit int) ([]*model.UserAccessToken, error) + CountNonCompliantExpiry(maxExpiresAt int64) (int64, error) + DeleteNonCompliantExpiry(maxExpiresAt int64, limit int) ([]string, error) Search(term string) ([]*model.UserAccessToken, error) UpdateTokenEnable(tokenID string) error UpdateTokenDisable(tokenID string) error diff --git a/server/channels/store/storetest/mocks/UserAccessTokenStore.go b/server/channels/store/storetest/mocks/UserAccessTokenStore.go index 8ac6117e3db1..0546df2c54a4 100644 --- a/server/channels/store/storetest/mocks/UserAccessTokenStore.go +++ b/server/channels/store/storetest/mocks/UserAccessTokenStore.go @@ -14,6 +14,34 @@ type UserAccessTokenStore struct { mock.Mock } +// CountNonCompliantExpiry provides a mock function with given fields: maxExpiresAt +func (_m *UserAccessTokenStore) CountNonCompliantExpiry(maxExpiresAt int64) (int64, error) { + ret := _m.Called(maxExpiresAt) + + if len(ret) == 0 { + panic("no return value specified for CountNonCompliantExpiry") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(int64) (int64, error)); ok { + return rf(maxExpiresAt) + } + if rf, ok := ret.Get(0).(func(int64) int64); ok { + r0 = rf(maxExpiresAt) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(maxExpiresAt) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Delete provides a mock function with given fields: tokenID func (_m *UserAccessTokenStore) Delete(tokenID string) error { ret := _m.Called(tokenID) @@ -78,6 +106,36 @@ func (_m *UserAccessTokenStore) DeleteByIds(tokenIDs []string) (int64, error) { return r0, r1 } +// DeleteNonCompliantExpiry provides a mock function with given fields: maxExpiresAt, limit +func (_m *UserAccessTokenStore) DeleteNonCompliantExpiry(maxExpiresAt int64, limit int) ([]string, error) { + ret := _m.Called(maxExpiresAt, limit) + + if len(ret) == 0 { + panic("no return value specified for DeleteNonCompliantExpiry") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(int64, int) ([]string, error)); ok { + return rf(maxExpiresAt, limit) + } + if rf, ok := ret.Get(0).(func(int64, int) []string); ok { + r0 = rf(maxExpiresAt, limit) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(int64, int) error); ok { + r1 = rf(maxExpiresAt, limit) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Get provides a mock function with given fields: tokenID func (_m *UserAccessTokenStore) Get(tokenID string) (*model.UserAccessToken, error) { ret := _m.Called(tokenID) diff --git a/server/channels/store/storetest/user_access_token_store.go b/server/channels/store/storetest/user_access_token_store.go index 6f9723844834..bea2ab936147 100644 --- a/server/channels/store/storetest/user_access_token_store.go +++ b/server/channels/store/storetest/user_access_token_store.go @@ -19,6 +19,7 @@ func TestUserAccessTokenStore(t *testing.T, rctx request.CTX, ss store.Store) { t.Run("UserAccessTokenSearch", func(t *testing.T) { testUserAccessTokenSearch(t, rctx, ss) }) t.Run("UserAccessTokenPagination", func(t *testing.T) { testUserAccessTokenPagination(t, rctx, ss) }) t.Run("UserAccessTokenExpiry", func(t *testing.T) { testUserAccessTokenExpiry(t, rctx, ss) }) + t.Run("UserAccessTokenNonCompliant", func(t *testing.T) { testUserAccessTokenNonCompliant(t, rctx, ss) }) } func testUserAccessTokenSaveGetDelete(t *testing.T, rctx request.CTX, ss store.Store) { @@ -356,3 +357,152 @@ func testUserAccessTokenExpiry(t *testing.T, rctx request.CTX, ss store.Store) { require.NoError(t, err) require.Equal(t, int64(0), deleted) } + +func testUserAccessTokenNonCompliant(t *testing.T, rctx request.CTX, ss store.Store) { + now := model.GetMillis() + day := int64(24 * 60 * 60 * 1000) + // maxExpiresAt is the latest expiry a 30-day policy permits. + maxExpiresAt := now + 30*day + // farCap is a much larger cap: only never-expiring tokens violate it. + farCap := now + 1000*day + + // The store counts non-compliant tokens DB-wide and other suite fixtures may + // linger, so assert deltas against a baseline rather than absolute totals. + baseline30, err := ss.UserAccessToken().CountNonCompliantExpiry(maxExpiresAt) + require.NoError(t, err) + baselineFar, err := ss.UserAccessToken().CountNonCompliantExpiry(farCap) + require.NoError(t, err) + + // Never-expiring active token — non-compliant. + noExpiry := &model.UserAccessToken{Token: model.NewId(), UserId: model.NewId(), Description: "no expiry"} + _, err = ss.UserAccessToken().Save(noExpiry) + require.NoError(t, err) + + // Active token expiring beyond the cap — non-compliant. + farFuture := &model.UserAccessToken{Token: model.NewId(), UserId: model.NewId(), Description: "far future", ExpiresAt: now + 60*day} + _, err = ss.UserAccessToken().Save(farFuture) + require.NoError(t, err) + + // Active token expiring within the cap — compliant. + compliant := &model.UserAccessToken{Token: model.NewId(), UserId: model.NewId(), Description: "compliant", ExpiresAt: now + 10*day} + _, err = ss.UserAccessToken().Save(compliant) + require.NoError(t, err) + + // Disabled never-expiring token — non-compliant by expiry, but inactive + // tokens cannot authenticate and are excluded. + inactive := &model.UserAccessToken{Token: model.NewId(), UserId: model.NewId(), Description: "inactive"} + _, err = ss.UserAccessToken().Save(inactive) + require.NoError(t, err) + require.NoError(t, ss.UserAccessToken().UpdateTokenDisable(inactive.Id)) + + // Never-expiring token owned by a bot — bots are exempt and excluded. + botUser, err := ss.User().Save(rctx, model.UserFromBot(&model.Bot{Username: "noncompliant_bot", OwnerId: model.NewId()})) + require.NoError(t, err) + _, nErr := ss.Bot().Save(&model.Bot{UserId: botUser.Id, Username: botUser.Username, OwnerId: model.NewId()}) + require.NoError(t, nErr) + botToken := &model.UserAccessToken{Token: model.NewId(), UserId: botUser.Id, Description: "bot token"} + _, err = ss.UserAccessToken().Save(botToken) + require.NoError(t, err) + + // Two non-compliant tokens owned by the same user — verifies that the + // returned slice has one entry per deleted token row, not one per user. + sharedUserID := model.NewId() + multiA := &model.UserAccessToken{Token: model.NewId(), UserId: sharedUserID, Description: "multi A"} + _, err = ss.UserAccessToken().Save(multiA) + require.NoError(t, err) + multiB := &model.UserAccessToken{Token: model.NewId(), UserId: sharedUserID, Description: "multi B", ExpiresAt: now + 60*day} + _, err = ss.UserAccessToken().Save(multiB) + require.NoError(t, err) + + // Sessions minted from the non-compliant tokens — DeleteNonCompliantExpiry + // must remove these along with the tokens. + noExpirySession, nErr := ss.Session().Save(rctx, &model.Session{Token: noExpiry.Token, UserId: noExpiry.UserId}) + require.NoError(t, nErr) + farFutureSession, nErr := ss.Session().Save(rctx, &model.Session{Token: farFuture.Token, UserId: farFuture.UserId}) + require.NoError(t, nErr) + + t.Cleanup(func() { + // noExpiry, farFuture, multiA, multiB are deleted by DeleteNonCompliantExpiry; + // only surviving tokens need explicit cleanup. + _ = ss.UserAccessToken().Delete(compliant.Id) + _ = ss.UserAccessToken().Delete(inactive.Id) + _ = ss.UserAccessToken().Delete(botToken.Id) + _ = ss.Bot().PermanentDelete(botUser.Id) + _ = ss.User().PermanentDelete(rctx, botUser.Id) + }) + + // Against the 30-day cap, at least our four active non-bot violators are counted. + // Use GreaterOrEqual to avoid flakiness from concurrent tests that may also + // hold non-compliant tokens when this test runs. + count, err := ss.UserAccessToken().CountNonCompliantExpiry(maxExpiresAt) + require.NoError(t, err) + require.GreaterOrEqual(t, count, baseline30+4) + + // A non-positive limit is a no-op. + noop, err := ss.UserAccessToken().DeleteNonCompliantExpiry(maxExpiresAt, 0) + require.NoError(t, err) + require.Empty(t, noop) + + // DeleteNonCompliantExpiry deletes all violators and their sessions, returns + // one UserId per deleted token row (not per user), and leaves + // compliant/inactive/bot tokens untouched. + // Use GreaterOrEqual for the same reason as the count check above. + userIDs, err := ss.UserAccessToken().DeleteNonCompliantExpiry(maxExpiresAt, 10000) + require.NoError(t, err) + require.GreaterOrEqual(t, len(userIDs), 4, "should return at least our four deleted tokens") + // Verify sharedUserID appears exactly twice — once per token, not once per user. + // This specifically guards against a SELECT DISTINCT regression. + sharedOccurrences := 0 + gotUserIDs := map[string]bool{} + for _, id := range userIDs { + gotUserIDs[id] = true + if id == sharedUserID { + sharedOccurrences++ + } + } + require.Equal(t, 2, sharedOccurrences, "sharedUserID should appear once per deleted token, not once per user") + require.True(t, gotUserIDs[noExpiry.UserId], "user of never-expiring token should be returned") + require.True(t, gotUserIDs[farFuture.UserId], "user of far-future token should be returned") + require.True(t, gotUserIDs[sharedUserID], "shared user with multiple tokens should be returned") + require.False(t, gotUserIDs[compliant.UserId], "compliant token user must not be returned") + require.False(t, gotUserIDs[inactive.UserId], "inactive token user must not be returned") + require.False(t, gotUserIDs[botToken.UserId], "bot token user must not be returned") + + // Token rows are gone. + _, err = ss.UserAccessToken().Get(noExpiry.Id) + require.Error(t, err, "never-expiring token should be deleted") + _, err = ss.UserAccessToken().Get(farFuture.Id) + require.Error(t, err, "far-future token should be deleted") + _, err = ss.UserAccessToken().Get(multiA.Id) + require.Error(t, err, "shared-user token A should be deleted") + _, err = ss.UserAccessToken().Get(multiB.Id) + require.Error(t, err, "shared-user token B should be deleted") + + // Sessions for deleted tokens are gone. + _, nErr = ss.Session().Get(rctx, noExpirySession.Token) + require.Error(t, nErr, "session for never-expiring token should be deleted") + _, nErr = ss.Session().Get(rctx, farFutureSession.Token) + require.Error(t, nErr, "session for far-future token should be deleted") + + // Surviving tokens are untouched. + _, err = ss.UserAccessToken().Get(compliant.Id) + require.NoError(t, err, "compliant token must survive") + _, err = ss.UserAccessToken().Get(inactive.Id) + require.NoError(t, err, "inactive token must survive") + _, err = ss.UserAccessToken().Get(botToken.Id) + require.NoError(t, err, "bot token must survive") + + // Count is back to at most baseline after deletion (could be lower if our + // delete swept up tokens from other concurrent tests; could equal baseline if + // no concurrent tests hold non-compliant tokens right now). + count, err = ss.UserAccessToken().CountNonCompliantExpiry(maxExpiresAt) + require.NoError(t, err) + require.LessOrEqual(t, count, baseline30) + + // Against the much larger cap, the never-expiring tokens were the only + // violators among our fixtures; after deletion the count should not exceed + // the baseline measured before we created anything. + count, err = ss.UserAccessToken().CountNonCompliantExpiry(farCap) + require.NoError(t, err) + require.LessOrEqual(t, count, baselineFar, "count under large cap must not exceed pre-test baseline") +} diff --git a/server/channels/store/timerlayer/timerlayer.go b/server/channels/store/timerlayer/timerlayer.go index 4afe96bce700..02f925b42f66 100644 --- a/server/channels/store/timerlayer/timerlayer.go +++ b/server/channels/store/timerlayer/timerlayer.go @@ -14241,6 +14241,22 @@ func (s *TimerLayerUserStore) VerifyEmail(userID string, email string) (string, return result, err } +func (s *TimerLayerUserAccessTokenStore) CountNonCompliantExpiry(maxExpiresAt int64) (int64, error) { + start := time.Now() + + result, err := s.UserAccessTokenStore.CountNonCompliantExpiry(maxExpiresAt) + + elapsed := float64(time.Since(start)) / float64(time.Second) + if s.Root.Metrics != nil { + success := "false" + if err == nil { + success = "true" + } + s.Root.Metrics.ObserveStoreMethodDuration("UserAccessTokenStore.CountNonCompliantExpiry", success, elapsed) + } + return result, err +} + func (s *TimerLayerUserAccessTokenStore) Delete(tokenID string) error { start := time.Now() @@ -14289,6 +14305,22 @@ func (s *TimerLayerUserAccessTokenStore) DeleteByIds(tokenIDs []string) (int64, return result, err } +func (s *TimerLayerUserAccessTokenStore) DeleteNonCompliantExpiry(maxExpiresAt int64, limit int) ([]string, error) { + start := time.Now() + + result, err := s.UserAccessTokenStore.DeleteNonCompliantExpiry(maxExpiresAt, limit) + + elapsed := float64(time.Since(start)) / float64(time.Second) + if s.Root.Metrics != nil { + success := "false" + if err == nil { + success = "true" + } + s.Root.Metrics.ObserveStoreMethodDuration("UserAccessTokenStore.DeleteNonCompliantExpiry", success, elapsed) + } + return result, err +} + func (s *TimerLayerUserAccessTokenStore) Get(tokenID string) (*model.UserAccessToken, error) { start := time.Now() diff --git a/server/cmd/mmctl/client/client.go b/server/cmd/mmctl/client/client.go index 3e130447ae15..3c9b3ac5f8c2 100644 --- a/server/cmd/mmctl/client/client.go +++ b/server/cmd/mmctl/client/client.go @@ -91,6 +91,8 @@ type Client interface { ConvertBotToUser(ctx context.Context, userID string, userPatch *model.UserPatch, setSystemAdmin bool) (*model.User, *model.Response, error) PromoteGuestToUser(ctx context.Context, userID string) (*model.Response, error) DemoteUserToGuest(ctx context.Context, guestID string) (*model.Response, error) + GetUserStatus(ctx context.Context, userID, etag string) (*model.Status, *model.Response, error) + UpdateUserStatus(ctx context.Context, userID string, userStatus *model.Status) (*model.Status, *model.Response, error) CreateCommand(ctx context.Context, cmd *model.Command) (*model.Command, *model.Response, error) ListCommands(ctx context.Context, teamID string, customOnly bool) ([]*model.Command, *model.Response, error) GetCommandById(ctx context.Context, cmdID string) (*model.Command, *model.Response, error) diff --git a/server/cmd/mmctl/commands/channel.go b/server/cmd/mmctl/commands/channel.go index 5e1399292c47..aecc221dc4ba 100644 --- a/server/cmd/mmctl/commands/channel.go +++ b/server/cmd/mmctl/commands/channel.go @@ -133,6 +133,8 @@ func init() { ChannelRenameCmd.Flags().String("name", "", "Channel Name") ChannelRenameCmd.Flags().String("display-name", "", "Channel Display Name") + ListChannelsCmd.Flags().BoolP("show-ids", "i", false, "Show channel IDs") + SearchChannelCmd.Flags().String("team", "", "Team name or ID") MoveChannelCmd.Flags().Bool("force", false, "Remove users that are not members of target team before moving the channel.") @@ -270,6 +272,12 @@ func getAllDeletedChannelsForTeam(c client.Client, teamID string) ([]*model.Chan func listChannelsCmdF(c client.Client, cmd *cobra.Command, args []string) error { teams := getTeamsFromTeamArgs(c, args) + showIds, _ := cmd.Flags().GetBool("show-ids") + namePrefix := "{{.Name}}" + if showIds { + namePrefix = "{{.Id}}: {{.Name}}" + } + var multierr *multierror.Error for i, team := range teams { if team == nil { @@ -285,7 +293,7 @@ func listChannelsCmdF(c client.Client, cmd *cobra.Command, args []string) error multierr = multierror.Append(multierr, err) } for _, channel := range publicChannels { - printer.PrintT("{{.Name}}", channel) + printer.PrintT(namePrefix, channel) } deletedChannels, err := getAllDeletedChannelsForTeam(c, team.Id) @@ -294,7 +302,7 @@ func listChannelsCmdF(c client.Client, cmd *cobra.Command, args []string) error multierr = multierror.Append(multierr, err) } for _, channel := range deletedChannels { - printer.PrintT("{{.Name}} (archived)", channel) + printer.PrintT(namePrefix+" (archived)", channel) } privateChannels, appErr := getPrivateChannels(c, team.Id) @@ -303,7 +311,7 @@ func listChannelsCmdF(c client.Client, cmd *cobra.Command, args []string) error multierr = multierror.Append(multierr, appErr) } for _, channel := range privateChannels { - printer.PrintT("{{.Name}} (private)", channel) + printer.PrintT(namePrefix+" (private)", channel) } } diff --git a/server/cmd/mmctl/commands/channel_test.go b/server/cmd/mmctl/commands/channel_test.go index d0c02537a48e..7b687671dee0 100644 --- a/server/cmd/mmctl/commands/channel_test.go +++ b/server/cmd/mmctl/commands/channel_test.go @@ -800,6 +800,130 @@ func (s *MmctlUnitTestSuite) TestListChannelsCmd() { s.Require().Equal(printer.GetLines()[1], publicChannel2) }) + s.Run("Show channel IDs with --show-ids", func() { + printer.Clean() + printer.SetFormat(printer.FormatPlain) + defer printer.SetFormat(printer.FormatJSON) + + args := []string{teamID} + cmd := &cobra.Command{} + cmd.Flags().Bool("show-ids", true, "") + + team := &model.Team{ + Id: teamID, + } + + publicChannel := &model.Channel{Id: "publicChannelId1", Name: "publicChannel1"} + archivedChannel := &model.Channel{Id: "archivedChannelId1", Name: "archivedChannel1"} + privateChannel := &model.Channel{Id: "privateChannelId1", Name: "privateChannel1"} + + s.client. + EXPECT(). + GetTeam(context.TODO(), teamID, ""). + Return(team, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetPublicChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return([]*model.Channel{publicChannel}, &model.Response{}, nil). + Times(1) + s.client. + EXPECT(). + GetPublicChannelsForTeam(context.TODO(), teamID, 1, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetDeletedChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return([]*model.Channel{archivedChannel}, &model.Response{}, nil). + Times(1) + s.client. + EXPECT(). + GetDeletedChannelsForTeam(context.TODO(), teamID, 1, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetPrivateChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return([]*model.Channel{privateChannel}, &model.Response{}, nil). + Times(1) + s.client. + EXPECT(). + GetPrivateChannelsForTeam(context.TODO(), teamID, 1, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + err := listChannelsCmdF(s.client, cmd, args) + + s.Require().Nil(err) + s.Len(printer.GetErrorLines(), 0) + s.Len(printer.GetLines(), 3) + s.Require().Equal("publicChannelId1: publicChannel1", printer.GetLines()[0]) + s.Require().Equal("archivedChannelId1: archivedChannel1 (archived)", printer.GetLines()[1]) + s.Require().Equal("privateChannelId1: privateChannel1 (private)", printer.GetLines()[2]) + }) + + s.Run("Omit channel IDs without --show-ids", func() { + printer.Clean() + printer.SetFormat(printer.FormatPlain) + defer printer.SetFormat(printer.FormatJSON) + + args := []string{teamID} + cmd := &cobra.Command{} + + team := &model.Team{ + Id: teamID, + } + + publicChannel := &model.Channel{Id: "publicChannelId1", Name: "publicChannel1"} + + s.client. + EXPECT(). + GetTeam(context.TODO(), teamID, ""). + Return(team, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetPublicChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return([]*model.Channel{publicChannel}, &model.Response{}, nil). + Times(1) + s.client. + EXPECT(). + GetPublicChannelsForTeam(context.TODO(), teamID, 1, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetDeletedChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetPrivateChannelsForTeam(context.TODO(), teamID, 0, web.PerPageMaximum, ""). + Return(emptyChannels, &model.Response{}, nil). + Times(1) + + err := listChannelsCmdF(s.client, cmd, args) + + s.Require().Nil(err) + s.Len(printer.GetErrorLines(), 0) + s.Len(printer.GetLines(), 1) + s.Require().Equal("publicChannel1", printer.GetLines()[0]) + }) + + s.Run("show-ids flag is registered on the command", func() { + flag := ListChannelsCmd.Flags().Lookup("show-ids") + s.Require().NotNil(flag) + s.Require().Equal("i", flag.Shorthand) + s.Require().Equal("false", flag.DefValue) + }) + s.Run("Team with archived channels", func() { printer.Clean() diff --git a/server/cmd/mmctl/commands/user.go b/server/cmd/mmctl/commands/user.go index 979aa9fe556a..421dff8e96f0 100644 --- a/server/cmd/mmctl/commands/user.go +++ b/server/cmd/mmctl/commands/user.go @@ -12,6 +12,7 @@ import ( "os" "sort" "testing" + "time" "github.com/mattermost/mattermost/server/public/model" "github.com/stretchr/testify/require" @@ -22,6 +23,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" ) var UserCmd = &cobra.Command{ @@ -211,6 +213,38 @@ var DemoteUserToGuestCmd = &cobra.Command{ Args: cobra.MinimumNArgs(1), } +var UserStatusCmd = &cobra.Command{ + Use: "status", + Short: "Get a user's status", + Long: "Get a user's presence status: online, away, dnd or offline.", + Example: ` # You can get the status of the currently authenticated user + $ mmctl user status + + # You can get the status of a specific user + $ mmctl user status --user user@example.com + + # In local mode there is no authenticated user, so the --user flag is required + $ mmctl --local user status --user user@example.com`, + Args: cobra.NoArgs, + RunE: withClient(userStatusGetCmdF), +} + +var UserStatusSetCmd = &cobra.Command{ + Use: "set [status]", + Short: "Set a user's status", + Long: "Set a user's presence status. Allowed values are online, away, dnd and offline.", + Example: ` # You can set the status of the currently authenticated user + $ mmctl user status set away + + # You can set the status of a specific user + $ mmctl user status set --user user@example.com dnd + + # You can set a "dnd" status that expires at a given time (ISO 8601) + $ mmctl user status set --user user@example.com --dnd-end-time 2100-01-02T15:04:05-07:00 dnd`, + Args: cobra.ExactArgs(1), + RunE: withClient(userStatusSetCmdF), +} + var UserConvertCmd = &cobra.Command{ Use: "convert (--bot [emails] [usernames] [userIds] | --user --password PASSWORD [--email EMAIL])", Short: "Convert users to bots, or a bot to a user", @@ -368,6 +402,10 @@ func init() { UserConvertCmd.Flags().String("locale", "", "The locale (ex: en, fr) for converted new user account. Required when the \"bot\" flag is set") UserConvertCmd.Flags().Bool("system-admin", false, "If supplied, the converted user will be a system administrator. Defaults to false. Required when the \"bot\" flag is set") + UserStatusCmd.Flags().String("user", "", "Optional. The user (specified by email, username or ID) whose status to get. Defaults to the currently authenticated user. Required in local mode.") + UserStatusSetCmd.Flags().String("user", "", "Optional. The user (specified by email, username or ID) whose status to set. Defaults to the currently authenticated user. Required in local mode.") + UserStatusSetCmd.Flags().String("dnd-end-time", "", "Optional. The time at which a \"dnd\" status expires, formatted as ISO 8601 (e.g. 2006-01-02T15:04:05-07:00). Only valid with the \"dnd\" status.") + ChangePasswordUserCmd.Flags().StringP("current", "c", "", "The current password of the user. Use only if changing your own password") ChangePasswordUserCmd.Flags().StringP("password", "p", "", "The new password for the user") ChangePasswordUserCmd.Flags().Bool("hashed", false, "The supplied password is already hashed") @@ -423,8 +461,12 @@ Global Flags: MigrateAuthCmd, PromoteGuestToUserCmd, DemoteUserToGuestCmd, + UserStatusCmd, PreferenceCmd, ) + UserStatusCmd.AddCommand( + UserStatusSetCmd, + ) PreferenceCmd.AddCommand( PreferenceListCmd, PreferenceGetCmd, @@ -746,7 +788,8 @@ first_name: {{.FirstName}} last_name: {{.LastName}} email: {{.Email}} auth_service: {{.AuthService}} -auth_data: {{.AuthData}}` +auth_data: {{.AuthData}} +roles: {{.Roles}}` if i > 0 { tpl = "------------------------------\n" + tpl } @@ -1072,6 +1115,91 @@ func demoteUserToGuestCmdF(c client.Client, _ *cobra.Command, userArgs []string) return errs.ErrorOrNil() } +// resolveStatusTargetUser resolves the user whose status a command operates on. +// When the --user flag is omitted, it falls back to the currently authenticated +// user, which is unavailable in local mode. +func resolveStatusTargetUser(c client.Client, cmd *cobra.Command) (*model.User, error) { + userArg, _ := cmd.Flags().GetString("user") + if userArg != "" { + return getUserFromArg(c, userArg) + } + + if viper.GetBool("local") { + return nil, errors.New("the --user flag is required in local mode") + } + + me, _, err := c.GetMe(context.TODO(), "") + if err != nil { + return nil, fmt.Errorf("could not retrieve the current user: %w", err) + } + return me, nil +} + +func userStatusGetCmdF(c client.Client, cmd *cobra.Command, _ []string) error { + printer.SetSingle(true) + + user, err := resolveStatusTargetUser(c, cmd) + if err != nil { + return err + } + + status, _, err := c.GetUserStatus(context.TODO(), user.Id, "") + if err != nil { + return fmt.Errorf("could not get status for user %s: %w", user.Id, err) + } + + printer.PrintT("@"+user.Username+" has status: {{.Status}}", status) + return nil +} + +func userStatusSetCmdF(c client.Client, cmd *cobra.Command, args []string) error { + printer.SetSingle(true) + + newStatus := args[0] + switch newStatus { + case model.StatusOnline, model.StatusAway, model.StatusDnd, model.StatusOffline: + default: + return fmt.Errorf("invalid status %q, must be one of: %s, %s, %s, %s", newStatus, model.StatusOnline, model.StatusAway, model.StatusDnd, model.StatusOffline) + } + + dndEndTimeArg, _ := cmd.Flags().GetString("dnd-end-time") + if dndEndTimeArg != "" && newStatus != model.StatusDnd { + return fmt.Errorf("the --dnd-end-time flag can only be used with the %q status", model.StatusDnd) + } + + var dndEndTime int64 + if dndEndTimeArg != "" { + endTime, err := time.Parse(time.RFC3339, dndEndTimeArg) + if err != nil { + return fmt.Errorf("invalid dnd-end-time %q, expected RFC3339 format (e.g. 2006-01-02T15:04:05-07:00 or 2006-01-02T15:04:05Z)", dndEndTimeArg) + } + if !endTime.After(time.Now()) { + return errors.New("dnd-end-time must be in the future") + } + // DNDEndTime is expressed in seconds rather than milliseconds. + dndEndTime = endTime.Unix() + } + + user, err := resolveStatusTargetUser(c, cmd) + if err != nil { + return err + } + + status := &model.Status{ + UserId: user.Id, + Status: newStatus, + DNDEndTime: dndEndTime, + } + + updatedStatus, _, err := c.UpdateUserStatus(context.TODO(), user.Id, status) + if err != nil { + return fmt.Errorf("could not set status for user %s: %w", user.Id, err) + } + + printer.PrintT("Set status of @"+user.Username+" to status: {{.Status}}", updatedStatus) + return nil +} + func userEditCompletionF(ctx context.Context, c client.Client, cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) >= 1 { return nil, cobra.ShellCompDirectiveNoFileComp diff --git a/server/cmd/mmctl/commands/user_e2e_test.go b/server/cmd/mmctl/commands/user_e2e_test.go index 0b149afe6f68..f053b9a27b35 100644 --- a/server/cmd/mmctl/commands/user_e2e_test.go +++ b/server/cmd/mmctl/commands/user_e2e_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "net/http" + "time" "github.com/hashicorp/go-multierror" "github.com/mattermost/mattermost/server/public/model" @@ -1812,3 +1813,173 @@ func (s *MmctlE2ETestSuite) TestUserEditAuthdataCmd() { s.Require().Equal(newAuthdata, *updatedUser.AuthData) }) } + +func (s *MmctlE2ETestSuite) TestUserStatusGetCmd() { + s.SetupTestHelper().InitBasic(s.T()) + + s.RunForSystemAdminAndLocal("Get the status of a specific user", func(c client.Client) { + printer.Clean() + + s.th.App.SaveAndBroadcastStatus(&model.Status{UserId: s.th.BasicUser.Id, Status: model.StatusOnline, Manual: true}) + + cmd := newUserStatusCmd() + s.Require().NoError(cmd.Flags().Set("user", s.th.BasicUser.Email)) + + err := userStatusGetCmdF(c, cmd, []string{}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + status, ok := printer.GetLines()[0].(*model.Status) + s.Require().True(ok) + s.Require().Equal(s.th.BasicUser.Id, status.UserId) + s.Require().Equal(model.StatusOnline, status.Status) + }) + + s.Run("Get the status of the authenticated user when --user is omitted", func() { + printer.Clean() + + s.th.App.SaveAndBroadcastStatus(&model.Status{UserId: s.th.SystemAdminUser.Id, Status: model.StatusOnline, Manual: true}) + + err := userStatusGetCmdF(s.th.SystemAdminClient, newUserStatusCmd(), []string{}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + status, ok := printer.GetLines()[0].(*model.Status) + s.Require().True(ok) + s.Require().Equal(s.th.SystemAdminUser.Id, status.UserId) + s.Require().Equal(model.StatusOnline, status.Status) + }) + + s.Run("A regular user can read another user's status", func() { + printer.Clean() + + s.th.App.SaveAndBroadcastStatus(&model.Status{UserId: s.th.BasicUser2.Id, Status: model.StatusOnline, Manual: true}) + + cmd := newUserStatusCmd() + s.Require().NoError(cmd.Flags().Set("user", s.th.BasicUser2.Email)) + + err := userStatusGetCmdF(s.th.Client, cmd, []string{}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + status, ok := printer.GetLines()[0].(*model.Status) + s.Require().True(ok) + s.Require().Equal(s.th.BasicUser2.Id, status.UserId) + s.Require().Equal(model.StatusOnline, status.Status) + }) + + s.RunForAllClients("Get the status of a nonexistent user", func(c client.Client) { + printer.Clean() + + cmd := newUserStatusCmd() + s.Require().NoError(cmd.Flags().Set("user", "nonexistent@example.com")) + + err := userStatusGetCmdF(c, cmd, []string{}) + s.Require().EqualError(err, "user nonexistent@example.com not found") + s.Require().Len(printer.GetLines(), 0) + }) +} + +func (s *MmctlE2ETestSuite) TestUserStatusSetCmd() { + s.SetupTestHelper().InitBasic(s.T()) + + s.RunForSystemAdminAndLocal("Set the status of a specific user", func(c client.Client) { + printer.Clean() + + cmd := newUserStatusSetCmd() + s.Require().NoError(cmd.Flags().Set("user", s.th.BasicUser.Email)) + + err := userStatusSetCmdF(c, cmd, []string{model.StatusDnd}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + status, ok := printer.GetLines()[0].(*model.Status) + s.Require().True(ok) + s.Require().Equal(model.StatusDnd, status.Status) + + stored, appErr := s.th.App.GetStatus(s.th.BasicUser.Id) + s.Require().Nil(appErr) + s.Require().Equal(model.StatusDnd, stored.Status) + }) + + s.RunForSystemAdminAndLocal("Set a dnd status with an end time", func(c client.Client) { + printer.Clean() + + endTimeArg := time.Now().Add(2 * time.Hour).Format(ISO8601Layout) + endTime, err := time.Parse(ISO8601Layout, endTimeArg) + s.Require().NoError(err) + + cmd := newUserStatusSetCmd() + s.Require().NoError(cmd.Flags().Set("user", s.th.BasicUser.Email)) + s.Require().NoError(cmd.Flags().Set("dnd-end-time", endTimeArg)) + + err = userStatusSetCmdF(c, cmd, []string{model.StatusDnd}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + stored, appErr := s.th.App.GetStatus(s.th.BasicUser.Id) + s.Require().Nil(appErr) + s.Require().Equal(model.StatusDnd, stored.Status) + // The server truncates the DND end time to the minute to align with the expiry job. + s.Require().Equal(endTime.Truncate(model.DNDExpiryInterval).Unix(), stored.DNDEndTime) + }) + + s.Run("Set the status of the authenticated user when --user is omitted", func() { + printer.Clean() + + err := userStatusSetCmdF(s.th.SystemAdminClient, newUserStatusSetCmd(), []string{model.StatusAway}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + stored, appErr := s.th.App.GetStatus(s.th.SystemAdminUser.Id) + s.Require().Nil(appErr) + s.Require().Equal(model.StatusAway, stored.Status) + }) + + s.Run("A regular user can set their own status when --user is omitted", func() { + printer.Clean() + + // Seed a distinct starting status so the read-back proves the write happened + // rather than passing on leftover state from earlier subtests. + s.th.App.SaveAndBroadcastStatus(&model.Status{UserId: s.th.BasicUser.Id, Status: model.StatusDnd, Manual: true}) + + err := userStatusSetCmdF(s.th.Client, newUserStatusSetCmd(), []string{model.StatusAway}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + + status, ok := printer.GetLines()[0].(*model.Status) + s.Require().True(ok) + s.Require().Equal(model.StatusAway, status.Status) + + stored, appErr := s.th.App.GetStatus(s.th.BasicUser.Id) + s.Require().Nil(appErr) + s.Require().Equal(model.StatusAway, stored.Status) + }) + + s.Run("A regular user cannot set another user's status", func() { + printer.Clean() + + cmd := newUserStatusSetCmd() + s.Require().NoError(cmd.Flags().Set("user", s.th.SystemAdminUser.Email)) + + err := userStatusSetCmdF(s.th.Client, cmd, []string{model.StatusOnline}) + s.Require().Error(err) + s.CheckErrorID(err, "api.context.permissions.app_error") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Reject an invalid status value", func() { + printer.Clean() + + err := userStatusSetCmdF(s.th.SystemAdminClient, newUserStatusSetCmd(), []string{"busy"}) + s.Require().EqualError(err, "invalid status \"busy\", must be one of: online, away, dnd, offline") + s.Require().Len(printer.GetLines(), 0) + }) +} diff --git a/server/cmd/mmctl/commands/user_test.go b/server/cmd/mmctl/commands/user_test.go index b84cc3488c44..61d388bcbb9d 100644 --- a/server/cmd/mmctl/commands/user_test.go +++ b/server/cmd/mmctl/commands/user_test.go @@ -10,6 +10,7 @@ import ( "net/http" "os" "strings" + "time" "github.com/mattermost/mattermost/server/public/model" @@ -18,6 +19,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func (s *MmctlUnitTestSuite) TestUserActivateCmd() { @@ -614,6 +616,27 @@ func (s *MmctlUnitTestSuite) TestSearchUserCmd() { s.Require().Len(printer.GetErrorLines(), 0) }) + s.Run("Plain output includes the user's roles", func() { + printer.Clean() + printer.SetFormat(printer.FormatPlain) + defer printer.SetFormat(printer.FormatJSON) + + emailArg := "example@example.com" + mockUser := &model.User{Username: "ExampleUser", Email: emailArg, Roles: "system_user system_admin"} + + s.client. + EXPECT(). + GetUserByEmail(context.TODO(), emailArg, ""). + Return(mockUser, &model.Response{}, nil). + Times(1) + + err := searchUserCmdF(s.client, &cobra.Command{}, []string{emailArg}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 1) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Contains(printer.GetLines()[0], "roles: system_user system_admin") + }) + s.Run("Search for a nonexistent user", func() { printer.Clean() arg := "example@example.com" @@ -3119,3 +3142,362 @@ func (s *MmctlUnitTestSuite) TestUserEditAuthdataCmd() { s.Require().EqualError(err, "failed to update user authdata: API error") }) } + +func newUserStatusCmd() *cobra.Command { + cmd := &cobra.Command{} + cmd.Flags().String("user", "", "") + return cmd +} + +func newUserStatusSetCmd() *cobra.Command { + cmd := newUserStatusCmd() + cmd.Flags().String("dnd-end-time", "", "") + return cmd +} + +func (s *MmctlUnitTestSuite) TestUserStatusCmdWiring() { + s.Run("status command is registered under user with a set subcommand", func() { + s.Require().True(UserCmd.HasSubCommands()) + s.Require().Contains(UserCmd.Commands(), UserStatusCmd) + s.Require().Contains(UserStatusCmd.Commands(), UserStatusSetCmd) + }) + + s.Run("the expected flags are registered", func() { + s.Require().NotNil(UserStatusCmd.Flags().Lookup("user")) + s.Require().NotNil(UserStatusSetCmd.Flags().Lookup("user")) + s.Require().NotNil(UserStatusSetCmd.Flags().Lookup("dnd-end-time")) + }) + + s.Run("argument contracts are enforced", func() { + s.Require().NoError(UserStatusCmd.Args(UserStatusCmd, []string{})) + s.Require().Error(UserStatusCmd.Args(UserStatusCmd, []string{"online"})) + s.Require().NoError(UserStatusSetCmd.Args(UserStatusSetCmd, []string{"online"})) + s.Require().Error(UserStatusSetCmd.Args(UserStatusSetCmd, []string{})) + }) +} + +func (s *MmctlUnitTestSuite) TestUserStatusGetCmd() { + s.Run("Get status of the current user when --user is omitted", func() { + printer.Clean() + + mockUser := model.User{Id: "me-id", Username: "me"} + mockStatus := &model.Status{UserId: "me-id", Status: model.StatusOnline} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUserStatus(context.TODO(), "me-id", ""). + Return(mockStatus, &model.Response{}, nil). + Times(1) + + err := userStatusGetCmdF(s.client, newUserStatusCmd(), []string{}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(mockStatus, printer.GetLines()[0]) + }) + + s.Run("Get status of a specific user via --user", func() { + printer.Clean() + + cmd := newUserStatusCmd() + err := cmd.Flags().Set("user", "target@example.com") + s.Require().NoError(err) + + mockUser := model.User{Id: "target-id", Username: "target", Email: "target@example.com"} + mockStatus := &model.Status{UserId: "target-id", Status: model.StatusDnd} + + s.client. + EXPECT(). + GetUserByEmail(context.TODO(), "target@example.com", ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUserStatus(context.TODO(), "target-id", ""). + Return(mockStatus, &model.Response{}, nil). + Times(1) + + err = userStatusGetCmdF(s.client, cmd, []string{}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(mockStatus, printer.GetLines()[0]) + }) + + s.Run("Require --user in local mode", func() { + printer.Clean() + prevLocal := viper.GetBool("local") + viper.Set("local", true) + defer viper.Set("local", prevLocal) + + err := userStatusGetCmdF(s.client, newUserStatusCmd(), []string{}) + s.Require().EqualError(err, "the --user flag is required in local mode") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Return error when status retrieval fails", func() { + printer.Clean() + + mockUser := model.User{Id: "me-id", Username: "me"} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUserStatus(context.TODO(), "me-id", ""). + Return(nil, &model.Response{}, errors.New("status error")). + Times(1) + + err := userStatusGetCmdF(s.client, newUserStatusCmd(), []string{}) + s.Require().EqualError(err, "could not get status for user me-id: status error") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Return error when user cannot be found", func() { + printer.Clean() + + cmd := newUserStatusCmd() + err := cmd.Flags().Set("user", "ghost") + s.Require().NoError(err) + + s.client. + EXPECT(). + GetUserByUsername(context.TODO(), "ghost", ""). + Return(nil, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUser(context.TODO(), "ghost", ""). + Return(nil, &model.Response{}, nil). + Times(1) + + err = userStatusGetCmdF(s.client, cmd, []string{}) + s.Require().EqualError(err, "user ghost not found") + s.Require().Len(printer.GetLines(), 0) + }) +} + +func (s *MmctlUnitTestSuite) TestUserStatusSetCmd() { + s.Run("Set status of the current user when --user is omitted", func() { + printer.Clean() + + mockUser := model.User{Id: "me-id", Username: "me"} + wantStatus := &model.Status{UserId: "me-id", Status: model.StatusAway} + returnedStatus := &model.Status{UserId: "me-id", Status: model.StatusAway, Manual: true} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + UpdateUserStatus(context.TODO(), "me-id", wantStatus). + Return(returnedStatus, &model.Response{}, nil). + Times(1) + + err := userStatusSetCmdF(s.client, newUserStatusSetCmd(), []string{model.StatusAway}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(returnedStatus, printer.GetLines()[0]) + }) + + s.Run("Set status of a specific user via --user", func() { + printer.Clean() + + cmd := newUserStatusSetCmd() + err := cmd.Flags().Set("user", "target@example.com") + s.Require().NoError(err) + + mockUser := model.User{Id: "target-id", Username: "target", Email: "target@example.com"} + wantStatus := &model.Status{UserId: "target-id", Status: model.StatusOffline} + + s.client. + EXPECT(). + GetUserByEmail(context.TODO(), "target@example.com", ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + UpdateUserStatus(context.TODO(), "target-id", wantStatus). + Return(wantStatus, &model.Response{}, nil). + Times(1) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusOffline}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(wantStatus, printer.GetLines()[0]) + }) + + s.Run("Set dnd status with an end time", func() { + printer.Clean() + + endTimeArg := time.Now().Add(24 * time.Hour).Format(ISO8601Layout) + endTime, err := time.Parse(ISO8601Layout, endTimeArg) + s.Require().NoError(err) + + cmd := newUserStatusSetCmd() + err = cmd.Flags().Set("dnd-end-time", endTimeArg) + s.Require().NoError(err) + + mockUser := model.User{Id: "me-id", Username: "me"} + wantStatus := &model.Status{UserId: "me-id", Status: model.StatusDnd, DNDEndTime: endTime.Unix()} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + UpdateUserStatus(context.TODO(), "me-id", wantStatus). + Return(wantStatus, &model.Response{}, nil). + Times(1) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusDnd}) + s.Require().NoError(err) + s.Require().Len(printer.GetErrorLines(), 0) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(wantStatus, printer.GetLines()[0]) + }) + + s.Run("Reject an invalid status value", func() { + printer.Clean() + + err := userStatusSetCmdF(s.client, newUserStatusSetCmd(), []string{"busy"}) + s.Require().EqualError(err, "invalid status \"busy\", must be one of: online, away, dnd, offline") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Reject --dnd-end-time with a non-dnd status", func() { + printer.Clean() + + cmd := newUserStatusSetCmd() + err := cmd.Flags().Set("dnd-end-time", time.Now().Add(time.Hour).Format(ISO8601Layout)) + s.Require().NoError(err) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusAway}) + s.Require().EqualError(err, "the --dnd-end-time flag can only be used with the \"dnd\" status") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Set dnd status with a UTC end time", func() { + printer.Clean() + + endTime := time.Now().Add(24 * time.Hour).UTC().Truncate(time.Second) + endTimeArg := endTime.Format(time.RFC3339) + + cmd := newUserStatusSetCmd() + err := cmd.Flags().Set("dnd-end-time", endTimeArg) + s.Require().NoError(err) + + mockUser := model.User{Id: "me-id", Username: "me"} + wantStatus := &model.Status{UserId: "me-id", Status: model.StatusDnd, DNDEndTime: endTime.Unix()} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + UpdateUserStatus(context.TODO(), "me-id", wantStatus). + Return(wantStatus, &model.Response{}, nil). + Times(1) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusDnd}) + s.Require().NoError(err) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(wantStatus, printer.GetLines()[0]) + }) + + s.Run("Reject a dnd-end-time in the past", func() { + printer.Clean() + + cmd := newUserStatusSetCmd() + err := cmd.Flags().Set("dnd-end-time", time.Now().Add(-time.Hour).Format(ISO8601Layout)) + s.Require().NoError(err) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusDnd}) + s.Require().EqualError(err, "dnd-end-time must be in the future") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Reject a malformed dnd-end-time", func() { + printer.Clean() + + cmd := newUserStatusSetCmd() + err := cmd.Flags().Set("dnd-end-time", "not-a-time") + s.Require().NoError(err) + + err = userStatusSetCmdF(s.client, cmd, []string{model.StatusDnd}) + s.Require().EqualError(err, "invalid dnd-end-time \"not-a-time\", expected RFC3339 format (e.g. 2006-01-02T15:04:05-07:00 or 2006-01-02T15:04:05Z)") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Return error when the current user cannot be resolved", func() { + printer.Clean() + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(nil, &model.Response{}, errors.New("me error")). + Times(1) + + err := userStatusSetCmdF(s.client, newUserStatusSetCmd(), []string{model.StatusOnline}) + s.Require().EqualError(err, "could not retrieve the current user: me error") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Require --user in local mode", func() { + printer.Clean() + prevLocal := viper.GetBool("local") + viper.Set("local", true) + defer viper.Set("local", prevLocal) + + err := userStatusSetCmdF(s.client, newUserStatusSetCmd(), []string{model.StatusOnline}) + s.Require().EqualError(err, "the --user flag is required in local mode") + s.Require().Len(printer.GetLines(), 0) + }) + + s.Run("Return error when status update fails", func() { + printer.Clean() + + mockUser := model.User{Id: "me-id", Username: "me"} + wantStatus := &model.Status{UserId: "me-id", Status: model.StatusOnline} + + s.client. + EXPECT(). + GetMe(context.TODO(), ""). + Return(&mockUser, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + UpdateUserStatus(context.TODO(), "me-id", wantStatus). + Return(nil, &model.Response{}, errors.New("update error")). + Times(1) + + err := userStatusSetCmdF(s.client, newUserStatusSetCmd(), []string{model.StatusOnline}) + s.Require().EqualError(err, "could not set status for user me-id: update error") + s.Require().Len(printer.GetLines(), 0) + }) +} diff --git a/server/cmd/mmctl/docs/mmctl_channel_list.rst b/server/cmd/mmctl/docs/mmctl_channel_list.rst index c96aca0f5b74..482a26922659 100644 --- a/server/cmd/mmctl/docs/mmctl_channel_list.rst +++ b/server/cmd/mmctl/docs/mmctl_channel_list.rst @@ -29,7 +29,8 @@ Options :: - -h, --help help for list + -h, --help help for list + -i, --show-ids Show channel IDs Options inherited from parent commands ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/server/cmd/mmctl/docs/mmctl_user.rst b/server/cmd/mmctl/docs/mmctl_user.rst index 5e01be8965c3..84033ee79e0e 100644 --- a/server/cmd/mmctl/docs/mmctl_user.rst +++ b/server/cmd/mmctl/docs/mmctl_user.rst @@ -54,5 +54,6 @@ SEE ALSO * `mmctl user reset-password `_ - Send users an email to reset their password * `mmctl user resetmfa `_ - Turn off MFA * `mmctl user search `_ - Search for users +* `mmctl user status `_ - Get a user's status * `mmctl user verify `_ - Mark user's email as verified diff --git a/server/cmd/mmctl/docs/mmctl_user_status.rst b/server/cmd/mmctl/docs/mmctl_user_status.rst new file mode 100644 index 000000000000..be0e4752fde8 --- /dev/null +++ b/server/cmd/mmctl/docs/mmctl_user_status.rst @@ -0,0 +1,60 @@ +.. _mmctl_user_status: + +mmctl user status +----------------- + +Get a user's status + +Synopsis +~~~~~~~~ + + +Get a user's presence status: online, away, dnd or offline. + +:: + + mmctl user status [flags] + +Examples +~~~~~~~~ + +:: + + # You can get the status of the currently authenticated user + $ mmctl user status + + # You can get the status of a specific user + $ mmctl user status --user user@example.com + + # In local mode there is no authenticated user, so the --user flag is required + $ mmctl --local user status --user user@example.com + +Options +~~~~~~~ + +:: + + -h, --help help for status + --user string Optional. The user (specified by email, username or ID) whose status to get. Defaults to the currently authenticated user. Required in local mode. + +Options inherited from parent commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + --config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") + --disable-pager disables paged output + --insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 + --insecure-tls-version allows to use TLS versions 1.0 and 1.1 + --json the output format will be in json format + --local allows communicating with the server through a unix socket + --quiet prevent mmctl to generate output for the commands + --strict will only run commands if the mmctl version matches the server one + --suppress-warnings disables printing warning messages + +SEE ALSO +~~~~~~~~ + +* `mmctl user `_ - Management of users +* `mmctl user status set `_ - Set a user's status + diff --git a/server/cmd/mmctl/docs/mmctl_user_status_set.rst b/server/cmd/mmctl/docs/mmctl_user_status_set.rst new file mode 100644 index 000000000000..3725498042f3 --- /dev/null +++ b/server/cmd/mmctl/docs/mmctl_user_status_set.rst @@ -0,0 +1,60 @@ +.. _mmctl_user_status_set: + +mmctl user status set +--------------------- + +Set a user's status + +Synopsis +~~~~~~~~ + + +Set a user's presence status. Allowed values are online, away, dnd and offline. + +:: + + mmctl user status set [status] [flags] + +Examples +~~~~~~~~ + +:: + + # You can set the status of the currently authenticated user + $ mmctl user status set away + + # You can set the status of a specific user + $ mmctl user status set --user user@example.com dnd + + # You can set a "dnd" status that expires at a given time (ISO 8601) + $ mmctl user status set --user user@example.com --dnd-end-time 2100-01-02T15:04:05-07:00 dnd + +Options +~~~~~~~ + +:: + + --dnd-end-time string Optional. The time at which a "dnd" status expires, formatted as ISO 8601 (e.g. 2006-01-02T15:04:05-07:00). Only valid with the "dnd" status. + -h, --help help for set + --user string Optional. The user (specified by email, username or ID) whose status to set. Defaults to the currently authenticated user. Required in local mode. + +Options inherited from parent commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + --config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config") + --disable-pager disables paged output + --insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1 + --insecure-tls-version allows to use TLS versions 1.0 and 1.1 + --json the output format will be in json format + --local allows communicating with the server through a unix socket + --quiet prevent mmctl to generate output for the commands + --strict will only run commands if the mmctl version matches the server one + --suppress-warnings disables printing warning messages + +SEE ALSO +~~~~~~~~ + +* `mmctl user status `_ - Get a user's status + diff --git a/server/cmd/mmctl/mocks/client_mock.go b/server/cmd/mmctl/mocks/client_mock.go index 44e0d8a2f377..ece5e6bd3536 100644 --- a/server/cmd/mmctl/mocks/client_mock.go +++ b/server/cmd/mmctl/mocks/client_mock.go @@ -1564,6 +1564,22 @@ func (mr *MockClientMockRecorder) GetUserByUsername(arg0, arg1, arg2 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockClient)(nil).GetUserByUsername), arg0, arg1, arg2) } +// GetUserStatus mocks base method. +func (m *MockClient) GetUserStatus(arg0 context.Context, arg1, arg2 string) (*model.Status, *model.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUserStatus", arg0, arg1, arg2) + ret0, _ := ret[0].(*model.Status) + ret1, _ := ret[1].(*model.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetUserStatus indicates an expected call of GetUserStatus. +func (mr *MockClientMockRecorder) GetUserStatus(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserStatus", reflect.TypeOf((*MockClient)(nil).GetUserStatus), arg0, arg1, arg2) +} + // GetUsers mocks base method. func (m *MockClient) GetUsers(arg0 context.Context, arg1, arg2 int, arg3 string) ([]*model.User, *model.Response, error) { m.ctrl.T.Helper() @@ -2575,6 +2591,22 @@ func (mr *MockClientMockRecorder) UpdateUserRoles(arg0, arg1, arg2 interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserRoles", reflect.TypeOf((*MockClient)(nil).UpdateUserRoles), arg0, arg1, arg2) } +// UpdateUserStatus mocks base method. +func (m *MockClient) UpdateUserStatus(arg0 context.Context, arg1 string, arg2 *model.Status) (*model.Status, *model.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateUserStatus", arg0, arg1, arg2) + ret0, _ := ret[0].(*model.Status) + ret1, _ := ret[1].(*model.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// UpdateUserStatus indicates an expected call of UpdateUserStatus. +func (mr *MockClientMockRecorder) UpdateUserStatus(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserStatus", reflect.TypeOf((*MockClient)(nil).UpdateUserStatus), arg0, arg1, arg2) +} + // UploadData mocks base method. func (m *MockClient) UploadData(arg0 context.Context, arg1 string, arg2 io.Reader) (*model.FileInfo, *model.Response, error) { m.ctrl.T.Helper() diff --git a/server/go.mod b/server/go.mod index 1d42904099d7..12dfe66a4f68 100644 --- a/server/go.mod +++ b/server/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/server/v8 -go 1.26.3 +go 1.26.4 require ( code.sajari.com/docconv/v2 v2.0.0-pre.4 diff --git a/server/i18n/en.json b/server/i18n/en.json index bb7f3b59512c..d5d740c997ba 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -9654,6 +9654,10 @@ "id": "app.user.verify_email.app_error", "translation": "Unable to update verify email field." }, + { + "id": "app.user_access_token.count_non_compliant.app_error", + "translation": "Unable to count the personal access tokens that violate the maximum lifetime policy." + }, { "id": "app.user_access_token.delete.app_error", "translation": "Unable to delete the personal access token." @@ -9690,6 +9694,14 @@ "id": "app.user_access_token.invalid_or_missing", "translation": "Invalid or missing token." }, + { + "id": "app.user_access_token.revoke_non_compliant.no_policy.app_error", + "translation": "No maximum personal access token lifetime is configured, so there are no non-compliant tokens to revoke." + }, + { + "id": "app.user_access_token.revoke_non_compliant.partial.app_error", + "translation": "The batch limit was reached before all non-compliant tokens could be revoked. Run the operation again to continue." + }, { "id": "app.user_access_token.save.app_error", "translation": "Unable to save the personal access token." diff --git a/server/public/go.mod b/server/public/go.mod index a1db0e3b1979..e0dd19cff457 100644 --- a/server/public/go.mod +++ b/server/public/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/server/public -go 1.26.3 +go 1.26.4 require ( github.com/Masterminds/semver/v3 v3.5.0 diff --git a/server/public/model/audit_events.go b/server/public/model/audit_events.go index 1f60ca130011..d9d0405ca8dc 100644 --- a/server/public/model/audit_events.go +++ b/server/public/model/audit_events.go @@ -453,45 +453,46 @@ const ( // Users const ( - AuditEventAttachDeviceId = "attachDeviceId" // attach device IDs (standard or VoIP) to user session for mobile app - AuditEventCreateUser = "createUser" // create user account - AuditEventCreateUserAccessToken = "createUserAccessToken" // create personal access token for user API access - AuditEventDeleteUser = "deleteUser" // delete user account - AuditEventDemoteUserToGuest = "demoteUserToGuest" // demote regular user to guest account with limited permissions - AuditEventDisableUserAccessToken = "disableUserAccessToken" // disable user personal access token - AuditEventEnableUserAccessToken = "enableUserAccessToken" // enable user personal access token - AuditEventExtendSessionExpiry = "extendSessionExpiry" // extend user session expiration time - AuditEventLocalDeleteUser = "localDeleteUser" // delete user locally - AuditEventLocalPermanentDeleteAllUsers = "localPermanentDeleteAllUsers" // permanently delete all users locally - AuditEventLogin = "login" // user login to system - AuditEventLoginWithDesktopToken = "loginWithDesktopToken" // user login to system with desktop token - AuditEventLogout = "logout" // user logout from system - AuditEventMarkMessagesRead = "markAllMessagesRead" // user marked all direct and group messages as read - AuditEventMarkTeamRead = "markFullTeamRead" // user marked an entire team as read - AuditEventMigrateAuthToLdap = "migrateAuthToLdap" // migrate user authentication method to LDAP - AuditEventMigrateAuthToSaml = "migrateAuthToSaml" // migrate user authentication method to SAML - AuditEventPatchUser = "patchUser" // update user properties - AuditEventPromoteGuestToUser = "promoteGuestToUser" // promote guest account to regular user - AuditEventResetPassword = "resetPassword" // reset user password - AuditEventResetPasswordFailedAttempts = "resetPasswordFailedAttempts" // reset failed password attempt counter - AuditEventRevokeAllSessionsAllUsers = "revokeAllSessionsAllUsers" // revoke all active sessions for all users - AuditEventRevokeAllSessionsForUser = "revokeAllSessionsForUser" // revoke all active sessions for specific user - AuditEventRevokeSession = "revokeSession" // revoke specific user session - AuditEventRejectExpiredUserAccessToken = "rejectExpiredUserAccessToken" // rejected an API request because the personal access token has expired - AuditEventRevokeUserAccessToken = "revokeUserAccessToken" // revoke user personal access token - AuditEventSendPasswordReset = "sendPasswordReset" // send password reset email to user - AuditEventSendVerificationEmail = "sendVerificationEmail" // send email verification link to user - AuditEventSetDefaultProfileImage = "setDefaultProfileImage" // set user profile image to default avatar - AuditEventSetProfileImage = "setProfileImage" // set custom profile image for user - AuditEventSwitchAccountType = "switchAccountType" // switch user authentication method from one to another - AuditEventUpdatePassword = "updatePassword" // update user password - AuditEventUpdateUser = "updateUser" // update user account properties - AuditEventUpdateUserActive = "updateUserActive" // update user active status - AuditEventUpdateUserAuth = "updateUserAuth" // update user authentication method - AuditEventUpdateUserMfa = "updateUserMfa" // update user multi-factor authentication settings - AuditEventUpdateUserRoles = "updateUserRoles" // update user roles - AuditEventVerifyUserEmail = "verifyUserEmail" // verify user email address using verification token - AuditEventVerifyUserEmailWithoutToken = "verifyUserEmailWithoutToken" // verify user email address without verification token + AuditEventAttachDeviceId = "attachDeviceId" // attach device IDs (standard or VoIP) to user session for mobile app + AuditEventCreateUser = "createUser" // create user account + AuditEventCreateUserAccessToken = "createUserAccessToken" // create personal access token for user API access + AuditEventDeleteUser = "deleteUser" // delete user account + AuditEventDemoteUserToGuest = "demoteUserToGuest" // demote regular user to guest account with limited permissions + AuditEventDisableUserAccessToken = "disableUserAccessToken" // disable user personal access token + AuditEventEnableUserAccessToken = "enableUserAccessToken" // enable user personal access token + AuditEventExtendSessionExpiry = "extendSessionExpiry" // extend user session expiration time + AuditEventLocalDeleteUser = "localDeleteUser" // delete user locally + AuditEventLocalPermanentDeleteAllUsers = "localPermanentDeleteAllUsers" // permanently delete all users locally + AuditEventLogin = "login" // user login to system + AuditEventLoginWithDesktopToken = "loginWithDesktopToken" // user login to system with desktop token + AuditEventLogout = "logout" // user logout from system + AuditEventMarkMessagesRead = "markAllMessagesRead" // user marked all direct and group messages as read + AuditEventMarkTeamRead = "markFullTeamRead" // user marked an entire team as read + AuditEventMigrateAuthToLdap = "migrateAuthToLdap" // migrate user authentication method to LDAP + AuditEventMigrateAuthToSaml = "migrateAuthToSaml" // migrate user authentication method to SAML + AuditEventPatchUser = "patchUser" // update user properties + AuditEventPromoteGuestToUser = "promoteGuestToUser" // promote guest account to regular user + AuditEventResetPassword = "resetPassword" // reset user password + AuditEventResetPasswordFailedAttempts = "resetPasswordFailedAttempts" // reset failed password attempt counter + AuditEventRevokeAllSessionsAllUsers = "revokeAllSessionsAllUsers" // revoke all active sessions for all users + AuditEventRevokeAllSessionsForUser = "revokeAllSessionsForUser" // revoke all active sessions for specific user + AuditEventRevokeSession = "revokeSession" // revoke specific user session + AuditEventRejectExpiredUserAccessToken = "rejectExpiredUserAccessToken" // rejected an API request because the personal access token has expired + AuditEventRevokeUserAccessToken = "revokeUserAccessToken" // revoke user personal access token + AuditEventRevokeNonCompliantUserAccessTokens = "revokeNonCompliantUserAccessTokens" // revoke all personal access tokens that violate the maximum lifetime policy + AuditEventSendPasswordReset = "sendPasswordReset" // send password reset email to user + AuditEventSendVerificationEmail = "sendVerificationEmail" // send email verification link to user + AuditEventSetDefaultProfileImage = "setDefaultProfileImage" // set user profile image to default avatar + AuditEventSetProfileImage = "setProfileImage" // set custom profile image for user + AuditEventSwitchAccountType = "switchAccountType" // switch user authentication method from one to another + AuditEventUpdatePassword = "updatePassword" // update user password + AuditEventUpdateUser = "updateUser" // update user account properties + AuditEventUpdateUserActive = "updateUserActive" // update user active status + AuditEventUpdateUserAuth = "updateUserAuth" // update user authentication method + AuditEventUpdateUserMfa = "updateUserMfa" // update user multi-factor authentication settings + AuditEventUpdateUserRoles = "updateUserRoles" // update user roles + AuditEventVerifyUserEmail = "verifyUserEmail" // verify user email address using verification token + AuditEventVerifyUserEmailWithoutToken = "verifyUserEmailWithoutToken" // verify user email address without verification token ) // Webhooks diff --git a/server/public/model/client4.go b/server/public/model/client4.go index f03dba36b391..1ed56e292ef8 100644 --- a/server/public/model/client4.go +++ b/server/public/model/client4.go @@ -1940,6 +1940,31 @@ func (c *Client4) GetUserAccessTokens(ctx context.Context, page int, perPage int return DecodeJSONFromResponse[[]*UserAccessToken](r) } +// GetNonCompliantUserAccessTokenCount returns the number of active personal +// access tokens that violate the configured maximum lifetime policy. It lets an +// admin preview the blast radius before revoking. Must have the 'manage_system' +// permission. +func (c *Client4) GetNonCompliantUserAccessTokenCount(ctx context.Context) (*NonCompliantUserAccessTokenResult, *Response, error) { + r, err := c.doAPIGet(ctx, c.userAccessTokensRoute().Join("non_compliant", "count"), "") + if err != nil { + return nil, BuildResponse(r), err + } + defer closeBody(r) + return DecodeJSONFromResponse[*NonCompliantUserAccessTokenResult](r) +} + +// RevokeNonCompliantUserAccessTokens revokes (hard-deletes) every active personal +// access token that violates the configured maximum lifetime policy and returns +// the number of tokens revoked. Must have the 'manage_system' permission. +func (c *Client4) RevokeNonCompliantUserAccessTokens(ctx context.Context) (*NonCompliantUserAccessTokenResult, *Response, error) { + r, err := c.doAPIPostJSON(ctx, c.usersRoute().Join("tokens", "non_compliant", "revoke"), nil) + if err != nil { + return nil, BuildResponse(r), err + } + defer closeBody(r) + return DecodeJSONFromResponse[*NonCompliantUserAccessTokenResult](r) +} + // GetUserAccessToken will get a user access tokens' id, description, is_active // and the user_id of the user it is for. The actual token will not be returned. // Must have the 'read_user_access_token' permission and if getting for another diff --git a/server/public/model/user_access_token.go b/server/public/model/user_access_token.go index 9acccbfeab94..964470ecd51e 100644 --- a/server/public/model/user_access_token.go +++ b/server/public/model/user_access_token.go @@ -7,6 +7,13 @@ import ( "net/http" ) +// NonCompliantUserAccessTokenResult is the response payload for the endpoints +// that count or revoke personal access tokens violating the maximum lifetime +// policy. Count carries the number of tokens previewed or actually revoked. +type NonCompliantUserAccessTokenResult struct { + Count int64 `json:"count"` +} + type UserAccessToken struct { Id string `json:"id"` Token string `json:"token,omitempty"` diff --git a/server/public/model/view.go b/server/public/model/view.go index d8b10b753d4b..d08b5571ffc3 100644 --- a/server/public/model/view.go +++ b/server/public/model/view.go @@ -30,6 +30,13 @@ const ( BoardsStatusOptionInProgress = "In Progress" BoardsStatusOptionComplete = "Complete" + // Default colours seeded for the protected Status field. Tokens map to the + // webapp's `colorTokenMap` in board_attributes_values.tsx; gray for unstarted + // work, blue for active, green for done — standard kanban convention. + BoardsStatusColorTodo = "default" + BoardsStatusColorInProgress = "blue" + BoardsStatusColorComplete = "green" + MaxKanbanColumns = 100 ) diff --git a/tools/mattermost-govet/go.mod b/tools/mattermost-govet/go.mod index 29980f9cf18b..01a3f9ccfe3d 100644 --- a/tools/mattermost-govet/go.mod +++ b/tools/mattermost-govet/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/tools/mattermost-govet -go 1.26.3 +go 1.26.4 require ( github.com/pb33f/libopenapi v0.36.4 diff --git a/tools/mmgotool/go.mod b/tools/mmgotool/go.mod index f1735f872397..6696a1d4accb 100644 --- a/tools/mmgotool/go.mod +++ b/tools/mmgotool/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/tools/mmgotool -go 1.26.3 +go 1.26.4 require github.com/spf13/cobra v1.10.2 diff --git a/tools/sharedchannel-test/go.mod b/tools/sharedchannel-test/go.mod index 2791befa3ae7..682e657d3ce8 100644 --- a/tools/sharedchannel-test/go.mod +++ b/tools/sharedchannel-test/go.mod @@ -1,6 +1,6 @@ module github.com/mattermost/mattermost/tools/sharedchannel-test -go 1.26.3 +go 1.26.4 require github.com/mattermost/mattermost/server/public v0.4.0 diff --git a/webapp/channels/src/actions/websocket_actions.ts b/webapp/channels/src/actions/websocket_actions.ts index 9f204da1b9fa..99bffba01a3f 100644 --- a/webapp/channels/src/actions/websocket_actions.ts +++ b/webapp/channels/src/actions/websocket_actions.ts @@ -18,7 +18,7 @@ import type {Group, GroupMember} from '@mattermost/types/groups'; import type {OpenDialogRequest} from '@mattermost/types/integrations'; import type {Post, PostAcknowledgement} from '@mattermost/types/posts'; import type {PreferenceType} from '@mattermost/types/preferences'; -import {SESSION_ATTRIBUTES_OBJECT_TYPE} from '@mattermost/types/properties'; +import {SESSION_ATTRIBUTES_OBJECT_TYPE} from '@mattermost/types/properties_user'; import type {Reaction} from '@mattermost/types/reactions'; import type {Role} from '@mattermost/types/roles'; import type {ScheduledPost} from '@mattermost/types/schedule_post'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/shared.test.tsx b/webapp/channels/src/components/admin_console/access_control/editors/shared.test.tsx index 928abeea8fcc..e176aa0070e7 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/shared.test.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/shared.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/shared.tsx b/webapp/channels/src/components/admin_console/access_control/editors/shared.tsx index 77d9e3ab0ab5..62e0d0d95fb1 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/shared.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/shared.tsx @@ -6,7 +6,7 @@ import {FormattedMessage} from 'react-intl'; import {Button} from '@mattermost/shared/components/button'; import {WithTooltip} from '@mattermost/shared/components/tooltip'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import Markdown from 'components/markdown'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/attribute_selector_menu.tsx b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/attribute_selector_menu.tsx index 569e37cedbd8..be897a1c9ae4 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/attribute_selector_menu.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/attribute_selector_menu.tsx @@ -20,7 +20,7 @@ import { } from '@mattermost/compass-icons/components'; import type IconProps from '@mattermost/compass-icons/components/props'; import {WithTooltip} from '@mattermost/shared/components/tooltip'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import * as Menu from 'components/menu'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.test.tsx b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.test.tsx index ea5f41381eee..bdcef21e6f22 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.test.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.test.tsx @@ -2,7 +2,8 @@ // See LICENSE.txt for license information. import type {AccessControlVisualAST} from '@mattermost/types/access_control'; -import type {FieldType, UserPropertyField} from '@mattermost/types/properties'; +import type {FieldType} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {isSimpleExpression, isSimpleCondition, isMultiselectOrGroup} from 'components/admin_console/access_control/editors/shared'; import {parseExpression, findFirstAvailableAttributeFromList, rowToCEL, celStringLiteral} from 'components/admin_console/access_control/editors/table_editor/table_editor'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx index 0e74c2e5e5e8..2cc8a2c65dff 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx @@ -5,7 +5,7 @@ import React, {useState, useEffect, useCallback, useMemo} from 'react'; import {FormattedMessage, useIntl} from 'react-intl'; import type {AccessControlVisualAST} from '@mattermost/types/access_control'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {searchUsersForExpression} from 'mattermost-redux/actions/access_control'; import type {ActionResult} from 'mattermost-redux/types/actions'; diff --git a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor_channel_admin.test.tsx b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor_channel_admin.test.tsx index 6c31c50aff9a..2ffedf4b2869 100644 --- a/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor_channel_admin.test.tsx +++ b/webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor_channel_admin.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen, waitFor} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/picker_row.tsx b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/picker_row.tsx index abab1d06821f..ba584b5136b4 100644 --- a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/picker_row.tsx +++ b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/picker_row.tsx @@ -7,7 +7,7 @@ import {FormattedMessage} from 'react-intl'; import type {AccessControlPolicy, PolicySimulationActionDecision} from '@mattermost/types/access_control'; import {POLICY_SIMULATION_BLAME_SOURCES} from '@mattermost/types/access_control'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {Client4} from 'mattermost-redux/client'; import {displayUsername} from 'mattermost-redux/utils/user_utils'; diff --git a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/session_attribute_editor.tsx b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/session_attribute_editor.tsx index c0b8dba741d2..89c78c4b129c 100644 --- a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/session_attribute_editor.tsx +++ b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/session_attribute_editor.tsx @@ -19,8 +19,8 @@ import React, {useCallback, useState} from 'react'; import {FormattedMessage, useIntl} from 'react-intl'; import {Button} from '@mattermost/shared/components/button'; -import type {UserPropertyField} from '@mattermost/types/properties'; import {supportsOptions} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import './session_attribute_editor.scss'; diff --git a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.test.tsx b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.test.tsx index 31ff51059916..3af756f2a43e 100644 --- a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.test.tsx +++ b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.test.tsx @@ -5,8 +5,8 @@ import React from 'react'; import type {AccessControlPolicy} from '@mattermost/types/access_control'; import {POLICY_SIMULATION_BLAME_SOURCES} from '@mattermost/types/access_control'; -import type {UserPropertyField} from '@mattermost/types/properties'; -import {SESSION_ATTRIBUTES_GROUP_ID} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; +import {SESSION_ATTRIBUTES_GROUP_ID} from '@mattermost/types/properties_user'; import {act, fireEvent, renderWithContext, screen, userEvent, waitFor, within} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; diff --git a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.tsx b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.tsx index 9d2f3e7359a7..a7d313d459ec 100644 --- a/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.tsx +++ b/webapp/channels/src/components/admin_console/access_control/modals/simulate_access/simulate_access_modal.tsx @@ -16,8 +16,8 @@ import type { PolicySimulationResponse, PolicySimulationUserOverride, } from '@mattermost/types/access_control'; -import type {UserPropertyField} from '@mattermost/types/properties'; -import {SESSION_ATTRIBUTES_GROUP_ID} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; +import {SESSION_ATTRIBUTES_GROUP_ID} from '@mattermost/types/properties_user'; import type {UserProfile} from '@mattermost/types/users'; import {simulatePolicyForUsers} from 'mattermost-redux/actions/access_control'; diff --git a/webapp/channels/src/components/admin_console/access_control/policy_details/policy_details.tsx b/webapp/channels/src/components/admin_console/access_control/policy_details/policy_details.tsx index 6428df4ea097..b493bf985fd9 100644 --- a/webapp/channels/src/components/admin_console/access_control/policy_details/policy_details.tsx +++ b/webapp/channels/src/components/admin_console/access_control/policy_details/policy_details.tsx @@ -12,7 +12,7 @@ import {getMembershipRule, buildRulesWithMembership} from '@mattermost/types/acc import type {ChannelSearchOpts, ChannelWithTeamData} from '@mattermost/types/channels'; import type {AccessControlSettings} from '@mattermost/types/config'; import type {JobTypeBase} from '@mattermost/types/jobs'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {ActionResult} from 'mattermost-redux/types/actions'; diff --git a/webapp/channels/src/components/admin_console/admin_definition.tsx b/webapp/channels/src/components/admin_console/admin_definition.tsx index 1ad28da9bfcb..c01756a5eed9 100644 --- a/webapp/channels/src/components/admin_console/admin_definition.tsx +++ b/webapp/channels/src/components/admin_console/admin_definition.tsx @@ -56,6 +56,7 @@ import BillingHistory, {searchableStrings as billingHistorySearchableStrings} fr import BillingSubscriptions, {searchableStrings as billingSubscriptionSearchableStrings} from './billing/billing_subscriptions'; import CompanyInfo, {searchableStrings as billingCompanyInfoSearchableStrings} from './billing/company_info'; import CompanyInfoEdit from './billing/company_info_edit'; +import BoardAttributes, {searchableStrings as boardAttributesSearchableStrings} from './board_attributes'; import BrandImageSetting from './brand_image_setting/brand_image_setting'; import ClassificationMarkings, {searchableStrings as classificationMarkingsSearchableStrings} from './classification_markings'; import ClientSideUserIdsSetting from './client_side_userids_setting'; @@ -114,6 +115,7 @@ import PermissionSystemSchemeSettings from './permission_schemes_settings/permis import PermissionTeamSchemeSettings from './permission_schemes_settings/permission_team_scheme_settings'; import {searchableStrings as pluginManagementSearchableStrings} from './plugin_management/plugin_management'; import PushNotificationsSettings, {searchableStrings as pushSearchableStrings} from './push_settings'; +import RevokeNonCompliantTokensButton from './revoke_non_compliant_tokens_button'; import SecureConnections, {searchableStrings as secureConnectionsSearchableStrings} from './secure_connections'; import SecureConnectionDetail from './secure_connections/secure_connection_detail'; import ServerLogs from './server_logs'; @@ -664,6 +666,19 @@ const AdminDefinition: AdminDefinitionType = { }, restrictedIndicator: getRestrictedIndicator(true, LicenseSkus.EnterpriseAdvanced), }, + board_attributes: { + url: 'system_attributes/board_attributes', + title: defineMessage({id: 'admin.sidebar.board_attributes', defaultMessage: 'Board Attributes'}), + searchableStrings: boardAttributesSearchableStrings, + isHidden: it.not(it.all( + it.minLicenseTier(LicenseSkus.Enterprise), + it.configIsTrue('FeatureFlags', 'IntegratedBoards'), + )), + schema: { + id: 'BoardAttributes', + component: BoardAttributes, + }, + }, attribute_based_access_control: { url: 'system_attributes/attribute_based_access_control', title: defineMessage({id: 'admin.sidebar.attributeBasedAccessControl', defaultMessage: 'Attribute-Based Access'}), @@ -6118,6 +6133,18 @@ const AdminDefinition: AdminDefinitionType = { it.stateIsFalse('ServiceSettings.EnableUserAccessTokens'), ), }, + { + type: 'custom', + key: 'RevokeNonCompliantTokensButton', + component: RevokeNonCompliantTokensButton, + showTitle: true, + label: defineMessage({id: 'admin.service.revokeNonCompliantTokensTitle', defaultMessage: 'Revoke non-compliant tokens:'}), + help_text: defineMessage({id: 'admin.service.revokeNonCompliantTokensDescription', defaultMessage: 'Permanently revokes all existing personal access tokens that do not comply with the maximum lifetime above (tokens that never expire or expire beyond the cap). The maximum lifetime only applies to newly created tokens, so use this to bring already-issued tokens into compliance. Bot account tokens are exempt. You will be shown how many tokens are affected before confirming.'}), + isDisabled: it.any( + it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.INTEGRATIONS.INTEGRATION_MANAGEMENT)), + it.stateIsFalse('ServiceSettings.EnableUserAccessTokens'), + ), + }, ], }, }, diff --git a/webapp/channels/src/components/admin_console/admin_definition_board_attributes.test.tsx b/webapp/channels/src/components/admin_console/admin_definition_board_attributes.test.tsx new file mode 100644 index 000000000000..67d142721cf2 --- /dev/null +++ b/webapp/channels/src/components/admin_console/admin_definition_board_attributes.test.tsx @@ -0,0 +1,86 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import type {AdminConfig, ClientLicense} from '@mattermost/types/config'; + +import {LicenseSkus} from 'utils/constants'; + +import AdminDefinition from './admin_definition'; +import type {AdminDefinitionSubSection, Check, ConsoleAccess} from './types'; + +const boardsFlagEnabled = { + FeatureFlags: { + IntegratedBoards: true, + }, +} as unknown as Partial; + +const boardsFlagDisabled = { + FeatureFlags: { + IntegratedBoards: false, + }, +} as unknown as Partial; + +const consoleAccess = { + read: {}, + write: {}, +} as ConsoleAccess; + +const professionalLicense = { + IsLicensed: 'true', + SkuShortName: LicenseSkus.Professional, +} as ClientLicense; + +const enterpriseLicense = { + IsLicensed: 'true', + SkuShortName: LicenseSkus.Enterprise, +} as ClientLicense; + +const enterpriseAdvancedLicense = { + IsLicensed: 'true', + SkuShortName: LicenseSkus.EnterpriseAdvanced, +} as ClientLicense; + +const entryLicense = { + IsLicensed: 'true', + SkuShortName: LicenseSkus.Entry, +} as ClientLicense; + +const unlicensed = { + IsLicensed: 'false', +} as ClientLicense; + +function isHidden(subsection: AdminDefinitionSubSection, config: Partial, license: ClientLicense) { + const check = subsection.isHidden as Extract boolean>; + return check(config, {}, license, true, consoleAccess); +} + +describe('AdminDefinition - Board Attributes license gating', () => { + const settingsSubsection = AdminDefinition.system_attributes.subsections.board_attributes; + + test('hides Board Attributes for Professional licenses', () => { + expect(isHidden(settingsSubsection, boardsFlagEnabled, professionalLicense)).toBe(true); + }); + + test('hides Board Attributes when unlicensed', () => { + expect(isHidden(settingsSubsection, boardsFlagEnabled, unlicensed)).toBe(true); + }); + + test('shows Board Attributes for Enterprise licenses', () => { + expect(isHidden(settingsSubsection, boardsFlagEnabled, enterpriseLicense)).toBe(false); + }); + + test('shows Board Attributes for Enterprise Advanced licenses', () => { + expect(isHidden(settingsSubsection, boardsFlagEnabled, enterpriseAdvancedLicense)).toBe(false); + }); + + test('shows Board Attributes for Entry licenses', () => { + expect(isHidden(settingsSubsection, boardsFlagEnabled, entryLicense)).toBe(false); + }); + + test('hides Board Attributes when the IntegratedBoards feature flag is disabled', () => { + // The disabled flag must override an otherwise-unlocking license. + expect(isHidden(settingsSubsection, boardsFlagDisabled, enterpriseLicense)).toBe(true); + expect(isHidden(settingsSubsection, boardsFlagDisabled, enterpriseAdvancedLicense)).toBe(true); + expect(isHidden(settingsSubsection, boardsFlagDisabled, professionalLicense)).toBe(true); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes.test.tsx new file mode 100644 index 000000000000..a966928816d9 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes.test.tsx @@ -0,0 +1,165 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; + +import BoardAttributes from './board_attributes'; + +// Mock the table hook so we can test the screen's wiring without +// dragging in API integration / Redux fetch flow. +const mockSave = jest.fn(); +const mockUseBoardAttributesTable = jest.fn(); + +jest.mock('./board_attributes_table', () => ({ + useBoardAttributesTable: () => mockUseBoardAttributesTable(), +})); + +// Mock the navigation-blocked action so we can assert it dispatches with +// the correct hasChanges value. The real action returns a sync action object +// the store handles; this returns a marker we can detect on dispatch. +const mockSetNavigationBlocked = jest.fn((blocked: boolean) => ({type: 'SET_NAVIGATION_BLOCKED_TEST', blocked})); +jest.mock('actions/admin_actions', () => ({ + setNavigationBlocked: (blocked: boolean) => mockSetNavigationBlocked(blocked), +})); + +function makeHookReturn(overrides: Partial<{ + content: React.ReactNode; + saving: boolean; + hasChanges: boolean; + isValid: boolean; + saveError: unknown; + save: () => void; +}> = {}) { + return { + content:
    {'table content'}
    , + saving: false, + hasChanges: false, + isValid: true, + saveError: undefined, + save: mockSave, + ...overrides, + }; +} + +describe('BoardAttributes (top-level screen)', () => { + beforeEach(() => { + // Use mockReset on both for consistency — it clears state AND any + // configured implementation/return value, so test-to-test isolation is + // guaranteed even if a future test adds .mockReturnValue or similar. + mockSave.mockReset(); + mockUseBoardAttributesTable.mockReset(); + mockSetNavigationBlocked.mockClear(); + }); + + it('renders the page title, section header, and the table content from the hook', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn()); + + renderWithContext(); + + expect(screen.getByTestId('boardAttributes')).toBeInTheDocument(); + expect(screen.getAllByText(/board attributes/i).length).toBeGreaterThanOrEqual(1); + expect(screen.getByText(/customize the attributes available by default/i)).toBeInTheDocument(); + expect(screen.getByTestId('table-content')).toBeInTheDocument(); + }); + + it('disables the save button when no changes are pending', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: false})); + + renderWithContext(); + + const save = screen.getByRole('button', {name: /^save$/i}); + expect(save).toBeDisabled(); + }); + + it('enables the save button when changes are pending and the form is valid', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true, isValid: true})); + + renderWithContext(); + + const save = screen.getByRole('button', {name: /^save$/i}); + expect(save).toBeEnabled(); + }); + + it('disables the save button when the form has validation errors (isValid=false)', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true, isValid: false})); + + renderWithContext(); + + const save = screen.getByRole('button', {name: /^save$/i}); + expect(save).toBeDisabled(); + }); + + it('disables the save button when the surrounding admin section is disabled', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true, isValid: true})); + + renderWithContext(); + + const save = screen.getByRole('button', {name: /^save$/i}); + expect(save).toBeDisabled(); + }); + + it('swaps the Save button label to the saving-in-progress message and disables it while saving=true', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true, isValid: true, saving: true})); + + renderWithContext(); + + // While saving, the "Save" label is replaced by the savingMessage we pass to SaveChangesPanel. + expect(screen.queryByRole('button', {name: /^save$/i})).not.toBeInTheDocument(); + const savingButton = screen.getByRole('button', {name: /saving configuration/i}); + expect(savingButton).toBeDisabled(); + }); + + it('calls save() when the Save button is clicked', async () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true, isValid: true})); + + renderWithContext(); + + await userEvent.click(screen.getByRole('button', {name: /^save$/i})); + + expect(mockSave).toHaveBeenCalledTimes(1); + }); + + it('renders the server-error message when saveError is set', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({ + hasChanges: true, + isValid: true, + saveError: new Error('boom'), + })); + + renderWithContext(); + + expect(screen.getByText(/there was an error while saving the configuration/i)).toBeInTheDocument(); + }); + + it('dispatches setNavigationBlocked(false) on initial mount when hasChanges=false', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: false})); + + renderWithContext(); + + expect(mockSetNavigationBlocked).toHaveBeenCalledWith(false); + }); + + it('dispatches setNavigationBlocked(true) when there are unsaved changes', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true})); + + renderWithContext(); + + expect(mockSetNavigationBlocked).toHaveBeenCalledWith(true); + }); + + it('dispatches setNavigationBlocked(false) on unmount so the block does not leak into the next screen', () => { + mockUseBoardAttributesTable.mockReturnValue(makeHookReturn({hasChanges: true})); + + const {unmount} = renderWithContext(); + + // Effect set the block to `true` on mount; clear the spy before + // unmount so the assertion is unambiguous about what unmount did. + mockSetNavigationBlocked.mockClear(); + + unmount(); + + expect(mockSetNavigationBlocked).toHaveBeenCalledWith(false); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes.tsx new file mode 100644 index 000000000000..20b41ba871e5 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes.tsx @@ -0,0 +1,99 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {useEffect} from 'react'; +import {FormattedMessage, defineMessages, useIntl} from 'react-intl'; +import {useDispatch} from 'react-redux'; + +import {setNavigationBlocked} from 'actions/admin_actions'; + +import AdminHeader from 'components/widgets/admin_console/admin_header'; + +import {useBoardAttributesTable} from './board_attributes_table'; + +import SaveChangesPanel from '../save_changes_panel'; +import {AdminSection, AdminWrapper, DangerText, SectionContent, SectionHeader, SectionHeading} from '../system_properties/controls'; +import type {SearchableStrings} from '../types'; + +type Props = { + disabled: boolean; +}; + +export default function BoardAttributes(props: Props) { + const {formatMessage} = useIntl(); + const dispatch = useDispatch(); + + const boardAttributes = useBoardAttributesTable(); + + const saving = boardAttributes.saving; + const hasChanges = boardAttributes.hasChanges; + const isValid = boardAttributes.isValid; + const saveError = boardAttributes.saveError; + + const handleSave = () => { + boardAttributes.save(); + }; + + useEffect(() => { + // block nav when changes are pending + dispatch(setNavigationBlocked(hasChanges)); + + // Reset on unmount so leaving with `hasChanges=true` (e.g. via the + // discard-changes prompt) doesn't leak a stale block into the next + // admin screen. + return () => { + dispatch(setNavigationBlocked(false)); + }; + }, [hasChanges, dispatch]); + + return ( +
    + + + + + + +
    + + +
    +
    + + {boardAttributes.content} + +
    +
    + + ) : undefined} + savingMessage={formatMessage({id: 'admin.system_properties.details.saving_changes', defaultMessage: 'Saving configuration…'})} + isDisabled={props.disabled || saving || !isValid} + /> +
    + ); +} + +const msg = defineMessages({ + pageTitle: {id: 'admin.board_attributes.page_title', defaultMessage: 'Board Attributes'}, +}); + +export const searchableStrings: SearchableStrings = Object.values(msg); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.test.tsx new file mode 100644 index 000000000000..d4dadea1572b --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.test.tsx @@ -0,0 +1,47 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; + +import RemoveBoardAttributeFieldModal from './board_attributes_delete_modal'; + +describe('RemoveBoardAttributeFieldModal', () => { + const renderModal = (overrides: Partial> = {}) => { + const props = { + onConfirm: jest.fn(), + onCancel: jest.fn(), + onExited: jest.fn(), + ...overrides, + }; + renderWithContext(); + return props; + }; + + it('renders the title, confirmation copy, and destructive confirm button', () => { + renderModal(); + + expect(screen.getByRole('heading', {name: /delete board attribute/i})).toBeInTheDocument(); + expect(screen.getByText(/are you sure you want to delete this board attribute/i)).toBeInTheDocument(); + expect(screen.getByRole('button', {name: /^delete$/i})).toBeInTheDocument(); + }); + + it('invokes onConfirm when the Delete button is clicked', async () => { + const props = renderModal(); + + await userEvent.click(screen.getByRole('button', {name: /^delete$/i})); + + expect(props.onConfirm).toHaveBeenCalledTimes(1); + expect(props.onCancel).not.toHaveBeenCalled(); + }); + + it('invokes onCancel when the Cancel button is clicked', async () => { + const props = renderModal(); + + await userEvent.click(screen.getByRole('button', {name: /cancel/i})); + + expect(props.onCancel).toHaveBeenCalledTimes(1); + expect(props.onConfirm).not.toHaveBeenCalled(); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.tsx new file mode 100644 index 000000000000..30237762e153 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_delete_modal.tsx @@ -0,0 +1,85 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; +import {useDispatch} from 'react-redux'; + +import {GenericModal} from '@mattermost/components'; + +import {openModal} from 'actions/views/modals'; + +import {ModalIdentifiers} from 'utils/constants'; + +type Props = { + onConfirm: () => void; + onCancel: () => void; + onExited: () => void; +}; + +export const useBoardAttributeFieldDelete = () => { + const dispatch = useDispatch(); + const promptDelete = () => { + return new Promise((resolve) => { + let settled = false; + const settle = (value: boolean) => { + if (!settled) { + settled = true; + resolve(value); + } + }; + dispatch(openModal({ + modalId: ModalIdentifiers.BOARD_ATTRIBUTE_FIELD_DELETE, + dialogType: RemoveBoardAttributeFieldModal, + dialogProps: { + onConfirm: () => settle(true), + onCancel: () => settle(false), + onExited: () => settle(false), + }, + })); + }); + }; + + return {promptDelete} as const; +}; + +function RemoveBoardAttributeFieldModal({ + onExited, + onCancel, + onConfirm, +}: Props) { + const {formatMessage} = useIntl(); + + const title = formatMessage({ + id: 'admin.board_attributes.delete_modal.title', + defaultMessage: 'Delete board attribute', + }); + + const confirmButtonText = formatMessage({ + id: 'admin.system_properties.confirm.delete.button', + defaultMessage: 'Delete', + }); + + const message = ( + + ); + + return ( + + {message} + + ); +} + +export default RemoveBoardAttributeFieldModal; diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.test.tsx new file mode 100644 index 000000000000..5c240da99690 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.test.tsx @@ -0,0 +1,158 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import type {BoardsPropertyField} from '@mattermost/types/properties_board'; + +import {fireEvent, renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils'; + +import DotMenu from './board_attributes_dot_menu'; + +function makeField(overrides: Partial = {}): BoardsPropertyField { + return { + id: 'field-1', + name: 'My Attribute', + type: 'text', + group_id: 'boards', + object_type: 'post', + create_at: 1700000000000, + delete_at: 0, + update_at: 1700000000000, + created_by: '', + updated_by: '', + target_id: '', + target_type: 'system', + attrs: {sort_order: 0}, + ...overrides, + } as BoardsPropertyField; +} + +function renderMenu(overrides: Partial> = {}) { + const props = { + field: makeField(), + canCreate: true, + createField: jest.fn(), + deleteField: jest.fn(), + ...overrides, + }; + renderWithContext(); + return props; +} + +describe('Board attributes DotMenu', () => { + it('disables the trigger button when the field is flagged for delete', () => { + renderMenu({field: makeField({delete_at: 1700000099999})}); + + expect(screen.getByTestId('board-attribute-field_dotmenu-field-1')).toBeDisabled(); + }); + + it('exposes Duplicate and Delete items when canCreate=true and field is not protected', async () => { + renderMenu(); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-field-1')); + + expect(screen.getByText('Duplicate')).toBeInTheDocument(); + expect(screen.getByText('Delete attribute')).toBeInTheDocument(); + }); + + it('hides the Duplicate item when canCreate=false', async () => { + renderMenu({canCreate: false}); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-field-1')); + + expect(screen.queryByText('Duplicate')).not.toBeInTheDocument(); + expect(screen.getByText('Delete attribute')).toBeInTheDocument(); + }); + + it('disables both items when the field is protected (and clicking them does NOT call createField/deleteField)', async () => { + const props = renderMenu({field: makeField({protected: true})}); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-field-1')); + + // Find the actual menuitem elements by role rather than walking up from + // text — the role query asserts the menuitem exists, and toBeDisabled() + // handles both `disabled` and `aria-disabled` styles uniformly. + const menuitems = screen.getAllByRole('menuitem'); + const duplicate = menuitems.find((el) => el.textContent?.includes('Duplicate')); + const del = menuitems.find((el) => el.textContent?.includes('Delete attribute')); + + expect(duplicate).toBeDefined(); + expect(del).toBeDefined(); + + // Menu.Item renders
  • ; the lib uses aria-disabled + // rather than the HTML `disabled` attribute (which has no meaning on
  • ). + expect(duplicate!).toHaveAttribute('aria-disabled', 'true'); + expect(del!).toHaveAttribute('aria-disabled', 'true'); + + // Behavioural check: dispatching a synthetic click anyway is a no-op for + // protected fields. userEvent.click refuses pointer-events:none elements + // (which disabled menu items have), so use fireEvent.click to bypass that + // safety and exercise the source's `if (isProtected) return` guards. + fireEvent.click(duplicate!); + fireEvent.click(del!); + await new Promise((resolve) => setTimeout(resolve, 0)); + expect(props.createField).not.toHaveBeenCalled(); + expect(props.deleteField).not.toHaveBeenCalled(); + }); + + it('invokes createField with the source field name when Duplicate is clicked', async () => { + const props = renderMenu({field: makeField({name: 'Priority'})}); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-field-1')); + const duplicate = screen.getByText('Duplicate').closest('[role="menuitem"]') as HTMLElement; + await userEvent.click(duplicate); + + // Menu.Item defers onClick for non-radio items until after the menu close animation completes + await waitFor(() => expect(props.createField).toHaveBeenCalledTimes(1)); + const createFieldMock = props.createField as jest.Mock; + const passed = createFieldMock.mock.calls[0][0] as BoardsPropertyField; + expect(passed.name).toBe('Priority'); + + // attrs should be a shallow copy, not the original reference + expect(passed.attrs).not.toBe(props.field.attrs); + }); + + it('skips the confirm prompt and deletes immediately when the field is create-pending (never saved)', async () => { + const pendingField = makeField({ + create_at: 0, + delete_at: 0, + id: 'pending_abc', + }); + const props = renderMenu({field: pendingField}); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-pending_abc')); + const del = screen.getByText('Delete attribute').closest('[role="menuitem"]') as HTMLElement; + await userEvent.click(del); + + // No confirm dialog is opened — deleteField is called directly with the field id + await waitFor(() => expect(props.deleteField).toHaveBeenCalledWith('pending_abc')); + expect(screen.queryByRole('heading', {name: /delete board attribute/i})).not.toBeInTheDocument(); + }); + + it('does NOT delete a saved field immediately (the confirm-modal branch defers via dispatch(openModal))', async () => { + // For saved fields (create_at > 0) the menu dispatches an openModal action + // through useBoardAttributeFieldDelete instead of calling deleteField directly. + // The modal renders via the global ModalController which isn't mounted in + // this test wrapper, so we verify the negative path: deleteField stays + // un-called after clicking Delete (proving the prompt branch was taken). + const props = renderMenu(); + + await userEvent.click(screen.getByTestId('board-attribute-field_dotmenu-field-1')); + const del = screen.getByText('Delete attribute').closest('[role="menuitem"]') as HTMLElement; + await userEvent.click(del); + + // The pending-path test above proves the deferred Menu.Item onClick *does* + // call deleteField for create-pending fields. For a saved field the source + // calls `promptDelete().then(...)` — `deleteField` only fires from inside + // the resolved `.then()`, which can't resolve in this test because no + // ModalController is mounted. Flush microtasks once to let the deferred + // onClick run, then assert deleteField stayed un-called. + await waitFor(() => { + // Wait for the deferred onClick to have *had a chance* to fire by + // asserting the menu is closed (close fires the deferred handler). + expect(screen.queryByText('Delete attribute')).not.toBeInTheDocument(); + }); + expect(props.deleteField).not.toHaveBeenCalled(); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.tsx new file mode 100644 index 000000000000..3b692cd7290b --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_dot_menu.tsx @@ -0,0 +1,115 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; + +import {ContentCopyIcon, DotsHorizontalIcon, TrashCanOutlineIcon} from '@mattermost/compass-icons/components'; +import type {BoardsPropertyField} from '@mattermost/types/properties_board'; + +import * as Menu from 'components/menu'; + +import {useBoardAttributeFieldDelete} from './board_attributes_delete_modal'; +import {isCreatePending} from './board_attributes_utils'; + +import '../system_properties/user_properties_dot_menu.scss'; + +type Props = { + field: BoardsPropertyField; + canCreate: boolean; + createField: (field: BoardsPropertyField) => void; + deleteField: (id: string) => void; +}; + +const menuId = 'board-attribute-field_dotmenu'; + +const DotMenu = ({ + field, + canCreate, + createField, + deleteField, +}: Props) => { + const {formatMessage} = useIntl(); + const {promptDelete} = useBoardAttributeFieldDelete(); + + const isProtected = Boolean(field.protected); + + const handleDuplicate = () => { + if (isProtected) { + return; + } + + // The create flow rewrites the name with a `(N)` suffix if needed, + // so we pass the bare field name here (any existing `(copy)` or + // `(N)` suffix is stripped to find the base name). + createField({...field, attrs: {...field.attrs}, name: field.name}); + }; + + const handleDelete = () => { + if (isProtected) { + return; + } + if (isCreatePending(field)) { + // skip prompt when field is pending creation + deleteField(field.id); + } else { + promptDelete().then((confirmed) => { + if (confirmed) { + deleteField(field.id); + } + }); + } + }; + + const menuButton = ( + , + dataTestId: `${menuId}-${field.id}`, + disabled: field.delete_at !== 0, + }} + menu={{ + id: `${menuId}-${field.id}-menu`, + 'aria-label': formatMessage({ + id: 'admin.board_attributes.dot_menu.label', + defaultMessage: 'Select an action', + }), + className: 'user-property-field-dotmenu-menu', + }} + > + {canCreate && ( + } + labels={( + + )} + /> + )} + } + labels={( + + )} + /> + + ); + + return menuButton; +}; + +export default DotMenu; diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_drag_preview.scss b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_drag_preview.scss new file mode 100644 index 000000000000..7b68dbcc0968 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_drag_preview.scss @@ -0,0 +1,24 @@ +.BoardAttributes__dragPreview { + padding: 6px 12px; + border: 1px solid rgba(var(--center-channel-color-rgb), 0.16); + border-radius: 4px; + background: var(--center-channel-bg); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); + color: var(--center-channel-color); + font-family: 'Open Sans', sans-serif; + font-size: 14px; + font-weight: 600; + line-height: 20px; +} + +.BoardAttributes__optionDragPreview { + display: inline-flex; + padding: 2px 10px; + border-radius: 4px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); + color: var(--center-channel-color); + font-family: 'Open Sans', sans-serif; + font-size: 12px; + font-weight: 600; + line-height: 18px; +} diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.scss b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.scss new file mode 100644 index 000000000000..8e69811e1cf4 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.scss @@ -0,0 +1,56 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +.BoardAttributesTable { + table.adminConsoleListTable { + + td, th { + &:after, &:before { + display: none; + } + } + + thead { + border-top: none; + border-bottom: 1px solid rgba(var(--center-channel-color-rgb), 0.08); + tr { + th.pinned { + background: rgba(var(--center-channel-color-rgb), 0.04); + padding-block-end: 8px; + padding-block-start: 8px; + } + } + } + + tbody { + tr { + border-top: none; + border-bottom: 1px solid rgba(var(--center-channel-color-rgb), 0.08); + border-bottom-color: rgba(var(--center-channel-color-rgb), 0.08) !important; + td { + padding-block-end: 0; + padding-block-start: 0; + + &:not(:first-child):not(:last-child) { + padding-inline-end: 0; + padding-inline-start: 0; + } + + &:last-child { + padding-inline-end: 12px; + } + &.pinned { + background: none; + } + } + } + } + + tfoot { + border-top: none; + } + } + .adminConsoleListTableContainer { + padding: 2px 0px; + } +} diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.test.tsx new file mode 100644 index 000000000000..0c343665f549 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.test.tsx @@ -0,0 +1,225 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import type {BoardsPropertyField} from '@mattermost/types/properties_board'; + +import {renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils'; + +import {BoardAttributesTable} from './board_attributes_table'; +import type {BoardPropertyFields} from './board_attributes_utils'; +import { + ValidationWarningNameRequired, + ValidationWarningNameTaken, + ValidationWarningNameUnique, +} from './board_attributes_utils'; + +function makeField(overrides: Partial = {}): BoardsPropertyField { + return { + id: 'field-1', + name: 'Priority', + type: 'text', + group_id: 'boards', + object_type: 'post', + create_at: 1700000000000, + delete_at: 0, + update_at: 1700000000000, + created_by: '', + updated_by: '', + target_id: '', + target_type: 'system', + attrs: {sort_order: 0}, + ...overrides, + } as BoardsPropertyField; +} + +function makeCollection(fields: BoardsPropertyField[], warnings?: BoardPropertyFields['warnings']): BoardPropertyFields { + const data: Record = {}; + const order: string[] = []; + for (const f of fields) { + data[f.id] = f; + order.push(f.id); + } + return {data, order, warnings}; +} + +function renderTable(overrides: Partial> = {}) { + const props = { + data: makeCollection([]), + canCreate: true, + createField: jest.fn(), + updateField: jest.fn(), + deleteField: jest.fn(), + reorderField: jest.fn(), + ...overrides, + }; + renderWithContext(); + return props; +} + +describe('BoardAttributesTable', () => { + describe('rendering', () => { + it('renders an empty data state when no fields exist', () => { + renderTable(); + + // No field-name inputs are present + expect(screen.queryAllByTestId('board-attribute-field-input')).toHaveLength(0); + }); + + it('renders one row per field with its name in the input', () => { + renderTable({ + data: makeCollection([ + makeField({id: '1', name: 'Priority', type: 'select'}), + makeField({id: '2', name: 'Owner', type: 'user'}), + makeField({id: '3', name: 'Due Date', type: 'date'}), + ]), + }); + + const inputs = screen.getAllByTestId('board-attribute-field-input') as HTMLInputElement[]; + expect(inputs).toHaveLength(3); + const values = inputs.map((i) => i.value); + expect(values).toEqual(expect.arrayContaining(['Priority', 'Owner', 'Due Date'])); + }); + + it('disables the name input for protected fields', () => { + renderTable({ + data: makeCollection([ + makeField({id: 'status', name: 'Status', type: 'select', protected: true}), + ]), + }); + + const input = screen.getByTestId('board-attribute-field-input') as HTMLInputElement; + expect(input).toBeDisabled(); + }); + + it('disables the name input for fields flagged for delete', () => { + renderTable({ + data: makeCollection([ + makeField({id: 'goner', name: 'Goner', delete_at: 1700000099999}), + ]), + }); + + const input = screen.getByTestId('board-attribute-field-input') as HTMLInputElement; + expect(input).toBeDisabled(); + }); + }); + + describe('validation warnings', () => { + it('surfaces the "name required" warning when the field has that warning attached', () => { + renderTable({ + data: makeCollection( + [makeField({id: '1', name: ''})], + {1: {name: ValidationWarningNameRequired}}, + ), + }); + + expect(screen.getByText(/please enter an attribute name/i)).toBeInTheDocument(); + }); + + it('surfaces the "name unique" warning', () => { + renderTable({ + data: makeCollection( + [ + makeField({id: '1', name: 'Dup'}), + makeField({id: '2', name: 'Dup'}), + ], + { + 1: {name: ValidationWarningNameUnique}, + 2: {name: ValidationWarningNameUnique}, + }, + ), + }); + + expect(screen.getAllByText(/attribute names must be unique/i).length).toBeGreaterThanOrEqual(1); + }); + + it('surfaces the "name taken" warning', () => { + renderTable({ + data: makeCollection( + [makeField({id: '1', name: 'Status'})], + {1: {name: ValidationWarningNameTaken}}, + ), + }); + + expect(screen.getByText(/attribute name already taken/i)).toBeInTheDocument(); + }); + + it('hides validation warnings on fields flagged for delete', () => { + renderTable({ + data: makeCollection( + [makeField({id: '1', name: 'X', delete_at: 1700000099999})], + {1: {name: ValidationWarningNameRequired}}, + ), + }); + + expect(screen.queryByText(/please enter an attribute name/i)).not.toBeInTheDocument(); + }); + }); + + describe('actions', () => { + it('renders the dot-menu trigger per row', () => { + renderTable({ + data: makeCollection([ + makeField({id: 'a', name: 'A'}), + makeField({id: 'b', name: 'B'}), + ]), + }); + + expect(screen.getByTestId('board-attribute-field_dotmenu-a')).toBeInTheDocument(); + expect(screen.getByTestId('board-attribute-field_dotmenu-b')).toBeInTheDocument(); + }); + + it('calls updateField when the name input is edited and blurred', async () => { + const props = renderTable({ + data: makeCollection([makeField({id: '1', name: 'Old'})]), + }); + + const input = screen.getByTestId('board-attribute-field-input') as HTMLInputElement; + await userEvent.clear(input); + await userEvent.type(input, 'New'); + await userEvent.tab(); + + await waitFor(() => expect(props.updateField).toHaveBeenCalled()); + const updateFieldMock = props.updateField as jest.Mock; + const lastCall = updateFieldMock.mock.calls.at(-1)![0] as BoardsPropertyField; + expect(lastCall.name).toBe('New'); + expect(lastCall.id).toBe('1'); + }); + }); + + describe('reorder wiring (without real drag events)', () => { + // Real drag-drop runs through PDND and needs a layout engine jsdom + // doesn't have. But we can still validate the prop wiring: the table + // builds a `meta.onReorder` callback that should resolve the source + // row by index and call reorderField with the resolved field + + // destination index. + it('routes meta.onReorder(prev, next) → reorderField(prevField, nextIndex)', () => { + const fieldA = makeField({id: 'a', name: 'A'}); + const fieldB = makeField({id: 'b', name: 'B'}); + const fieldC = makeField({id: 'c', name: 'C'}); + const reorderField = jest.fn(); + + // Render the table and read back the `meta` wiring through the data-testids + // exposed on the rendered rows. We can't easily reach the tanstack `table` + // instance from the outside, but the meta.onReorder closure captures + // the collection — so we re-implement what it does: + // reorderField(collection.data[collection.order[prev]], next) + // and assert reorderField is called consistently when DnD fires. + // + // This stays a unit-level wiring sanity check; full drag flow is in E2E. + renderTable({ + data: makeCollection([fieldA, fieldB, fieldC]), + reorderField, + }); + + // Simulate what useListTableDnd would call on drop: pretend the user + // dragged row 0 to slot 2. The closure inside `meta.onReorder` is + // what we want to exercise — invoke it by reaching into the table's + // exported wiring. Since we can't reach `table` here, this assertion + // is the negative-path companion: reorderField is NOT called just + // by rendering, so any spurious wiring would surface as an extra call. + expect(reorderField).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.tsx new file mode 100644 index 000000000000..d11977057253 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_table.tsx @@ -0,0 +1,395 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {createColumnHelper, getCoreRowModel, getSortedRowModel, useReactTable, type ColumnDef} from '@tanstack/react-table'; +import type {ReactNode} from 'react'; +import React, {useEffect, useMemo, useState} from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; +import styled from 'styled-components'; + +import {LockOutlineIcon, PlusIcon} from '@mattermost/compass-icons/components'; +import {WithTooltip} from '@mattermost/shared/components/tooltip'; +import {supportsOptions} from '@mattermost/types/properties'; +import {type BoardsPropertyField} from '@mattermost/types/properties_board'; +import {collectionToArray} from '@mattermost/types/utilities'; + +import LoadingScreen from 'components/loading_screen'; + +import BoardAttributesDotMenu from './board_attributes_dot_menu'; +import SelectType from './board_attributes_type_menu'; +import type {BoardPropertyFields} from './board_attributes_utils'; +import {isCreatePending, useBoardPropertyFields, ValidationWarningNameRequired, ValidationWarningNameTaken, ValidationWarningNameUnique} from './board_attributes_utils'; +import BoardAttributesValues from './board_attributes_values'; + +import {AdminConsoleListTable} from '../list_table'; +import {DangerText, BorderlessInput, LinkButton} from '../system_properties/controls'; +import type {SectionHook} from '../system_properties/section_utils'; + +import './board_attributes_drag_preview.scss'; +import './board_attributes_table.scss'; + +const MAX_BOARD_ATTRIBUTES = 20; + +const col = createColumnHelper(); + +type FieldActions = { + createField: (field: BoardsPropertyField) => void; + updateField: (field: BoardsPropertyField) => void; + deleteField: (id: string) => void; + reorderField: (field: BoardsPropertyField, nextOrder: number) => void; +}; + +export const useBoardAttributesTable = (): SectionHook => { + const [boardPropertyFields, readIO, pendingIO, itemOps] = useBoardPropertyFields(); + const nonDeletedCount = Object.values(boardPropertyFields.data).filter((f: BoardsPropertyField) => f.delete_at === 0).length; + + const canCreate = nonDeletedCount < MAX_BOARD_ATTRIBUTES; + + const create = () => { + itemOps.create(); + }; + + const save = async () => { + const newData = await pendingIO.commit(); + + // reconcile - zero pending changes + if (newData && !newData.errors) { + readIO.setData(newData); + } + }; + + const content = readIO.loading ? ( + + ) : ( + <> + + {canCreate && ( + + + + + )} + + ); + + return { + content, + loading: readIO.loading, + hasChanges: pendingIO.hasChanges, + isValid: !boardPropertyFields.warnings, + save, + cancel: pendingIO.reset, + saving: pendingIO.saving, + saveError: pendingIO.error, + }; +}; + +type Props = { + data: BoardPropertyFields; + canCreate: boolean; +}; + +export function BoardAttributesTable({ + data: collection, + canCreate, + createField, + updateField, + deleteField, + reorderField, +}: Props & FieldActions) { + const {formatMessage} = useIntl(); + const data = collectionToArray(collection); + const columns = useMemo>>(() => { + return [ + col.accessor('name', { + size: 180, + header: () => { + return ( + + + + ); + }, + cell: ({getValue, row}) => { + const toDelete = row.original.delete_at !== 0; + const isProtected = Boolean(row.original.protected); + const warningId = collection.warnings?.[row.original.id]?.name; + + let warning; + + if (warningId === ValidationWarningNameRequired) { + warning = ( + + ); + } else if (warningId === ValidationWarningNameUnique) { + warning = ( + + ); + } else if (warningId === ValidationWarningNameTaken) { + warning = ( + + ); + } + + return ( + <> + { + updateField({...row.original, name: value.trim()}); + }} + /> + {!toDelete && warning} + + ); + }, + enableHiding: false, + enableSorting: false, + }), + col.accessor('type', { + size: 100, + header: () => { + return ( + + + + ); + }, + cell: ({row}) => { + return ( + + ); + }, + enableHiding: false, + enableSorting: false, + }), + col.display({ + id: 'options', + size: 300, + header: () => ( + + + + ), + cell: ({row}) => ( + + ), + enableHiding: false, + enableSorting: false, + }), + col.display({ + id: 'actions', + size: 72, + header: () => { + return ( + + + + ); + }, + cell: ({row}) => { + return ( + + ); + }, + enableHiding: false, + enableSorting: false, + }), + ]; + }, [createField, updateField, deleteField, collection.warnings, canCreate]); + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + enableSortingRemoval: false, + enableMultiSort: false, + renderFallbackValue: '', + meta: { + tableId: 'boardAttributes', + disablePaginationControls: true, + onReorder: (prev: number, next: number) => { + reorderField(collection.data[collection.order[prev]], next); + }, + isRowDragDisabled: (rowId: string) => Boolean(collection.data[rowId]?.protected), + getRowDragPreview: (rowId: string) => { + const name = collection.data[rowId]?.name; + if (!name) { + return undefined; + } + const node = document.createElement('div'); + node.className = 'BoardAttributes__dragPreview'; + node.textContent = name; + return node; + }, + }, + manualPagination: true, + }); + + return ( +
    + table={table}/> +
    + ); +} + +const ColHeaderLeft = styled.div` + display: inline-block; +`; + +const ColHeaderRight = styled.div` + display: inline-block; + width: 100%; + text-align: right; +`; + +const ActionsRoot = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + gap: 4px; +`; + +const ProtectedLock = styled.span` + display: inline-flex; + align-items: center; + justify-content: center; + color: rgba(var(--center-channel-color-rgb), 0.56); +`; + +type ActionsCellProps = { + field: BoardsPropertyField; + canCreate: boolean; + createField: (field: BoardsPropertyField) => void; + deleteField: (id: string) => void; +}; + +const ActionsCell = ({field, canCreate, createField, deleteField}: ActionsCellProps) => { + const {formatMessage} = useIntl(); + return ( + + {field.protected && ( + + + + + + )} + + + ); +}; + +type EditCellProps = { + value: string; + label?: string; + testid?: string; + setValue: (value: string) => void; + autoFocus?: boolean; + disabled?: boolean; + deleted?: boolean; + footer?: ReactNode; + strong?: boolean; + maxLength?: number; +}; +const EditCell = (props: EditCellProps) => { + const [value, setValue] = useState(props.value); + + useEffect(() => { + setValue(props.value); + }, [props.value]); + + return ( + <> + ) => { + if (props.autoFocus) { + e.target.select(); + } + }} + value={value} + onChange={(e: React.ChangeEvent) => { + setValue(e.target.value); + }} + onBlur={() => { + if (value !== props.value) { + props.setValue(value); + } + }} + /> + {props.footer} + + ); +}; diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.test.tsx new file mode 100644 index 000000000000..1286122c1b00 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.test.tsx @@ -0,0 +1,117 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import type {BoardsPropertyField} from '@mattermost/types/properties_board'; + +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; + +import SelectType from './board_attributes_type_menu'; + +function makeField(overrides: Partial = {}): BoardsPropertyField { + return { + id: 'field-1', + name: 'My Attribute', + type: 'text', + group_id: 'boards', + object_type: 'post', + create_at: 1700000000000, + delete_at: 0, + update_at: 1700000000000, + created_by: '', + updated_by: '', + target_id: '', + target_type: 'system', + attrs: {sort_order: 0}, + ...overrides, + } as BoardsPropertyField; +} + +describe('SelectType (board attributes type menu)', () => { + it('renders the current type label on the trigger button', () => { + renderWithContext( + , + ); + + expect(screen.getByTestId('fieldTypeSelectorMenuButton')).toHaveTextContent(/select/i); + }); + + it('disables the trigger button when the field is protected', () => { + renderWithContext( + , + ); + + expect(screen.getByTestId('fieldTypeSelectorMenuButton')).toBeDisabled(); + }); + + it('disables the trigger button when the field is flagged for delete', () => { + renderWithContext( + , + ); + + expect(screen.getByTestId('fieldTypeSelectorMenuButton')).toBeDisabled(); + }); + + it('exposes all five known field types when the menu opens', async () => { + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('fieldTypeSelectorMenuButton')); + + // The menu surfaces all the supported types + expect(screen.getByRole('menuitemradio', {name: /text/i})).toBeInTheDocument(); + expect(screen.getByRole('menuitemradio', {name: /^select$/i})).toBeInTheDocument(); + expect(screen.getByRole('menuitemradio', {name: /multi-select/i})).toBeInTheDocument(); + expect(screen.getByRole('menuitemradio', {name: /date/i})).toBeInTheDocument(); + expect(screen.getByRole('menuitemradio', {name: /user/i})).toBeInTheDocument(); + }); + + it('marks the current type as checked', async () => { + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('fieldTypeSelectorMenuButton')); + + const selectItem = screen.getByRole('menuitemradio', {name: /^select$/i}); + expect(selectItem).toHaveAttribute('aria-checked', 'true'); + + const textItem = screen.getByRole('menuitemradio', {name: /text/i}); + expect(textItem).toHaveAttribute('aria-checked', 'false'); + }); + + it('calls updateField with the chosen type when a menu item is selected', async () => { + const updateField = jest.fn(); + const field = makeField({type: 'text'}); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('fieldTypeSelectorMenuButton')); + await userEvent.click(screen.getByRole('menuitemradio', {name: /^select$/i})); + + expect(updateField).toHaveBeenCalledTimes(1); + expect(updateField).toHaveBeenCalledWith({...field, type: 'select'}); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.tsx new file mode 100644 index 000000000000..ad6c5d687f02 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_type_menu.tsx @@ -0,0 +1,192 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import classNames from 'classnames'; +import type {ComponentType} from 'react'; +import React, {useMemo, useState} from 'react'; +import type {MessageDescriptor} from 'react-intl'; +import {defineMessage, FormattedMessage, useIntl} from 'react-intl'; +import {css} from 'styled-components'; + +import {AccountOutlineIcon, CalendarOutlineIcon, CheckIcon, ChevronDownCircleOutlineIcon, FormatListBulletedIcon, MenuVariantIcon} from '@mattermost/compass-icons/components'; +import type IconProps from '@mattermost/compass-icons/components/props'; +import type {FieldType} from '@mattermost/types/properties'; +import type {BoardsPropertyField} from '@mattermost/types/properties_board'; +import type {IDMappedObjects} from '@mattermost/types/utilities'; + +import * as Menu from 'components/menu'; + +import {isPropertyDisabled} from './board_attributes_utils'; + +import '../system_properties/user_properties_type_menu.scss'; + +interface Props { + field: BoardsPropertyField; + updateField: (field: BoardsPropertyField) => void; +} + +const SelectType = (props: Props) => { + const {formatMessage} = useIntl(); + const [filter, setFilter] = useState(''); + + const onFilterChange = (e: React.ChangeEvent) => { + setFilter(e.target.value); + }; + + const handleTypeChange = (descriptor: TypeDescriptor) => { + props.updateField({...props.field, type: descriptor.fieldType}); + setFilter(''); + }; + + const options = useMemo(() => { + return Object.values(TYPE_DESCRIPTOR).filter((descriptor) => { + return formatMessage(descriptor.label).toLowerCase().includes(filter.toLowerCase()); + }); + }, [filter, formatMessage]); + + const currentTypeDescriptor = useMemo(() => { + return getTypeDescriptor(props.field); + }, [props.field]); + const CurrentTypeIcon = currentTypeDescriptor.icon; + + const isDisabled = isPropertyDisabled(props.field); + + return ( + + + + + ), + dataTestId: 'fieldTypeSelectorMenuButton', + disabled: isDisabled, + }} + menu={{ + id: `type-selector-menu-${props.field.id}`, + 'aria-label': formatMessage({ + id: 'admin.board_attributes.type_menu.label', + defaultMessage: 'Select type', + }), + className: 'select-type-mui-menu', + }} + > + {[ + , + ]} + {options.map((descriptor) => { + const {id, icon: Icon, label} = descriptor; + + return ( + handleTypeChange(descriptor)} + labels={} + leadingElement={} + trailingElements={id === currentTypeDescriptor.id && ( + + )} + /> + ); + })} + + ); +}; + +export default SelectType; + +const getTypeDescriptor = (field: BoardsPropertyField): TypeDescriptor => { + for (const descriptor of Object.values(TYPE_DESCRIPTOR)) { + if (descriptor.fieldType === field.type) { + return descriptor; + } + } + + return TYPE_DESCRIPTOR.text; +}; + +// The property types Integrated Boards supports. Enumerated explicitly (a +// deliberate subset of FieldType) so the IDMappedObjects typing on +// TYPE_DESCRIPTOR forces a descriptor entry for each supported type. +type TypeID = 'text' | 'select' | 'multiselect' | 'date' | 'user'; + +type TypeDescriptor = { + id: TypeID; + fieldType: FieldType; + icon: ComponentType; + label: MessageDescriptor; +}; + +const TYPE_DESCRIPTOR: IDMappedObjects = { + text: { + id: 'text', + fieldType: 'text', + icon: MenuVariantIcon, + label: defineMessage({ + id: 'admin.board_attributes.table.select_type.text', + defaultMessage: 'Text', + }), + }, + select: { + id: 'select', + fieldType: 'select', + icon: ChevronDownCircleOutlineIcon, + label: defineMessage({ + id: 'admin.board_attributes.table.select_type.select', + defaultMessage: 'Select', + }), + }, + multiselect: { + id: 'multiselect', + fieldType: 'multiselect', + icon: FormatListBulletedIcon, + label: defineMessage({ + id: 'admin.board_attributes.table.select_type.multi_select', + defaultMessage: 'Multi-select', + }), + }, + date: { + id: 'date', + fieldType: 'date', + icon: CalendarOutlineIcon, + label: defineMessage({ + id: 'admin.board_attributes.table.select_type.date', + defaultMessage: 'Date', + }), + }, + user: { + id: 'user', + fieldType: 'user', + icon: AccountOutlineIcon, + label: defineMessage({ + id: 'admin.board_attributes.table.select_type.user', + defaultMessage: 'User', + }), + }, +} as const; + +const menuInputContainerStyles = css` + padding: 0 12px; +`; diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.test.ts b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.test.ts new file mode 100644 index 000000000000..5bf88e842d55 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.test.ts @@ -0,0 +1,198 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import type {PropertyFieldOption} from '@mattermost/types/properties'; + +import { + isCreatePending, + isDeletePending, + isOptionNameTaken, + isPendingId, + newPendingBoardField, + newPendingId, + stripPendingOptionIds, +} from './board_attributes_utils'; + +describe('board_attributes_utils', () => { + describe('newPendingId / isPendingId', () => { + test('newPendingId returns a string prefixed with pending_', () => { + expect(newPendingId()).toMatch(/^pending_/); + }); + + test('newPendingId returns unique ids on each call', () => { + const ids = new Set([newPendingId(), newPendingId(), newPendingId()]); + expect(ids.size).toBe(3); + }); + + test('isPendingId is true for ids generated by newPendingId', () => { + expect(isPendingId(newPendingId())).toBe(true); + }); + + test('isPendingId is false for non-pending ids', () => { + expect(isPendingId('')).toBe(false); + expect(isPendingId('real-server-id-abc')).toBe(false); + expect(isPendingId('pending')).toBe(false); + expect(isPendingId('pending-with-dash')).toBe(false); + }); + }); + + describe('stripPendingOptionIds', () => { + test('returns undefined for undefined input', () => { + expect(stripPendingOptionIds(undefined)).toBeUndefined(); + }); + + test('returns empty array for empty input', () => { + expect(stripPendingOptionIds([])).toEqual([]); + }); + + test('replaces pending ids with empty strings', () => { + const pendingId = newPendingId(); + const options: PropertyFieldOption[] = [ + {id: pendingId, name: 'Pending option'}, + ]; + + const result = stripPendingOptionIds(options); + expect(result).toEqual([{id: '', name: 'Pending option'}]); + }); + + test('leaves real server ids untouched', () => { + const options: PropertyFieldOption[] = [ + {id: 'real-server-id-abc123', name: 'Saved option', color: 'red'}, + ]; + + const result = stripPendingOptionIds(options); + expect(result).toEqual([{id: 'real-server-id-abc123', name: 'Saved option', color: 'red'}]); + }); + + test('handles mixed pending and real ids in one array', () => { + const pendingId = newPendingId(); + const options: PropertyFieldOption[] = [ + {id: 'real-1', name: 'A'}, + {id: pendingId, name: 'B'}, + {id: 'real-2', name: 'C'}, + ]; + + const result = stripPendingOptionIds(options); + expect(result).toEqual([ + {id: 'real-1', name: 'A'}, + {id: '', name: 'B'}, + {id: 'real-2', name: 'C'}, + ]); + }); + + test('preserves option properties beyond id (name, color)', () => { + const pendingId = newPendingId(); + const options: PropertyFieldOption[] = [ + {id: pendingId, name: 'X', color: 'blue'}, + ]; + + const result = stripPendingOptionIds(options); + expect(result?.[0]).toEqual({id: '', name: 'X', color: 'blue'}); + }); + }); + + describe('newPendingBoardField', () => { + test('returns a field with a pending id', () => { + const field = newPendingBoardField({name: 'Priority'}); + expect(isPendingId(field.id)).toBe(true); + }); + + test('defaults to text type', () => { + const field = newPendingBoardField({name: 'Priority'}); + expect(field.type).toBe('text'); + }); + + test('zeroes out create_at/delete_at/update_at to mark as create-pending', () => { + const field = newPendingBoardField({name: 'Priority'}); + expect(field.create_at).toBe(0); + expect(field.delete_at).toBe(0); + expect(field.update_at).toBe(0); + expect(isCreatePending(field)).toBe(true); + }); + + test('sets group_id to "boards" and target_type to "system"', () => { + const field = newPendingBoardField({name: 'Priority'}); + expect(field.group_id).toBe('boards'); + expect(field.target_type).toBe('system'); + expect(field.object_type).toBe('post'); + }); + + test('assigns pending ids to each option in attrs.options', () => { + const field = newPendingBoardField({ + name: 'Status', + type: 'select', + attrs: { + sort_order: 0, + options: [ + {id: 'whatever', name: 'Todo'}, + {id: '', name: 'Done'}, + ], + }, + }); + + const options = field.attrs.options ?? []; + expect(options).toHaveLength(2); + expect(options.every((o) => isPendingId(o.id))).toBe(true); + + // ids must be unique across options so chips remain individually keyable + const ids = new Set(options.map((o) => o.id)); + expect(ids.size).toBe(2); + }); + + test('does not touch attrs.options when not provided', () => { + const field = newPendingBoardField({name: 'Title'}); + expect(field.attrs.options).toBeUndefined(); + }); + }); + + describe('isCreatePending / isDeletePending', () => { + test('isCreatePending true when create_at and delete_at are both 0', () => { + expect(isCreatePending({id: 'x', create_at: 0, delete_at: 0})).toBe(true); + }); + + test('isCreatePending false when create_at is non-zero (already saved)', () => { + expect(isCreatePending({id: 'x', create_at: 1234, delete_at: 0})).toBe(false); + }); + + test('isDeletePending true when item was saved (create_at > 0) and is now flagged for delete (delete_at > 0)', () => { + expect(isDeletePending({create_at: 1234, delete_at: 5678})).toBe(true); + }); + + test('isDeletePending false for never-saved items, even if delete_at is set', () => { + // An item that was added and removed before saving is neither create-pending nor delete-pending + expect(isDeletePending({create_at: 0, delete_at: 5678})).toBe(false); + }); + }); + + describe('isOptionNameTaken', () => { + const options: PropertyFieldOption[] = [ + {id: '1', name: 'Todo'}, + {id: '2', name: 'In Progress'}, + {id: '3', name: 'Done'}, + ]; + + test('returns true when candidate matches another option (case-insensitive)', () => { + expect(isOptionNameTaken('todo', options)).toBe(true); + expect(isOptionNameTaken('TODO', options)).toBe(true); + expect(isOptionNameTaken('Todo', options)).toBe(true); + }); + + test('returns true when candidate has whitespace padding matching another option', () => { + expect(isOptionNameTaken(' Todo ', options)).toBe(true); + }); + + test('returns false when candidate is unique', () => { + expect(isOptionNameTaken('Blocked', options)).toBe(false); + }); + + test('excludes a given option from the conflict check (used during rename)', () => { + // Renaming "Todo" → "Todo" should not flag itself as a conflict + expect(isOptionNameTaken('Todo', options, options[0])).toBe(false); + }); + + test('still flags conflicts against other options when excluding', () => { + // Renaming option 1 to "Done" should still conflict with option 3 + expect(isOptionNameTaken('Done', options, options[0])).toBe(true); + }); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.ts b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.ts new file mode 100644 index 000000000000..02fbcade508a --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_utils.ts @@ -0,0 +1,458 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import groupBy from 'lodash/groupBy'; +import isEmpty from 'lodash/isEmpty'; +import {useMemo} from 'react'; + +import type {ClientError} from '@mattermost/client'; +import type {PropertyField, PropertyFieldOption} from '@mattermost/types/properties'; +import {supportsOptions} from '@mattermost/types/properties'; +import type {BoardsPropertyField, BoardsPropertyFieldPatch} from '@mattermost/types/properties_board'; +import {BOARDS_PROPERTY_GROUP_NAME, BOARDS_PROPERTY_OBJECT_TYPE, BOARDS_PROPERTY_TARGET_TYPE} from '@mattermost/types/properties_board'; +import {collectionAddItem, collectionFromArray, collectionRemoveItem, collectionReplaceItem, collectionToArray} from '@mattermost/types/utilities'; +import type {IDMappedCollection, IDMappedObjects} from '@mattermost/types/utilities'; + +import {Client4} from 'mattermost-redux/client'; +import {insertWithoutDuplicates} from 'mattermost-redux/utils/array_utils'; + +import {generateId} from 'utils/utils'; + +import type {CollectionIO, PendingOps} from '../system_properties/section_utils'; +import {useThing, usePendingThing, BatchProcessingError} from '../system_properties/section_utils'; + +export type BoardPropertyFields = IDMappedCollection; + +// A field can't be edited once it's a protected (system) field or pending deletion. +export const isPropertyDisabled = (field: BoardsPropertyField): boolean => + Boolean(field.protected) || field.delete_at !== 0; + +// Options are editable only on option-bearing types (supportsOptions already +// excludes user/multiuser) that aren't protected system fields. +export const canEditFieldOptions = (field: BoardsPropertyField): boolean => + supportsOptions(field) && !field.protected; + +export const useBoardPropertyFields = () => { + // current fields + const [fieldCollection, readIO] = useThing(useMemo(() => ({ + get: async () => { + const data = await Client4.getPropertyFields(BOARDS_PROPERTY_GROUP_NAME, BOARDS_PROPERTY_OBJECT_TYPE, BOARDS_PROPERTY_TARGET_TYPE); + + // Protected (system) fields render first, then custom fields ordered by sort_order. + const sorted = (data as BoardsPropertyField[]).sort((a, b) => { + if (Boolean(a.protected) !== Boolean(b.protected)) { + return a.protected ? -1 : 1; + } + return (a.attrs?.sort_order ?? 0) - (b.attrs?.sort_order ?? 0); + }); + return collectionFromArray(sorted); + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + select: (state) => { + return undefined; + }, + opts: {forceInitialGet: true}, + }), []), collectionFromArray([])); + + // pending fields to be saved + const [pendingCollection, pendingIO] = usePendingThing>(fieldCollection, useMemo(() => ({ + commit: async (collection: BoardPropertyFields, prevCollection: BoardPropertyFields) => { + // Invariant: a field that is "created and then deleted" before save + // never reaches this loop — itemOps.delete short-circuits via + // collectionRemoveItem when isCreatePending(field), so create_at=0 + // delete_at!=0 combinations don't end up in either op bucket. + const process = collectionToArray(collection).reduce>((ops, item) => { + // don't process unchanged items + if (item === prevCollection.data[item.id]) { + return ops; + } + + switch (true) { + case isCreatePending(item): + ops.create.push(item); + break; + case isDeletePending(item): + ops.delete.push(item); + break; + case item !== prevCollection.data[item.id]: + ops.edit.push(item); + break; + } + + return ops; + }, {delete: [], edit: [], create: []}); + + const next: BoardPropertyFields = { + data: {...collection.data}, + order: [...collection.order], + errors: {}, // start with errors cleared; don't keep stale errors + }; + + // delete + await Promise.all(process.delete.map(async ({id, protected: isProtected}) => { + if (isProtected) { + return undefined; + } + return Client4.deletePropertyField(BOARDS_PROPERTY_GROUP_NAME, BOARDS_PROPERTY_OBJECT_TYPE, id). + then(() => { + // data:deleted + Reflect.deleteProperty(next.data, id); + + // order:deleted + next.order = next.order.filter((orderId) => orderId !== id); + }). + catch((reason: ClientError) => { + next.errors = {...next.errors, [id]: reason}; + }); + })); + + // update + await Promise.all(process.edit.map(async (pendingItem) => { + // Protected fields are immutable via the generic property API. + if (pendingItem.protected) { + next.data[pendingItem.id] = prevCollection.data[pendingItem.id]; + return undefined; + } + + const {id, name, type, attrs} = pendingItem; + const patch: BoardsPropertyFieldPatch = { + name, + type, + attrs: stripIrrelevantOptions(stripPendingFromAttrs(attrs), type), + }; + + return Client4.patchPropertyField(BOARDS_PROPERTY_GROUP_NAME, BOARDS_PROPERTY_OBJECT_TYPE, id, patch as Partial & Record). + then((nextItem) => { + // data:updated + next.data[id] = nextItem as BoardsPropertyField; + }). + catch((reason: ClientError) => { + next.errors = {...next.errors, [id]: reason}; + }); + })); + + // create + await Promise.all(process.create.map(async (pendingItem) => { + const {id, name, type, attrs} = pendingItem; + + return Client4.createPropertyField(BOARDS_PROPERTY_GROUP_NAME, BOARDS_PROPERTY_OBJECT_TYPE, { + name, + type, + attrs: stripIrrelevantOptions(stripPendingFromAttrs(attrs), type), + target_type: BOARDS_PROPERTY_TARGET_TYPE, + target_id: '', + }). + then((newItem) => { + // data:created (delete pending data) + Reflect.deleteProperty(next.data, id); + next.data[newItem?.id] = newItem as BoardsPropertyField; + + // order:created (replace pending id with created id) + next.order = next.order.map((orderId) => (orderId === pendingItem?.id ? newItem.id : orderId)); + }). + catch((reason: ClientError) => { + next.errors = {...next.errors, [id]: reason}; + }); + })); + + if (isEmpty(next.errors)) { + Reflect.deleteProperty(next, 'errors'); + } else { + // set pendingIO master error + throw new BatchProcessingError('error processing operations', {cause: next.errors}); + } + + return next; + }, + beforeUpdate: (pending, current) => { + const byNamesLower = (data: IDMappedObjects) => { + return groupBy(data, ({name}) => name.toLowerCase()); + }; + + // Name + const pendingByName = byNamesLower(pending.data); + const currentByName = byNamesLower(current.data); + + const warnings = Object.values(pending.data).reduce>((acc, field) => { + // Skip validation for protected fields - they can't be edited + if (field.protected) { + return acc; + } + + if (!field.name) { + // name not provided + acc[field.id] = {name: ValidationWarningNameRequired}; + } else if (pendingByName[field.name.toLowerCase()]?.filter((x) => x.delete_at === 0)?.length > 1) { + // duplicate pending name + acc[field.id] = {name: ValidationWarningNameUnique}; + } else if ( + currentByName?.[field.name.toLowerCase()]?.length >= 1 && + field.id !== currentByName?.[field.name.toLowerCase()]?.[0]?.id + ) { + // name already in use + const correspondingPending = pending.data[currentByName?.[field.name.toLowerCase()]?.[0]?.id]; + + // except when corresponding field is going to be deleted, then it is no longer in conflict + if (correspondingPending.delete_at === 0) { + // not going to be deleted, so in conflict + acc[field.id] = {name: ValidationWarningNameTaken}; + } + } + + if (supportsOptions(field)) { + const optionWarning = validateSelectOptions(field.attrs?.options); + if (optionWarning) { + acc[field.id] = {...acc[field.id], ...optionWarning}; + } + } + + return acc; + }, {}); + + const next = {...pending, warnings}; + + if (isEmpty(warnings)) { + Reflect.deleteProperty(next, 'warnings'); + } + + return next; + }, + isEqual: (a, b) => { + if (a.order.length !== b.order.length) { + return false; + } + if (!a.order.every((id, i) => id === b.order[i])) { + return false; + } + const aKeys = Object.keys(a.data); + const bKeys = Object.keys(b.data); + if (aKeys.length !== bKeys.length) { + return false; + } + return aKeys.every((key) => a.data[key] === b.data[key]); + }, + + }), [])); + + // edit pending fields before saving + const itemOps = useMemo(() => ({ + update: (field) => { + pendingIO.apply((pending) => { + return collectionReplaceItem(pending, field); + }); + }, + create: (patch?) => { + pendingIO.apply((pending) => { + const nextOrder = Object.values(pending.data).filter((x) => !isDeletePending(x)).length; + + const field = newPendingBoardField({ + type: 'text', + ...patch, + name: getIncrementedName(patch?.name ?? 'Text', pending), + attrs: { + ...patch?.attrs, + sort_order: nextOrder, + }, + }); + + return collectionAddItem(pending, field); + }); + }, + reorder: ({id}, nextItemOrder) => { + pendingIO.apply((pending) => { + const draggedField = pending.data[id]; + + // Protected fields cannot be reordered. + if (draggedField?.protected) { + return pending; + } + + // Protected fields must remain at the top of the list, so a + // custom field cannot be dropped above any protected sibling. + const protectedCount = pending.order.filter((oid) => pending.data[oid]?.protected).length; + const clampedOrder = Math.max(nextItemOrder, protectedCount); + + const nextOrder = insertWithoutDuplicates(pending.order, id, clampedOrder); + + if (nextOrder === pending.order) { + return pending; + } + + const nextItems = Object.values(pending.data).reduce((changedItems, item) => { + // never patch sort_order on protected fields + if (item.protected) { + return changedItems; + } + + const itemCurrentOrder = item.attrs?.sort_order; + const itemNextOrder = nextOrder.indexOf(item.id); + + if (itemNextOrder !== itemCurrentOrder) { + changedItems.push({...item, attrs: {...item.attrs, sort_order: itemNextOrder}}); + } + + return changedItems; + }, []); + + return collectionReplaceItem({...pending, order: nextOrder}, ...nextItems); + }); + }, + delete: (id: string) => { + pendingIO.apply((pending) => { + const field = pending.data[id]; + + // skip if protected + if (field.protected) { + return pending; + } + + if (isCreatePending(field)) { + // immediately remove if deleting a field that is pending creation + return collectionRemoveItem(pending, field); + } + + return collectionReplaceItem(pending, {...field, delete_at: Date.now()}); + }); + }, + } satisfies CollectionIO), [pendingIO.apply]); + + return [pendingCollection, readIO, pendingIO, itemOps] as const; +}; + +export const ValidationWarningNameRequired = 'board_attributes.validation.name_required'; +export const ValidationWarningNameUnique = 'board_attributes.validation.name_unique'; +export const ValidationWarningNameTaken = 'board_attributes.validation.name_taken'; +export const ValidationWarningOptionsRequired = 'board_attributes.validation.options_required'; +export const ValidationWarningOptionsUnique = 'board_attributes.validation.options_unique'; + +const normalizeOptionName = (name: string) => name.trim().toLowerCase(); + +const hasDuplicateOptionNames = (options: PropertyFieldOption[]) => { + const names = options.map((o) => normalizeOptionName(o.name)); + return new Set(names).size !== names.length; +}; + +// Cell-level pre-commit check: is `candidate` already taken by some other +// option in `options`? Used for live feedback inside the rename dropdown so +// the user sees the conflict before the edit reaches the collection. +export const isOptionNameTaken = ( + candidate: string, + options: PropertyFieldOption[], + excluding?: PropertyFieldOption, +): boolean => { + const normalized = normalizeOptionName(candidate); + return options.some((o) => o !== excluding && normalizeOptionName(o.name) === normalized); +}; + +const validateSelectOptions = (options: PropertyFieldOption[] | undefined): {attrs: string} | undefined => { + if (!options?.length) { + return {attrs: ValidationWarningOptionsRequired}; + } + if (hasDuplicateOptionNames(options)) { + return {attrs: ValidationWarningOptionsUnique}; + } + return undefined; +}; + +// Strip trailing ` (copy)` or ` (N)` suffixes (repeatedly) so that duplicating +// `Text (copy)` yields `Text (2)` and duplicating `Text (2)` yields `Text (3)`, +// not `Text (2) (copy)` / `Text (2) (copy) (copy)`. +const stripDuplicateSuffix = (name: string) => { + let base = name; + const suffix = / \((copy|\d+)\)$/; + while (suffix.test(base)) { + base = base.replace(suffix, ''); + } + return base; +}; + +const getIncrementedName = (desiredName: string, collection: BoardPropertyFields) => { + const names = new Set(Object.values(collection.data).map(({name}) => name)); + const base = stripDuplicateSuffix(desiredName); + + // If the bare base name is free (e.g. first "+ Add" of this type), use it. + if (!names.has(base)) { + return base; + } + + // Otherwise find the next available "(N)" suffix, starting at 2. + let n = 2; + while (names.has(`${base} (${n})`)) { + n++; + } + return `${base} (${n})`; +}; + +const PENDING = 'pending_'; +export const isCreatePending = (item: T) => { + // has not been created and is not deleted + return item.create_at === 0 && item.delete_at === 0; +}; + +export const isDeletePending = (item: T) => { + // has been created and needs to be deleted + return item.create_at !== 0 && item.delete_at !== 0; +}; + +export const newPendingId = () => `${PENDING}${generateId()}`; + +export const isPendingId = (id: string) => id.startsWith(PENDING); + +// Pending ids are a frontend-only convention so unsaved chips can be uniquely +// keyed (for React keys, FLIP animations, DnD lookups). The server doesn't +// know about them — clear them out before send so the server treats those +// options as creates rather than failing to find a matching record. +export const stripPendingOptionIds = (options?: PropertyFieldOption[]) => + options?.map((o) => (isPendingId(o.id) ? {...o, id: ''} : o)); + +const stripPendingFromAttrs = (attrs: A): A => { + if (!attrs?.options) { + return attrs; + } + return {...attrs, options: stripPendingOptionIds(attrs.options)}; +}; + +// Remove `options` from `attrs` when the field type doesn't carry an option +// list, so a stale options array left over from a recent type-switch can't +// be persisted on either create or update. +const stripIrrelevantOptions = (attrs: A, type: BoardsPropertyField['type']): A => { + if (type === 'select' || type === 'multiselect') { + return attrs; + } + if (!attrs?.options) { + return attrs; + } + const next = {...attrs} as A; + Reflect.deleteProperty(next, 'options'); + return next; +}; + +export const newPendingBoardField = (patch: BoardsPropertyFieldPatch & Pick): BoardsPropertyField => { + const attrs = {...patch.attrs}; + + if (attrs.options) { + // Give each option a pending id so chips remain individually keyable + // (React key, FLIP, DnD). `stripPendingFromAttrs` on save replaces + // these with '' before hitting the server. + attrs.options = patch.attrs?.options?.map((option) => ({...option, id: newPendingId()})); + } + + return { + type: 'text', + ...patch, + group_id: BOARDS_PROPERTY_GROUP_NAME, + object_type: BOARDS_PROPERTY_OBJECT_TYPE, + id: newPendingId(), + create_at: 0, + delete_at: 0, + update_at: 0, + created_by: '', + updated_by: '', + target_id: '', + target_type: BOARDS_PROPERTY_TARGET_TYPE, + attrs: { + sort_order: 0, + ...attrs, + }, + }; +}; diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.test.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.test.tsx new file mode 100644 index 000000000000..ebf3755529f0 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.test.tsx @@ -0,0 +1,430 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import type {PropertyFieldOption} from '@mattermost/types/properties'; +import type {BoardsPropertyField, BoardsPropertyFieldOption} from '@mattermost/types/properties_board'; + +import {renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils'; + +import {isPendingId, ValidationWarningOptionsUnique} from './board_attributes_utils'; +import BoardAttributesValues from './board_attributes_values'; + +function makeField(overrides: Partial = {}): BoardsPropertyField { + return { + id: 'field-1', + name: 'Status', + type: 'select', + group_id: 'boards', + object_type: 'post', + create_at: 1700000000000, + delete_at: 0, + update_at: 1700000000000, + created_by: '', + updated_by: '', + target_id: '', + target_type: 'system', + attrs: { + sort_order: 0, + options: [], + }, + ...overrides, + } as BoardsPropertyField; +} + +describe('BoardAttributesValues', () => { + it('renders an em-dash placeholder for user-typed fields (no options to manage)', () => { + const field = makeField({type: 'user', attrs: {sort_order: 0}}); + renderWithContext( + , + ); + + // Em-dash is rendered when field type doesn't support options + expect(screen.getByText('—')).toBeInTheDocument(); + }); + + it('renders an em-dash placeholder for text-typed fields', () => { + const field = makeField({type: 'text', attrs: {sort_order: 0}}); + renderWithContext( + , + ); + + expect(screen.getByText('—')).toBeInTheDocument(); + }); + + describe('protected (system) select fields', () => { + const protectedField = makeField({ + protected: true, + attrs: { + sort_order: 0, + options: [ + {id: 'opt-1', name: 'Todo'}, + {id: 'opt-2', name: 'In Progress'}, + {id: 'opt-3', name: 'Complete'}, + ], + }, + }); + + it('renders a read-only chip per option', () => { + renderWithContext( + , + ); + + const readonly = screen.getByTestId('property-values-readonly'); + expect(readonly).toBeInTheDocument(); + expect(readonly).toHaveTextContent('Todo'); + expect(readonly).toHaveTextContent('In Progress'); + expect(readonly).toHaveTextContent('Complete'); + }); + + it('does NOT render the editable container or Add button', () => { + renderWithContext( + , + ); + + expect(screen.queryByTestId('property-values-input')).not.toBeInTheDocument(); + expect(screen.queryByRole('button', {name: /add value/i})).not.toBeInTheDocument(); + }); + }); + + describe('editable select fields', () => { + it('renders an editable container with one chip per option', () => { + const field = makeField({ + attrs: { + sort_order: 0, + options: [ + {id: 'opt-a', name: 'Low'}, + {id: 'opt-b', name: 'High'}, + ], + }, + }); + renderWithContext( + , + ); + + const container = screen.getByTestId('property-values-input'); + expect(container).toBeInTheDocument(); + expect(container).toHaveTextContent('Low'); + expect(container).toHaveTextContent('High'); + }); + + it('renders an Add button when editable', () => { + renderWithContext( + , + ); + + expect(screen.getByRole('button', {name: /add value/i})).toBeInTheDocument(); + }); + + it('appends a new option with a pending id when Add is clicked', async () => { + const updateField = jest.fn(); + const field = makeField({ + attrs: { + sort_order: 0, + options: [{id: 'existing', name: 'Existing'}], + }, + }); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByRole('button', {name: /add value/i})); + + expect(updateField).toHaveBeenCalledTimes(1); + const next = updateField.mock.calls[0][0] as BoardsPropertyField; + const options = next.attrs.options ?? []; + expect(options).toHaveLength(2); + + // Existing option is preserved + expect(options[0]).toEqual({id: 'existing', name: 'Existing'}); + + // New option got a pending id (not '', not a duplicate of the existing id) + const added = options[1]; + expect(isPendingId(added.id)).toBe(true); + expect(added.id).not.toBe(''); + expect(added.id).not.toBe('existing'); + }); + + it('generates a unique default name for new options that does not collide with siblings', async () => { + const updateField = jest.fn(); + const field = makeField({ + attrs: { + sort_order: 0, + options: [ + {id: '1', name: 'Option 1'}, + {id: '2', name: 'Option 2'}, + ], + }, + }); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByRole('button', {name: /add value/i})); + + const next = updateField.mock.calls[0][0] as BoardsPropertyField; + const added = (next.attrs.options ?? []).at(-1) as PropertyFieldOption; + + // First "Option 1" / "Option 2" are taken; the next one available is "Option 3" + expect(added.name).toBe('Option 3'); + }); + + it('renders chips with stable data-flip-key attributes (used by FLIP animation)', () => { + const field = makeField({ + attrs: { + sort_order: 0, + options: [ + {id: 'opt-a', name: 'A'}, + {id: 'opt-b', name: 'B'}, + ], + }, + }); + + renderWithContext( + , + ); + + const container = screen.getByTestId('property-values-input'); + + // Two chips, each with a data-flip-key matching its option id + expect(container.querySelector('[data-flip-key="opt-a"]')).toBeInTheDocument(); + expect(container.querySelector('[data-flip-key="opt-b"]')).toBeInTheDocument(); + }); + + it('renders the unique-options validation warning when passed via the warning prop', () => { + const field = makeField({ + attrs: { + sort_order: 0, + options: [ + {id: '1', name: 'Same'}, + {id: '2', name: 'Same'}, + ], + }, + }); + + renderWithContext( + , + ); + + // The exact copy comes from i18n; just confirm the warning surface renders + // by checking that container holds something beyond the chips. + expect(screen.getByTestId('property-values-input')).toBeInTheDocument(); + + // Look for the warning text via its i18n default (matches the component) + expect(screen.getByText(/values must be unique/i)).toBeInTheDocument(); + }); + }); + + describe('EditableChip interactions', () => { + const makeFieldWithOptions = (options: BoardsPropertyFieldOption[]) => + makeField({attrs: {sort_order: 0, options}}); + + it('removes the option when the chip X button is clicked', async () => { + const updateField = jest.fn(); + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Low'}, + {id: 'opt-2', name: 'High'}, + ]); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('property-option-delete-opt-1')); + + expect(updateField).toHaveBeenCalledTimes(1); + const next = updateField.mock.calls[0][0] as BoardsPropertyField; + expect(next.attrs.options).toEqual([{id: 'opt-2', name: 'High'}]); + }); + + it('does NOT render the X button when only one option remains (cannot delete the last value)', () => { + const field = makeFieldWithOptions([{id: 'only', name: 'Only'}]); + + renderWithContext( + , + ); + + expect(screen.queryByTestId('property-option-delete-only')).not.toBeInTheDocument(); + }); + + it('commits a renamed option when the rename input is blurred', async () => { + const updateField = jest.fn(); + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Old name'}, + {id: 'opt-2', name: 'Other'}, + ]); + + renderWithContext( + , + ); + + // Open the chip's edit menu + await userEvent.click(screen.getByTestId('property-option-chip-opt-1')); + + // The rename input is autofocused; clear and type a new name + const input = screen.getByPlaceholderText(/option name/i) as HTMLInputElement; + await userEvent.clear(input); + await userEvent.type(input, 'New name'); + + // `await userEvent.tab()` blurs through the userEvent queue so React's + // onBlur-driven commit flushes deterministically; an imperative .blur() + // bypasses the queue and would only pass by microtask-timing luck. + await userEvent.tab(); + + await waitFor(() => expect(updateField).toHaveBeenCalledTimes(1)); + const next = updateField.mock.calls[0][0] as BoardsPropertyField; + expect(next.attrs.options).toEqual([ + {id: 'opt-1', name: 'New name'}, + {id: 'opt-2', name: 'Other'}, + ]); + }); + + it('does NOT commit when the rename leaves the name empty', async () => { + const updateField = jest.fn(); + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Keep me'}, + {id: 'opt-2', name: 'Other'}, + ]); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('property-option-chip-opt-1')); + + const input = screen.getByPlaceholderText(/option name/i) as HTMLInputElement; + await userEvent.clear(input); + await userEvent.tab(); + + // Empty rename is a no-op — the collection isn't updated. Wait a + // microtask to be sure no late-flush commit slips through. + await new Promise((resolve) => setTimeout(resolve, 0)); + expect(updateField).not.toHaveBeenCalled(); + }); + + it('does NOT commit when the new name equals the original (after trimming)', async () => { + const updateField = jest.fn(); + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Same'}, + {id: 'opt-2', name: 'Other'}, + ]); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('property-option-chip-opt-1')); + + const input = screen.getByPlaceholderText(/option name/i) as HTMLInputElement; + + // Replace value with padded original — commitRename trims and compares. + await userEvent.clear(input); + await userEvent.type(input, ' Same '); + await userEvent.tab(); + + await new Promise((resolve) => setTimeout(resolve, 0)); + expect(updateField).not.toHaveBeenCalled(); + }); + + it('surfaces the live in-menu duplicate-name warning when typing a name already taken by a sibling', async () => { + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Alpha'}, + {id: 'opt-2', name: 'Beta'}, + ]); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('property-option-chip-opt-1')); + + const input = screen.getByPlaceholderText(/option name/i) as HTMLInputElement; + await userEvent.clear(input); + await userEvent.type(input, 'Beta'); + + // Live warning surfaces in the menu (RenameError role=alert) + expect(screen.getByText(/a value with this name already exists/i)).toBeInTheDocument(); + expect(input).toHaveAttribute('aria-invalid', 'true'); + }); + + it('updates the option color when a color picker item is selected', async () => { + const updateField = jest.fn(); + const field = makeFieldWithOptions([ + {id: 'opt-1', name: 'Tagged'}, + {id: 'opt-2', name: 'Other'}, + ]); + + renderWithContext( + , + ); + + await userEvent.click(screen.getByTestId('property-option-chip-opt-1')); + + // Color picker items are role=menuitemradio (so onClick fires immediately). + // Pick a non-default color and verify the new attrs.options carries it. + await userEvent.click(screen.getByRole('menuitemradio', {name: /blue/i})); + + // Exactly one updateField call — guards against false positives + // where an unrelated earlier flush would satisfy `toHaveBeenCalled()`. + expect(updateField).toHaveBeenCalledTimes(1); + const lastCall = updateField.mock.calls[0][0] as BoardsPropertyField; + const updatedOption = (lastCall.attrs.options ?? []).find((o) => o.id === 'opt-1'); + expect(updatedOption?.color).toBe('blue'); + }); + }); +}); diff --git a/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.tsx b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.tsx new file mode 100644 index 000000000000..e758f8233306 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/board_attributes_values.tsx @@ -0,0 +1,603 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {DropIndicator} from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box'; +import React, {useEffect, useMemo, useRef, useState} from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; +import styled, {css} from 'styled-components'; + +import {CheckIcon, CloseCircleIcon, LockOutlineIcon, PlusIcon, TrashCanOutlineIcon} from '@mattermost/compass-icons/components'; +import {WithTooltip} from '@mattermost/shared/components/tooltip'; +import {supportsOptions} from '@mattermost/types/properties'; +import {type BoardsPropertyField, type BoardsPropertyFieldOption} from '@mattermost/types/properties_board'; + +import * as Menu from 'components/menu'; + +import {useFLIPAnimation} from 'hooks/use_flip_animation'; +import { + COLOR_DESCRIPTOR, + BOARDS_COLOR_TOKEN_NAMES, + type BoardsColorToken, + normalizeColor, +} from 'utils/board_property_colors'; + +import {ValidationWarningOptionsUnique, canEditFieldOptions, isOptionNameTaken, newPendingId} from './board_attributes_utils'; +import {useBoardOptionDnd} from './hooks/use_board_option_dnd'; +import {useBoardOptionsDnd} from './hooks/use_board_options_dnd'; + +import {DangerText} from '../system_properties/controls'; + +const MAX_OPTION_NAME_LENGTH = 64; + +type Props = { + field: BoardsPropertyField; + updateField: (field: BoardsPropertyField) => void; + warning?: string; + autoFocus?: boolean; +}; + +const BoardAttributesValues = ({field, updateField, warning}: Props) => { + const {formatMessage} = useIntl(); + const containerRef = useRef(null); + + const isEditable = canEditFieldOptions(field); + + const options = field.attrs?.options ?? []; + + const setOptions = (next: BoardsPropertyFieldOption[]) => { + updateField({...field, attrs: {...field.attrs, options: next}}); + }; + + const chipKeys = options.map((option) => option.id); + useFLIPAnimation({ + items: chipKeys, + getElement: (key) => containerRef.current?.querySelector(`[data-flip-key="${key}"]`) ?? null, + }); + + useBoardOptionsDnd({fieldId: field.id, options, setOptions, enabled: isEditable}); + + if (!supportsOptions(field)) { + return ( + + {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} + {'—'} + + ); + } + + if (field.protected) { + // Reuse the editable layout — same ValuesContainer, same ChipDropZone, + // same ChipShell — so protected and editable rows align by construction + // rather than by keeping two separate styled trees in sync. + return ( + + + {options.map((option) => ( + + ))} + + + + ); + } + + const generateDefaultName = () => { + const existing = new Set(options.map((o) => o.name.toLowerCase())); + let counter = 1; + let name = `Option ${counter}`; + while (existing.has(name.toLowerCase())) { + counter++; + name = `Option ${counter}`; + } + return name; + }; + + const handleAdd = () => { + setOptions([...options, {id: newPendingId(), name: generateDefaultName()}]); + }; + + return ( + <> + + {options.map((option) => ( + + ))} + + + + + + + {warning === ValidationWarningOptionsUnique && ( + + )} + + ); +}; + +type ChipProps = { + option: BoardsPropertyFieldOption; + options: BoardsPropertyFieldOption[]; + setOptions: (next: BoardsPropertyFieldOption[]) => void; + fieldId: string; + + // When true, render the chip with no menu, no delete affordance, and no + // drag-and-drop wiring — but keep the exact same outer markup so + // protected (Status) rows align pixel-for-pixel with editable rows. + readonly?: boolean; +}; + +const EditableChip = ({option, options, setOptions, fieldId, readonly = false}: ChipProps) => { + const {formatMessage} = useIntl(); + const [editValue, setEditValue] = useState(option.name); + const inputRef = useRef(null); + const [chipElement, setChipElement] = useState(null); + const [dropZoneElement, setDropZoneElement] = useState(null); + const canDelete = options.length > 1; + + // Normalize once: unknown legacy values fall back to `default` consistently + // across the chip's background, the drag preview, and the menu's + // selected-state check. + const color = normalizeColor(option.color); + + // The committed name conflicts with a sibling — render the chip with a + // red border so the conflict is visible without opening the dropdown. + const isInvalid = isOptionNameTaken(option.name, options, option); + + useEffect(() => { + setEditValue(option.name); + }, [option.name]); + + const optionKey = option.id; + const {closestEdge} = useBoardOptionDnd({ + fieldId, + optionKey, + chipElement, + dropZoneElement, + getDragPreview: () => { + const node = document.createElement('span'); + node.className = 'BoardAttributes__optionDragPreview'; + node.style.backgroundColor = COLOR_DESCRIPTOR[color].color; + node.textContent = option.name; + return node; + }, + }); + + // True while the input value (typed or committed) would duplicate a + // sibling. Provides immediate in-menu feedback before the edit reaches + // the collection; the hook's beforeUpdate still runs the authoritative + // check and BoardAttributesValues surfaces the persistent warning under + // the chip list. + const liveRenameTaken = useMemo( + () => Boolean(editValue.trim()) && isOptionNameTaken(editValue, options, option), + [editValue, options, option], + ); + + // Commit any non-empty distinct value to the collection — even a duplicate. + // Surfacing the conflict is the warning's job (live in the menu, plus + // collection-level under the chip list). We don't discard the edit. + const commitRename = () => { + const trimmed = editValue.trim(); + if (!trimmed || trimmed === option.name) { + setEditValue(option.name); + return; + } + setOptions(options.map((o) => (o === option ? {...o, name: trimmed} : o))); + }; + + const setColor = (color: BoardsColorToken) => { + setOptions(options.map((o) => (o === option ? {...o, color} : o))); + }; + + const handleDelete = () => { + if (!canDelete) { + return; + } + setOptions(options.filter((o) => o !== option)); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + e.stopPropagation(); + if (e.key === 'Enter') { + commitRename(); + inputRef.current?.blur(); + } else if (e.key === 'Escape') { + setEditValue(option.name); + inputRef.current?.blur(); + } + }; + + const menuId = `board-option-${option.id || option.name}`; + + const handleDeleteClick = (e: React.MouseEvent) => { + e.stopPropagation(); + handleDelete(); + }; + + if (readonly) { + // Same outer wrappers as the editable chip so protected chips align + // pixel-for-pixel with editable ones (no separate ReadonlyChip + // styled component to drift over time). No Menu.Container, no + // delete button, and the chip + dropzone refs stay unset so + // useBoardOptionDnd never wires up DnD for this option. + return ( + + + + {option.name} + + + + ); + } + + return ( + + + {option.name}, + dataTestId: `property-option-chip-${option.id || option.name}`, + }} + menu={{ + id: `${menuId}-menu`, + 'aria-label': formatMessage({ + id: 'admin.board_attributes.values.option_menu_label', + defaultMessage: 'Edit option', + }), + className: 'property-option-menu', + }} + > + + setEditValue(e.target.value)} + onFocus={(e) => e.target.select()} + onKeyDown={handleKeyDown} + onBlur={commitRename} + maxLength={MAX_OPTION_NAME_LENGTH} + placeholder={formatMessage({ + id: 'admin.board_attributes.values.rename_placeholder', + defaultMessage: 'Option name', + })} + autoFocus={true} + aria-invalid={liveRenameTaken} + /> + {liveRenameTaken && ( + + + + )} + + {canDelete && ( + } + labels={( + + )} + /> + )} + + + + + {BOARDS_COLOR_TOKEN_NAMES.map((token) => ( + setColor(token)} + leadingElement={} + labels={} + trailingElements={color === token ? ( + + ) : undefined} + /> + ))} + + {canDelete && ( + + + + )} + + {closestEdge && } + + ); +}; + +export default BoardAttributesValues; + +const EmptyValues = styled.span` + padding: 4px 8px; + color: rgba(var(--center-channel-color-rgb), 0.48); +`; + +const ValuesContainer = styled.div` + display: flex; + flex-wrap: wrap; + row-gap: 3px; + column-gap: 0; + align-items: center; + padding: 6px 0; + min-height: 40px; +`; + +const ChipDropZone = styled.span` + position: relative; + display: inline-flex; + padding: 0 3px; +`; + +/* Outer pill: takes the option's colour as background, holds the menu-trigger + button and the inline X delete button as siblings so they render as one + visual chip but remain individually focusable. Read-only chips reuse this + same shell (via EditableChip's `readonly` branch) so protected and editable + rows align by construction. + position: relative is required so DropIndicator (absolute-positioned) clips + to the chip boundary. + + All chip-internal CSS lives on this component (trigger button reset, focus + ring, readonly variant) so the rules are scoped to a single chip rather + than to whatever container the chip happens to render inside. */ +const ChipShell = styled.span<{$invalid?: boolean; $readonly?: boolean}>` + position: relative; + display: inline-flex; + align-items: center; + border-radius: 4px; + user-select: none; + cursor: ${({$readonly}) => ($readonly ? 'default' : 'grab')}; + transition: filter 0.15s ease, box-shadow 0.15s ease; + + &:active { + cursor: ${({$readonly}) => ($readonly ? 'default' : 'grabbing')}; + } + + ${({$readonly}) => !$readonly && css` + &:hover { + filter: brightness(0.97); + } + `} + + ${({$invalid}) => $invalid && css` + box-shadow: 0 0 0 1px var(--error-text); + `} + + /* Trigger element inside the chip: the menu button in editable mode, a + plain wrapping the label in readonly mode. Same class either + way; readonly-specific tweaks are conditional on $readonly below. */ + .property-option-chip-trigger { + padding: 2px 4px 2px 8px; + margin: 0; + border: 0; + background: transparent; + min-height: 0; + line-height: normal; + box-shadow: none; + outline: none; + color: var(--center-channel-color); + font-family: 'Open Sans'; + font-size: 12px; + font-weight: 600; + cursor: pointer; + } + + /* Keyboard focus ring on the trigger button — mirrors ChipDeleteButton's + pattern. Mouse focus (:focus without :focus-visible) stays ring-less. */ + .property-option-chip-trigger:focus-visible { + outline: 2px solid var(--button-bg); + outline-offset: 2px; + border-radius: 4px; + } + + ${({$readonly}) => $readonly && css` + /* Readonly: balance the right padding (no trailing X), and use the + default cursor since the span has no menu to open. */ + .property-option-chip-trigger { + padding-right: 8px; + cursor: default; + } + `} +`; + +const ChipLabel = styled.span` + white-space: nowrap; + line-height: 18px; +`; + +const ChipDeleteButton = styled.button` + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 6px 0 2px; + margin: 0; + height: 100%; + border: 0; + background: transparent; + cursor: pointer; + color: rgba(var(--center-channel-color-rgb), 0.56); + + &:hover { + color: var(--center-channel-color); + } + + &:focus-visible { + outline: 2px solid var(--button-bg); + outline-offset: -2px; + border-radius: 2px; + } +`; + +/* Rounded-square colour preview shown inside menu items. 20px square with a + 1px hairline border, per Figma node 696:91067. Rendered as a block so it + centres on the parent flex row's cross-axis without inheriting an + inline-block baseline offset. */ +const ColorPreview = styled.span` + display: block; + width: 20px; + height: 20px; + border-radius: 4px; + flex-shrink: 0; + align-self: center; + box-shadow: inset 0 0 0 1px rgba(var(--center-channel-color-rgb), 0.08); +`; + +const ColorsLabel = styled.div` + padding: 8px 16px 4px; + font-family: 'Open Sans'; + font-size: 11px; + font-weight: 600; + line-height: 16px; + text-transform: uppercase; + letter-spacing: 0.02em; + color: rgba(var(--center-channel-color-rgb), 0.56); +`; + +const AddButton = styled.button` + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + padding: 0; + border: none; + border-radius: 4px; + background: transparent; + color: rgba(var(--center-channel-color-rgb), 0.72); + cursor: pointer; + transition: all 0.15s ease; + + &:hover { + color: var(--center-channel-color); + background: rgba(var(--center-channel-color-rgb), 0.08); + } +`; + +const RenameInputWrapper = styled.div` + padding: 8px 12px; +`; + +const RenameInput = styled.input` + width: 100%; + padding: 6px 10px; + border: 1px solid rgba(var(--center-channel-color-rgb), 0.16); + border-radius: 4px; + background: var(--center-channel-bg); + color: var(--center-channel-color); + font-family: 'Open Sans'; + font-size: 14px; + line-height: 20px; + outline: none; + + &:focus { + border-color: var(--button-bg); + box-shadow: 0 0 0 2px rgba(var(--button-bg-rgb), 0.2); + } + + &::placeholder { + color: rgba(var(--center-channel-color-rgb), 0.48); + } + + &[aria-invalid='true'] { + border-color: var(--error-text); + } + + &[aria-invalid='true']:focus { + border-color: var(--error-text); + box-shadow: 0 0 0 2px rgba(var(--error-text-color-rgb), 0.2); + } +`; + +const RenameError = styled.div` + margin-top: 6px; + font-family: 'Open Sans'; + font-size: 12px; + line-height: 16px; + color: var(--error-text); +`; + diff --git a/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_option_dnd.ts b/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_option_dnd.ts new file mode 100644 index 000000000000..ccf6f9a04874 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_option_dnd.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {combine} from '@atlaskit/pragmatic-drag-and-drop/combine'; +import {draggable, dropTargetForElements} from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; +import {setCustomNativeDragPreview} from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview'; +import type {Edge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {attachClosestEdge, extractClosestEdge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {useEffect, useState} from 'react'; + +import {useLatest} from 'hooks/useLatest'; + +type UseBoardOptionDndOptions = { + fieldId: string; + optionKey: string; + chipElement: HTMLElement | null; + dropZoneElement: HTMLElement | null; + getDragPreview: () => HTMLElement; +}; + +type UseBoardOptionDndResult = { + closestEdge: Edge | null; +}; + +/** + * Wires PDND draggable + dropTarget for a single board option chip. + * The chip element is the drag source; the drop zone element (which may have + * extended padding) is the drop target. Returns closestEdge for DropIndicator. + */ +export function useBoardOptionDnd({ + fieldId, + optionKey, + chipElement, + dropZoneElement, + getDragPreview, +}: UseBoardOptionDndOptions): UseBoardOptionDndResult { + const [closestEdge, setClosestEdge] = useState(null); + + // Read via ref so the ghost reflects the option's latest state without re-registering. + const getDragPreviewRef = useLatest(getDragPreview); + + useEffect(() => { + if (!chipElement || !dropZoneElement) { + return undefined; + } + const dragKind = `board-option-chip:${fieldId}`; + + return combine( + draggable({ + element: chipElement, + getInitialData: () => ({kind: dragKind, optionKey}), + onGenerateDragPreview: ({nativeSetDragImage}) => { + setCustomNativeDragPreview({ + nativeSetDragImage, + render: ({container}) => { + container.appendChild(getDragPreviewRef.current()); + }, + }); + }, + }), + dropTargetForElements({ + element: dropZoneElement, + canDrop: ({source}) => + source.data.kind === dragKind && + source.data.optionKey !== optionKey, + getData: ({input, element}) => + attachClosestEdge( + {kind: dragKind, optionKey}, + {input, element, allowedEdges: ['left', 'right']}, + ), + onDrag: ({self}) => setClosestEdge(extractClosestEdge(self.data)), + onDragLeave: () => setClosestEdge(null), + onDrop: () => setClosestEdge(null), + }), + ); + + // getDragPreview read via ref (above); re-registering would tear down PDND state mid-drag. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [chipElement, dropZoneElement, fieldId, optionKey]); + + return {closestEdge}; +} diff --git a/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_options_dnd.ts b/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_options_dnd.ts new file mode 100644 index 000000000000..bd94970bbdc4 --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/hooks/use_board_options_dnd.ts @@ -0,0 +1,84 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {monitorForElements} from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; +import type {Edge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {extractClosestEdge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {useEffect} from 'react'; + +import type {BoardsPropertyFieldOption} from '@mattermost/types/properties_board'; + +import {useLatest} from 'hooks/useLatest'; + +type BoardOption = BoardsPropertyFieldOption; + +type UseBoardOptionsDndOptions = { + fieldId: string; + options: BoardOption[]; + setOptions: (next: BoardOption[]) => void; + enabled: boolean; +}; + +/** + * Registers a container-level PDND monitor scoped to board option chips for a + * specific field. Reorders options in place when a chip is dropped. + * Safe to call unconditionally; no-ops when enabled is false. + */ +export function useBoardOptionsDnd({fieldId, options, setOptions, enabled}: UseBoardOptionsDndOptions): void { + const optionsRef = useLatest(options); + const setOptionsRef = useLatest(setOptions); + + useEffect(() => { + if (!enabled) { + return undefined; + } + const dragKind = `board-option-chip:${fieldId}`; + return monitorForElements({ + canMonitor: ({source}) => source.data.kind === dragKind, + onDrop: ({source, location}) => { + const target = location.current.dropTargets[0]; + if (!target) { + return; + } + const sourceKey = source.data.optionKey as string; + const targetKey = target.data.optionKey as string; + const edge = extractClosestEdge(target.data); + const current = optionsRef.current; + const sourceIndex = current.findIndex((o) => o.id === sourceKey); + const targetIndex = current.findIndex((o) => o.id === targetKey); + if (sourceIndex === -1 || targetIndex === -1) { + return; + } + const dropIndex = getDropIndex(sourceIndex, targetIndex, edge); + if (dropIndex !== sourceIndex) { + const next = [...current]; + const [moved] = next.splice(sourceIndex, 1); + next.splice(dropIndex, 0, moved); + setOptionsRef.current(next); + } + }, + }); + + // Refs handle options/setOptions freshness; re-register only when fieldId or enabled changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fieldId, enabled]); +} + +function getDropIndex( + sourceIndex: number, + targetIndex: number, + edge: Edge | null, +): number { + if (edge === 'left' || edge === 'top') { + if (sourceIndex < targetIndex) { + return targetIndex - 1; + } + return targetIndex; + } + + // 'right' or 'bottom' — insert after the target + if (sourceIndex < targetIndex) { + return targetIndex; + } + return targetIndex + 1; +} diff --git a/webapp/channels/src/components/admin_console/board_attributes/index.ts b/webapp/channels/src/components/admin_console/board_attributes/index.ts new file mode 100644 index 000000000000..74690ec17ffc --- /dev/null +++ b/webapp/channels/src/components/admin_console/board_attributes/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +export {default, searchableStrings} from './board_attributes'; diff --git a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.test.tsx b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.test.tsx index aea9e4b80e39..6f05468ad02c 100644 --- a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.test.tsx +++ b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField, UserPropertyFieldGroupID, UserPropertyFieldType} from '@mattermost/types/properties'; +import type {UserPropertyField, UserPropertyFieldGroupID, UserPropertyFieldType} from '@mattermost/types/properties_user'; import {Client4} from 'mattermost-redux/client'; diff --git a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx index 7354660b8f44..4aa56d51e9c9 100644 --- a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx +++ b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx @@ -11,7 +11,7 @@ import {FormattedMessage, defineMessage} from 'react-intl'; import {useSelector} from 'react-redux'; import {Link} from 'react-router-dom'; -import type {UserPropertyField, UserPropertyFieldType} from '@mattermost/types/properties'; +import type {UserPropertyField, UserPropertyFieldType} from '@mattermost/types/properties_user'; import {Client4} from 'mattermost-redux/client'; import {getCustomProfileAttributes} from 'mattermost-redux/selectors/entities/general'; diff --git a/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.test.ts b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.test.ts new file mode 100644 index 000000000000..fd03da99014c --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.test.ts @@ -0,0 +1,252 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {act} from '@testing-library/react'; + +import {renderHookWithContext} from 'tests/react_testing_utils'; + +import {useListTableDnd} from './use_list_table_dnd'; + +type MonitorConfig = { + canMonitor: (args: {source: {data: Record}}) => boolean; + onDrop: (args: { + source: {data: Record}; + location: {current: {dropTargets: Array<{data: Record}>}}; + }) => void; +}; + +// Capture PDND registrations so tests can invoke the callbacks directly. +// PDND only fires these from real HTML5 drag events, which jsdom doesn't +// dispatch — invoking them by hand is the practical way to exercise the +// hook's reorder math. +// +// Names are intentionally `mock`-prefixed: babel-plugin-jest-hoist hoists +// `jest.mock(...)` calls to the top of the module and only allows the +// factory to reference identifiers whose name matches `/^mock/i`. +const mockRegisteredMonitors: MonitorConfig[] = []; +const mockCleanupSpies: jest.Mock[] = []; + +let mockNextExtractedEdge: 'top' | 'bottom' | null = 'bottom'; + +jest.mock('@atlaskit/pragmatic-drag-and-drop/element/adapter', () => ({ + monitorForElements: (config: MonitorConfig) => { + mockRegisteredMonitors.push(config); + const cleanup = jest.fn(() => { + const idx = mockRegisteredMonitors.indexOf(config); + if (idx !== -1) { + mockRegisteredMonitors.splice(idx, 1); + } + }); + mockCleanupSpies.push(cleanup); + return cleanup; + }, +})); + +jest.mock('@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge', () => ({ + extractClosestEdge: () => mockNextExtractedEdge, +})); + +function dropTargets(...targets: Array>) { + return {current: {dropTargets: targets.map((data) => ({data}))}}; +} + +describe('useListTableDnd', () => { + beforeEach(() => { + mockRegisteredMonitors.length = 0; + mockCleanupSpies.length = 0; + mockNextExtractedEdge = 'bottom'; + }); + + test('does not register a monitor when onReorder is not provided', () => { + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder: undefined})); + + expect(mockRegisteredMonitors).toHaveLength(0); + expect(mockCleanupSpies).toHaveLength(0); + }); + + test('registers exactly one monitor when onReorder is provided', () => { + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder: jest.fn()})); + + expect(mockRegisteredMonitors).toHaveLength(1); + }); + + test('unmount runs the monitor cleanup', () => { + const {unmount} = renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder: jest.fn()})); + + expect(mockCleanupSpies).toHaveLength(1); + expect(mockCleanupSpies[0]).not.toHaveBeenCalled(); + + unmount(); + + expect(mockCleanupSpies[0]).toHaveBeenCalledTimes(1); + expect(mockRegisteredMonitors).toHaveLength(0); + }); + + test('canMonitor accepts only sources whose kind matches dragKind', () => { + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder: jest.fn()})); + + const {canMonitor} = mockRegisteredMonitors[0]; + expect(canMonitor({source: {data: {kind: 'kind-a'}}})).toBe(true); + expect(canMonitor({source: {data: {kind: 'kind-b'}}})).toBe(false); + expect(canMonitor({source: {data: {}}})).toBe(false); + }); + + test('onDrop is a no-op when the location has no drop targets', () => { + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 2}}, + location: {current: {dropTargets: []}}, + }); + }); + + expect(onReorder).not.toHaveBeenCalled(); + }); + + // The four-case truth table for getDropIndex is the core "reorder math" + // for the whole table primitive. Drive it through the captured onDrop + // since the helper itself is module-private. + describe('getDropIndex resolution (top/bottom × source position)', () => { + test('drop on TOP edge of a target BELOW the source → target - 1', () => { + mockNextExtractedEdge = 'top'; + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 1}}, + location: dropTargets({kind: 'kind-a', rowIndex: 4}), + }); + }); + + expect(onReorder).toHaveBeenCalledWith(1, 3); + }); + + test('drop on TOP edge of a target ABOVE the source → target', () => { + mockNextExtractedEdge = 'top'; + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 5}}, + location: dropTargets({kind: 'kind-a', rowIndex: 2}), + }); + }); + + expect(onReorder).toHaveBeenCalledWith(5, 2); + }); + + test('drop on BOTTOM edge of a target BELOW the source → target', () => { + mockNextExtractedEdge = 'bottom'; + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 1}}, + location: dropTargets({kind: 'kind-a', rowIndex: 4}), + }); + }); + + expect(onReorder).toHaveBeenCalledWith(1, 4); + }); + + test('drop on BOTTOM edge of a target ABOVE the source → target + 1', () => { + mockNextExtractedEdge = 'bottom'; + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 5}}, + location: dropTargets({kind: 'kind-a', rowIndex: 2}), + }); + }); + + expect(onReorder).toHaveBeenCalledWith(5, 3); + }); + + test('does not call onReorder when computed dropIndex equals sourceIndex', () => { + // Drop on TOP edge of the row directly after source (3 → top of 4) + // resolves to 3, which is a no-op. + mockNextExtractedEdge = 'top'; + const onReorder = jest.fn(); + renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder})); + + act(() => { + mockRegisteredMonitors[0].onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 3}}, + location: dropTargets({kind: 'kind-a', rowIndex: 4}), + }); + }); + + expect(onReorder).not.toHaveBeenCalled(); + }); + }); + + test('uses the latest onReorder via ref without re-registering the monitor', () => { + // Mirrors the typical consumer pattern: a fresh closure is built + // every render. The hook intentionally omits onReorder from its + // dependency array (it reads through useLatest) so the PDND + // registration is not torn down on every parent render. + let currentOnReorder: jest.Mock = jest.fn(); + + const {rerender} = renderHookWithContext(() => + useListTableDnd({dragKind: 'kind-a', onReorder: currentOnReorder})); + + expect(mockRegisteredMonitors).toHaveLength(1); + const firstMonitor = mockRegisteredMonitors[0]; + + const replacement = jest.fn(); + currentOnReorder = replacement; + rerender(); + + expect(mockRegisteredMonitors).toHaveLength(1); + expect(mockRegisteredMonitors[0]).toBe(firstMonitor); + expect(mockCleanupSpies[0]).not.toHaveBeenCalled(); + + act(() => { + firstMonitor.onDrop({ + source: {data: {kind: 'kind-a', rowIndex: 1}}, + location: dropTargets({kind: 'kind-a', rowIndex: 4}), + }); + }); + + expect(replacement).toHaveBeenCalledWith(1, 4); + }); + + test('changing dragKind tears down the old monitor and registers a new one', () => { + // The hook keeps `dragKind` in the dep array because the monitor's + // `canMonitor` predicate is captured by identity; a real change + // must re-register. + let currentKind = 'kind-a'; + + const {rerender} = renderHookWithContext(() => + useListTableDnd({dragKind: currentKind, onReorder: jest.fn()})); + + expect(mockRegisteredMonitors).toHaveLength(1); + + currentKind = 'kind-b'; + rerender(); + + expect(mockCleanupSpies[0]).toHaveBeenCalledTimes(1); + expect(mockRegisteredMonitors).toHaveLength(1); + + // The fresh monitor accepts only the new kind. + expect(mockRegisteredMonitors[0].canMonitor({source: {data: {kind: 'kind-a'}}})).toBe(false); + expect(mockRegisteredMonitors[0].canMonitor({source: {data: {kind: 'kind-b'}}})).toBe(true); + }); +}); diff --git a/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.ts b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.ts new file mode 100644 index 000000000000..177d57c0a289 --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_dnd.ts @@ -0,0 +1,67 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {monitorForElements} from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; +import type {Edge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {extractClosestEdge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {useEffect} from 'react'; + +import {useLatest} from 'hooks/useLatest'; + +type UseListTableDndOptions = { + dragKind: string; + onReorder?: (prev: number, next: number) => void; +}; + +/** + * Registers a container-level PDND monitor for the given drag kind. + * Resolves the final drop index and calls onReorder when a row is dropped. + * Safe to call unconditionally; no-ops when onReorder is undefined. + */ +export function useListTableDnd({dragKind, onReorder}: UseListTableDndOptions): void { + const onReorderRef = useLatest(onReorder); + + useEffect(() => { + if (!onReorder) { + return undefined; + } + return monitorForElements({ + canMonitor: ({source}) => source.data.kind === dragKind, + onDrop: ({source, location}) => { + const target = location.current.dropTargets[0]; + if (!target) { + return; + } + const sourceIndex = source.data.rowIndex as number; + const targetIndex = target.data.rowIndex as number; + const edge = extractClosestEdge(target.data); + const dropIndex = getDropIndex(sourceIndex, targetIndex, edge); + if (dropIndex !== sourceIndex) { + onReorderRef.current?.(sourceIndex, dropIndex); + } + }, + }); + + // onReorder identity is captured via ref; only re-register when dragKind changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dragKind, Boolean(onReorder)]); +} + +function getDropIndex( + sourceIndex: number, + targetIndex: number, + edge: Edge | null, +): number { + if (edge === 'top') { + if (sourceIndex < targetIndex) { + return targetIndex - 1; + } + return targetIndex; + } + + // 'bottom' — insert after the target + if (sourceIndex < targetIndex) { + return targetIndex; + } + return targetIndex + 1; +} diff --git a/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.test.ts b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.test.ts new file mode 100644 index 000000000000..4b937ee6e5fc --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.test.ts @@ -0,0 +1,300 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {act} from '@testing-library/react'; + +import {renderHookWithContext} from 'tests/react_testing_utils'; + +import {useListTableRowDnd} from './use_list_table_row_dnd'; + +type DraggableConfig = { + element: HTMLElement; + dragHandle?: HTMLElement; + getInitialData: () => Record; + onGenerateDragPreview: (args: {nativeSetDragImage: jest.Mock}) => void; +}; + +type DropTargetConfig = { + element: HTMLElement; + canDrop: (args: {source: {data: Record}}) => boolean; + getData: (args: {input: unknown; element: HTMLElement}) => Record; + onDrag: (args: {self: {data: Record}}) => void; + onDragLeave: () => void; + onDrop: () => void; +}; + +// Capture PDND registrations so tests can drive their callbacks directly — +// PDND only fires these from real HTML5 drag events, which jsdom doesn't +// dispatch. +// +// Names are intentionally `mock`-prefixed: babel-plugin-jest-hoist hoists +// `jest.mock(...)` calls to the top of the module and only allows the +// factory to reference identifiers whose name matches `/^mock/i`. +const mockDraggableRegistrations: DraggableConfig[] = []; +const mockDropTargetRegistrations: DropTargetConfig[] = []; +const mockCleanupSpies: jest.Mock[] = []; + +let mockNextExtractedEdge: 'top' | 'bottom' | null = 'bottom'; +const mockSetCustomNativeDragPreviewSpy = jest.fn(); + +jest.mock('@atlaskit/pragmatic-drag-and-drop/element/adapter', () => ({ + draggable: (config: DraggableConfig) => { + mockDraggableRegistrations.push(config); + const cleanup = jest.fn(); + mockCleanupSpies.push(cleanup); + return cleanup; + }, + dropTargetForElements: (config: DropTargetConfig) => { + mockDropTargetRegistrations.push(config); + const cleanup = jest.fn(); + mockCleanupSpies.push(cleanup); + return cleanup; + }, +})); + +jest.mock('@atlaskit/pragmatic-drag-and-drop/combine', () => ({ + combine: (...cleanups: Array<() => void>) => { + // `combine` in real PDND returns a single cleanup that runs all + // inner cleanups. Match that semantics so unmount fires every + // captured cleanup spy in order. + return () => { + for (const c of cleanups) { + c(); + } + }; + }, +})); + +jest.mock('@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview', () => ({ + setCustomNativeDragPreview: (args: unknown) => { + mockSetCustomNativeDragPreviewSpy(args); + }, +})); + +jest.mock('@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge', () => ({ + attachClosestEdge: (data: Record) => ({...data, __edge: 'attached'}), + extractClosestEdge: () => mockNextExtractedEdge, +})); + +function makeRow() { + return document.createElement('tr'); +} + +function makeHandle() { + return document.createElement('button'); +} + +const baseOptions = { + dragKind: 'list-table-row:test', + rowId: 'row-1', + rowIndex: 2, + enabled: true, +} as const; + +describe('useListTableRowDnd', () => { + beforeEach(() => { + mockDraggableRegistrations.length = 0; + mockDropTargetRegistrations.length = 0; + mockCleanupSpies.length = 0; + mockSetCustomNativeDragPreviewSpy.mockClear(); + mockNextExtractedEdge = 'bottom'; + }); + + test('returns {closestEdge: null} initially', () => { + const {result} = renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + })); + + expect(result.current.closestEdge).toBeNull(); + }); + + test('does not register when rowElement is null', () => { + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: null, + handleElement: null, + })); + + expect(mockDraggableRegistrations).toHaveLength(0); + expect(mockDropTargetRegistrations).toHaveLength(0); + }); + + test('does not register when enabled is false', () => { + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + enabled: false, + rowElement: makeRow(), + handleElement: makeHandle(), + })); + + expect(mockDraggableRegistrations).toHaveLength(0); + expect(mockDropTargetRegistrations).toHaveLength(0); + }); + + test('registers both draggable and dropTarget when enabled with a row element', () => { + const rowElement = makeRow(); + const handleElement = makeHandle(); + + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement, + handleElement, + })); + + expect(mockDraggableRegistrations).toHaveLength(1); + expect(mockDropTargetRegistrations).toHaveLength(1); + + expect(mockDraggableRegistrations[0].element).toBe(rowElement); + expect(mockDraggableRegistrations[0].dragHandle).toBe(handleElement); + + expect(mockDraggableRegistrations[0].getInitialData()).toEqual({ + kind: baseOptions.dragKind, + rowId: baseOptions.rowId, + rowIndex: baseOptions.rowIndex, + }); + }); + + test('canDrop accepts other rows with the same kind and rejects the source row itself', () => { + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + })); + + const {canDrop} = mockDropTargetRegistrations[0]; + + expect(canDrop({source: {data: {kind: baseOptions.dragKind, rowId: 'row-other'}}})).toBe(true); + expect(canDrop({source: {data: {kind: baseOptions.dragKind, rowId: baseOptions.rowId}}})).toBe(false); + expect(canDrop({source: {data: {kind: 'different-kind', rowId: 'row-other'}}})).toBe(false); + }); + + test('getData attaches the row identity together with the closest-edge payload', () => { + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + })); + + const data = mockDropTargetRegistrations[0].getData({ + input: {clientX: 0, clientY: 0}, + element: makeRow(), + }); + + expect(data).toMatchObject({ + kind: baseOptions.dragKind, + rowId: baseOptions.rowId, + rowIndex: baseOptions.rowIndex, + __edge: 'attached', + }); + }); + + test('onDrag updates closestEdge; onDragLeave and onDrop reset it to null', () => { + mockNextExtractedEdge = 'top'; + const {result} = renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + })); + + const target = mockDropTargetRegistrations[0]; + + act(() => { + target.onDrag({self: {data: {kind: baseOptions.dragKind}}}); + }); + expect(result.current.closestEdge).toBe('top'); + + act(() => { + target.onDragLeave(); + }); + expect(result.current.closestEdge).toBeNull(); + + mockNextExtractedEdge = 'bottom'; + act(() => { + target.onDrag({self: {data: {kind: baseOptions.dragKind}}}); + }); + expect(result.current.closestEdge).toBe('bottom'); + + act(() => { + target.onDrop(); + }); + expect(result.current.closestEdge).toBeNull(); + }); + + test('unmount runs the combined cleanup so both draggable and dropTarget are torn down', () => { + const {unmount} = renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + })); + + expect(mockCleanupSpies).toHaveLength(2); + expect(mockCleanupSpies.every((s) => !s.mock.calls.length)).toBe(true); + + unmount(); + + expect(mockCleanupSpies.every((s) => s.mock.calls.length === 1)).toBe(true); + }); + + test('onGenerateDragPreview installs a custom native preview only when one is provided', () => { + const previewEl = document.createElement('div'); + previewEl.textContent = 'preview'; + + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + getDragPreview: () => previewEl, + })); + + const draggable = mockDraggableRegistrations[0]; + draggable.onGenerateDragPreview({nativeSetDragImage: jest.fn()}); + + expect(mockSetCustomNativeDragPreviewSpy).toHaveBeenCalledTimes(1); + }); + + test('onGenerateDragPreview is a no-op when getDragPreview returns nothing', () => { + renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement: makeRow(), + handleElement: null, + getDragPreview: () => undefined, + })); + + const draggable = mockDraggableRegistrations[0]; + draggable.onGenerateDragPreview({nativeSetDragImage: jest.fn()}); + + expect(mockSetCustomNativeDragPreviewSpy).not.toHaveBeenCalled(); + }); + + test('ghost reads the latest getDragPreview after a re-render without re-registering (regression: stale preview on a renamed new row)', () => { + const stalePreview = document.createElement('div'); + stalePreview.textContent = 'Text'; + const latestPreview = document.createElement('div'); + latestPreview.textContent = 'Priority'; + + // Stable deps; only the preview closure changes (a renamed new row). + const rowElement = makeRow(); + let getDragPreview = () => stalePreview; + + const {rerender} = renderHookWithContext(() => useListTableRowDnd({ + ...baseOptions, + rowElement, + handleElement: null, + getDragPreview, + })); + + getDragPreview = () => latestPreview; + rerender(); + + expect(mockDraggableRegistrations).toHaveLength(1); + + const container = document.createElement('div'); + mockSetCustomNativeDragPreviewSpy.mockImplementationOnce(({render}: {render: (a: {container: HTMLElement}) => void}) => render({container})); + mockDraggableRegistrations[0].onGenerateDragPreview({nativeSetDragImage: jest.fn()}); + + // Without the ref this would be the captured 'Text' preview. + expect(container.textContent).toBe('Priority'); + }); +}); diff --git a/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.ts b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.ts new file mode 100644 index 000000000000..b7280f99c1b4 --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/hooks/use_list_table_row_dnd.ts @@ -0,0 +1,86 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {combine} from '@atlaskit/pragmatic-drag-and-drop/combine'; +import {draggable, dropTargetForElements} from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; +import {setCustomNativeDragPreview} from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview'; +import type {Edge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {attachClosestEdge, extractClosestEdge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {useEffect, useState} from 'react'; + +import {useLatest} from 'hooks/useLatest'; + +type UseListTableRowDndOptions = { + dragKind: string; + rowId: string; + rowIndex: number; + rowElement: HTMLElement | null; + handleElement: HTMLElement | null; + enabled: boolean; + getDragPreview?: () => HTMLElement | undefined; +}; + +type UseListTableRowDndResult = { + closestEdge: Edge | null; +}; + +// Wires PDND draggable + dropTarget onto a table row; returns the active drop edge. +export function useListTableRowDnd({ + dragKind, + rowId, + rowIndex, + rowElement, + handleElement, + enabled, + getDragPreview, +}: UseListTableRowDndOptions): UseListTableRowDndResult { + const [closestEdge, setClosestEdge] = useState(null); + + // Read via ref so the ghost reflects the row's latest name without re-registering. + const getDragPreviewRef = useLatest(getDragPreview); + + useEffect(() => { + if (!rowElement || !enabled) { + return undefined; + } + + return combine( + draggable({ + element: rowElement, + dragHandle: handleElement ?? undefined, + getInitialData: () => ({kind: dragKind, rowId, rowIndex}), + onGenerateDragPreview: ({nativeSetDragImage}) => { + const previewEl = getDragPreviewRef.current?.(); + if (!previewEl) { + return; + } + setCustomNativeDragPreview({ + nativeSetDragImage, + render: ({container}) => { + container.appendChild(previewEl); + }, + }); + }, + }), + dropTargetForElements({ + element: rowElement, + canDrop: ({source}) => + source.data.kind === dragKind && + source.data.rowId !== rowId, + getData: ({input, element}) => + attachClosestEdge( + {kind: dragKind, rowId, rowIndex}, + {input, element, allowedEdges: ['top', 'bottom']}, + ), + onDrag: ({self}) => setClosestEdge(extractClosestEdge(self.data)), + onDragLeave: () => setClosestEdge(null), + onDrop: () => setClosestEdge(null), + }), + ); + + // getDragPreview read via ref (above); re-registering would tear down PDND state mid-drag. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [rowElement, handleElement, enabled, dragKind, rowId, rowIndex]); + + return {closestEdge}; +} diff --git a/webapp/channels/src/components/admin_console/list_table/list_table.scss b/webapp/channels/src/components/admin_console/list_table/list_table.scss index 6720cff2576f..5d830c9cf597 100644 --- a/webapp/channels/src/components/admin_console/list_table/list_table.scss +++ b/webapp/channels/src/components/admin_console/list_table/list_table.scss @@ -123,8 +123,6 @@ table.adminConsoleListTable { font-weight: 400; line-height: 20px; - - &.clickable:hover { background-color: $sysCenterChannelColorWith8Alpha; cursor: pointer; @@ -217,11 +215,32 @@ table.adminConsoleListTable { display: inline-flex; width: 24px; height: calc(100% - 1px); + padding: 0; + border: 0; + + // Reset native + ) + )} + {cell.getIsPlaceholder() ? null : flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + {closestEdge && rowElement && ( + + )} + + ); +} + /** * A wrapper around the react-table component that provides a consistent look and feel for the admin console list tables. * It also provides a default pagination component. This table is not meant to be used outside of the admin console since it relies on the admin console styles. @@ -122,13 +234,10 @@ export function ListTable( } } - const handleDragEnd = (result: DropResult) => { - const {source, destination} = result; - if (!destination) { - return; - } - tableMeta.onReorder?.(source.index, destination.index); - }; + useListTableDnd({ + dragKind: `list-table-row:${tableMeta.tableId}`, + onReorder: tableMeta.onReorder, + }); const colCount = props.table.getAllColumns().length; const rowCount = props.table.getRowModel().rows.length; @@ -207,104 +316,61 @@ export function ListTable( ))} - - - {(provided, snap) => ( - + {props.table.getRowModel().rows.map((row, _, rows) => ( + + ))} + + {/* State where it is initially loading the data */} + {(tableMeta.loadingState === LoadingStates.Loading && rowCount === 0) && ( + + + + + + )} + + {/* State where there is no data */} + {(tableMeta.loadingState === LoadingStates.Loaded && rowCount === 0) && ( + + - {props.table.getRowModel().rows.map((row) => ( - - {(provided) => { - return ( - - {row.getVisibleCells().map((cell, i) => ( - - {tableMeta.onReorder && i === 0 && ( - - - - )} - {cell.getIsPlaceholder() ? null : flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ); - }} - - - ))} - - {provided.placeholder} - - {/* State where it is initially loading the data */} - {(tableMeta.loadingState === LoadingStates.Loading && rowCount === 0) && ( - - - - - - )} - - {/* State where there is no data */} - {(tableMeta.loadingState === LoadingStates.Loaded && rowCount === 0) && ( - - - {tableMeta.emptyDataMessage || formatMessage({id: 'adminConsole.list.table.genericNoData', defaultMessage: 'No data'})} - - - )} - - {/* State where there is an error loading the data */} - {tableMeta.loadingState === LoadingStates.Failed && ( - - - {formatMessage({id: 'adminConsole.list.table.genericError', defaultMessage: 'There was an error loading the data, please try again'})} - - - )} - - )} - - + {tableMeta.emptyDataMessage || formatMessage({id: 'adminConsole.list.table.genericNoData', defaultMessage: 'No data'})} + + + )} + + {/* State where there is an error loading the data */} + {tableMeta.loadingState === LoadingStates.Failed && ( + + + {formatMessage({id: 'adminConsole.list.table.genericError', defaultMessage: 'There was an error loading the data, please try again'})} + + + )} + {props.table.getFooterGroups().map((footerGroup) => ( diff --git a/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.scss b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.scss new file mode 100644 index 000000000000..457abca1d11b --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.scss @@ -0,0 +1,4 @@ +.listTableRowDropIndicator { + z-index: 1500; + pointer-events: none; +} diff --git a/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.test.tsx b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.test.tsx new file mode 100644 index 000000000000..29eac388fa06 --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.test.tsx @@ -0,0 +1,93 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {act, renderWithContext, screen} from 'tests/react_testing_utils'; + +import {RowDropIndicator} from './row_drop_indicator'; + +// The actual indicator rendering details come from PDND's React adapter, +// which uses CSS pseudo-elements we can't reliably observe in jsdom. Swap +// it for a data-attribute marker so we can assert the `edge` prop is +// threaded through correctly. +jest.mock('@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box', () => ({ + DropIndicator: ({edge}: {edge: string}) => ( + + ), +})); + +describe('RowDropIndicator', () => { + function renderWithRow(edge: 'top' | 'bottom') { + // jsdom does not lay rows out, but the floating-ui middleware here + // only reads `getBoundingClientRect()`, which jsdom returns zero + // values for — perfectly fine for asserting render structure. + // + // The render is wrapped in act() so the post-mount flushSync that + // @floating-ui/react fires from `whileElementsMounted: autoUpdate` + // is settled inside an act() boundary, avoiding a noisy (but + // benign) console warning. + const row = document.createElement('tr'); + document.body.appendChild(row); + act(() => { + renderWithContext( + , + ); + }); + return row; + } + + afterEach(() => { + // Clean up rows appended directly to body to keep tests isolated. + document.querySelectorAll('tr').forEach((tr) => tr.remove()); + }); + + test('renders the floating indicator container with the listTableRowDropIndicator class', () => { + renderWithRow('top'); + + // FloatingPortal places the element directly under document.body + // (default portal root), so query the whole document for it. + const indicators = document.querySelectorAll('.listTableRowDropIndicator'); + expect(indicators).toHaveLength(1); + }); + + test('forwards the given edge to the inner PDND DropIndicator', () => { + renderWithRow('bottom'); + + const inner = screen.getByTestId('inner-drop-indicator'); + expect(inner).toHaveAttribute('data-edge', 'bottom'); + }); + + test('re-renders with a new edge when the prop changes', () => { + const row = document.createElement('tr'); + document.body.appendChild(row); + + let rerender: (ui: React.ReactElement) => void = () => undefined; + act(() => { + const r = renderWithContext( + , + ); + rerender = r.rerender; + }); + expect(screen.getByTestId('inner-drop-indicator')).toHaveAttribute('data-edge', 'top'); + + act(() => { + rerender( + , + ); + }); + expect(screen.getByTestId('inner-drop-indicator')).toHaveAttribute('data-edge', 'bottom'); + }); +}); diff --git a/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.tsx b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.tsx new file mode 100644 index 000000000000..eeb6e73aa264 --- /dev/null +++ b/webapp/channels/src/components/admin_console/list_table/row_drop_indicator.tsx @@ -0,0 +1,43 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import type {Edge} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; +import {DropIndicator} from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box'; +import {FloatingPortal, autoUpdate, offset, size, useFloating} from '@floating-ui/react'; +import React from 'react'; + +import './row_drop_indicator.scss'; + +type Props = { + rowElement: HTMLElement; + edge: Edge; +}; + +export function RowDropIndicator({rowElement, edge}: Props) { + const {refs, floatingStyles} = useFloating({ + elements: {reference: rowElement}, + whileElementsMounted: autoUpdate, + placement: 'top-start', + middleware: [ + offset(({rects}) => -rects.reference.height), + size({ + apply({rects, elements}) { + elements.floating.style.width = `${rects.reference.width}px`; + elements.floating.style.height = `${rects.reference.height}px`; + }, + }), + ], + }); + + return ( + +
    + +
    +
    + ); +} diff --git a/webapp/channels/src/components/admin_console/permission_policies/policy_details/permission_policy_details.tsx b/webapp/channels/src/components/admin_console/permission_policies/policy_details/permission_policy_details.tsx index 6716f6c36bb3..bff2f8048844 100644 --- a/webapp/channels/src/components/admin_console/permission_policies/policy_details/permission_policy_details.tsx +++ b/webapp/channels/src/components/admin_console/permission_policies/policy_details/permission_policy_details.tsx @@ -10,7 +10,7 @@ import {GenericModal} from '@mattermost/components'; import {buttonClassNames} from '@mattermost/shared/components/button'; import type {AccessControlPolicy, AccessControlPolicyRule} from '@mattermost/types/access_control'; import type {AccessControlSettings} from '@mattermost/types/config'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {isPolicySimulationEnabled} from 'mattermost-redux/selectors/entities/general'; import type {ActionResult} from 'mattermost-redux/types/actions'; diff --git a/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/index.ts b/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/index.ts new file mode 100644 index 000000000000..afe3f64d231b --- /dev/null +++ b/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +export {default} from './revoke_non_compliant_tokens_button'; diff --git a/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/revoke_non_compliant_tokens_button.tsx b/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/revoke_non_compliant_tokens_button.tsx new file mode 100644 index 000000000000..eae0e9f25279 --- /dev/null +++ b/webapp/channels/src/components/admin_console/revoke_non_compliant_tokens_button/revoke_non_compliant_tokens_button.tsx @@ -0,0 +1,180 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {useCallback, useEffect, useState} from 'react'; +import {FormattedMessage} from 'react-intl'; + +import {Client4} from 'mattermost-redux/client'; + +import AlertBanner from 'components/alert_banner'; +import ConfirmModal from 'components/confirm_modal'; + +type SaveAction = () => Promise<{error?: {message?: string}}>; + +type Props = { + + // True when the surrounding setting is read-only for this admin. + disabled?: boolean; + + // System Console save-action hooks. Registered actions run after the config + // has been persisted, so we use one to refresh the count once the admin + // saves a new policy. + registerSaveAction?: (saveAction: SaveAction) => void; + unRegisterSaveAction?: (saveAction: SaveAction) => void; +}; + +// RevokeNonCompliantTokensButton lets an admin bulk-revoke every personal access +// token that violates the configured MaximumPersonalAccessTokenLifetimeDays +// policy. The non-compliant count comes from the server (the source of truth for +// the persisted policy) and is shown up front, refreshed after a save, and after +// a revoke, so the blast radius is visible without clicking and the button is +// disabled when there is nothing to revoke. The remaining click always confirms +// the irreversible hard-delete first, satisfying MM-69075. +const RevokeNonCompliantTokensButton = ({disabled, registerSaveAction, unRegisterSaveAction}: Props) => { + const [showConfirm, setShowConfirm] = useState(false); + const [busy, setBusy] = useState(false); + + // null = not yet loaded; a number once the count has been fetched. + const [count, setCount] = useState(null); + const [error, setError] = useState(''); + const [revokedCount, setRevokedCount] = useState(null); + + const refreshCount = useCallback(async () => { + try { + const {count: nonCompliant} = await Client4.getNonCompliantUserAccessTokenCount(); + setCount(nonCompliant); + setError(''); + } catch (err) { + setError(err instanceof Error ? err.message : ''); + } + }, []); + + // Load the count when the setting renders, and register a save action so it + // refreshes right after the admin saves a new policy (patchConfig has + // already persisted by the time save actions run, so the server returns the + // count for the new policy). + useEffect(() => { + refreshCount(); + + const saveAction: SaveAction = async () => { + setRevokedCount(null); + await refreshCount(); + return {}; + }; + registerSaveAction?.(saveAction); + return () => unRegisterSaveAction?.(saveAction); + }, [refreshCount, registerSaveAction, unRegisterSaveAction]); + + const handleConfirm = useCallback(async () => { + setBusy(true); + try { + const {count: revoked} = await Client4.revokeNonCompliantUserAccessTokens(); + setRevokedCount(revoked); + setCount(0); + setError(''); + } catch (err) { + setError(err.message); + } finally { + setBusy(false); + setShowConfirm(false); + } + }, []); + + const openConfirm = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setError(''); + setRevokedCount(null); + setShowConfirm(true); + }, []); + + const handleCancel = useCallback(() => setShowConfirm(false), []); + + const nothingToRevoke = count === null || count === 0; + + return ( +
    + + {error && ( + + )} + /> + )} + {!error && revokedCount !== null && ( + + )} + /> + )} + {!error && revokedCount === null && count !== null && ( + 0 ? 'danger' : 'success'} + message={count > 0 ? ( + + ) : ( + + )} + /> + )} + + )} + message={( + + )} + confirmButtonVariant='destructive' + confirmButtonText={( + + )} + onConfirm={handleConfirm} + onCancel={handleCancel} + /> +
    + ); +}; + +export default React.memo(RevokeNonCompliantTokensButton); diff --git a/webapp/channels/src/components/admin_console/system_properties/orphaned_fields_utils.ts b/webapp/channels/src/components/admin_console/system_properties/orphaned_fields_utils.ts index 3c1e69de67d2..e063818859c3 100644 --- a/webapp/channels/src/components/admin_console/system_properties/orphaned_fields_utils.ts +++ b/webapp/channels/src/components/admin_console/system_properties/orphaned_fields_utils.ts @@ -3,7 +3,7 @@ import {useSelector} from 'react-redux'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {GlobalState} from 'types/store'; diff --git a/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.test.tsx b/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.test.tsx index 0c02f3d8b01e..647fb6bae500 100644 --- a/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen, userEvent, within} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.tsx b/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.tsx index eb8d683519a5..19d3abc78665 100644 --- a/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/ranked_schema_modal.tsx @@ -10,7 +10,8 @@ import {FormattedMessage, useIntl} from 'react-intl'; import {DragVerticalIcon, PlusIcon, TrashCanOutlineIcon} from '@mattermost/compass-icons/components'; import {GenericModal} from '@mattermost/components'; -import type {PropertyFieldOption, UserPropertyField} from '@mattermost/types/properties'; +import type {PropertyFieldOption} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import Constants from 'utils/constants'; diff --git a/webapp/channels/src/components/admin_console/system_properties/section_utils.ts b/webapp/channels/src/components/admin_console/system_properties/section_utils.ts index 5578acf14d73..d5fe4c0a737c 100644 --- a/webapp/channels/src/components/admin_console/system_properties/section_utils.ts +++ b/webapp/channels/src/components/admin_console/system_properties/section_utils.ts @@ -57,6 +57,8 @@ export interface CollectionIO { reorder?: (item: T, nextOrder: number) => void; } +export type PendingOps = {[op: string]: T[]}; + /** * Monitored async operation with stateful error and loading status handling. * @param initialStatus Provide default loading status. e.g. `true` if operation starts immediately or `false` if manually triggered. diff --git a/webapp/channels/src/components/admin_console/system_properties/system_properties.test.tsx b/webapp/channels/src/components/admin_console/system_properties/system_properties.test.tsx index a0c088d5c1d3..30cf43c6d84f 100644 --- a/webapp/channels/src/components/admin_console/system_properties/system_properties.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/system_properties.test.tsx @@ -4,7 +4,7 @@ import {screen, waitFor} from '@testing-library/react'; import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {DeepPartial} from '@mattermost/types/utilities'; import {Client4} from 'mattermost-redux/client'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.test.tsx index 717024bb1d27..4a425a94fe18 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {openModal} from 'actions/views/modals'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.tsx index e0c61e2170c8..ada7f81f69fe 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_delete_modal.tsx @@ -6,7 +6,7 @@ import {FormattedMessage, useIntl} from 'react-intl'; import {useDispatch} from 'react-redux'; import {GenericModal} from '@mattermost/components'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {openModal} from 'actions/views/modals'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.test.tsx index de405e15b746..b1475fba3362 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.test.tsx @@ -4,7 +4,7 @@ import type {ComponentProps} from 'react'; import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {Client4} from 'mattermost-redux/client'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.tsx index e9f4ad04849c..67939a24e20f 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_dot_menu.tsx @@ -2,11 +2,12 @@ // See LICENSE.txt for license information. import React from 'react'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, useIntl} from 'react-intl'; import {useDispatch} from 'react-redux'; import {CheckIcon, ChevronRightIcon, DotsHorizontalIcon, EyeOutlineIcon, FormatListNumberedIcon, LockOutlineIcon, PencilOutlineIcon, SyncIcon, TrashCanOutlineIcon, ContentCopyIcon} from '@mattermost/compass-icons/components'; -import type {FieldVisibility, UserPropertyField} from '@mattermost/types/properties'; +import type {FieldVisibility} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {openModal} from 'actions/views/modals'; @@ -116,6 +117,7 @@ const DotMenu = ({ updateField, deleteField, }: Props) => { + const {formatMessage} = useIntl(); const dispatch = useDispatch(); const {promptDelete} = useUserPropertyFieldDelete(); const {promptEditLdapLink, promptEditSamlLink} = useAttributeLinkModal(field, updateField); @@ -213,8 +215,11 @@ const DotMenu = ({ disabled: field.delete_at !== 0 || isProtected, }} menu={{ - id: `${menuId}-menu`, - 'aria-label': 'Select an action', + id: `${menuId}-${field.id}-menu`, + 'aria-label': formatMessage({ + id: 'admin.system_properties.user_properties.dotmenu.label', + defaultMessage: 'Select an action', + }), className: 'user-property-field-dotmenu-menu', }} > diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_orphaned_delete_button.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_orphaned_delete_button.tsx index 1b4280c7b3cc..43fb0f277858 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_orphaned_delete_button.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_orphaned_delete_button.tsx @@ -4,7 +4,7 @@ import React from 'react'; import {TrashCanOutlineIcon} from '@mattermost/compass-icons/components'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {useUserPropertyFieldDelete} from './user_properties_delete_modal'; import {isCreatePending} from './user_properties_utils'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.test.tsx index eacfdb09bb72..c6e020fcafee 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.tsx index d149fd6cf464..0b3039183c61 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_rank_values.tsx @@ -9,7 +9,8 @@ import {components} from 'react-select'; import {css} from 'styled-components'; import {CheckIcon, ChevronRightIcon} from '@mattermost/compass-icons/components'; -import type {PropertyFieldOption, UserPropertyField} from '@mattermost/types/properties'; +import type {PropertyFieldOption} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import * as Menu from 'components/menu'; import type {CustomMessageInputType} from 'components/widgets/inputs/input/input'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.test.tsx index 9108bd9106c3..a269f1677e7a 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.test.tsx @@ -4,7 +4,7 @@ import {act} from '@testing-library/react'; import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {collectionFromArray} from '@mattermost/types/utilities'; import {Client4} from 'mattermost-redux/client'; @@ -181,6 +181,67 @@ describe('UserPropertiesTable', () => { expect(deletedInput).toBeDisabled(); }); + // Regression coverage for the react-beautiful-dnd → Pragmatic Drag and + // Drop migration in list_table. These tests don't drive native drag + // events (jsdom can't), but they confirm the keyboard reorder path — + // which is the most user-visible accessibility-critical surface — is + // still wired through to the consumer's reorderField callback. + describe('DnD migration regression — keyboard reorder', () => { + beforeEach(() => { + reorderField.mockClear(); + }); + + it('ArrowDown on row 0\u2019s drag handle calls reorderField with the row 0 field at next index 1', async () => { + renderComponent(); + + const handles = screen.getAllByRole('button', {name: /reorder row/i}); + handles[0].focus(); + await userEvent.keyboard('{ArrowDown}'); + + expect(reorderField).toHaveBeenCalledTimes(1); + expect(reorderField).toHaveBeenCalledWith(baseFields[0], 1); + }); + + it('ArrowUp on row 1\u2019s drag handle calls reorderField with the row 1 field at next index 0', async () => { + renderComponent(); + + const handles = screen.getAllByRole('button', {name: /reorder row/i}); + handles[1].focus(); + await userEvent.keyboard('{ArrowUp}'); + + expect(reorderField).toHaveBeenCalledTimes(1); + expect(reorderField).toHaveBeenCalledWith(baseFields[1], 0); + }); + + it('ArrowUp on the first row is a no-op (cannot move above index 0)', async () => { + renderComponent(); + + const handles = screen.getAllByRole('button', {name: /reorder row/i}); + handles[0].focus(); + await userEvent.keyboard('{ArrowUp}'); + + expect(reorderField).not.toHaveBeenCalled(); + }); + + it('ArrowDown on the last row is a no-op (cannot move past the bottom)', async () => { + renderComponent(); + + const handles = screen.getAllByRole('button', {name: /reorder row/i}); + handles[handles.length - 1].focus(); + await userEvent.keyboard('{ArrowDown}'); + + expect(reorderField).not.toHaveBeenCalled(); + }); + + it('renders one drag handle per row (DnD wiring is enabled, not silently disabled)', () => { + renderComponent(); + + // User properties does not pass `isRowDragDisabled`, so every + // visible row gets an interactive drag handle button. + expect(screen.getAllByRole('button', {name: /reorder row/i})).toHaveLength(baseFields.length); + }); + }); + const renderWithBanners = (fields: UserPropertyField[], collection = collectionFromArray(fields)) => { return renderWithContext( <> diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx index dcc0de53954e..c86a3963e805 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_table.tsx @@ -9,7 +9,8 @@ import styled, {css} from 'styled-components'; import {AlertOutlineIcon, InformationOutlineIcon, PlusIcon} from '@mattermost/compass-icons/components'; import {WithTooltip} from '@mattermost/shared/components/tooltip'; -import {supportsOptions, type UserPropertyField} from '@mattermost/types/properties'; +import {supportsOptions} from '@mattermost/types/properties'; +import {type UserPropertyField} from '@mattermost/types/properties_user'; import {collectionToArray} from '@mattermost/types/utilities'; import AlertBanner from 'components/alert_banner'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.test.tsx index 717c48849994..6993039cc67c 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.tsx index 3c9e14d33c9e..68a517b973a9 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_type_menu.tsx @@ -10,7 +10,8 @@ import {css} from 'styled-components'; import {CheckIcon, ChevronDownCircleOutlineIcon, EmailOutlineIcon, FormatListBulletedIcon, LinkVariantIcon, MenuVariantIcon, PoundIcon, SortAscendingIcon} from '@mattermost/compass-icons/components'; import type IconProps from '@mattermost/compass-icons/components/props'; -import type {FieldType, FieldValueType, UserPropertyField} from '@mattermost/types/properties'; +import type {FieldType, FieldValueType} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {IDMappedObjects} from '@mattermost/types/utilities'; import useGetFeatureFlagValue from 'components/common/hooks/useGetFeatureFlagValue'; @@ -80,8 +81,11 @@ const SelectType = (props: Props) => { disabled: isDisabled, }} menu={{ - id: 'type-selector-menu', - 'aria-label': 'Select type', + id: `type-selector-menu-${props.field.id}`, + 'aria-label': formatMessage({ + id: 'admin.system_properties.user_properties.type_menu.label', + defaultMessage: 'Select type', + }), className: 'select-type-mui-menu', }} > diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.test.ts b/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.test.ts index 8aa164441e57..e6ab3bfc505e 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.test.ts +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.test.ts @@ -3,7 +3,7 @@ import {act} from '@testing-library/react'; -import type {UserPropertyField, UserPropertyFieldPatch} from '@mattermost/types/properties'; +import type {UserPropertyField, UserPropertyFieldPatch} from '@mattermost/types/properties_user'; import type {DeepPartial} from '@mattermost/types/utilities'; import {Client4} from 'mattermost-redux/client'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.ts b/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.ts index 84b4be53eb68..f3244941e079 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.ts +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_utils.ts @@ -6,7 +6,8 @@ import isEmpty from 'lodash/isEmpty'; import {useMemo} from 'react'; import type {ClientError} from '@mattermost/client'; -import {supportsOptions, type FieldValueType, type FieldVisibility, type UserPropertyField, type UserPropertyFieldGroupID, type UserPropertyFieldPatch} from '@mattermost/types/properties'; +import {supportsOptions, type FieldValueType, type FieldVisibility} from '@mattermost/types/properties'; +import type {UserPropertyField, UserPropertyFieldGroupID, UserPropertyFieldPatch} from '@mattermost/types/properties_user'; import {collectionAddItem, collectionFromArray, collectionRemoveItem, collectionReplaceItem, collectionToArray} from '@mattermost/types/utilities'; import type {IDMappedCollection, IDMappedObjects} from '@mattermost/types/utilities'; @@ -16,13 +17,11 @@ import {insertWithoutDuplicates} from 'mattermost-redux/utils/array_utils'; import {validateCPAFieldName} from 'utils/properties'; import {generateId} from 'utils/utils'; -import type {CollectionIO} from './section_utils'; +import type {CollectionIO, PendingOps} from './section_utils'; import {useThing, usePendingThing, BatchProcessingError} from './section_utils'; export type UserPropertyFields = IDMappedCollection; -type PendingOps = {[op: string]: T[]}; - export const useUserPropertyFields = () => { // current fields const [fieldCollection, readIO] = useThing(useMemo(() => ({ diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_values.test.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_values.test.tsx index f5bacfaa08dc..c957b9367556 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_values.test.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_values.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {fireEvent, renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; diff --git a/webapp/channels/src/components/admin_console/system_properties/user_properties_values.tsx b/webapp/channels/src/components/admin_console/system_properties/user_properties_values.tsx index 1ec266e3641a..3e247a603d2f 100644 --- a/webapp/channels/src/components/admin_console/system_properties/user_properties_values.tsx +++ b/webapp/channels/src/components/admin_console/system_properties/user_properties_values.tsx @@ -11,7 +11,8 @@ import type {CreatableProps} from 'react-select/creatable'; import CreatableSelect from 'react-select/creatable'; import {SyncIcon, PowerPlugOutlineIcon} from '@mattermost/compass-icons/components'; -import {supportsOptions, type PropertyFieldOption, type UserPropertyField} from '@mattermost/types/properties'; +import {supportsOptions, type PropertyFieldOption} from '@mattermost/types/properties'; +import {type UserPropertyField} from '@mattermost/types/properties_user'; import {getPluginDisplayName} from 'selectors/plugins'; diff --git a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.test.tsx b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.test.tsx index ca683547e5ce..0d91c8ef2d3d 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.test.tsx +++ b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type {IntlShape} from 'react-intl'; import type {RouteComponentProps} from 'react-router-dom'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {UserProfile} from '@mattermost/types/users'; import SystemUserDetail, {getUserAuthenticationTextField} from 'components/admin_console/system_user_detail/system_user_detail'; diff --git a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx index feb41003c98a..f1367db2ecc2 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx +++ b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx @@ -16,7 +16,8 @@ import {SyncIcon, PowerPlugOutlineIcon, CheckIcon, ChevronDownIcon} from '@matte import {Button} from '@mattermost/shared/components/button'; import {WithTooltip} from '@mattermost/shared/components/tooltip'; import type {ServerError} from '@mattermost/types/errors'; -import {supportsOptions, type PropertyFieldOption, type UserPropertyField} from '@mattermost/types/properties'; +import {supportsOptions, type PropertyFieldOption} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {Team, TeamMembership} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_details.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_details.tsx index 2b8996e0055f..3cb90c341ad4 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_details.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_details.tsx @@ -11,7 +11,7 @@ import type {Channel, ChannelModeration as ChannelPermissions, ChannelModeration import {SyncableType} from '@mattermost/types/groups'; import type {SyncablePatch, Group} from '@mattermost/types/groups'; import type {JobTypeBase} from '@mattermost/types/jobs'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import type {Scheme} from '@mattermost/types/schemes'; import type {Team} from '@mattermost/types/teams'; import type {UserProfile} from '@mattermost/types/users'; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.test.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.test.tsx index 58793d41774d..ca3921905681 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.test.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.test.tsx @@ -5,7 +5,8 @@ import React from 'react'; import type {AccessControlPolicy} from '@mattermost/types/access_control'; import type {Channel} from '@mattermost/types/channels'; -import type {UserPropertyField, FieldVisibility, FieldValueType} from '@mattermost/types/properties'; +import type {FieldVisibility, FieldValueType} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.tsx index 363e8e57ef10..74cce0d18638 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_level_access_rules.tsx @@ -6,7 +6,7 @@ import {FormattedMessage, defineMessage} from 'react-intl'; import {useSelector} from 'react-redux'; import type {Channel} from '@mattermost/types/channels'; -import type {UserPropertyField} from '@mattermost/types/properties'; +import type {UserPropertyField} from '@mattermost/types/properties_user'; import {getAccessControlSettings} from 'mattermost-redux/selectors/entities/access_control'; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/__snapshots__/team_details.test.tsx.snap b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/__snapshots__/team_details.test.tsx.snap index 17dfbfb9127e..bf6847f2fe18 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/team/details/__snapshots__/team_details.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/team_channel_settings/team/details/__snapshots__/team_details.test.tsx.snap @@ -23,7 +23,18 @@ exports[`admin_console/team_channel_settings/team/TeamDetails should match snaps class="admin-console__content" >
    - TeamProfile + +